API / Minn\Support

Minn\Support

Escaping, serialized readers, small helpers. 32 classes, 109 public methods and 42 internals. This page is the public surface; each class name opens the whole class.

Accents final class

public/minn/src/Minn/Support/Accents.php · 35 lines · Open the class →

Accented and special characters to their plain spelling, from the reference's own table (data/accents.json, captured with tests/tools/accents-capture.php): text is put in composed form first, a locale with spellings of its own (German, Danish, Catalan, Serbian, Bosnian) has them, and a string that is not UTF-8 is read as Latin-1. Anything the table does not name stays as it is.

staticstrip(string $text, string $locale = ''): string

The text with its accented characters spelled plainly, as the locale spells them.

insidedata()

Backtrace final class

public/minn/src/Minn/Support/Backtrace.php · 32 lines · Open the class →

A call stack named as wp_debug_backtrace_summary names it (probe placeholders-a): Class->method, Class::method and function names; a hook's function with the hook named; an included file by its path with the given prefixes taken off, in order. Innermost first.

staticsummary(array $frames, ?string $ignoreClass, int $skip, array $truncate): array

The frames' names, after the first $skip.

@param list<array<string, mixed>> $frames debug_backtrace()'s frames, innermost first
@param list<string> $truncate path prefixes taken off an included file
@return list<string>

DirectoryListing final class

public/minn/src/Minn/Support/DirectoryListing.php · 34 lines · Open the class →

Walks a directory the way the filesystem API lists it: named entries, dot entries skipped, hidden ones optional, recursion optional.

staticread(string $path, bool $includeHidden, bool $recursive, ?string $onlyName, callable $describe): array|false

A directory's entries described one by one, or false when unreadable.

@param callable(string): array<string, mixed> $describe the entry's own fields for an absolute path
@return array<string, array<string, mixed>>|false false when the path is not a readable directory

Email final class

public/minn/src/Minn/Support/Email.php · 69 lines · Open the class →

The address rules the reference applies: a local part from a fixed character class, a dotted domain of hyphen-trimmed labels. `check` names the first rule an address breaks; `sanitize` strips what it can and names why it gave up.

staticcheck(string $email): ?string

Why an address is invalid, or null when it passes the reference's checks.

staticsanitize(string $raw): array

An address with the characters the reference strips removed, and what was removed.

@return array{0: string, 1: string|null} the cleaned address (empty when refused) and the reason

Entities final class

public/minn/src/Minn/Support/Entities.php · 82 lines · Open the class →

HTML special-character encoding with the reference's quote styles and its "do not double encode" rule: an ampersand that already starts a known named or numeric entity stays as it is.

staticspecialchars(string $text, string|int|false $quoteStyle, bool $doubleEncode, callable $knownEntity): string

The reference's special-characters escaping, with its quote styles and double-encoding rule.

@param callable(string): bool $knownEntity whether a named entity is in the allowed table
staticdecode(string $text, string|int $quoteStyle): string

The reverse of specialchars: the five characters back, with the quote pairs the style asks for.

staticconvertInvalid(string $text): string

Windows-1252 numeric references rewritten as the Unicode references they meant.

insideencodeStrayAmpersands(), windows1252()

Escape final class

public/minn/src/Minn/Support/Escape.php · 25 lines · Open the class →

Text made safe for HTML the way WordPress's escapers make it (esc_html, esc_attr): invalid UTF-8 emptied, entities already present normalised rather than encoded again, the specials and both quotes encoded, then the filter plugins hook (esc_html, attribute_escape) handed the result and the original.

statichtml(mixed $text): string

Text for an element's content.

staticattr(mixed $text): string

Text for an attribute's value.

insideencoded()

FileHeaders final class

public/minn/src/Minn/Support/FileHeaders.php · 27 lines · Open the class →

Header values from a plugin or theme file. The labels (Plugin Name, Theme Name, Version) are the published file-header contract; the reader is a line scan of the first 8 KB, never PHP execution.

staticvalues(string $file, array $labels): array

The header values of a plugin or theme file, by label.

@param list<string> $labels
@return array<string, string>

FileTree final class

public/minn/src/Minn/Support/FileTree.php · 70 lines · Open the class →

Whole-directory reads and copies. The engine's own installer, the update unpacker and the plugins that reach for WordPress's copy_dir all want the same two operations: list a tree, and duplicate one.

staticfiles(string $dir, int $depth = 0, array $skip = array ( ), int $level = 1): array|false

Every file under a directory, and every directory itself with a trailing slash, to the given depth. Depth 0 means no limit; depth 1 stops at the directory's own entries and names its subdirectories without descending.

@param list<string> $skip names to leave out at every level
@return list<string>|false false when the directory cannot be read
staticcopy(string $from, string $to, array $skip = array ( )): bool

Copies a directory's contents into another, creating it if it is not there. Names in $skip are left behind at the top level only, which is how the update unpacker keeps a directory it means to preserve.

@param list<string> $skip

Files final class

public/minn/src/Minn/Support/Files.php · 66 lines · Open the class →

Recursive filesystem work behind WP_Filesystem_Direct: best-effort tree delete and chmod (suppressed errors, keep-going semantics, the AND of every step as the result), and the symbolic-to-octal permission string conversion. The facade class keeps the reference's argument handling and maps each operation here.

staticoctalFromSymbolic(string $mode): string

drwxr-xr-x (or any rwx string) to its octal digits, the reference's tallying shape.

staticdeleteTree(string $path): bool

Delete a directory tree, files first, best effort; true only when everything went. A symlinked directory is unlinked, never followed: the dev sites symlink plugin folders into the tree, and a delete that reached through one would empty the real source.

staticchmodTree(string $path, int $mode): bool

Apply a mode to every FILE under a directory (the directories themselves keep theirs); always reports true.

Flag final class

public/minn/src/Minn/Support/Flag.php · 11 lines · Open the class →

A yes or no as WordPress reads one from loose input (wp_validate_boolean).

staticof(mixed $value): bool

The string "false" in any case is no; anything else is PHP's truth.

Hierarchy final class

public/minn/src/Minn/Support/Hierarchy.php · 52 lines · Open the class →

Loops in a parent chain, found with two walkers: a slow one that takes one step at a time and a fast one that takes two (probe functions-utils, the hierarchy-loop finders). They meet only when the chain loops; it ends when a parent is empty. Each walker reads parents through the closure it is given, so a caller can override any node's parent.

staticmeeting(Closure $parentOf, mixed $start): mixed

The node where the slow walker meets the fast one, or null when the chain ends.

@param Closure(mixed): mixed $parentOf a node's parent
staticwalked(Closure $parentOf, mixed $start): ?array

Every node either walker stepped on before they met, in the order first reached (the slow walker's node, then the fast one's two steps), or null when the chain ends without a loop.

@param Closure(mixed): mixed $parentOf a node's parent
@return array<int|string, true>|null
insidewalk()

Ip final class

public/minn/src/Minn/Support/Ip.php · 22 lines · Open the class →

Addresses with their identifying tail removed, for logs and analytics that must not keep a visitor's exact address. An IPv4 address loses its last octet, an IPv6 address its last four groups. Anything that is not an address at all reads as the unspecified IPv4 address rather than as itself, so a malformed value can never leak through unchanged.

staticanonymize(string $address): string

An address with its last octet, or its tail, zeroed.

Kses final class

public/minn/src/Minn/Support/Kses.php · 481 lines · Open the class →

The HTML a user without unfiltered_html may store. Tags outside the allowlist are removed and their text kept; attributes outside the tag's list are dropped; URL attributes lose unsafe schemes; style attributes keep only listed properties and no code. Comments keep their text, and block delimiters are written back with their attribute values filtered.

constCOMMENT = array ( 'a' => array ( 0 => 'href', 1 => 'title', 2 => 'rel', ), 'abbr' => array ( 0 => 'title', ), 'acronym' => array ( 0 => 'title', ), 'b' => array ( ), 'blockquote' => array ( 0 => 'cite', ), 'cite' => array ( ), 'code' => array ( ), 'del' => array ( 0 => 'datetime', ), 'em' => array ( ), 'i' => array ( ), 'q' => array ( 0 => 'cite', ), 's' => array ( ), 'strike' => array ( ), 'strong' => array ( ), )
constURI_ATTRIBUTES = array ( 0 => 'action', 1 => 'archive', 2 => 'background', 3 => 'cite', 4 => 'classid', 5 => 'codebase', 6 => 'data', 7 => 'formaction', 8 => 'href', 9 => 'icon', 10 => 'longdesc', 11 => 'manifest', 12 => 'poster', 13 => 'profile', 14 => 'src', 15 => 'usemap', 16 => 'xmlns', )

