Skip to content

chore: add php lint, phpcs and phpstan - #12

Merged
vitormattos merged 4 commits into
mainfrom
chore/static-analysis
Sep 29, 2026
Merged

vitormattos merged 4 commits into
mainfrom
chore/static-analysis

Conversation

@YvesCesar

Copy link
Copy Markdown
Member

The theme had no Composer setup, no lint, no coding standard and no CI beyond the translation workflows. This adds PHP lint, PHPCS and PHPStan, each as a Composer script and a GitHub workflow.

Tooling

  • composer lint, composer cs, composer stan and composer ci (all three, in this order).
  • Each tool lives in its own vendor-bin/ project (bamarni/composer-bin-plugin), so their dependencies do not mix.
  • One workflow per tool: php-lint.yml, phpcs.yml, phpstan.yml. The PHP versions come from composer.json (>=8.3 <8.6) through typisttech/php-matrix-action, so the matrix is 8.3, 8.4 and 8.5.
  • Third-party actions are pinned by commit SHA, with the version next to it.
  • PHPCS uses a lean ruleset (security, database, deprecated APIs, i18n, global prefixes and PHP compatibility) instead of the full WordPress-Extra, so the diff stays reviewable. PHPStan runs at level 5 with the WordPress extension and the WooCommerce stubs.
  • style.css and readme.txt now declare Requires at least: 7.0, Tested up to: 7.0 and Requires PHP: 8.3, the versions the checks run against. readme.txt said Requires PHP: 5.7.

Changes to the theme

  • Prefix: the theme used two prefixes, libresign_theme_ and libresign_. The libresign-wp-customizations plugin also uses libresign_, and both are loaded on the same site, so a function added to either one with a name the other already has is a fatal error. The 23 functions that used libresign_ now use libresign_theme_, the prefix the fragment and webhook code already had. Option names, theme mods, user meta and error codes keep their values. Code that unhooks the old names, such as remove_filter( 'get_custom_logo', 'libresign_filter_custom_logo' ), stops working; none of the LibreSign plugins installed alongside the theme references them.
  • WooCommerce template override: woocommerce/myaccount/form-login.php is excluded from the prefix rule. The hooks it fires are WooCommerce's own, and WooCommerce includes the template inside a function, so its variables are not global. The username and email fields echo the posted value back escaped, like the WooCommerce template does; the nonce is checked by WooCommerce before the form is processed, so those lines add NonceVerification.Missing to the existing ignore.
  • Input sanitizing: redirect_to goes through wp_sanitize_redirect() before wp_validate_redirect(), which already calls it, and REQUEST_URI goes through esc_url_raw() before only its path is compared with /lost-password/.
  • Pattern escaping: the link in the text-centered-statement-small pattern is built inline and the sentence is printed through wp_kses_post(). The rendered markup is the same.
  • PHPStan findings in the fragment code: checks that the types already guarantee were removed (is_wp_error() on a WP_Error, isset() on a regex group that always exists, is_string() on a strtok() of a non-empty locale), and array_filter( ..., 'strlen' ) became a callback that drops empty strings. The salts used to decrypt the deploy token (AUTH_KEY, SECURE_AUTH_SALT, NONCE_SALT) are defined in wp-config.php, and WC()->cart is null until WooCommerce loads the cart although the stubs type it as WC_Cart; both are ignored in phpstan.neon.dist, scoped to their file.

Verification

  • composer ci passes locally.
  • On a WordPress 7.0 install with WooCommerce, the HTML of the account page, /lost-password/, ?action=lostpassword, the shop, the cart, two product pages, the checkout redirect and a 404 is byte for byte the same on main and on this branch (nonces and asset versions normalized).
  • The normalized locale tags, locale lookup keys, root-relative URL rewriting and optional 404 detection return the same values as before for the inputs the fragment sync uses.

Signed-off-by: YvesCesar <yvesamorim73@gmail.com>
…nd php versions

Signed-off-by: YvesCesar <yvesamorim73@gmail.com>
Signed-off-by: YvesCesar <yvesamorim73@gmail.com>
Signed-off-by: YvesCesar <yvesamorim73@gmail.com>
@vitormattos
vitormattos merged commit 7160df2 into main Sep 29, 2026
13 checks passed
@vitormattos
vitormattos deleted the chore/static-analysis branch September 29, 2026 15:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants