Skip to content

Releases: veronalabs/wp-scoper

v1.4.2

Choose a tag to compare

@mostafasoufi mostafasoufi released this 11 Sep 08:45

Fixed

  • Quoted text fragments renamed as if they were class references: ClassmapReplacer prefixed every quoted occurrence of a global class name, including quoted words that are not class references at all but pieces of a string being concatenated. The most damaging case was Eloquent, which derives accessor and mutator method names with 'get' . Str::studly($key) . 'Attribute' — because Symfony's php80 polyfill declares a global Attribute stub, the trailing fragment became '<Prefix>Attribute' and every get*Attribute() / set*Attribute() on every model silently stopped being called, with raw column values surfacing instead of the accessor's return value. No error was raised, so the breakage only showed up as wrong data at runtime. Quoted strings adjacent to a concatenation dot on either side are now left untouched; standalone quoted class references (class_exists('Foo'), array keys, $class = 'Foo') are still prefixed as before.

v1.4.1

Choose a tag to compare

@mostafasoufi mostafasoufi released this 11 Sep 08:45

Changed

  • Internal refactor only, no behaviour change: deduplicated the replacer-apply sequence into Prefixer::applyReplacers() (shared by the dependency loop, dev-package loop, and call-site updates — the latter still skips the nullable fixer), shared the PHP-constraint detection as Plugin::detectPhpConstraint() across the plugin hook and wp-scope command, and removed an unreachable guard in NullableParamReplacer. Scoped output is identical to 1.4.0.

v1.4.0

Choose a tag to compare

@mostafasoufi mostafasoufi released this 11 Sep 08:45

Added

  • PHP cross-version compatibility fixing via extra.wp-scoper.php_compat: true (default false): opt-in pass that rewrites implicitly-nullable parameters (Type $x = null) in scoped dependency code to the explicit form (?Type $x = null, and A|B $x = nullA|B|null $x = null). PHP 8.4 deprecates the implicit form, so dependencies pinned for an older PHP floor (e.g. thecodingmachine/safe kept for PHP 8.0 support) otherwise flood PHP 8.4/8.5 runtimes with E_DEPRECATED notices. The rewrite is behaviour-identical and valid on any PHP ≥ 7.1. The target PHP floor is auto-detected from the host composer.json (config.platform.php preferred, require.php fallback) — no hardcoded version — and gates the fixer so rewritten syntax stays valid for the declared minimum. Skips already-nullable types, mixed, unions already containing null, intersection types, untyped params, and non-null defaults. Applied to copied dependency files only — the host project's own source is never rewritten. New NullableParamReplacer; new Config API: isPhpCompatEnabled(), getTargetPhpFloor(), targetPhpAtLeast(), parsePhpFloor(), and a new optional $phpConstraint parameter on Config::fromArray(). Existing configs without php_compat are unaffected.

v1.3.0

Choose a tag to compare

@mostafasoufi mostafasoufi released this 04 May 06:58

Added

  • Profile-aware scoping via extra.wp-scoper.profiles.{name}: a single composer.json can now express a base set of scoped packages plus zero-or-more named profiles that contribute additional packages (and override scalar keys). Build scripts pick the profile via the SCOPER_PROFILE environment variable (e.g., SCOPER_PROFILE=premium composer install). packages arrays are appended + de-duplicated; all other keys (namespace_prefix, target_directory, etc.) replace base values when present in the profile. dev_packages.packages follow the same append-and-dedupe rule. Throws InvalidArgumentException if SCOPER_PROFILE names a profile that isn't defined — fail-loud over silent-wrong-output. Public API: Config::applyProfile(array, ?string): array and a new optional $profile parameter on Config::fromArray(). Existing composer.json configs without profiles are unaffected.

v1.2.8

Choose a tag to compare

@mostafasoufi mostafasoufi released this 02 May 05:58

Fixed

  • Stale autoload_files.php / autoload_static.php references after delete_vendor_packages: true: when a scoped package declared an autoload.files entry (Symfony polyfills, league/csv function file, etc.), wp-scoper deleted the original package directory but left Composer's eager-load tables pointing at the now-missing path, triggering require failures on autoloader boot. FileCopier::deleteVendorPackages() now strips entries for the removed packages from both files automatically, so consumers no longer need a custom bin/fix-autoload.php post-script.

Full changelog: v1.2.7...v1.2.8

v1.2.7

Choose a tag to compare

@mostafasoufi mostafasoufi released this 22 Apr 19:00
7a000ab

Fixed

  • Polyfill stub classes incorrectly prefixed: Symfony polyfill packages (polyfill-intl-normalizer, polyfill-php73, polyfill-php80) ship stub files that declare classes in the global namespace so they act as fallbacks when the corresponding PHP extension or version is missing. ClassmapReplacer prefixed these stubs alongside other global classes, which broke the fallbacks and caused fatal Class "X" not found errors at runtime on servers that lacked the native implementation — most visibly Normalizer on hosts without the intl extension, but also Attribute, JsonException, PhpToken, and UnhandledMatchError on older PHP versions. The built-in allowlist now covers these five classes, plus the related CompileError, UnitEnum, BackedEnum, SensitiveParameter, and Override globals.

Full changelog: v1.2.6...v1.2.7

v1.2.6

Choose a tag to compare

@mostafasoufi mostafasoufi released this 18 Apr 05:19

Fixed

  • Unanchored built-in directory exclude patterns dropped legitimate directories: ext/, examples?/, tests?/, php4/, dev-bin/, .github/, .gitlab/ behaved as substring matches, so e.g. Text/ and Context/ were treated as ext/ and silently omitted from the scoped output. The seven patterns now anchor to path-start or immediately after /.

v1.2.5 - Fix use-as-alias form in NamespaceReplacer

Choose a tag to compare

@mostafasoufi mostafasoufi released this 07 Apr 07:06

Fixed

  • use Namespace as Alias; form not prefixed

    When a use statement imported a namespace itself (no trailing class) with an alias — e.g. use Symfony\Polyfill\Mbstring as p; in Symfony polyfill bootstrap files — NamespaceReplacer left it unchanged. After scoping, the aliased reference resolved to a non-existent class and produced fatal Class not found errors at runtime on hosts where the polyfill code path actually executed (e.g. servers without the native mbstring extension).

    Pattern 3 in NamespaceReplacer now accepts an optional as <alias> group between the namespace and the trailing semicolon, and preserves the alias verbatim in the replacement.

    Regression tests added covering both the alias form and the no-double-prefix case.

Affected plugins

Any plugin scoped with wp-scoper that pulls in Symfony polyfill packages (polyfill-mbstring, polyfill-ctype, polyfill-intl-grapheme, polyfill-intl-normalizer, polyfill-php73, polyfill-php80) and runs on a host missing the corresponding native PHP extension. Symptom: fatal Class Symfony\Polyfill\<Name>\<Name> not found from cron or page load.

Action required

Re-run composer update veronalabs/wp-scoper in affected plugins to regenerate the scoped polyfill bootstraps.

v1.2.4

Choose a tag to compare

@mostafasoufi mostafasoufi released this 05 Mar 08:52

Added

  • ABSPATH guard (if (!defined('ABSPATH')) exit;) to generated autoload.php and autoload-classmap.php for WordPress.org plugin compliance

v1.2.3

Choose a tag to compare

@mostafasoufi mostafasoufi released this 21 Feb 11:36

Added

  • Built-in exclude patterns for certificate/key files (.pem, .crt, .cer, .key)