Every attribute the reference treats as holding a URI, so its scheme is judged wherever the attribute is allowed.

constSCHEMES = array ( 0 => 'http', 1 => 'https', 2 => 'ftp', 3 => 'ftps', 4 => 'mailto', 5 => 'news', 6 => 'irc', 7 => 'gopher', 8 => 'nntp', 9 => 'feed', 10 => 'telnet', 11 => 'mms', 12 => 'rtsp', 13 => 'sms', 14 => 'svn', 15 => 'tel', 16 => 'fax', 17 => 'xmpp', 18 => 'webcal', 19 => 'urn', )

The URI schemes allowed by default.

staticpost(string $html): string

Post content as an author without unfiltered_html may store it.

staticcomment(string $html): string

A comment, profile or term description as anyone without unfiltered_html may store it: listed attributes only.

staticsanitize(string $html, Minn\Support\KsesPolicy $policy): string

The whole pass wp_kses makes with its default hooks: control characters out, references normalized, a "<" that opens no tag escaped, block attribute values filtered the same way, then the tags.

staticwithoutControls(string $html): string

The control characters kses removes (tab, newline and carriage return stay).

staticnormalizeEntities(string $html): string

Every "&" made a reference, in one pass: a known name or a code point kses accepts stays one (decimal padded to three digits, hex with a lower-case x), anything else becomes "&".

staticlessThan(string $html, ?Closure $escape = NULL): string

A "<" that reaches the next "<" or the end without a ">" is text: the run is escaped the way esc_html escapes it (quotes included).

@param (Closure(string): string)|null $escape
staticescapeHtml(string $text): string

Text escaped for HTML with references kept: invalid UTF-8 gives nothing, quotes become " and '.

staticblockAttributes(string $html, Closure $clean): string

Block markup with every attribute key and string value passed through the same filter, and the delimiters written back in their canonical form ("--->" read as "-->"). Markup without a comment is left alone.

@param Closure(string): string $clean
staticfilter(string $html, Minn\Support\KsesPolicy $policy): string

The tag pass: each run from "<" to the next ">" (or the end) is a comment, an inert bogus comment ("</" before a non-letter, "<!" before a lower-case letter), or an element judged by the policy; anything else in angle brackets goes. Text between keeps its references, with stray ones escaped. Run alone (wp_kses_split), a last "<" with no ">" still reads as a tag; inside sanitize() the less-than pass has already escaped it.

statictag(string $run, Minn\Support\KsesPolicy $policy): string

One run of the tag pass on its own (wp_kses_split2): a comment, a tag, or, for anything not starting with "<", a lone ">".

staticelement(string $element, string $attributes, Minn\Support\KsesPolicy $policy): string

An element rebuilt with the attributes the policy allows it (wp_kses_attr), its name as written and an XHTML slash kept; an element the policy does not know keeps none.

staticattributeList(string $raw): ?array

The attributes written inside a tag, read the way kses reads them: a name, then "=" and a quoted or bare value, or no value at all; junk between (stray quotes, "=", "/") is skipped; the first of two same-named attributes wins. Null when a quoted value never closes, which costs the tag every attribute.

@return array<string, array{name: string, value: ?string, whole: string}>|null
statictext(string $value): string

Plain text: tags gone, whitespace collapsed, control characters dropped.

staticurl(string $url): string

A URL for a stored field: empty when its scheme is not one the reference allows. The scheme is judged as a browser reads it, without the tabs, line breaks and other control characters it drops (java, a tab, then script: is javascript:).

staticattributeUrl(string $url, array $schemes = self::SCHEMES): string

A URL inside markup: whatever stands before the first colon, once every character reference and percent escape is decoded as deep as it goes and the invisible characters are dropped, must be an allowed scheme, or it is cut off and the rest is judged again. The reference cuts "?q=a:b" to "b" and "javascript:alert(1)//http://" to "//" the same way. A value with a good scheme is returned as given.

@param list<string> $schemes
staticvalidCodePoint(int $code): bool

Whether a code point is one a reference may name (valid_unicode): tab, line feed, carriage return, and the rest of Unicode from space up, except the surrogates and U+FFFE and U+FFFF.

