diff --git a/changelog.txt b/changelog.txt index 1700450..e1013fc 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,38 +1,5 @@ == Changelog == -= 1.2.2 = - -_Release date: 2026-08-24_ - -**Highlights** - -* Manager (by ROBOTSTXT) detection now uses the ecosystem presence constant ROBOTSTXT_MANAGER_NOTICED (Manager 1.6.2+), with a plugin-list scan fallback for older Manager versions - -**Changed** - -* `robotstxt_docmd_is_manager_active()` now checks the ROBOTSTXT_MANAGER_NOTICED presence constant (Manager 1.6.2+) and falls back to scanning the plugin list (get_plugins() + is_plugin_active()) when the constant is absent; same function name and return type, so callers are unaffected - -**Security** - -* `composer update` (phpstan 2.2.9, nette/schema 1.3.6 — dev tooling only); `composer audit` clean, no known CVEs - -**Compatibility** - -* WordPress: 4.2 - 7.1 (floor re-verified with WP-Compat; smoke-tested on 7.2-alpha) -* PHP: 8.0 - 8.5 (floor re-verified with PHPCompatibility 5.6-8.5 full-range scan) - -**Translations** - -* Spanish (es_ES) and Catalan (ca): verified complete and in sync (156 strings, no changes needed) - -**Tests** - -* PHP Coding Standards: PHPCS with WordPress-Core, WordPress-Docs, WordPress-Extra — 0 errors -* PHPStan: level 9, 0 errors -* PHPCompatibility: PHP 8.0-8.5 validated (full-range scan 5.6-8.5) -* WP-Compat: WordPress 4.2 floor validated -* PHPUnit: 23 tests pass (17 plugin header tests + 6 new Manager-detection tests covering both detection paths) - = 1.2.1 = _Release date: 2026-08-17_ diff --git a/readme.txt b/readme.txt index ac59063..5c061f8 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Tags: github, documentation, markdown, sync, automation Requires at least: 4.2 Tested up to: 7.1 Requires PHP: 8.0 -Stable tag: 1.2.2 +Stable tag: 1.2.1 License: GPLv3 or later License URI: https://www.gnu.org/licenses/gpl-3.0.html @@ -189,22 +189,6 @@ Then go to Documentation → Settings, and you'll see a "Debug Tools" section at For the complete changelog, see [changelog.txt](https://www.robotstxt.software/plugins/robotstxt-documentation-markdown/). -= 1.2.2 - 2026-08-24 = - -**Changed** - -* Manager (by ROBOTSTXT) detection now uses the ecosystem presence constant `ROBOTSTXT_MANAGER_NOTICED` (Manager 1.6.2+), falling back to a plugin-list scan for older Manager versions — same function name and behavior for callers -* New unit tests for both detection paths (constant defined / plugin-list fallback) - -**Compatibility** - -* WordPress: 4.2 - 7.1 (floor re-verified with WP-Compat; smoke-tested on 7.2-alpha) -* PHP: 8.0 - 8.5 (floor re-verified with PHPCompatibility 5.6-8.5 full-range scan) - -**Translations** - -* Spanish (es_ES) and Catalan (ca): verified complete and in sync (156 strings, no changes needed) - = 1.2.1 - 2026-08-17 = **Changed** @@ -254,10 +238,41 @@ For the complete changelog, see [changelog.txt](https://www.robotstxt.software/p * Inline `onclick` confirm on Delete replaced with a `data-confirm` attribute + delegated handler (CSP-friendlier, less fragile) * Add Mapping "existing content" dropdown now queries only public post types (excludes attachments and the internal mapping CPT) with `no_found_rows` for better performance on large sites -== Upgrade Notice == +**Compatibility** -= 1.2.2 = -Manager (by ROBOTSTXT) detection updated: now uses the ROBOTSTXT_MANAGER_NOTICED presence constant (Manager 1.6.2+) with a fallback for older Manager versions. +* Minimum WordPress raised to 6.8 (latest stable + two previous majors) +* Verified compatible with WordPress 7.1 +* Declared PHP minimum made consistent across `readme.txt`, `composer.json`, `phpstan.neon`, and the PHPCompatibility scan range — real minimum remains 8.0 + += 1.1.1 - 2026-06-08 = + +**Security** + +* CommonMark: disabled raw HTML passthrough (`html_input: strip`, `allow_unsafe_links: false`) — prevents stored XSS via a compromised upstream repository +* Settings option now stored with `autoload = false` — encrypted GitHub token no longer loaded on every WordPress request +* Replaced `serialize()` with `wp_json_encode()` in updater HMAC cache signature +* Added strict base64 length validation before IV extraction in token decryption +* Added `base64_decode()` return-value check in GitHub file content fetch + +**Fixed** + +* Admin notices now display results for all operations: mapping created, updated, deleted, sync complete, and errors — previously only "Settings saved" was shown +* `wp_update_post()` return value now checked during sync — silent failures no longer reported as success +* Wrong textdomain in updater class (`'robotstxt-smtp'` → `'robotstxt-documentation-markdown'`) + +**Changed** + +* Renamed `robotstxt-updater.php` → `class-robotstxt-updater.php` (WordPress file naming convention) +* Minimum PHP version corrected to 8.0 (real minimum confirmed by PHPCompatibility scan — no PHP 8.1 or 8.2 specific features used) + +**Developer** + +* Added full tooling: `composer.json`, `phpstan.neon` (level 9), `.phpcs.xml`, `bin/deploy.sh`, `phpunit.xml.dist` +* PHPCompatibility updated to 10.0.0-alpha2 (PHP 8.x feature detection) +* PHPUnit: 17 plugin header tests added +* PHPCS, PHPStan level 9, PHPUnit all pass with 0 errors + +== Upgrade Notice == = 1.2.1 = Automatic updates now require the Manager (by ROBOTSTXT) plugin. A notice with the download link is shown on the Plugins and Settings pages. diff --git a/robotstxt-documentation-markdown.php b/robotstxt-documentation-markdown.php index a6430a2..e52d538 100644 --- a/robotstxt-documentation-markdown.php +++ b/robotstxt-documentation-markdown.php @@ -3,7 +3,7 @@ * Plugin Name: Documentation Markdown (by ROBOTSTXT) * Plugin URI: https://www.robotstxt.software/plugins/robotstxt-documentation-markdown/ * Description: Synchronizes Markdown documentation from GitHub repositories to WordPress pages and posts automatically. - * Version: 1.2.2 + * Version: 1.2.1 * Requires at least: 4.2 * Requires PHP: 8.0 * Security: robotstxt@robotstxt.es @@ -25,7 +25,7 @@ if ( ! defined( 'ABSPATH' ) ) { } // Define plugin constants. -define( 'ROBOTSTXT_DOCMD_VERSION', '1.2.2' ); +define( 'ROBOTSTXT_DOCMD_VERSION', '1.2.1' ); define( 'ROBOTSTXT_DOCMD_PLUGIN_FILE', __FILE__ ); define( 'ROBOTSTXT_DOCMD_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); define( 'ROBOTSTXT_DOCMD_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); @@ -1676,41 +1676,17 @@ function robotstxt_docmd_debug_fix_crons() { } /** - * Check whether the Manager (by ROBOTSTXT) plugin is installed and active + * Check whether the Manager (by ROBOTSTXT) plugin is active * * Updates for this plugin are delivered through the Manager plugin. This - * helper detects whether it is installed and active: it uses the ecosystem - * presence constant (Manager 1.6.2+) and falls back to a plugin-list scan - * for older Manager versions. + * helper detects whether it is installed and active. * * @since 1.2.1 - * @since 1.2.2 Switched to the ROBOTSTXT_MANAGER_NOTICED presence constant - * with a plugin-list scan fallback for Manager < 1.6.2. * * @return bool True if Manager (by ROBOTSTXT) is active, false otherwise. */ function robotstxt_docmd_is_manager_active(): bool { - if ( defined( 'ROBOTSTXT_MANAGER_NOTICED' ) && ROBOTSTXT_MANAGER_NOTICED ) { - return true; - } - - if ( ! function_exists( 'get_plugins' ) ) { - require_once ABSPATH . 'wp-admin/includes/plugin.php'; - } - - foreach ( get_plugins() as $file => $data ) { - $slug = dirname( $file ); - - if ( '.' === $slug ) { - $slug = basename( $file, '.php' ); - } - - if ( 'robotstxt-manager' === $slug ) { - return is_plugin_active( $file ); - } - } - - return false; + return defined( 'ROBOTSTXT_MANAGER_VERSION' ); } /** diff --git a/update.json b/update.json new file mode 100644 index 0000000..4fa49e4 --- /dev/null +++ b/update.json @@ -0,0 +1,27 @@ +{ + "name": "Documentation Markdown (by ROBOTSTXT)", + "slug": "robotstxt-documentation-markdown", + "version": "1.2.1", + "download_url": "https://git.robotstxt.es/ROBOTSTXT/robotstxt-documentation-markdown/releases/download/1.2.1/robotstxt-documentation-markdown-1.2.1.zip", + "requires": "6.8", + "requires_php": "8.0", + "tested": "7.1", + "last_updated": "2026-08-07", + "author": "ROBOTSTXT", + "author_profile": "https://www.robotstxt.es/", + "homepage": "https://git.robotstxt.es/ROBOTSTXT/robotstxt-documentation-markdown", + "description": "Synchronizes Markdown documentation from GitHub repositories to WordPress pages and posts automatically. Perfect for maintaining technical documentation, API references, knowledge bases, and more with version control.", + "changelog": "", + "sections": { + "description": "

