Generate a complete PHP-Scoper
config from the php-stubs/* packages your static-analysis setup already
pulls in — instead of brittle hand-written exclude-* regexes.
You already maintain the source of truth for "what belongs to the host":
the WordPress (and WooCommerce, ACF, …) stub files PHPStan bootstraps.
This package reuses those exact files to drive php-scoper's
exclude-functions / exclude-classes / exclude-constants, so the two
never drift.
A typical .php-scoper.inc.php guesses with patterns like /^wp_.*/,
/^get_.*/, /^is_.*/. That over-matches (a vendor get_thing()
silently escapes prefixing) and under-matches (comment_form,
wp_authenticate, Walker_Comment, wpdb have no wp_/WP_
prefix). Driving the excludes from the stub file is exact: ~3,900
functions and ~570 classes for WordPress 6.9, including every one the
regexes miss.
composer require --dev pinkcrab/php-scoper-helperThat's it — the stub packages are bundled (hard requires of this
library), so they're present wherever this lib is, with nothing extra to
install. Select them by short name:
| Short name | Package |
|---|---|
wordpress |
php-stubs/wordpress-stubs |
wordpress-tests |
php-stubs/wordpress-tests-stubs |
woocommerce |
php-stubs/woocommerce-stubs |
woocommerce-subscriptions |
php-stubs/woocommerce-subscriptions-stubs |
acf-pro |
php-stubs/acf-pro-stubs |
gravity-forms |
php-stubs/gravity-forms-stubs |
wp-cli |
php-stubs/wp-cli-stubs |
facetwp |
php-stubs/facetwp-stubs |
genesis |
php-stubs/genesis-stubs |
buddypress |
gin0115/buddypress-stubs |
Underscores are accepted (gravity_forms == gravity-forms). An
explicit path to any other stub file works too:
->with('/path/to/custom-stubs.php').
The whole .php-scoper.inc.php becomes one chain (mirrors
pinkcrab/enqueue: preferred static constructor, fluent setters, one
finaliser — config(), like Enqueue's register()):
<?php // .php-scoper.inc.php
use PinkCrab\PHP_Scoper_Helper\PHP_Scoper_Helper;
use Isolated\Symfony\Component\Finder\Finder;
$finders = array(
Finder::create()->files()->name('*.php')->in('src'),
Finder::create()->files()->ignoreVCS(true)->in('vendor'),
);
return PHP_Scoper_Helper::for_wordpress() // WP stubs +
->prefix('PinkCrab\\Comment_Moderation\\Vendor') // curated WP
->finders($finders) // constants +
->first_party_from_composer(__DIR__ . '/composer.json')// expose-global
->config();for_wordpress() is the preset: WordPress stubs, the curated WordPress
runtime constants (see below), and expose-global-* all on.
This is the core of the library. Pass any bundled stub short names and their symbols are unioned into the exclude lists. Three equivalent ways:
// 1. As arguments to the WordPress preset — WP + Woo + BuddyPress:
PHP_Scoper_Helper::for_wordpress('woocommerce', 'buddypress')
->prefix('PinkCrab\\Comment_Moderation\\Vendor')
->finders($finders)
->first_party_from_composer(__DIR__ . '/composer.json')
->config();
// 2. Chained onto the preset (identical result):
PHP_Scoper_Helper::for_wordpress()
->with('woocommerce', 'buddypress')
->prefix('PinkCrab\\Comment_Moderation\\Vendor')
->config();
// 3. No preset — a fully explicit list (no curated WP constants):
PHP_Scoper_Helper::stubs('wordpress', 'woocommerce', 'buddypress')
->prefix('Acme\\Vendor')
->config();Order doesn't matter — results are merged, de-duped and sorted. Short
names are the lookup keys in the table above (woocommerce,
buddypress, gravity-forms / gravity_forms, acf-pro, wp-cli,
facetwp, genesis, wordpress-tests, woocommerce-subscriptions).
An explicit path to any other stub file also works:
->with('/path/to/custom-stubs.php').
first_party_from_composer() reads the autoload / autoload-dev
PSR-4 prefixes from your composer.json and feeds them to
exclude-namespaces — your plugin's own code stays un-prefixed, with no
hand-written regex. Or set them yourself with
->with_namespaces('Acme\\Plugin').
PHP_Scoper_Helper::for_wordpress()
->prefix('Acme\\Vendor')
->with('/path/to/custom-stubs.php') // another stub file
->with_classes('Some_Legacy_Class') // + exclude-classes
->with_functions('legacy_helper') // + exclude-functions
->with_constants('MY_FLAG') // + exclude-constants
->exclude_files('config/secrets.php') // copied, never scoped
->config();php-stubs/wordpress-stubs declares functions and classes only — WP
runtime constants (ABSPATH, WPINC, OBJECT, ARRAY_A, …) are defined
when WordPress boots, not stubbed. So this package ships one small,
curated, overridable list of those genuinely-global WP constants, applied
only by for_wordpress() (or when wordpress is selected). Drop it with
->without_default_constants(); add your own with ->with_constants(…).
Every config key has a fluent setter, so the builder is a lossless replacement for a hand-written config:
| Key | Method |
|---|---|
prefix |
prefix() |
php-version |
php_version() |
output-dir |
output_dir() |
finders |
finders() / add_finder() |
patchers |
add_patcher() |
exclude-files |
exclude_files() |
exclude-namespaces |
first_party_from_composer() / with_namespaces() |
exclude-classes |
(stub-driven) + with_classes() |
exclude-functions |
(stub-driven) + with_functions() |
exclude-constants |
(stub-driven + curated WP) + with_constants() |
expose-global-constants/classes/functions |
expose_globals() / expose_global_*() |
expose-namespaces/classes/functions/constants |
expose_namespaces() / expose_classes() / expose_functions() / expose_constants() |
Anything future: ->set('some-new-key', $value) — applied last, wins.
Prefer to hand-assemble? Use the accessors:
$helper = PHP_Scoper_Helper::for_wordpress();
return array(
'prefix' => 'Acme\\Vendor',
'finders' => $finders,
'exclude-classes' => $helper->get_excluded_classes(),
'exclude-functions' => $helper->get_excluded_functions(),
'exclude-constants' => $helper->get_excluded_constants(),
);
// or: array_merge($config, $helper->as_scoper_excludes())MIT — see LICENSE.