staticpdfObject(string $url, string $uploadsUrl): bool

Whether a URL may be an object's data in post content: an http or https URL on the uploads host and port, no credentials, query or fragment, whose path ends in ".pdf".

insidecleanValue(), run(), htmlComment(), deepDecode(), visible(), normalizeText(), normalizeAttribute(), named(), codePoint(), attributes(), rendered(), srcset()

KsesAttributes final class

public/minn/src/Minn/Support/KsesAttributes.php · 76 lines · Open the class →

Kses one attribute at a time, for the shortcode pass that runs inside HTML tags: an opening tag cut into its attributes, and one attribute judged as kses judges it on its element. Probe shortcode-run.

staticelementParts(string $element): ?array

An opening tag cut as wp_kses_attr_parse cuts it: the start ("<a "), each attribute with the whitespace after it (a shortcode standing as a name counts as one), and the end (">" or "/>"). Null for a closing tag, a comment, CDATA, or anything between the brackets that is not attributes.

@return list<string>|null
staticparse(string $attributes): ?array

An attribute string cut into its attributes, each with the whitespace after it (wp_kses_hair_parse): a name (or a shortcode standing as one), then "=" and a quoted or bare value, or nothing. Null when anything in it is not an attribute: leading whitespace, a stray quote, a quoted value that never closes.

@return list<string>|null
staticoneAttribute(string $attr, string $element, Minn\Support\KsesPolicy $policy): string

One attribute as written, judged as kses judges it on the element (wp_kses_one_attr): the value escaped for an attribute and kept in its own quotes (a bare one gains double quotes), a URL's bad scheme cut away, style kept to the allowed properties; nothing when the element may not carry it or a quoted value never closes. The whitespace around it stays.

KsesCss final class

public/minn/src/Minn/Support/KsesCss.php · 138 lines · Open the class →

The style attribute as kses keeps it (safecss_filter_attr): each declaration whose property is on the list stays, a value's url() only on the properties that may hold one and only with a safe scheme, the gradients and CSS functions the reference allows, and nothing that could end the declaration. Plugins widen the list and the verdict through the hooks the facade wires in (safe_style_css, safecss_filter_attr_allow_css).

staticstyle(string $style): string

A style attribute's value with only the listed properties kept.

staticstyleHooks(Closure $properties, Closure $allow): void

The runtime's say over style attributes: the property list (safe_style_css) and each declaration (safecss_filter_attr_allow_css). The facade sets these as it loads.

@param Closure(list<string>): list<string> $properties
@param Closure(bool, string): bool $allow
insidecss(), cssTestString()

KsesEntities final class

public/minn/src/Minn/Support/KsesEntities.php · 30 lines · Open the class →

The named references kses keeps as written: the list captured from the reference (data/kses.json) plus the five XML ones. Any other name is stored as "&name;".

staticknown(string $name): bool

Whether "&name;" is a reference kses leaves alone.

staticallowlist(string $context): array

An allowlist the reference ships, by context ("post" or "data").

@return array<string, array<string, mixed>>
insidetable()

KsesPolicy final readonly class

public/minn/src/Minn/Support/KsesPolicy.php · 115 lines · Open the class →

What one kses pass allows: the tags, each tag's attributes (allowed plainly or with value rules), whether a tag takes data- attributes, which attributes hold URIs, and the schemes those URIs may use.

propreadonly array $schemes
staticpost(): self

Post content from an author without unfiltered_html: the reference's post allowlist as captured.

staticcomment(): self

Comments, profiles and term descriptions: only the attributes each tag lists, nothing global.

staticfromAllowlist(array $allowedHtml, array $schemes, array $uriAttributes): self

A caller's own allowlist taken literally: a listed attribute is allowed whatever it maps to (false included, as the reference only asks whether the name is there), an array carries value rules, and "data-*" lets the tag take any data- name. Nothing else is implied.

@param array<array-key, mixed> $allowedHtml
@param list<string> $schemes
@param list<string> $uriAttributes
methodallowsTag(string $tag): bool

Whether the tag may appear at all.

methodrules(string $tag, string $name): ?array

The rules an attribute carries on a tag: an empty list when it is allowed plainly, null when it is not allowed.

@return array<array-key, mixed>|null
methodrequired(string $tag): array

