Releases: veronalabs/wp-scoper
Release list
v1.4.2
Fixed
- Quoted text fragments renamed as if they were class references:
ClassmapReplacerprefixed 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 globalAttributestub, the trailing fragment became'<Prefix>Attribute'and everyget*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
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 asPlugin::detectPhpConstraint()across the plugin hook andwp-scopecommand, and removed an unreachable guard inNullableParamReplacer. Scoped output is identical to 1.4.0.
v1.4.0
Added
- PHP cross-version compatibility fixing via
extra.wp-scoper.php_compat: true(defaultfalse): opt-in pass that rewrites implicitly-nullable parameters (Type $x = null) in scoped dependency code to the explicit form (?Type $x = null, andA|B $x = null→A|B|null $x = null). PHP 8.4 deprecates the implicit form, so dependencies pinned for an older PHP floor (e.g.thecodingmachine/safekept for PHP 8.0 support) otherwise flood PHP 8.4/8.5 runtimes withE_DEPRECATEDnotices. The rewrite is behaviour-identical and valid on any PHP ≥ 7.1. The target PHP floor is auto-detected from the hostcomposer.json(config.platform.phppreferred,require.phpfallback) — no hardcoded version — and gates the fixer so rewritten syntax stays valid for the declared minimum. Skips already-nullable types,mixed, unions already containingnull, intersection types, untyped params, and non-nulldefaults. Applied to copied dependency files only — the host project's own source is never rewritten. NewNullableParamReplacer; newConfigAPI:isPhpCompatEnabled(),getTargetPhpFloor(),targetPhpAtLeast(),parsePhpFloor(), and a new optional$phpConstraintparameter onConfig::fromArray(). Existing configs withoutphp_compatare unaffected.
v1.3.0
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 theSCOPER_PROFILEenvironment variable (e.g.,SCOPER_PROFILE=premium composer install).packagesarrays are appended + de-duplicated; all other keys (namespace_prefix, target_directory, etc.) replace base values when present in the profile.dev_packages.packagesfollow the same append-and-dedupe rule. ThrowsInvalidArgumentExceptionifSCOPER_PROFILEnames a profile that isn't defined — fail-loud over silent-wrong-output. Public API:Config::applyProfile(array, ?string): arrayand a new optional$profileparameter onConfig::fromArray(). Existingcomposer.jsonconfigs withoutprofilesare unaffected.
v1.2.8
Fixed
- Stale
autoload_files.php/autoload_static.phpreferences afterdelete_vendor_packages: true: when a scoped package declared anautoload.filesentry (Symfony polyfills,league/csvfunction file, etc.), wp-scoper deleted the original package directory but left Composer's eager-load tables pointing at the now-missing path, triggeringrequirefailures on autoloader boot.FileCopier::deleteVendorPackages()now strips entries for the removed packages from both files automatically, so consumers no longer need a custombin/fix-autoload.phppost-script.
Full changelog: v1.2.7...v1.2.8
v1.2.7
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.ClassmapReplacerprefixed these stubs alongside other global classes, which broke the fallbacks and caused fatalClass "X" not founderrors at runtime on servers that lacked the native implementation — most visiblyNormalizeron hosts without theintlextension, but alsoAttribute,JsonException,PhpToken, andUnhandledMatchErroron older PHP versions. The built-in allowlist now covers these five classes, plus the relatedCompileError,UnitEnum,BackedEnum,SensitiveParameter, andOverrideglobals.
Full changelog: v1.2.6...v1.2.7
v1.2.6
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/andContext/were treated asext/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
Fixed
-
use Namespace as Alias;form not prefixedWhen a
usestatement imported a namespace itself (no trailing class) with an alias — e.g.use Symfony\Polyfill\Mbstring as p;in Symfony polyfill bootstrap files —NamespaceReplacerleft it unchanged. After scoping, the aliased reference resolved to a non-existent class and produced fatalClass not founderrors at runtime on hosts where the polyfill code path actually executed (e.g. servers without the nativembstringextension).Pattern 3 in
NamespaceReplacernow accepts an optionalas <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
Added
- ABSPATH guard (
if (!defined('ABSPATH')) exit;) to generatedautoload.phpandautoload-classmap.phpfor WordPress.org plugin compliance
v1.2.3
Added
- Built-in exclude patterns for certificate/key files (
.pem,.crt,.cer,.key)