From ff5f0a0372160d76afd25b6d83e46c7417dd4db9 Mon Sep 17 00:00:00 2001 From: Eryk Mika <eryk.mika@wpdesk.eu> Date: Thu, 10 Apr 2025 15:09:26 +0200 Subject: [PATCH 1/9] feature: toggle field --- changelog.txt | 4 +++ src/Field/ToggleField.php | 14 ++++++++++ templates/input-toggle.php | 56 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 src/Field/ToggleField.php create mode 100644 templates/input-toggle.php diff --git a/changelog.txt b/changelog.txt index c21b67c..fd47444 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ # Changelog +## [3.3.0] - 2025-04-XX +### Added +- ToggleField class, extends CheckboxField for toggle button functionality. + ## [3.2.1] - 2024-10-30 ### Changed - Raised required PHP version to 7.4. diff --git a/src/Field/ToggleField.php b/src/Field/ToggleField.php new file mode 100644 index 0000000..79ff440 --- /dev/null +++ b/src/Field/ToggleField.php @@ -0,0 +1,14 @@ +<?php + +namespace WPDesk\Forms\Field; + +class ToggleField extends CheckboxField { + + public function __construct() { + $this->add_class( 'wpd-toggle-field' ); + } + + public function get_template_name(): string { + return 'input-toggle'; + } +} diff --git a/templates/input-toggle.php b/templates/input-toggle.php new file mode 100644 index 0000000..848cdf8 --- /dev/null +++ b/templates/input-toggle.php @@ -0,0 +1,56 @@ +<?php +/** + * @var \WPDesk\Forms\Field $field + * @var \WPDesk\View\Renderer\Renderer $renderer + * @var string $name_prefix + * @var string $value + * @var string $template_name Real field template. + */ + +?> + +<style> + input[type="checkbox"].wpd-toggle-field { + all:unset; + background: #fff; + border:1px solid #949494; + width:32px; + height: 16px; + position: relative; + cursor: pointer; + border-radius: 200px; + } + input[type="checkbox"].wpd-toggle-field::before { + all:unset; + content: ""; + display: block !important; + height: 14px; + width:14px; + background: #1c1c1c; + border-radius: 100%; + position: absolute; + left: 1px; + top:1px; + transition: 0.25s; + transition-timing-function: ease-out; + } + input[type="checkbox"].wpd-toggle-field:checked { + background: var(--wp-admin-theme-color, #1851e0); + border-color: var(--wp-admin-theme-color, #1851e0); + } + input[type="checkbox"].wpd-toggle-field:checked:before { + left: 17px; + background: #fff; + } + +</style> +<?php +$renderer->output_render( + 'input', + [ + 'field' => $field, + 'renderer' => $renderer, + 'name_prefix' => $name_prefix, + 'value' => $value, + ] +); -- GitLab From e97a84a5dc8795f0de3b85222191d9fd2d7817c2 Mon Sep 17 00:00:00 2001 From: Eryk Mika <eryk.mika@wpdesk.eu> Date: Thu, 10 Apr 2025 15:16:22 +0200 Subject: [PATCH 2/9] chore: allow failure for phpstan --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b865367..1677565 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,3 +6,5 @@ variables: IS_LIBRARY: 1 include: 'https://gitlab.com/wpdesk/gitlab-ci/raw/master/gitlab-ci-1.2.yml' +phpstan: + allow_failure: true -- GitLab From 891c8b299e9580d27eacecd81d8e83afe84443bf Mon Sep 17 00:00:00 2001 From: Eryk Mika <eryk.mika@wpdesk.eu> Date: Thu, 10 Apr 2025 15:28:34 +0200 Subject: [PATCH 3/9] chore: phpstan, baseline --- .gitlab-ci.yml | 2 - .phpstan-baseline.php | 347 ++++++++++++++++++++++++++++++++++++++++++ phpstan.neon.dist | 2 + 3 files changed, 349 insertions(+), 2 deletions(-) create mode 100644 .phpstan-baseline.php diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1677565..b865367 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,5 +6,3 @@ variables: IS_LIBRARY: 1 include: 'https://gitlab.com/wpdesk/gitlab-ci/raw/master/gitlab-ci-1.2.yml' -phpstan: - allow_failure: true diff --git a/.phpstan-baseline.php b/.phpstan-baseline.php new file mode 100644 index 0000000..b624e6e --- /dev/null +++ b/.phpstan-baseline.php @@ -0,0 +1,347 @@ +<?php declare(strict_types = 1); + +$ignoreErrors = []; +$ignoreErrors[] = [ + 'message' => '#^Method WPDesk\\\\Forms\\\\Field\\\\BasicField\\:\\:get_type\\(\\) should return string but returns mixed\\.$#', + 'identifier' => 'return.type', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Method WPDesk\\\\Forms\\\\Field\\\\BasicField\\:\\:unset_attribute\\(\\) has invalid return type WPDesk\\\\Forms\\\\Field\\\\Traits\\\\HtmlAttributes\\.$#', + 'identifier' => 'return.trait', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Method WPDesk\\\\Forms\\\\Field\\\\BasicField\\:\\:unset_attribute\\(\\) should return WPDesk\\\\Forms\\\\Field\\\\Traits\\\\HtmlAttributes but returns \\$this\\(WPDesk\\\\Forms\\\\Field\\\\BasicField\\)\\.$#', + 'identifier' => 'return.type', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Offset \'class\' on array\\{placeholder\\: string, name\\: string, id\\: string, class\\: array\\<string\\>\\} on left side of \\?\\? always exists and is not nullable\\.$#', + 'identifier' => 'nullCoalesce.offset', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Offset \'data\' on array\\{default_value\\: string, possible_values\\?\\: array\\<string\\>, sublabel\\?\\: string, priority\\: int, label\\: string, description\\: string, description_tip\\: string, data\\: array\\<int\\|string\\>\\} on left side of \\?\\? always exists and is not nullable\\.$#', + 'identifier' => 'nullCoalesce.offset', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Offset \'default_value\' on array\\{default_value\\: string, possible_values\\?\\: array\\<string\\>, sublabel\\?\\: string, priority\\: int, label\\: string, description\\: string, description_tip\\: string, data\\: array\\<int\\|string\\>\\} on left side of \\?\\? always exists and is not nullable\\.$#', + 'identifier' => 'nullCoalesce.offset', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Offset \'description\' on array\\{default_value\\: string, possible_values\\?\\: array\\<string\\>, sublabel\\?\\: string, priority\\: int, label\\: string, description\\: string, description_tip\\: string, data\\: array\\<int\\|string\\>\\} on left side of \\?\\? always exists and is not nullable\\.$#', + 'identifier' => 'nullCoalesce.offset', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Offset \'description_tip\' on array\\{default_value\\: string, possible_values\\?\\: array\\<string\\>, sublabel\\?\\: string, priority\\: int, label\\: string, description\\: string, description_tip\\: string, data\\: array\\<int\\|string\\>\\} on left side of \\?\\? always exists and is not nullable\\.$#', + 'identifier' => 'nullCoalesce.offset', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Offset \'disabled\' on array\\{placeholder\\: string, name\\: string, id\\: string, class\\: array\\<string\\>\\} on left side of \\?\\? does not exist\\.$#', + 'identifier' => 'nullCoalesce.offset', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Offset \'id\' on array\\{placeholder\\: string, name\\: string, id\\: string, class\\: array\\<string\\>\\} on left side of \\?\\? always exists and is not nullable\\.$#', + 'identifier' => 'nullCoalesce.offset', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Offset \'label\' on array\\{default_value\\: string, possible_values\\?\\: array\\<string\\>, sublabel\\?\\: string, priority\\: int, label\\: string, description\\: string, description_tip\\: string, data\\: array\\<int\\|string\\>\\} on left side of \\?\\? always exists and is not nullable\\.$#', + 'identifier' => 'nullCoalesce.offset', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Offset \'multiple\' on array\\{placeholder\\: string, name\\: string, id\\: string, class\\: array\\<string\\>\\} in isset\\(\\) does not exist\\.$#', + 'identifier' => 'isset.offset', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Offset \'name\' on array\\{placeholder\\: string, name\\: string, id\\: string, class\\: array\\<string\\>\\} on left side of \\?\\? always exists and is not nullable\\.$#', + 'identifier' => 'nullCoalesce.offset', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Offset \'placeholder\' on array\\{placeholder\\: string, name\\: string, id\\: string, class\\: array\\<string\\>\\} on left side of \\?\\? always exists and is not nullable\\.$#', + 'identifier' => 'nullCoalesce.offset', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Offset \'readonly\' on array\\{placeholder\\: string, name\\: string, id\\: string, class\\: array\\<string\\>\\} on left side of \\?\\? does not exist\\.$#', + 'identifier' => 'nullCoalesce.offset', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Offset \'required\' on array\\{placeholder\\: string, name\\: string, id\\: string, class\\: array\\<string\\>\\} in isset\\(\\) does not exist\\.$#', + 'identifier' => 'isset.offset', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Offset \'type\' does not exist on array\\{default_value\\: string, possible_values\\?\\: array\\<string\\>, sublabel\\?\\: string, priority\\: int, label\\: string, description\\: string, description_tip\\: string, data\\: array\\<int\\|string\\>\\}\\.$#', + 'identifier' => 'offsetAccess.notFound', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Offset string on array\\{placeholder\\: string, name\\: string, id\\: string, class\\: array\\<string\\>\\} on left side of \\?\\? always exists and is not nullable\\.$#', + 'identifier' => 'nullCoalesce.offset', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Property WPDesk\\\\Forms\\\\Field\\\\BasicField\\:\\:\\$attributes \\(array\\{placeholder\\: string, name\\: string, id\\: string, class\\: array\\<string\\>\\}\\) does not accept array\\{placeholder\\?\\: string, name\\?\\: string, id\\?\\: string, class\\?\\: array\\<string\\>\\}\\.$#', + 'identifier' => 'assign.propertyType', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Property WPDesk\\\\Forms\\\\Field\\\\BasicField\\:\\:\\$attributes \\(array\\{placeholder\\: string, name\\: string, id\\: string, class\\: array\\<string\\>\\}\\) does not accept default value of type array\\{\\}\\.$#', + 'identifier' => 'property.defaultValue', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Property WPDesk\\\\Forms\\\\Field\\\\BasicField\\:\\:\\$attributes \\(array\\{placeholder\\: string, name\\: string, id\\: string, class\\: array\\<string\\>\\}\\) does not accept non\\-empty\\-array\\<string, array\\<string\\>\\|bool\\|string\\>\\.$#', + 'identifier' => 'assign.propertyType', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Return type \\(array\\<array\\<string\\>\\|bool\\|string\\>\\) of method WPDesk\\\\Forms\\\\Field\\\\BasicField\\:\\:get_attributes\\(\\) should be covariant with return type \\(array\\<string\\>\\) of method WPDesk\\\\Forms\\\\Field\\:\\:get_attributes\\(\\)$#', + 'identifier' => 'method.childReturnType', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/BasicField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Offset \'sublabel\' might not exist on array\\{default_value\\: string, possible_values\\?\\: array\\<string\\>, sublabel\\?\\: string, priority\\: int, label\\: string, description\\: string, description_tip\\: string, data\\: array\\<int\\|string\\>\\}\\.$#', + 'identifier' => 'offsetAccess.notFound', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/CheckboxField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Parameter \\#1 \\$action of class WPDesk\\\\Forms\\\\Validator\\\\NonceValidator constructor expects string, mixed given\\.$#', + 'identifier' => 'argument.type', + 'count' => 1, + 'path' => __DIR__ . '/src/Field/NoOnceField.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Method WPDesk\\\\Forms\\\\FieldRenderer\\:\\:render_fields\\(\\) has parameter \\$fields_data with no value type specified in iterable type array\\.$#', + 'identifier' => 'missingType.iterableValue', + 'count' => 1, + 'path' => __DIR__ . '/src/FieldRenderer.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Method WPDesk\\\\Forms\\\\FieldRenderer\\:\\:render_fields\\(\\) return type has no value type specified in iterable type array\\.$#', + 'identifier' => 'missingType.iterableValue', + 'count' => 1, + 'path' => __DIR__ . '/src/FieldRenderer.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Method WPDesk\\\\Forms\\\\Form\\:\\:get_normalized_data\\(\\) return type has no value type specified in iterable type array\\.$#', + 'identifier' => 'missingType.iterableValue', + 'count' => 1, + 'path' => __DIR__ . '/src/Form.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Method WPDesk\\\\Forms\\\\Form\\:\\:handle_request\\(\\) has parameter \\$request with no value type specified in iterable type array\\.$#', + 'identifier' => 'missingType.iterableValue', + 'count' => 1, + 'path' => __DIR__ . '/src/Form.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Method WPDesk\\\\Forms\\\\Form\\\\FormWithFields\\:\\:get_action\\(\\) should return string but returns mixed\\.$#', + 'identifier' => 'return.type', + 'count' => 1, + 'path' => __DIR__ . '/src/Form/FormWithFields.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Method WPDesk\\\\Forms\\\\Form\\\\FormWithFields\\:\\:get_data\\(\\) should return array\\<int\\|string\\> but returns array\\.$#', + 'identifier' => 'return.type', + 'count' => 1, + 'path' => __DIR__ . '/src/Form/FormWithFields.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Method WPDesk\\\\Forms\\\\Form\\\\FormWithFields\\:\\:get_method\\(\\) should return string but returns mixed\\.$#', + 'identifier' => 'return.type', + 'count' => 1, + 'path' => __DIR__ . '/src/Form/FormWithFields.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Method WPDesk\\\\Forms\\\\Form\\\\FormWithFields\\:\\:get_normalized_data\\(\\) return type has no value type specified in iterable type array\\.$#', + 'identifier' => 'missingType.iterableValue', + 'count' => 1, + 'path' => __DIR__ . '/src/Form/FormWithFields.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Method WPDesk\\\\Forms\\\\Form\\\\FormWithFields\\:\\:handle_request\\(\\) has parameter \\$request with no value type specified in iterable type array\\.$#', + 'identifier' => 'missingType.iterableValue', + 'count' => 1, + 'path' => __DIR__ . '/src/Form/FormWithFields.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Method WPDesk\\\\Forms\\\\Form\\\\FormWithFields\\:\\:unset_attribute\\(\\) has invalid return type WPDesk\\\\Forms\\\\Field\\\\Traits\\\\HtmlAttributes\\.$#', + 'identifier' => 'return.trait', + 'count' => 1, + 'path' => __DIR__ . '/src/Form/FormWithFields.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Method WPDesk\\\\Forms\\\\Form\\\\FormWithFields\\:\\:unset_attribute\\(\\) should return WPDesk\\\\Forms\\\\Field\\\\Traits\\\\HtmlAttributes but returns \\$this\\(WPDesk\\\\Forms\\\\Form\\\\FormWithFields\\)\\.$#', + 'identifier' => 'return.type', + 'count' => 1, + 'path' => __DIR__ . '/src/Form/FormWithFields.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Offset \'action\' does not exist on array\\{placeholder\\: string, name\\: string, id\\: string, class\\: array\\<string\\>\\}\\.$#', + 'identifier' => 'offsetAccess.notFound', + 'count' => 1, + 'path' => __DIR__ . '/src/Form/FormWithFields.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Offset \'method\' does not exist on array\\{placeholder\\: string, name\\: string, id\\: string, class\\: array\\<string\\>\\}\\.$#', + 'identifier' => 'offsetAccess.notFound', + 'count' => 1, + 'path' => __DIR__ . '/src/Form/FormWithFields.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Offset string on array\\{placeholder\\: string, name\\: string, id\\: string, class\\: array\\<string\\>\\} on left side of \\?\\? always exists and is not nullable\\.$#', + 'identifier' => 'nullCoalesce.offset', + 'count' => 1, + 'path' => __DIR__ . '/src/Form/FormWithFields.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Parameter \\#2 \\$value of method WPDesk\\\\Persistence\\\\PersistentContainer\\:\\:set\\(\\) expects array\\|float\\|int\\|string, mixed given\\.$#', + 'identifier' => 'argument.type', + 'count' => 2, + 'path' => __DIR__ . '/src/Form/FormWithFields.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Property WPDesk\\\\Forms\\\\Form\\\\FormWithFields\\:\\:\\$attributes \\(array\\{placeholder\\: string, name\\: string, id\\: string, class\\: array\\<string\\>\\}\\) does not accept array\\{placeholder\\?\\: string, name\\?\\: string, id\\?\\: string, class\\?\\: array\\<string\\>\\}\\.$#', + 'identifier' => 'assign.propertyType', + 'count' => 1, + 'path' => __DIR__ . '/src/Form/FormWithFields.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Property WPDesk\\\\Forms\\\\Form\\\\FormWithFields\\:\\:\\$attributes \\(array\\{placeholder\\: string, name\\: string, id\\: string, class\\: array\\<string\\>\\}\\) does not accept default value of type array\\{\\}\\.$#', + 'identifier' => 'property.defaultValue', + 'count' => 1, + 'path' => __DIR__ . '/src/Form/FormWithFields.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Property WPDesk\\\\Forms\\\\Form\\\\FormWithFields\\:\\:\\$attributes \\(array\\{placeholder\\: string, name\\: string, id\\: string, class\\: array\\<string\\>\\}\\) does not accept non\\-empty\\-array\\<string, array\\<string\\>\\|bool\\|string\\>\\.$#', + 'identifier' => 'assign.propertyType', + 'count' => 1, + 'path' => __DIR__ . '/src/Form/FormWithFields.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Property WPDesk\\\\Forms\\\\Form\\\\FormWithFields\\:\\:\\$updated_data type has no value type specified in iterable type array\\.$#', + 'identifier' => 'missingType.iterableValue', + 'count' => 1, + 'path' => __DIR__ . '/src/Form/FormWithFields.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Method WPDesk\\\\Forms\\\\Persistence\\\\FieldPersistenceStrategy\\:\\:load_fields\\(\\) return type has no value type specified in iterable type array\\.$#', + 'identifier' => 'missingType.iterableValue', + 'count' => 1, + 'path' => __DIR__ . '/src/Persistence/FieldPersistenceStrategy.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Method WPDesk\\\\Forms\\\\Persistence\\\\FieldPersistenceStrategy\\:\\:persist_fields\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#', + 'identifier' => 'missingType.iterableValue', + 'count' => 1, + 'path' => __DIR__ . '/src/Persistence/FieldPersistenceStrategy.php', +]; +$ignoreErrors[] = [ + 'message' => '#^PHPDoc tag @return with type void is incompatible with native type array\\.$#', + 'identifier' => 'return.phpDocType', + 'count' => 1, + 'path' => __DIR__ . '/src/Persistence/FieldPersistenceStrategy.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Parameter \\#1 \\$value of method WPDesk\\\\Forms\\\\Serializer\\:\\:unserialize\\(\\) expects string, mixed given\\.$#', + 'identifier' => 'argument.type', + 'count' => 1, + 'path' => __DIR__ . '/src/Persistence/FieldPersistenceStrategy.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Parameter \\#2 \\$value of method WPDesk\\\\Persistence\\\\PersistentContainer\\:\\:set\\(\\) expects array\\|float\\|int\\|string, mixed given\\.$#', + 'identifier' => 'argument.type', + 'count' => 1, + 'path' => __DIR__ . '/src/Persistence/FieldPersistenceStrategy.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Method WPDesk\\\\Forms\\\\Renderer\\\\JsonNormalizedRenderer\\:\\:render_fields\\(\\) has parameter \\$fields_data with no value type specified in iterable type array\\.$#', + 'identifier' => 'missingType.iterableValue', + 'count' => 1, + 'path' => __DIR__ . '/src/Renderer/JsonNormalizedRenderer.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Method WPDesk\\\\Forms\\\\Renderer\\\\JsonNormalizedRenderer\\:\\:render_fields\\(\\) return type has no value type specified in iterable type array\\.$#', + 'identifier' => 'missingType.iterableValue', + 'count' => 1, + 'path' => __DIR__ . '/src/Renderer/JsonNormalizedRenderer.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Method WPDesk\\\\Forms\\\\Sanitizer\\\\CallableSanitizer\\:\\:sanitize\\(\\) should return string but returns mixed\\.$#', + 'identifier' => 'return.type', + 'count' => 1, + 'path' => __DIR__ . '/src/Sanitizer/CallableSanitizer.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Parameter \\#1 \\$email of function sanitize_email expects string, mixed given\\.$#', + 'identifier' => 'argument.type', + 'count' => 1, + 'path' => __DIR__ . '/src/Sanitizer/EmailSanitizer.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Parameter \\#1 \\$callback of function array_map expects \\(callable\\(mixed\\)\\: mixed\\)\\|null, \'sanitize_text_field\' given\\.$#', + 'identifier' => 'argument.type', + 'count' => 1, + 'path' => __DIR__ . '/src/Sanitizer/TextFieldSanitizer.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Parameter \\#1 \\$str of function sanitize_text_field expects string, mixed given\\.$#', + 'identifier' => 'argument.type', + 'count' => 1, + 'path' => __DIR__ . '/src/Sanitizer/TextFieldSanitizer.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Method WPDesk\\\\Forms\\\\Validator\\\\ChainValidator\\:\\:get_messages\\(\\) should return array\\<string\\> but returns array\\.$#', + 'identifier' => 'return.type', + 'count' => 1, + 'path' => __DIR__ . '/src/Validator/ChainValidator.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Property WPDesk\\\\Forms\\\\Validator\\\\ChainValidator\\:\\:\\$messages type has no value type specified in iterable type array\\.$#', + 'identifier' => 'missingType.iterableValue', + 'count' => 1, + 'path' => __DIR__ . '/src/Validator/ChainValidator.php', +]; +$ignoreErrors[] = [ + 'message' => '#^Parameter \\#1 \\$nonce of function wp_verify_nonce expects string, mixed given\\.$#', + 'identifier' => 'argument.type', + 'count' => 1, + 'path' => __DIR__ . '/src/Validator/NonceValidator.php', +]; + +return ['parameters' => ['ignoreErrors' => $ignoreErrors]]; diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 200d200..422f90c 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,3 +1,5 @@ +includes: + - .phpstan-baseline.php parameters: level: max paths: -- GitLab From b2e743f250912044ec86ee9c107d4693102cd3c2 Mon Sep 17 00:00:00 2001 From: Eryk Mika <eryk.mika@wpdesk.eu> Date: Thu, 10 Apr 2025 15:33:35 +0200 Subject: [PATCH 4/9] chore: phpstan, cbf, cs scripts in composer --- composer.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/composer.json b/composer.json index 9274422..874f03f 100644 --- a/composer.json +++ b/composer.json @@ -44,6 +44,9 @@ } }, "scripts": { + "phpcs": "phpcs", + "phpstan": "php -d memory_limit=1G vendor/bin/phpstan", + "phpcbf": "phpcbf src", "phpunit-unit": "phpunit --configuration phpunit-unit.xml --coverage-text --colors=never", "phpunit-unit-fast": "phpunit --configuration phpunit-unit.xml --no-coverage", "phpunit-integration": "phpunit --configuration phpunit-integration.xml --coverage-text --colors=never", -- GitLab From f49de6835a235764010b9cfeee714038bf1e6766 Mon Sep 17 00:00:00 2001 From: Eryk Mika <eryk.mika@wpdesk.eu> Date: Mon, 14 Apr 2025 11:01:31 +0200 Subject: [PATCH 5/9] refactor: phpcs --- src/Persistence/FieldPersistenceStrategy.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Persistence/FieldPersistenceStrategy.php b/src/Persistence/FieldPersistenceStrategy.php index 3102f1c..7fa7dcc 100644 --- a/src/Persistence/FieldPersistenceStrategy.php +++ b/src/Persistence/FieldPersistenceStrategy.php @@ -43,9 +43,7 @@ class FieldPersistenceStrategy { } else { $data[ $field_key ] = $this->persistence->get( $field_key ); } - } catch ( NotFoundExceptionInterface $not_found ) { - // TODO: Logger - // LoggerFactory::get_logger()->info( "FieldPersistenceStrategy:: Field {$field_key} not found" ); + } catch ( NotFoundExceptionInterface $not_found ) { //phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch } } -- GitLab From 2849c241bb03b837bcd30255632faf526950e514 Mon Sep 17 00:00:00 2001 From: Eryk Mika <eryk.mika@wpdesk.eu> Date: Mon, 14 Apr 2025 11:12:07 +0200 Subject: [PATCH 6/9] chore: changelog update --- changelog.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index fd47444..a5b85e1 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,8 +1,13 @@ # Changelog -## [3.3.0] - 2025-04-XX +## [4.0.0] - 2025-04-XX ### Added - ToggleField class, extends CheckboxField for toggle button functionality. +### Changed +- Declared nullable parameter types (e.g. `?string`, `?Renderer`) to fix PHP 8.4 deprecation warnings about implicitly nullable parameters. +### Removed +- Support for PHP < 7.1. + ## [3.2.1] - 2024-10-30 ### Changed -- GitLab From 9b04361d83bc2cc848bcd65bf7d48f16388b9fbb Mon Sep 17 00:00:00 2001 From: Eryk Mika <eryk.mika@wpdesk.eu> Date: Mon, 14 Apr 2025 11:12:31 +0200 Subject: [PATCH 7/9] refactor: phpstan nullable --- src/Field.php | 2 +- src/Field/Traits/HtmlAttributes.php | 2 +- src/Resolver/DefaultFormFieldResolver.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Field.php b/src/Field.php index b932f27..14b0259 100644 --- a/src/Field.php +++ b/src/Field.php @@ -55,7 +55,7 @@ interface Field { */ public function get_attributes( array $except = [] ): array; - public function get_attribute( string $name, string $default = null ): string; + public function get_attribute( string $name, ?string $default = null ): string; public function is_attribute_set( string $name ): bool; diff --git a/src/Field/Traits/HtmlAttributes.php b/src/Field/Traits/HtmlAttributes.php index aac835d..95a7a42 100644 --- a/src/Field/Traits/HtmlAttributes.php +++ b/src/Field/Traits/HtmlAttributes.php @@ -57,7 +57,7 @@ trait HtmlAttributes { return ! empty( $this->attributes[ $name ] ); } - final public function get_attribute( string $name, string $default = null ): string { + final public function get_attribute( string $name, ?string $default = null ): string { if ( is_array( $this->attributes[ $name ] ) ) { // Be aware of coercing - if implode returns string(0) '', then return $default value. return implode( ' ', $this->attributes[ $name ] ) ?: $default ?? ''; diff --git a/src/Resolver/DefaultFormFieldResolver.php b/src/Resolver/DefaultFormFieldResolver.php index 4e3077a..23f5a52 100644 --- a/src/Resolver/DefaultFormFieldResolver.php +++ b/src/Resolver/DefaultFormFieldResolver.php @@ -20,7 +20,7 @@ class DefaultFormFieldResolver implements Resolver { $this->dir_resolver = new DirResolver( __DIR__ . '/../../templates' ); } - public function resolve( $name, Renderer $renderer = null ): string { + public function resolve( $name, ?Renderer $renderer = null ): string { return $this->dir_resolver->resolve( $name, $renderer ); } } -- GitLab From b019e8b2bbd7011cf129091e8a8a8ed3a83ed9af Mon Sep 17 00:00:00 2001 From: Eryk Mika <eryk.mika@wpdesk.eu> Date: Mon, 14 Apr 2025 11:13:30 +0200 Subject: [PATCH 8/9] chore: updated changelog. Info for support drop is not necessary --- changelog.txt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/changelog.txt b/changelog.txt index a5b85e1..387ec70 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,13 +1,10 @@ # Changelog -## [4.0.0] - 2025-04-XX +## [3.3.0] - 2025-04-XX ### Added - ToggleField class, extends CheckboxField for toggle button functionality. ### Changed - Declared nullable parameter types (e.g. `?string`, `?Renderer`) to fix PHP 8.4 deprecation warnings about implicitly nullable parameters. -### Removed -- Support for PHP < 7.1. - ## [3.2.1] - 2024-10-30 ### Changed -- GitLab From 71e0f62730ccc1bcc4116e999e6359d8675d04ba Mon Sep 17 00:00:00 2001 From: Eryk Mika <eryk.mika@wpdesk.eu> Date: Tue, 15 Apr 2025 12:24:44 +0200 Subject: [PATCH 9/9] chore: release date update --- changelog.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.txt b/changelog.txt index 387ec70..bf68f37 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,6 @@ # Changelog -## [3.3.0] - 2025-04-XX +## [3.3.0] - 2025-04-15 ### Added - ToggleField class, extends CheckboxField for toggle button functionality. ### Changed -- GitLab