The attributes a tag must keep: lose one and the tag keeps none.

@return list<string>
methodholdsUri(string $name): bool

Whether the attribute holds a URI whose scheme must be judged.

KsesValues final class

public/minn/src/Minn/Support/KsesValues.php · 38 lines · Open the class →

The value rules an allowlist attribute may carry, as the reference judges them: lengths count bytes, bounds need a whole number (up to six digits, up to six spaces either side), "valueless" compares the attribute's form, "values" compares without case, and a callback decides for itself. A rule the reference does not know passes. Where the reference fatals (a values rule that is not a list, a callback that does not exist) the value fails.

staticsatisfies(string $value, string $valueless, array $rules): bool

Whether a value meets every rule its attribute carries; "required" is the tag's concern, so it is skipped here.

@param array<array-key, mixed> $rules
staticcheck(string $value, string $valueless, string $rule, mixed $expected): bool

One rule against one value; $valueless is "y" for a bare attribute and "n" for one with a value.

insidewholeNumber()

Lists final class

public/minn/src/Minn/Support/Lists.php · 190 lines · Open the class →

List shaping behind the facade's array utilities: arguments over their defaults (wp_parse_args), plucking and filtering (WP_List_Util), the multi-field sort wp_list_sort() promises (loose comparison per field, first difference wins) and the row-shape conversions wpdb hands back for its OBJECT_K / ARRAY_A / ARRAY_N output formats.

staticargs(mixed $args, mixed $defaults = array ( )): array

Arguments as WordPress takes them (wp_parse_args): an object's properties, an array, or a query string, over the defaults.

@param array<array-key, mixed> $defaults
@return array<array-key, mixed>
staticpluck(array $items, string|int $field, string|int|null $indexKey = NULL): array

One field of each item (wp_list_pluck), keyed as the list was, or by another field when one is named (items without it are appended); anything not an array or an object is passed over.

@param array<array-key, mixed> $items
@return array<array-key, mixed>
staticfilter(array $items, array $fields, string $operator): array

The items matching all the fields given (AND), any of them (OR), or none (NOT), compared loosely, keys kept; nothing for another operator.

@param array<array-key, mixed> $items @param array<array-key, mixed> $fields
@return array<array-key, mixed>
staticitems(mixed $input): array

A list as arguments give one (wp_parse_list): an array's entries trimmed, the empty ones dropped (keys kept); a string split on commas and whitespace.

@return array<int|string, string>
staticids(mixed $input): array

Ids as arguments give them (wp_parse_id_list): each a whole number made positive, each once, in first-seen order.

@return list<int>
staticsort(array $items, array $orderby, bool $preserveKeys): array

Items sorted by several fields, each ascending or descending.

@param array<int|string, mixed> $items
@param array<string, string> $orderby field => ASC|DESC
@return array<int|string, mixed>
staticshapeRows(array $rows, string $output): array

Rows of stdClass shaped for a wpdb output format: keyed by their first column (first row wins a duplicate key), associative, or numeric.

@param list<object> $rows
@return array<int|string, mixed>
staticdescendants(array $items, int $rootId, callable $id, callable $parent, array $visited = array ( )): array

Every descendant of one root in a flat parent-linked list, preorder (a child ahead of its own children), the shape _get_term_children and get_page_children walk. Visited ids guard against a parent cycle.

@param list<mixed> $items
@param callable(mixed): int $id
@param callable(mixed): int $parent
@param list<int> $visited
@return list<mixed>
insidekeyedByFirstColumn()

Locale final class

public/minn/src/Minn/Support/Locale.php · 31 lines · Open the class →

The locale's calendar and number vocabulary as data: the names a site prints for weekdays, months and meridiems, and how it separates thousands and decimals.

The names are English here because the engine carries no core translations yet; the facade runs each one through the translation filters on the way out, so a catalogue can answer for them later without this class changing.

constWEEKDAYS = array ( 0 => 'Sunday', 1 => 'Monday', 2 => 'Tuesday', 3 => 'Wednesday', 4 => 'Thursday', 5 => 'Friday', 6 => 'Saturday', )
constMONTHS = array ( 0 => 'January', 1 => 'February', 2 => 'March', 3 => 'April', 4 => 'May', 5 => 'June', 6 => 'July', 7 => 'August', 8 => 'September', 9 => 'October', 10 => 'November', 11 => 'December', )
constMERIDIEM = array ( 'am' => 'am', 'pm' => 'pm', 'AM' => 'AM', 'PM' => 'PM', )
constNUMBER_FORMAT = array ( 'thousands_sep' => ',', 'decimal_point' => '.', )
constLIST_ITEM_SEPARATOR = ', '
constWORD_COUNT_TYPE = 'words'
constTEXT_DIRECTION = 'ltr'
staticweekdayInitial(string $day): string