Documentation Markdown is a powerful WordPress plugin that enables seamless synchronization of Markdown documentation files from GitHub repositories into your WordPress site.

Key Features

Use Cases

Requirements

", + "changelog": "" + }, + "banners": { + "low": "", + "high": "" + }, + "icons": { + "1x": "", + "2x": "" + } +} diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 350ecaf..6194647 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -275,17 +275,17 @@ }, { "name": "nette/schema", - "version": "v1.3.6", - "version_normalized": "1.3.6.0", + "version": "v1.3.5", + "version_normalized": "1.3.5.0", "source": { "type": "git", "url": "https://github.com/nette/schema.git", - "reference": "c54350438cd6914616f790a49cb424605f421562" + "reference": "f0ab1a3cda782dbc5da270d28545236aa80c4002" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/schema/zipball/c54350438cd6914616f790a49cb424605f421562", - "reference": "c54350438cd6914616f790a49cb424605f421562", + "url": "https://api.github.com/repos/nette/schema/zipball/f0ab1a3cda782dbc5da270d28545236aa80c4002", + "reference": "f0ab1a3cda782dbc5da270d28545236aa80c4002", "shasum": "" }, "require": { @@ -299,7 +299,7 @@ "phpstan/phpstan": "^2.1.39@stable", "tracy/tracy": "^2.8" }, - "time": "2026-08-16T21:58:41+00:00", + "time": "2026-02-23T03:47:12+00:00", "type": "library", "extra": { "branch-alias": { @@ -339,7 +339,7 @@ ], "support": { "issues": "https://github.com/nette/schema/issues", - "source": "https://github.com/nette/schema/tree/v1.3.6" + "source": "https://github.com/nette/schema/tree/v1.3.5" }, "install-path": "../nette/schema" }, diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index a249c41..dfced0b 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -38,9 +38,9 @@ 'dev_requirement' => false, ), 'nette/schema' => array( - 'pretty_version' => 'v1.3.6', - 'version' => '1.3.6.0', - 'reference' => 'c54350438cd6914616f790a49cb424605f421562', + 'pretty_version' => 'v1.3.5', + 'version' => '1.3.5.0', + 'reference' => 'f0ab1a3cda782dbc5da270d28545236aa80c4002', 'type' => 'library', 'install_path' => __DIR__ . '/../nette/schema', 'aliases' => array(), diff --git a/vendor/nette/schema/readme.md b/vendor/nette/schema/readme.md index 7e52878..ce9d0d1 100644 --- a/vendor/nette/schema/readme.md +++ b/vendor/nette/schema/readme.md @@ -126,7 +126,7 @@ Expect::null() Expect::array($default = []) ``` -And then all types [supported by the Validators](https://doc.nette.org/validators#toc-expected-types) via `Expect::type('scalar')` or abbreviated `Expect::scalar()`. Also class or interface names are accepted, e.g. `Expect::type('AddressEntity')`. +And then all types [supported by the Validators](https://doc.nette.org/validators#toc-validation-rules) via `Expect::type('scalar')` or abbreviated `Expect::scalar()`. Also class or interface names are accepted, e.g. `Expect::type('AddressEntity')`. You can also use union notation: diff --git a/vendor/nette/schema/src/Schema/Context.php b/vendor/nette/schema/src/Schema/Context.php index b42b1ed..a002d5c 100644 --- a/vendor/nette/schema/src/Schema/Context.php +++ b/vendor/nette/schema/src/Schema/Context.php @@ -10,9 +10,6 @@ namespace Nette\Schema; use function count; -/** - * Accumulates errors and warnings during schema validation and tracks the current path. - */ final class Context { public bool $skipDefaults = false; @@ -47,10 +44,7 @@ final class Context } - /** - * Returns a closure that returns true as long as no new errors have been added since the call. - * @return \Closure(): bool - */ + /** @return \Closure(): bool */ public function createChecker(): \Closure { $count = count($this->errors); diff --git a/vendor/nette/schema/src/Schema/Elements/AnyOf.php b/vendor/nette/schema/src/Schema/Elements/AnyOf.php index 582cf13..09e21c9 100644 --- a/vendor/nette/schema/src/Schema/Elements/AnyOf.php +++ b/vendor/nette/schema/src/Schema/Elements/AnyOf.php @@ -14,9 +14,6 @@ use Nette\Schema\Schema; use function array_merge, array_unique, implode, is_array; -/** - * Schema that accepts any of a fixed set of values or sub-schemas (union type / enumeration). - */ final class AnyOf implements Schema { use Base; @@ -35,9 +32,6 @@ final class AnyOf implements Schema } - /** - * Sets the first variant as the default value (instead of null). - */ public function firstIsDefault(): self { $this->default = $this->set[0]; @@ -45,9 +39,6 @@ final class AnyOf implements Schema } - /** - * Allows null as an accepted value in addition to the defined variants. - */ public function nullable(): self { $this->set[] = null; @@ -55,9 +46,6 @@ final class AnyOf implements Schema } - /** - * Allows the value to be a DynamicParameter as an accepted variant. - */ public function dynamic(): self { $this->set[] = new Type(Nette\Schema\DynamicParameter::class); @@ -100,13 +88,10 @@ final class AnyOf implements Schema foreach ($this->set as $item) { if ($item instanceof Schema) { $dolly = new Context; - $dolly->skipDefaults = $context->skipDefaults; - $dolly->isKey = $context->isKey; $dolly->path = $context->path; $res = $item->complete($item->normalize($value, $dolly), $dolly); if (!$dolly->errors) { $context->warnings = array_merge($context->warnings, $dolly->warnings); - $context->dynamics = array_merge($context->dynamics, $dolly->dynamics); return $res; } diff --git a/vendor/nette/schema/src/Schema/Elements/Base.php b/vendor/nette/schema/src/Schema/Elements/Base.php index c4e3dd6..6e83eb7 100644 --- a/vendor/nette/schema/src/Schema/Elements/Base.php +++ b/vendor/nette/schema/src/Schema/Elements/Base.php @@ -43,10 +43,7 @@ trait Base } - /** - * Sets a pre-normalization callback applied to the raw input value before any validation. - * @param callable(mixed): mixed $handler - */ + /** @param callable(mixed): mixed $handler */ public function before(callable $handler): self { $this->before = $handler(...); @@ -54,19 +51,13 @@ trait Base } - /** - * Casts the validated value to a built-in type or instantiates the given class. - */ public function castTo(string $type): self { return $this->transform(Helpers::getCastStrategy($type)); } - /** - * Adds a post-validation transformation callback. The handler may also report errors via Context. - * @param callable(mixed, Context): mixed $handler - */ + /** @param callable(mixed, Context): mixed $handler */ public function transform(callable $handler): self { $this->transforms[] = $handler(...); @@ -74,10 +65,7 @@ trait Base } - /** - * Adds a custom validation assertion; optionally describe it for error messages. - * @param callable(mixed): bool $handler - */ + /** @param callable(mixed): bool $handler */ public function assert(callable $handler, ?string $description = null): self { $expected = $description ?? (is_string($handler) ? "$handler()" : '#' . count($this->transforms)); @@ -90,14 +78,11 @@ trait Base Nette\Schema\Message::FailedAssertion, ['value' => $value, 'assertion' => $expected], ); - return null; }); } - /** - * Marks the item as deprecated; emits a warning with the given message when the item is used. - */ + /** Marks as deprecated */ public function deprecated(string $message = 'The item %path% is deprecated.'): self { $this->deprecated = $message; @@ -153,7 +138,7 @@ trait Base } - /** @deprecated use Nette\Schema\Helpers::validateType() */ + /** @deprecated use Nette\Schema\Validators::validateType() */ private function doValidate(mixed $value, string $expected, Context $context): bool { $isOk = $context->createChecker(); @@ -163,7 +148,7 @@ trait Base /** - * @deprecated use Nette\Schema\Helpers::validateRange() + * @deprecated use Nette\Schema\Validators::validateRange() * @param array{?float, ?float} $range */ private static function doValidateRange(mixed $value, array $range, Context $context, string $types = ''): bool diff --git a/vendor/nette/schema/src/Schema/Elements/Structure.php b/vendor/nette/schema/src/Schema/Elements/Structure.php index a6cf02d..1abf49f 100644 --- a/vendor/nette/schema/src/Schema/Elements/Structure.php +++ b/vendor/nette/schema/src/Schema/Elements/Structure.php @@ -39,9 +39,6 @@ final class Structure implements Schema } - /** - * Not supported for structures; always throws. - */ public function default(mixed $value): self { throw new Nette\InvalidStateException('Structure cannot have default value.'); @@ -62,9 +59,6 @@ final class Structure implements Schema } - /** - * Allows extra keys not defined in the shape, validating their values against the given type. - */ public function otherItems(string|Schema $type = 'mixed'): self { $this->otherItems = $type instanceof Schema ? $type : new Type($type); @@ -72,9 +66,6 @@ final class Structure implements Schema } - /** - * When enabled, properties whose value equals the default are omitted from the output. - */ public function skipDefaults(bool $state = true): self { $this->skipDefaults = $state; @@ -82,10 +73,7 @@ final class Structure implements Schema } - /** - * Creates a new structure by merging this shape with additional properties. - * @param Schema[]|self $shape - */ + /** @param Schema[]|self $shape */ public function extend(array|self $shape): self { $shape = $shape instanceof self ? $shape->items : $shape; @@ -215,17 +203,8 @@ final class Structure implements Schema public function completeDefault(Context $context): mixed { - if (!$this->required) { - return null; - } - - // the item is missing in the input, do not report it as used deprecated - $deprecated = $this->deprecated; - $this->deprecated = null; - try { - return $this->complete([], $context); - } finally { - $this->deprecated = $deprecated; - } + return $this->required + ? $this->complete([], $context) + : null; } } diff --git a/vendor/nette/schema/src/Schema/Elements/Type.php b/vendor/nette/schema/src/Schema/Elements/Type.php index 880f4bb..4413f69 100644 --- a/vendor/nette/schema/src/Schema/Elements/Type.php +++ b/vendor/nette/schema/src/Schema/Elements/Type.php @@ -11,7 +11,6 @@ use Nette\Schema\Context; use Nette\Schema\DynamicParameter; use Nette\Schema\Helpers; use Nette\Schema\Schema; -use Nette\Utils\Validators; use function array_key_exists, array_pop, implode, is_array, str_replace, strpos; @@ -37,9 +36,6 @@ final class Type implements Schema } - /** - * Allows the value to be null in addition to the declared type. - */ public function nullable(): self { $this->type = 'null|' . $this->type; @@ -47,9 +43,6 @@ final class Type implements Schema } - /** - * Controls whether the default value is merged with the input array (enabled by default). - */ public function mergeDefaults(bool $state = true): self { $this->merge = $state; @@ -57,9 +50,6 @@ final class Type implements Schema } - /** - * Allows the value to be a DynamicParameter, which is recorded for deferred validation. - */ public function dynamic(): self { $this->type = DynamicParameter::class . '|' . $this->type; @@ -96,9 +86,6 @@ final class Type implements Schema } - /** - * Sets a regex pattern the string value must match entirely (anchored to start and end). - */ public function pattern(?string $pattern): self { $this->pattern = $pattern; @@ -175,7 +162,7 @@ final class Type implements Schema $merge = false; } - if ($value === null && is_array($this->default) && !Validators::is(null, $this->type)) { + if ($value === null && is_array($this->default)) { $value = []; // is unable to distinguish null from array in NEON } @@ -186,13 +173,13 @@ final class Type implements Schema $isOk() && Helpers::validateRange($value, $this->range, $context, $this->type); $isOk() && $value !== null && $this->pattern !== null && Helpers::validatePattern($value, $this->pattern, $context); $isOk() && is_array($value) && $this->validateItems($value, $context); - $isOk() && $merge && $value !== null && $value = Helpers::merge($value, $this->default); + $isOk() && $merge && $value = Helpers::merge($value, $this->default); $isOk() && $value = $this->doTransform($value, $context); if (!$isOk()) { return null; } - if ($value instanceof DynamicParameter && $this->type !== DynamicParameter::class) { + if ($value instanceof DynamicParameter) { $expected = $this->type . ($this->range === [null, null] ? '' : ':' . implode('..', $this->range)); $context->dynamics[] = [$value, str_replace(DynamicParameter::class . '|', '', $expected), $context->path]; } @@ -203,7 +190,7 @@ final class Type implements Schema /** @param array $value */ private function validateItems(array &$value, Context $context): void { - if (!($itemsValue = $this->itemsValue)) { + if (!$this->itemsValue) { return; } @@ -211,15 +198,9 @@ final class Type implements Schema foreach ($value as $key => $val) { $context->path[] = $key; $context->isKey = true; - $isKeyOk = $context->createChecker(); $key = $this->itemsKey ? $this->itemsKey->complete($key, $context) : $key; $context->isKey = false; - $keyOk = $isKeyOk(); - $val = $itemsValue->complete($val, $context); - if ($keyOk) { - $res[$key] = $val; - } - + $res[$key ?? ''] = $this->itemsValue->complete($val, $context); array_pop($context->path); } $value = $res; diff --git a/vendor/nette/schema/src/Schema/Expect.php b/vendor/nette/schema/src/Schema/Expect.php index 44cf25b..64e31f2 100644 --- a/vendor/nette/schema/src/Schema/Expect.php +++ b/vendor/nette/schema/src/Schema/Expect.php @@ -42,38 +42,26 @@ final class Expect } - /** - * Creates a schema for a custom type expression (e.g., 'int|string', 'null|float'). - */ public static function type(string $type): Type { return new Type($type); } - /** - * Creates a union schema that accepts any of the given values or sub-schemas. - */ public static function anyOf(mixed ...$set): AnyOf { return new AnyOf(...$set); } - /** - * Creates a structure schema with defined properties; output is stdClass. - * @param Schema[] $shape - */ + /** @param Schema[] $shape */ public static function structure(array $shape): Structure { return new Structure($shape); } - /** - * Generates a structure schema from a class instance by reflecting its properties or constructor parameters. - * @param array $items Optional overrides for specific properties. - */ + /** @param array $items */ public static function from(object $object, array $items = []): Structure { $ro = new \ReflectionObject($object); @@ -107,8 +95,6 @@ final class Expect /** - * Creates an array schema. When passed Schema elements, behaves like structure() but outputs an array. - * Without Schema elements, creates a plain array type with the given default value. * @param mixed[] $shape */ public static function array(?array $shape = []): Structure|Type @@ -120,18 +106,12 @@ final class Expect } - /** - * Creates an associative or indexed array schema where every value matches the given type. - */ public static function arrayOf(string|Schema $valueType, string|Schema|null $keyType = null): Type { return (new Type('array'))->items($valueType, $keyType); } - /** - * Creates a list schema (sequentially indexed from 0) where every element matches the given type. - */ public static function listOf(string|Schema $type): Type { return (new Type('list'))->items($type); diff --git a/vendor/nette/schema/src/Schema/Helpers.php b/vendor/nette/schema/src/Schema/Helpers.php index e15bf50..79a4a3c 100644 --- a/vendor/nette/schema/src/Schema/Helpers.php +++ b/vendor/nette/schema/src/Schema/Helpers.php @@ -9,7 +9,7 @@ namespace Nette\Schema; use Nette; use Nette\Utils\Reflection; -use function array_map, count, explode, get_debug_type, implode, in_array, is_array, is_float, is_int, is_object, is_scalar, is_string, is_subclass_of, method_exists, preg_match, preg_quote, preg_replace, preg_replace_callback, settype, str_replace, strlen, trim, var_export; +use function count, explode, get_debug_type, implode, in_array, is_array, is_float, is_int, is_object, is_scalar, is_string, method_exists, preg_match, preg_quote, preg_replace, preg_replace_callback, settype, str_replace, strlen, trim, var_export; /** @@ -54,9 +54,6 @@ final class Helpers } - /** - * Returns the type of a property or parameter as a string, or null if not determinable. - */ public static function getPropertyType(\ReflectionProperty|\ReflectionParameter $prop): ?string { if ($type = Nette\Utils\Type::fromReflection($prop)) { @@ -92,9 +89,6 @@ final class Helpers } - /** - * Formats a value for use in error messages (e.g., 'hello', true, object stdClass). - */ public static function formatValue(mixed $value): string { if ($value instanceof DynamicParameter) { @@ -111,9 +105,6 @@ final class Helpers } - /** - * Adds a TypeMismatch error to the context if the value does not match the expected type. - */ public static function validateType(mixed $value, string $expected, Context $context): void { if (!Nette\Utils\Validators::is($value, $expected)) { @@ -128,10 +119,7 @@ final class Helpers } - /** - * Adds a range error to the context if the value (or its length for strings/arrays) is outside the given range. - * @param array{?float, ?float} $range - */ + /** @param array{?float, ?float} $range */ public static function validateRange(mixed $value, array $range, Context $context, string $types = ''): void { if (is_array($value) || is_string($value)) { @@ -158,10 +146,7 @@ final class Helpers } - /** - * Checks whether a value falls within the given [min, max] range (null means no bound). - * @param array{?float, ?float} $range - */ + /** @param array{?float, ?float} $range */ public static function isInRange(mixed $value, array $range): bool { return ($range[0] === null || $value >= $range[0]) @@ -169,9 +154,6 @@ final class Helpers } - /** - * Adds a PatternMismatch error to the context if the value does not match the pattern. - */ public static function validatePattern(string $value, string $pattern, Context $context): void { if (!preg_match("\x01^(?:$pattern)$\x01Du", $value)) { @@ -184,10 +166,7 @@ final class Helpers } - /** - * Returns a closure that casts a value to the given type (built-in, backed enum, class with constructor, or plain class). - * @return \Closure(mixed, Context): mixed - */ + /** @return \Closure(mixed): mixed */ public static function getCastStrategy(string $type): \Closure { if (Nette\Utils\Validators::isBuiltinType($type)) { @@ -195,37 +174,12 @@ final class Helpers settype($value, $type); return $value; }; - - } elseif (is_subclass_of($type, \BackedEnum::class)) { - return static function ($value, Context $context) use ($type) { - try { - return $type::from($value); - } catch (\TypeError | \ValueError) { - $context->addError( - 'The %label% %path% expects to be %expected%, %value% given.', - Message::TypeMismatch, - ['value' => $value, 'expected' => implode('|', array_map(fn(\BackedEnum $case) => self::formatValue($case->value), $type::cases()))], - ); - return null; - } - }; - - } elseif (is_subclass_of($type, \UnitEnum::class)) { - throw new Nette\InvalidStateException("Cannot cast value to pure enum $type."); - } - - $factory = method_exists($type, '__construct') - ? static fn($value) => is_array($value) || $value instanceof \stdClass + } elseif (method_exists($type, '__construct')) { + return static fn($value) => is_array($value) || $value instanceof \stdClass ? new $type(...(array) $value) - : new $type($value) - : static fn($value) => Nette\Utils\Arrays::toObject((array) $value, new $type); - - return static function ($value) use ($factory, $type) { - try { - return $factory($value); - } catch (\Error $e) { - throw new Nette\InvalidStateException("Unable to cast value to $type: " . $e->getMessage(), 0, $e); - } - }; + : new $type($value); + } else { + return static fn($value) => Nette\Utils\Arrays::toObject((array) $value, new $type); + } } } diff --git a/vendor/nette/schema/src/Schema/Message.php b/vendor/nette/schema/src/Schema/Message.php index f06f172..4923f14 100644 --- a/vendor/nette/schema/src/Schema/Message.php +++ b/vendor/nette/schema/src/Schema/Message.php @@ -7,12 +7,9 @@ namespace Nette\Schema; -use function array_key_exists, implode, preg_replace_callback; +use function implode, preg_replace_callback; -/** - * Represents a single validation error or warning with a message template, error code, path, and variables. - */ final class Message { /** variables: {value: mixed, expected: string} */ @@ -75,9 +72,6 @@ final class Message } - /** - * Formats the message template by substituting %variable% placeholders with their values. - */ public function toString(): string { $vars = $this->variables; @@ -89,9 +83,7 @@ final class Message return preg_replace_callback('~( ?)%(\w+)%~', function ($m) use ($vars) { [, $space, $key] = $m; - return array_key_exists($key, $vars) - ? ($vars[$key] === null ? '' : $space . $vars[$key]) - : $m[0]; + return $vars[$key] === null ? '' : $space . $vars[$key]; }, $this->message); } } diff --git a/vendor/nette/schema/src/Schema/Processor.php b/vendor/nette/schema/src/Schema/Processor.php index 3ce576a..4a2ef7b 100644 --- a/vendor/nette/schema/src/Schema/Processor.php +++ b/vendor/nette/schema/src/Schema/Processor.php @@ -21,9 +21,6 @@ final class Processor private bool $skipDefaults = false; - /** - * When enabled, properties with default values are omitted from the output. - */ public function skipDefaults(bool $value = true): void { $this->skipDefaults = $value; @@ -38,9 +35,9 @@ final class Processor { $this->createContext(); $data = $schema->normalize($data, $this->context); - $this->throwErrors(); + $this->throwsErrors(); $data = $schema->complete($data, $this->context); - $this->throwErrors(); + $this->throwsErrors(); return $data; } @@ -57,35 +54,30 @@ final class Processor $first = true; foreach ($dataset as $data) { $data = $schema->normalize($data, $this->context); - $this->throwErrors(); + $this->throwsErrors(); $flatten = $first ? $data : $schema->merge($data, $flatten); $first = false; } $data = $schema->complete($flatten, $this->context); - $this->throwErrors(); + $this->throwsErrors(); return $data; } - /** - * Returns all deprecation warnings collected during the last processing run. - * @return list - */ + /** @return list */ public function getWarnings(): array { $res = []; - if (isset($this->context)) { - foreach ($this->context->warnings as $message) { - $res[] = $message->toString(); - } + foreach ($this->context->warnings as $message) { + $res[] = $message->toString(); } return $res; } - private function throwErrors(): void + private function throwsErrors(): void { if ($this->context->errors) { throw new ValidationException(null, $this->context->errors); diff --git a/vendor/nette/schema/src/Schema/Schema.php b/vendor/nette/schema/src/Schema/Schema.php index 619ebcf..1616f64 100644 --- a/vendor/nette/schema/src/Schema/Schema.php +++ b/vendor/nette/schema/src/Schema/Schema.php @@ -8,31 +8,27 @@ namespace Nette\Schema; -/** - * Defines the contract for schema elements used in data validation and normalization. - */ interface Schema { /** - * Applies pre-processing transformations to the raw input value (e.g., via before() hooks). + * Normalization. * @return mixed */ function normalize(mixed $value, Context $context); /** - * Merges two normalized values, with $value taking priority over $base. + * Merging. * @return mixed */ function merge(mixed $value, mixed $base); /** - * Validates the value and applies defaults, transforms, and assertions. + * Validation and finalization. * @return mixed */ function complete(mixed $value, Context $context); /** - * Returns the default value, or adds a missing-item error if the field is required. * @return mixed */ function completeDefault(Context $context); diff --git a/vendor/nette/schema/src/Schema/ValidationException.php b/vendor/nette/schema/src/Schema/ValidationException.php index cefca43..396320f 100644 --- a/vendor/nette/schema/src/Schema/ValidationException.php +++ b/vendor/nette/schema/src/Schema/ValidationException.php @@ -18,16 +18,13 @@ class ValidationException extends Nette\InvalidStateException public function __construct( ?string $message, /** @var list */ - private readonly array $messages = [], + private array $messages = [], ) { parent::__construct($message ?? $messages[0]->toString()); } - /** - * Returns all validation error messages as formatted strings. - * @return list - */ + /** @return list */ public function getMessages(): array { $res = []; @@ -39,10 +36,7 @@ class ValidationException extends Nette\InvalidStateException } - /** - * Returns all validation error messages as Message objects. - * @return list - */ + /** @return list */ public function getMessageObjects(): array { return $this->messages;