A weekday's one-letter form.

staticabbreviation(string $name): string

A weekday's or month's three-letter form; May is already three letters.

staticmonthKey(string|int $month): string

Months are keyed by their zero-padded number, both ways round.

Markers final class

public/minn/src/Minn/Support/Markers.php · 59 lines · Open the class →

The BEGIN/END marker blocks insert_with_markers() maintains in files like .htaccess: the captured shape keeps everything outside the markers, replaces the block inside them, and writes the reference's four-line do-not-edit preamble ahead of the inserted lines.

staticwrite(string $file, string $marker, array $lines): bool

Replaces the lines between a marker's begin and end comments in a file.

@param list<string> $lines
staticread(string $file, string $marker): array

The lines between a marker's begin and end comments, every block of it in order. A line opens or closes a block when it contains the comment anywhere (case-sensitive); lines that start with "#" are left out, so the preamble and any nested markers are, while indented comments stay. Lines split on "\n" only, and a block left open at the end of the file keeps the empty line after its final newline.

@return list<string>

Paths final class

public/minn/src/Minn/Support/Paths.php · 75 lines · Open the class →

File-system path and permission spellings.

statictranslationDir(string $domain, string $locale, string $langDir, ?string $customPath, ?Closure $listed = NULL): string|false

The trailing-slashed directory holding a text domain's {domain}-{locale}.mo: a custom path first, then the language dir's plugins and themes folders, then the dir itself for the default domain; false when none has the file. $listed, when given, lists a folder's files (the textdomain registry's own lister, which plugins may answer for) and is read instead of the disk.

@param (\Closure(string): array<int, string>)|null $listed
staticnormalize(string $path): string

Forward slashes only, runs collapsed, a stream wrapper kept, a Windows drive letter upper-cased.

staticsymbolicMode(int $mode): string

The `ls -l` spelling of a mode: type letter, then rwx for owner, group and world with the setuid, setgid and sticky bits folded in.

ScriptTag final class

public/minn/src/Minn/Support/ScriptTag.php · 69 lines · Open the class →

Script elements as the reference builds them (probe script-tags): the attributes sorted by name, a src or href through esc_url and every other value escaped (true or null printed bare, false left out); inline code between newlines, with any "<script" or "</script" that would end or open an element written with its "s" as a \u escape. Only JavaScript and JSON can carry that escape: a script of another type whose code holds such a sequence is not printed at all.

staticelement(array $attributes): string

The empty element for a script file.

@param array<string, mixed> $attributes
staticinline(string $code, array $attributes): string

The element for inline code (already between its newlines), or '' when its type cannot hold the code safely.

@param array<string, mixed> $attributes
insideattributes()

SearchReplace final class

public/minn/src/Minn/Support/SearchReplace.php · 38 lines · Open the class →

String replace that walks serialized-PHP arrays of scalars without unserialize, so a domain change in an option blob keeps its lengths.

staticin(string $value, string $old, string $new): array

A value with one string replaced, and how many times.

@return array{0: string, 1: int} replacement and how many times $old occurred
insidewalk()

Serialized final class

public/minn/src/Minn/Support/Serialized.php · 356 lines · Open the class →

Tolerant readers for the serialized-PHP blobs WordPress stores. Nothing here executes the blob; each reader scans for the one shape it needs.

constINVALID = '' . "\0" . 'minn:invalid' . "\0" . ''

Returned by decode() when the blob is not a serialized value the reader accepts.

staticstringList(?string $blob): array

The string values of a serialized string list.

staticserializeStringList(array $values): string

A flat string list in the stored form.

staticfield(?string $blob, string $field): ?string

The first "field";value pair inside a blob: string, int, or float value as a string.

staticdecode(string $blob, ?Closure $revive = NULL): mixed

A serialized scalar or array as PHP data, parsed by this reader: strings, integers, floats, booleans, null, and arrays of those. An object record becomes a stdClass of its properties, or whatever the reviver makes of the class name and those properties; nothing here instantiates anything itself. A blob with trailing bytes or a malformed shape is INVALID.

@param ?\Closure(string, \stdClass): object $revive
staticstoredClass(object $object): ?string

The class an object was stored as, when it came back as a stdClass of its properties.

staticlooksSerialized(string $data): bool

Whether a string has the shape of serialized data, as is_serialized() judges it: what maybe_serialize() stores serialized again so it reads back as the string it was.

staticencode(mixed $value): string

PHP's serialize() for the values decode() accepts: null, bool, int, float, string, arrays of those, and objects written as their class.

staticintList(?string $blob): array

The integer values of a serialized list such as sticky_posts.

insideread(), readValue(), readObject(), encodeRecord(), encodeWrapper(), expect(), size(), until(), encodeValue(), encodeObject()

Slashes final class

public/minn/src/Minn/Support/Slashes.php · 32 lines · Open the class →

Magic-quote slashes the way WordPress keeps them (wp_slash, wp_unslash): added to or stripped from every string inside a value, arrays and objects walked all the way down, anything else left as it is.

staticadd(mixed $value): mixed

Every string in a value with its quotes and backslashes slashed.

staticstrip(mixed $value): mixed

Every string in a value with one level of slashes taken off.

insidedeep()

SqlTable final class

public/minn/src/Minn/Support/SqlTable.php · 63 lines · Open the class →

The table a SQL statement is about, as wpdb::get_table_from_query reports it, and a database host string read into its parts (probe wpdb). A name is letters, digits, $ _ . - and backticks (dropped), plus two-byte UTF-8.

staticof(string $query): ?string

The table a statement names (backticks dropped), or null when it names none the reference recognises.

statichost(string $host): ?array

A DB_HOST read as host, port, socket and whether the host is IPv6: a socket after ":/", an IPv6 address in brackets (more than one colon), a port only when it is digits. Null when nothing parses.

@return array{0: string, 1: ?int, 2: ?string, 3: bool}|null

Time final class

public/minn/src/Minn/Support/Time.php · 21 lines · Open the class →

Human-scale spans: a number of seconds as the largest whole unit it fills, rounded, never below one.

staticspan(int $seconds): array

A number of seconds as its largest whole unit and count.

@return array{0: int, 1: string} count and unit name

TimezoneChoice final class

public/minn/src/Minn/Support/TimezoneChoice.php · 109 lines · Open the class →

The timezone choices a settings form offers (wp_timezone_choice, probe placeholder-helpers): the zones of each continent, cities in natural order (a zone with three parts reads "City - Sub-city"), then UTC, then the offsets set by hand. "Select a city" leads when nothing is chosen, and a real zone outside the list (an old name, Etc/) leads when it is the one chosen. Each choice is a line of its own.

statichtml(string $selected, Closure $translate): string

The choices as option lines, the chosen zone marked.

@param \Closure(string, string): string $translate a text in a text domain, translated
insidezones(), groups(), outsideList(), offset(), offsets(), option()

Url final class

public/minn/src/Minn/Support/Url.php · 231 lines · Open the class →

URL shaping the escaping and query helpers share: the character cleanup esc_url applies, bracket encoding outside the authority, and query argument merging. Behaviour pinned by contracts/fixtures/api/functions.json.

staticwithTrailingSlash(string $value): string

The value with one trailing slash, whatever slashes or backslashes it ended in (trailingslashit).

staticwithoutTrailingSlash(string $value): string

The value with every trailing slash and backslash taken off (untrailingslashit).

staticclean(string $url, string $scheme = 'http'): string

Spaces encoded, stray characters dropped, ";//" healed, a bare host given http; '' when nothing survives.

staticencodeBrackets(string $url, array $parsed): string

Square brackets after the authority are percent-encoded; the authority itself is left alone. @param array<string, mixed> $parsed

@param array<string, mixed> $parsed
staticwithQuery(string $uri, array $new, Closure $encode, Closure $build): string

The URI with query arguments merged in (false removes one), the fragment kept, a bare query string treated as such; a URI that is only a query (or nothing) keeps its leading question mark.

@param array<string, mixed> $new
@param Closure(array): array $encode encodes the existing arguments the way the reference does
@param Closure(array): string $build builds the query string
staticvalidateForHttp(string $url, string $homeHost, int $homePort, Closure $externalAllowed, ?Closure $safePorts = NULL): ?string

The checks wp_http_validate_url makes on a URL whose protocol already passed: an http(s) scheme, a host without credentials or a colon, no private address unless it is this site or allowed, only the safe ports (80, 443 and 8080 unless the caller's list says otherwise; the site's own always). Returns the URL, or null when refused.

@param Closure(string, string): bool $externalAllowed whether a private host may be fetched anyway
@param (Closure(list<int>, string, string): array)|null $safePorts the port list for a URL that names a port
staticbuildQuery(array $data, string $prefix = ''): string

A query string in the reference's spelling (probe query-args): keys and values as given, nested keys as `a%5Bb%5D`, null left out, booleans as 0/1.

staticparse(string $url, int $component = -1): array|string|int|false|null

parse_url that also accepts scheme-relative and path-only URLs; a single component by its PHP_URL_* constant.

staticwithScheme(string $url, string $scheme): string

The URL under a scheme, or scheme-and-host stripped for 'relative'; a protocol-relative URL is read as http first.

staticsafeRedirect(string $location, Closure $allowedHosts): ?string

A redirect target the site may send a browser to: http(s) only and a host the caller allows (local paths always pass). Credentials before the host are kept, as the reference keeps them: the host decides.

@param Closure(string): list<string> $allowedHosts the hosts allowed for the target's host
insideisPrivate()

Utf8 final class

public/minn/src/Minn/Support/Utf8.php · 154 lines · Open the class →

UTF-8 as the reference reads it. Well-formed means no overlong forms, surrogates, code points past U+10FFFF, stray continuation bytes or truncated sequences; noncharacters, NUL and a byte order mark pass. Split into characters (the multibyte fallbacks in compat.php), a malformed byte is one character and so is the longest start of a sequence that breaks off, so "\xE2\x82" counts once.

staticisValid(string $bytes): bool

True for well-formed UTF-8, including the empty string.

staticcharacters(string $bytes): array

The bytes cut into characters, a malformed byte or a broken-off sequence counting as one.

@return list<string>
staticscan(string $bytes, int $at, ?int $maxBytes = NULL, ?int $maxCodePoints = NULL): array

Reads well-formed characters from $at, as the reference's scanner does (probe utf8). It stops $maxBytes past $at (a character begun before that is read whole), after $maxCodePoints, or at a malformed byte. The answer: the characters read, where it stopped, the length of the malformed run there (a broken-off start of a sequence, else one byte, cut at the byte limit; 0 when there is none), and whether a character that could be a noncharacter was one (null when none could be: only EF and four-byte sequences hold them).

@return array{int, int, int, ?bool}
staticisNoncharacter(int $code): bool

Whether a code point is a noncharacter: U+FDD0 to U+FDEF, or the last two of any plane.

statichasNoncharacters(string $bytes): bool

Whether any well-formed character is a noncharacter, malformed bytes stepped over.

staticscrub(string $bytes): string

The bytes with each malformed run (as characters() cuts them) replaced by U+FFFD.

staticspan(string $bytes, int $offset, int $maxCodePoints): array

How many bytes from $offset the first $maxCodePoints characters take, and how many there were.

@return array{int, int}
statictoLatin1(string $bytes): string

UTF-8 as ISO-8859-1: a character past U+00FF, or a malformed run, becomes "?".

statickeptBy(string $bytes, string $charset): string

What a column in this charset keeps: utf8mb4 drops each malformed run, utf8 (utf8mb3) every four-byte character too; any other charset keeps the bytes.

staticfromLatin1(string $bytes): string

ISO-8859-1 as UTF-8: each byte the character of its value.

staticfromCodePoint(int $code): ?string

The UTF-8 bytes for a code point, or null for a negative one, a surrogate, or one past U+10FFFF.

staticfirstCodePoint(string $bytes): ?int

The code point of the first character, or null when the bytes do not start with a whole, well-formed one.

WebServer final class

public/minn/src/Minn/Support/WebServer.php · 8 lines · Open the class →

What the SERVER_SOFTWARE string says about the web server in front of the site.

staticisApache(string $software): bool

Whether the server speaks Apache's module and .htaccess conventions: Apache itself, or LiteSpeed.