From d883ad1df42cc8d5df224cd076e557f252bfe7fd Mon Sep 17 00:00:00 2001 From: Pedro de Carvalho
Date: Sat, 20 Jun 2026 18:14:20 +0800
Subject: [PATCH 01/86] Update build
---
build/Gruntfile.js | 43 -
build/composer.json | 60 -
build/composer.lock | 1574 ---
build/grunt/config/config.json | 15 -
build/grunt/config/localenv.json | 3 -
build/grunt/config/localenv.sample.json | 3 -
build/grunt/more-tasks/postcss.js | 23 -
build/grunt/more-tasks/sass.js | 21 -
build/grunt/tasks/browsersync.js | 30 -
build/grunt/tasks/checktextdomain.js | 45 -
build/grunt/tasks/default.js | 4 -
build/grunt/tasks/i18n.js | 4 -
build/grunt/tasks/makepot.js | 42 -
build/grunt/tasks/notify.js | 15 -
build/grunt/tasks/rel_archive.js | 17 -
build/grunt/tasks/rel_clean.js | 13 -
build/grunt/tasks/rel_copy.js | 26 -
build/grunt/tasks/rel_cssmin.js | 18 -
build/grunt/tasks/rel_finish.js | 9 -
build/grunt/tasks/rel_finish_bump.js | 13 -
build/grunt/tasks/rel_gittag.js | 14 -
build/grunt/tasks/rel_new-bump.js | 27 -
build/grunt/tasks/rel_new.js | 21 -
build/grunt/tasks/rel_version.js | 14 -
build/grunt/tasks/shell.js | 14 -
build/grunt/tasks/watch.js | 48 -
build/package-lock.json | 13224 ----------------------
build/package.json | 37 -
28 files changed, 15377 deletions(-)
delete mode 100644 build/Gruntfile.js
delete mode 100644 build/composer.json
delete mode 100644 build/composer.lock
delete mode 100644 build/grunt/config/config.json
delete mode 100644 build/grunt/config/localenv.json
delete mode 100644 build/grunt/config/localenv.sample.json
delete mode 100644 build/grunt/more-tasks/postcss.js
delete mode 100644 build/grunt/more-tasks/sass.js
delete mode 100644 build/grunt/tasks/browsersync.js
delete mode 100644 build/grunt/tasks/checktextdomain.js
delete mode 100644 build/grunt/tasks/default.js
delete mode 100644 build/grunt/tasks/i18n.js
delete mode 100644 build/grunt/tasks/makepot.js
delete mode 100644 build/grunt/tasks/notify.js
delete mode 100644 build/grunt/tasks/rel_archive.js
delete mode 100644 build/grunt/tasks/rel_clean.js
delete mode 100644 build/grunt/tasks/rel_copy.js
delete mode 100644 build/grunt/tasks/rel_cssmin.js
delete mode 100644 build/grunt/tasks/rel_finish.js
delete mode 100644 build/grunt/tasks/rel_finish_bump.js
delete mode 100644 build/grunt/tasks/rel_gittag.js
delete mode 100644 build/grunt/tasks/rel_new-bump.js
delete mode 100644 build/grunt/tasks/rel_new.js
delete mode 100644 build/grunt/tasks/rel_version.js
delete mode 100644 build/grunt/tasks/shell.js
delete mode 100644 build/grunt/tasks/watch.js
delete mode 100644 build/package-lock.json
delete mode 100644 build/package.json
diff --git a/build/Gruntfile.js b/build/Gruntfile.js
deleted file mode 100644
index ca5dbe5a..00000000
--- a/build/Gruntfile.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/* global module require process */
-module.exports = function(grunt) {
- var path = require( 'path' );
-
-
- // Project configuration
- var localenv = grunt.file.readJSON( 'grunt/config/localenv.json' );
- var localconfig = grunt.file.readJSON( 'grunt/config/config.json' );
- var localpkg = grunt.file.readJSON( 'package.json' );
-
-
- var grunt_config = {
- pkg: localpkg,
- cfg: localconfig,
- env: localenv,
- };
-
- grunt.initConfig( grunt_config );
-
- // load modules & tasks
- grunt.loadTasks( 'grunt/tasks' );
-
- // Default task.
- grunt.registerTask( 'default', ['build', 'bs-init', 'watch'] );
-
- // Browser Sync
- grunt.registerTask( 'bs', [ 'bs-init', 'watch'] );
-
- // internationalization
- grunt.registerTask( 'i18n', ['checktextdomain', 'makepot'] );
-
- // compiles all files for dev
- grunt.registerTask( 'build', ['shell:release', 'notify', 'i18n'] );
- grunt.registerTask( 'dev', ['build'] );
-
- // compiles all files for staging/production
- grunt.registerTask( 'prod', ['build'] );
-
- // Release task
- grunt.registerTask( 'bump', [ 'increment-version', 'version', 'gittag', 'finish-bump' ]);
- grunt.registerTask( 'release', [ 'clean', 'new-release', 'shell:release', 'cssmin', 'copy', 'archive', 'finish-release' ]);
-
-};
diff --git a/build/composer.json b/build/composer.json
deleted file mode 100644
index 1ad17a3e..00000000
--- a/build/composer.json
+++ /dev/null
@@ -1,60 +0,0 @@
-{
- "name": "saltus/pluginframework",
- "description": "Saltus Plugin Framework",
- "type": "wordpress-plugin",
- "keywords": [
- "wordpress",
- "plugin"
- ],
- "homepage": "https://saltus.io/",
- "license": "GPL-3.0+",
- "authors": [
- {
- "name": "Saltus Framework",
- "email": "web@saltus.io",
- "homepage": "https://saltus.io/"
- }
- ],
- "support": {
- "issues": "https://saltus.io/",
- "source": "https://saltus.io/",
- "1": {
- "type": "vcs",
- "url": "git@github.com:SaltusDev/saltus-framework.git"
- },
- "2": {
- "type": "path",
- "url": "../../../../packages/saltus-framework"
- }
- },
- "repositories": {
- "0": {
- "type": "composer",
- "url": "https://wpackagist.org"
- },
- "1": {
- "type": "vcs",
- "url": "git@github.com:SaltusDev/saltus-framework.git"
- }
- },
- "autoload": {
- "psr-4": {
- "Saltus\\WP\\Plugin\\Saltus\\PluginFrameworkDemo\\": "../src/"
- }
- },
- "autoload-dev": {
- "psr-4": {
- "Saltus\\WP\\Plugin\\Saltus\\PluginFrameworkDemo\\Tests\\": "../tests/"
- }
- },
- "config": {
- "vendor-dir": "../vendor/"
- },
- "require": {
- "saltus/framework": "dev-main"
- },
- "minimum-stability": "dev",
- "require-dev": {
- "phpunit/phpunit": "^8"
- }
-}
diff --git a/build/composer.lock b/build/composer.lock
deleted file mode 100644
index d050be90..00000000
--- a/build/composer.lock
+++ /dev/null
@@ -1,1574 +0,0 @@
-{
- "_readme": [
- "This file locks the dependencies of your project to a known state",
- "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
- "This file is @generated automatically"
- ],
- "content-hash": "b50bca40970bbe105007a91923ecc707",
- "packages": [
- {
- "name": "hassankhan/config",
- "version": "3.1.0",
- "source": {
- "type": "git",
- "url": "https://github.com/hassankhan/config.git",
- "reference": "8e1c07f4fdc2b986b8a781f0dcba155af2a579b6"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/hassankhan/config/zipball/8e1c07f4fdc2b986b8a781f0dcba155af2a579b6",
- "reference": "8e1c07f4fdc2b986b8a781f0dcba155af2a579b6",
- "shasum": ""
- },
- "require": {
- "php": ">=7.4"
- },
- "require-dev": {
- "phpunit/phpunit": "^9.5",
- "scrutinizer/ocular": "^1.9",
- "squizlabs/php_codesniffer": "^3.6",
- "symfony/yaml": "^5.4"
- },
- "suggest": {
- "symfony/yaml": "^5.4"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Noodlehaus\\": "src"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Hassan Khan",
- "homepage": "http://hassankhan.me/",
- "role": "Developer"
- }
- ],
- "description": "Lightweight configuration file loader that supports PHP, INI, XML, JSON, and YAML files",
- "homepage": "http://hassankhan.me/config/",
- "keywords": [
- "config",
- "configuration",
- "ini",
- "json",
- "microphp",
- "unframework",
- "xml",
- "yaml",
- "yml"
- ],
- "support": {
- "issues": "https://github.com/hassankhan/config/issues",
- "source": "https://github.com/hassankhan/config/tree/3.1.0"
- },
- "time": "2022-12-20T19:48:37+00:00"
- },
- {
- "name": "saltus/framework",
- "version": "dev-main",
- "source": {
- "type": "git",
- "url": "https://github.com/SaltusDev/saltus-framework.git",
- "reference": "879d0fe34df3fe91159588c9fe4d7373790305dc"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/SaltusDev/saltus-framework/zipball/879d0fe34df3fe91159588c9fe4d7373790305dc",
- "reference": "879d0fe34df3fe91159588c9fe4d7373790305dc",
- "shasum": ""
- },
- "require": {
- "hassankhan/config": "^3.1.0",
- "php": ">=7.2"
- },
- "require-dev": {
- "phpunit/phpunit": "^9.6.0",
- "squizlabs/php_codesniffer": "^3.2.3"
- },
- "default-branch": true,
- "type": "project",
- "autoload": {
- "psr-4": {
- "Saltus\\WP\\Framework\\": "src/"
- },
- "files": [
- "lib/codestar-framework/codestar-framework.php"
- ]
- },
- "autoload-dev": {
- "psr-4": {
- "Saltus\\WP\\Framework\\Tests\\": "tests/"
- }
- },
- "scripts": {
- "test": [
- "vendor/bin/phpcs"
- ]
- },
- "license": [
- "GPL-3.0-only"
- ],
- "authors": [
- {
- "name": "Saltus Plugin Framework",
- "email": "web@saltus.io",
- "homepage": "https://saltus.io/"
- }
- ],
- "homepage": "https://saltus.io/",
- "keywords": [
- "composer",
- "vagrant",
- "wordpress",
- "wp"
- ],
- "support": {
- "source": "https://github.com/SaltusDev/saltus-framework/tree/main",
- "issues": "https://github.com/SaltusDev/saltus-framework/issues"
- },
- "time": "2023-10-25T20:54:35+00:00"
- }
- ],
- "packages-dev": [
- {
- "name": "doctrine/instantiator",
- "version": "1.5.x-dev",
- "source": {
- "type": "git",
- "url": "https://github.com/doctrine/instantiator.git",
- "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b",
- "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b",
- "shasum": ""
- },
- "require": {
- "php": "^7.1 || ^8.0"
- },
- "require-dev": {
- "doctrine/coding-standard": "^9 || ^11",
- "ext-pdo": "*",
- "ext-phar": "*",
- "phpbench/phpbench": "^0.16 || ^1",
- "phpstan/phpstan": "^1.4",
- "phpstan/phpstan-phpunit": "^1",
- "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
- "vimeo/psalm": "^4.30 || ^5.4"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Marco Pivetta",
- "email": "ocramius@gmail.com",
- "homepage": "https://ocramius.github.io/"
- }
- ],
- "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
- "homepage": "https://www.doctrine-project.org/projects/instantiator.html",
- "keywords": [
- "constructor",
- "instantiate"
- ],
- "support": {
- "issues": "https://github.com/doctrine/instantiator/issues",
- "source": "https://github.com/doctrine/instantiator/tree/1.5.0"
- },
- "funding": [
- {
- "url": "https://www.doctrine-project.org/sponsorship.html",
- "type": "custom"
- },
- {
- "url": "https://www.patreon.com/phpdoctrine",
- "type": "patreon"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
- "type": "tidelift"
- }
- ],
- "time": "2022-12-30T00:15:36+00:00"
- },
- {
- "name": "myclabs/deep-copy",
- "version": "1.x-dev",
- "source": {
- "type": "git",
- "url": "https://github.com/myclabs/DeepCopy.git",
- "reference": "f6f48cfecf52ab791fe18cc1b11d6345512dc4b8"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/f6f48cfecf52ab791fe18cc1b11d6345512dc4b8",
- "reference": "f6f48cfecf52ab791fe18cc1b11d6345512dc4b8",
- "shasum": ""
- },
- "require": {
- "php": "^7.1 || ^8.0"
- },
- "conflict": {
- "doctrine/collections": "<1.6.8",
- "doctrine/common": "<2.13.3 || >=3 <3.2.2"
- },
- "require-dev": {
- "doctrine/collections": "^1.6.8",
- "doctrine/common": "^2.13.3 || ^3.2.2",
- "phpspec/prophecy": "^1.10",
- "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
- },
- "default-branch": true,
- "type": "library",
- "autoload": {
- "files": [
- "src/DeepCopy/deep_copy.php"
- ],
- "psr-4": {
- "DeepCopy\\": "src/DeepCopy/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "description": "Create deep copies (clones) of your objects",
- "keywords": [
- "clone",
- "copy",
- "duplicate",
- "object",
- "object graph"
- ],
- "support": {
- "issues": "https://github.com/myclabs/DeepCopy/issues",
- "source": "https://github.com/myclabs/DeepCopy/tree/1.x"
- },
- "funding": [
- {
- "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
- "type": "tidelift"
- }
- ],
- "time": "2023-07-30T10:01:33+00:00"
- },
- {
- "name": "phar-io/manifest",
- "version": "dev-master",
- "source": {
- "type": "git",
- "url": "https://github.com/phar-io/manifest.git",
- "reference": "67729272c564ab9f953c81f48db44e8b1cb1e1c3"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/phar-io/manifest/zipball/67729272c564ab9f953c81f48db44e8b1cb1e1c3",
- "reference": "67729272c564ab9f953c81f48db44e8b1cb1e1c3",
- "shasum": ""
- },
- "require": {
- "ext-dom": "*",
- "ext-libxml": "*",
- "ext-phar": "*",
- "ext-xmlwriter": "*",
- "phar-io/version": "^3.0.1",
- "php": "^7.3 || ^8.0"
- },
- "default-branch": true,
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.0.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Arne Blankerts",
- "email": "arne@blankerts.de",
- "role": "Developer"
- },
- {
- "name": "Sebastian Heuer",
- "email": "sebastian@phpeople.de",
- "role": "Developer"
- },
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "Developer"
- }
- ],
- "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
- "support": {
- "issues": "https://github.com/phar-io/manifest/issues",
- "source": "https://github.com/phar-io/manifest/tree/master"
- },
- "funding": [
- {
- "url": "https://github.com/theseer",
- "type": "github"
- }
- ],
- "time": "2023-06-01T14:19:47+00:00"
- },
- {
- "name": "phar-io/version",
- "version": "3.2.1",
- "source": {
- "type": "git",
- "url": "https://github.com/phar-io/version.git",
- "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
- "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
- "shasum": ""
- },
- "require": {
- "php": "^7.2 || ^8.0"
- },
- "type": "library",
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Arne Blankerts",
- "email": "arne@blankerts.de",
- "role": "Developer"
- },
- {
- "name": "Sebastian Heuer",
- "email": "sebastian@phpeople.de",
- "role": "Developer"
- },
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "Developer"
- }
- ],
- "description": "Library for handling version information and constraints",
- "support": {
- "issues": "https://github.com/phar-io/version/issues",
- "source": "https://github.com/phar-io/version/tree/3.2.1"
- },
- "time": "2022-02-21T01:04:05+00:00"
- },
- {
- "name": "phpunit/php-code-coverage",
- "version": "7.0.x-dev",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "819f92bba8b001d4363065928088de22f25a3a48"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/819f92bba8b001d4363065928088de22f25a3a48",
- "reference": "819f92bba8b001d4363065928088de22f25a3a48",
- "shasum": ""
- },
- "require": {
- "ext-dom": "*",
- "ext-xmlwriter": "*",
- "php": ">=7.2",
- "phpunit/php-file-iterator": "^2.0.2",
- "phpunit/php-text-template": "^1.2.1",
- "phpunit/php-token-stream": "^3.1.3 || ^4.0",
- "sebastian/code-unit-reverse-lookup": "^1.0.1",
- "sebastian/environment": "^4.2.2",
- "sebastian/version": "^2.0.1",
- "theseer/tokenizer": "^1.1.3"
- },
- "require-dev": {
- "phpunit/phpunit": "^8.2.2"
- },
- "suggest": {
- "ext-xdebug": "^2.7.2"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "7.0-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
- }
- ],
- "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
- "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
- "keywords": [
- "coverage",
- "testing",
- "xunit"
- ],
- "support": {
- "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
- "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/7.0"
- },
- "funding": [
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- }
- ],
- "time": "2021-07-26T12:20:09+00:00"
- },
- {
- "name": "phpunit/php-file-iterator",
- "version": "2.0.x-dev",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
- "reference": "42c5ba5220e6904cbfe8b1a1bda7c0cfdc8c12f5"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/42c5ba5220e6904cbfe8b1a1bda7c0cfdc8c12f5",
- "reference": "42c5ba5220e6904cbfe8b1a1bda7c0cfdc8c12f5",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1"
- },
- "require-dev": {
- "phpunit/phpunit": "^8.5"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.0.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
- }
- ],
- "description": "FilterIterator implementation that filters files based on a list of suffixes.",
- "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
- "keywords": [
- "filesystem",
- "iterator"
- ],
- "support": {
- "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
- "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/2.0"
- },
- "funding": [
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- }
- ],
- "time": "2021-12-02T12:42:26+00:00"
- },
- {
- "name": "phpunit/php-text-template",
- "version": "1.2.1",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/php-text-template.git",
- "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
- "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
- "shasum": ""
- },
- "require": {
- "php": ">=5.3.3"
- },
- "type": "library",
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
- }
- ],
- "description": "Simple template engine.",
- "homepage": "https://github.com/sebastianbergmann/php-text-template/",
- "keywords": [
- "template"
- ],
- "support": {
- "issues": "https://github.com/sebastianbergmann/php-text-template/issues",
- "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1"
- },
- "time": "2015-06-21T13:50:34+00:00"
- },
- {
- "name": "phpunit/php-timer",
- "version": "2.1.x-dev",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/php-timer.git",
- "reference": "2454ae1765516d20c4ffe103d85a58a9a3bd5662"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/2454ae1765516d20c4ffe103d85a58a9a3bd5662",
- "reference": "2454ae1765516d20c4ffe103d85a58a9a3bd5662",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1"
- },
- "require-dev": {
- "phpunit/phpunit": "^8.5"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.1-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
- }
- ],
- "description": "Utility class for timing",
- "homepage": "https://github.com/sebastianbergmann/php-timer/",
- "keywords": [
- "timer"
- ],
- "support": {
- "issues": "https://github.com/sebastianbergmann/php-timer/issues",
- "source": "https://github.com/sebastianbergmann/php-timer/tree/2.1"
- },
- "funding": [
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- }
- ],
- "time": "2020-11-30T08:20:02+00:00"
- },
- {
- "name": "phpunit/php-token-stream",
- "version": "dev-master",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/php-token-stream.git",
- "reference": "76fc0567751d177847112bd3e26e4890529c98da"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/76fc0567751d177847112bd3e26e4890529c98da",
- "reference": "76fc0567751d177847112bd3e26e4890529c98da",
- "shasum": ""
- },
- "require": {
- "ext-tokenizer": "*",
- "php": "^7.3 || ^8.0"
- },
- "require-dev": {
- "phpunit/phpunit": "^9.0"
- },
- "default-branch": true,
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "4.0-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- }
- ],
- "description": "Wrapper around PHP's tokenizer extension.",
- "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
- "keywords": [
- "tokenizer"
- ],
- "support": {
- "issues": "https://github.com/sebastianbergmann/php-token-stream/issues",
- "source": "https://github.com/sebastianbergmann/php-token-stream/tree/master"
- },
- "funding": [
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- }
- ],
- "abandoned": true,
- "time": "2020-08-06T06:03:05+00:00"
- },
- {
- "name": "phpunit/phpunit",
- "version": "8.5.x-dev",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "622bec1510712358f2bd9201a40183a3b527173d"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/622bec1510712358f2bd9201a40183a3b527173d",
- "reference": "622bec1510712358f2bd9201a40183a3b527173d",
- "shasum": ""
- },
- "require": {
- "doctrine/instantiator": "^1.3.1",
- "ext-dom": "*",
- "ext-json": "*",
- "ext-libxml": "*",
- "ext-mbstring": "*",
- "ext-xml": "*",
- "ext-xmlwriter": "*",
- "myclabs/deep-copy": "^1.10.0",
- "phar-io/manifest": "^2.0.3",
- "phar-io/version": "^3.0.2",
- "php": ">=7.2",
- "phpunit/php-code-coverage": "^7.0.12",
- "phpunit/php-file-iterator": "^2.0.4",
- "phpunit/php-text-template": "^1.2.1",
- "phpunit/php-timer": "^2.1.2",
- "sebastian/comparator": "^3.0.5",
- "sebastian/diff": "^3.0.2",
- "sebastian/environment": "^4.2.3",
- "sebastian/exporter": "^3.1.5",
- "sebastian/global-state": "^3.0.0",
- "sebastian/object-enumerator": "^3.0.3",
- "sebastian/resource-operations": "^2.0.1",
- "sebastian/type": "^1.1.3",
- "sebastian/version": "^2.0.1"
- },
- "suggest": {
- "ext-soap": "To be able to generate mocks based on WSDL files",
- "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage",
- "phpunit/php-invoker": "To allow enforcing time limits"
- },
- "bin": [
- "phpunit"
- ],
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "8.5-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
- }
- ],
- "description": "The PHP Unit Testing framework.",
- "homepage": "https://phpunit.de/",
- "keywords": [
- "phpunit",
- "testing",
- "xunit"
- ],
- "support": {
- "issues": "https://github.com/sebastianbergmann/phpunit/issues",
- "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/8.5"
- },
- "funding": [
- {
- "url": "https://phpunit.de/sponsors.html",
- "type": "custom"
- },
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
- "type": "tidelift"
- }
- ],
- "time": "2023-10-26T07:26:24+00:00"
- },
- {
- "name": "sebastian/code-unit-reverse-lookup",
- "version": "1.0.x-dev",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
- "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/1de8cd5c010cb153fcd68b8d0f64606f523f7619",
- "reference": "1de8cd5c010cb153fcd68b8d0f64606f523f7619",
- "shasum": ""
- },
- "require": {
- "php": ">=5.6"
- },
- "require-dev": {
- "phpunit/phpunit": "^8.5"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.0.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- }
- ],
- "description": "Looks up which function or method a line of code belongs to",
- "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
- "support": {
- "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
- "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0"
- },
- "funding": [
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- }
- ],
- "time": "2020-11-30T08:15:22+00:00"
- },
- {
- "name": "sebastian/comparator",
- "version": "3.0.x-dev",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/comparator.git",
- "reference": "1dc7ceb4a24aede938c7af2a9ed1de09609ca770"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dc7ceb4a24aede938c7af2a9ed1de09609ca770",
- "reference": "1dc7ceb4a24aede938c7af2a9ed1de09609ca770",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1",
- "sebastian/diff": "^3.0",
- "sebastian/exporter": "^3.1"
- },
- "require-dev": {
- "phpunit/phpunit": "^8.5"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.0-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- },
- {
- "name": "Jeff Welch",
- "email": "whatthejeff@gmail.com"
- },
- {
- "name": "Volker Dusch",
- "email": "github@wallbash.com"
- },
- {
- "name": "Bernhard Schussek",
- "email": "bschussek@2bepublished.at"
- }
- ],
- "description": "Provides the functionality to compare PHP values for equality",
- "homepage": "https://github.com/sebastianbergmann/comparator",
- "keywords": [
- "comparator",
- "compare",
- "equality"
- ],
- "support": {
- "issues": "https://github.com/sebastianbergmann/comparator/issues",
- "source": "https://github.com/sebastianbergmann/comparator/tree/3.0.5"
- },
- "funding": [
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- }
- ],
- "time": "2022-09-14T12:31:48+00:00"
- },
- {
- "name": "sebastian/diff",
- "version": "3.0.x-dev",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/diff.git",
- "reference": "6296a0c086dd0117c1b78b059374d7fcbe7545ae"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/6296a0c086dd0117c1b78b059374d7fcbe7545ae",
- "reference": "6296a0c086dd0117c1b78b059374d7fcbe7545ae",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1"
- },
- "require-dev": {
- "phpunit/phpunit": "^7.5 || ^8.0",
- "symfony/process": "^2 || ^3.3 || ^4"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.0-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- },
- {
- "name": "Kore Nordmann",
- "email": "mail@kore-nordmann.de"
- }
- ],
- "description": "Diff implementation",
- "homepage": "https://github.com/sebastianbergmann/diff",
- "keywords": [
- "diff",
- "udiff",
- "unidiff",
- "unified diff"
- ],
- "support": {
- "issues": "https://github.com/sebastianbergmann/diff/issues",
- "source": "https://github.com/sebastianbergmann/diff/tree/3.0"
- },
- "funding": [
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- }
- ],
- "time": "2023-05-07T05:30:20+00:00"
- },
- {
- "name": "sebastian/environment",
- "version": "4.2.x-dev",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/environment.git",
- "reference": "a8cb2aa3eca438e75a4b7895f04bc8f5f990bc49"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a8cb2aa3eca438e75a4b7895f04bc8f5f990bc49",
- "reference": "a8cb2aa3eca438e75a4b7895f04bc8f5f990bc49",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1"
- },
- "require-dev": {
- "phpunit/phpunit": "^7.5"
- },
- "suggest": {
- "ext-posix": "*"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "4.2-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- }
- ],
- "description": "Provides functionality to handle HHVM/PHP environments",
- "homepage": "http://www.github.com/sebastianbergmann/environment",
- "keywords": [
- "Xdebug",
- "environment",
- "hhvm"
- ],
- "support": {
- "issues": "https://github.com/sebastianbergmann/environment/issues",
- "source": "https://github.com/sebastianbergmann/environment/tree/4.2"
- },
- "funding": [
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- }
- ],
- "time": "2021-08-17T14:54:22+00:00"
- },
- {
- "name": "sebastian/exporter",
- "version": "3.1.x-dev",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/exporter.git",
- "reference": "73a9676f2833b9a7c36968f9d882589cd75511e6"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/73a9676f2833b9a7c36968f9d882589cd75511e6",
- "reference": "73a9676f2833b9a7c36968f9d882589cd75511e6",
- "shasum": ""
- },
- "require": {
- "php": ">=7.0",
- "sebastian/recursion-context": "^3.0"
- },
- "require-dev": {
- "ext-mbstring": "*",
- "phpunit/phpunit": "^8.5"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.1.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- },
- {
- "name": "Jeff Welch",
- "email": "whatthejeff@gmail.com"
- },
- {
- "name": "Volker Dusch",
- "email": "github@wallbash.com"
- },
- {
- "name": "Adam Harvey",
- "email": "aharvey@php.net"
- },
- {
- "name": "Bernhard Schussek",
- "email": "bschussek@gmail.com"
- }
- ],
- "description": "Provides the functionality to export PHP variables for visualization",
- "homepage": "http://www.github.com/sebastianbergmann/exporter",
- "keywords": [
- "export",
- "exporter"
- ],
- "support": {
- "issues": "https://github.com/sebastianbergmann/exporter/issues",
- "source": "https://github.com/sebastianbergmann/exporter/tree/3.1"
- },
- "funding": [
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- }
- ],
- "time": "2022-09-14T06:00:17+00:00"
- },
- {
- "name": "sebastian/global-state",
- "version": "3.0.x-dev",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/global-state.git",
- "reference": "66783ce213de415b451b904bfef9dda0cf9aeae0"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/66783ce213de415b451b904bfef9dda0cf9aeae0",
- "reference": "66783ce213de415b451b904bfef9dda0cf9aeae0",
- "shasum": ""
- },
- "require": {
- "php": ">=7.2",
- "sebastian/object-reflector": "^1.1.1",
- "sebastian/recursion-context": "^3.0"
- },
- "require-dev": {
- "ext-dom": "*",
- "phpunit/phpunit": "^8.0"
- },
- "suggest": {
- "ext-uopz": "*"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.0-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- }
- ],
- "description": "Snapshotting of global state",
- "homepage": "http://www.github.com/sebastianbergmann/global-state",
- "keywords": [
- "global state"
- ],
- "support": {
- "issues": "https://github.com/sebastianbergmann/global-state/issues",
- "source": "https://github.com/sebastianbergmann/global-state/tree/3.0"
- },
- "funding": [
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- }
- ],
- "time": "2023-08-02T09:23:32+00:00"
- },
- {
- "name": "sebastian/object-enumerator",
- "version": "3.0.x-dev",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/object-enumerator.git",
- "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2",
- "reference": "e67f6d32ebd0c749cf9d1dbd9f226c727043cdf2",
- "shasum": ""
- },
- "require": {
- "php": ">=7.0",
- "sebastian/object-reflector": "^1.1.1",
- "sebastian/recursion-context": "^3.0"
- },
- "require-dev": {
- "phpunit/phpunit": "^6.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.0.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- }
- ],
- "description": "Traverses array structures and object graphs to enumerate all referenced objects",
- "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
- "support": {
- "issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
- "source": "https://github.com/sebastianbergmann/object-enumerator/tree/3.0"
- },
- "funding": [
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- }
- ],
- "time": "2020-11-30T07:40:27+00:00"
- },
- {
- "name": "sebastian/object-reflector",
- "version": "1.1.x-dev",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/object-reflector.git",
- "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/9b8772b9cbd456ab45d4a598d2dd1a1bced6363d",
- "reference": "9b8772b9cbd456ab45d4a598d2dd1a1bced6363d",
- "shasum": ""
- },
- "require": {
- "php": ">=7.0"
- },
- "require-dev": {
- "phpunit/phpunit": "^6.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.1-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- }
- ],
- "description": "Allows reflection of object attributes, including inherited and non-public ones",
- "homepage": "https://github.com/sebastianbergmann/object-reflector/",
- "support": {
- "issues": "https://github.com/sebastianbergmann/object-reflector/issues",
- "source": "https://github.com/sebastianbergmann/object-reflector/tree/1.1"
- },
- "funding": [
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- }
- ],
- "time": "2020-11-30T07:37:18+00:00"
- },
- {
- "name": "sebastian/recursion-context",
- "version": "3.0.x-dev",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/recursion-context.git",
- "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/367dcba38d6e1977be014dc4b22f47a484dac7fb",
- "reference": "367dcba38d6e1977be014dc4b22f47a484dac7fb",
- "shasum": ""
- },
- "require": {
- "php": ">=7.0"
- },
- "require-dev": {
- "phpunit/phpunit": "^6.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.0.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- },
- {
- "name": "Jeff Welch",
- "email": "whatthejeff@gmail.com"
- },
- {
- "name": "Adam Harvey",
- "email": "aharvey@php.net"
- }
- ],
- "description": "Provides functionality to recursively process PHP variables",
- "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
- "support": {
- "issues": "https://github.com/sebastianbergmann/recursion-context/issues",
- "source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0"
- },
- "funding": [
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- }
- ],
- "time": "2020-11-30T07:34:24+00:00"
- },
- {
- "name": "sebastian/resource-operations",
- "version": "2.0.x-dev",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/resource-operations.git",
- "reference": "31d35ca87926450c44eae7e2611d45a7a65ea8b3"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/31d35ca87926450c44eae7e2611d45a7a65ea8b3",
- "reference": "31d35ca87926450c44eae7e2611d45a7a65ea8b3",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.0-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- }
- ],
- "description": "Provides a list of PHP built-in functions that operate on resources",
- "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
- "support": {
- "issues": "https://github.com/sebastianbergmann/resource-operations/issues",
- "source": "https://github.com/sebastianbergmann/resource-operations/tree/2.0"
- },
- "funding": [
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- }
- ],
- "time": "2020-11-30T07:30:19+00:00"
- },
- {
- "name": "sebastian/type",
- "version": "1.1.x-dev",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/type.git",
- "reference": "49529de1ea06aa1f7d30e9c6ce2d196575ff56ad"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/49529de1ea06aa1f7d30e9c6ce2d196575ff56ad",
- "reference": "49529de1ea06aa1f7d30e9c6ce2d196575ff56ad",
- "shasum": ""
- },
- "require": {
- "php": ">=7.2"
- },
- "require-dev": {
- "phpunit/phpunit": "^8.2"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.1-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
- }
- ],
- "description": "Collection of value objects that represent the types of the PHP type system",
- "homepage": "https://github.com/sebastianbergmann/type",
- "support": {
- "issues": "https://github.com/sebastianbergmann/type/issues",
- "source": "https://github.com/sebastianbergmann/type/tree/1.1"
- },
- "funding": [
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- }
- ],
- "time": "2022-03-09T17:11:40+00:00"
- },
- {
- "name": "sebastian/version",
- "version": "2.0.1",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/version.git",
- "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019",
- "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019",
- "shasum": ""
- },
- "require": {
- "php": ">=5.6"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "2.0.x-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
- }
- ],
- "description": "Library that helps with managing the version number of Git-hosted PHP projects",
- "homepage": "https://github.com/sebastianbergmann/version",
- "support": {
- "issues": "https://github.com/sebastianbergmann/version/issues",
- "source": "https://github.com/sebastianbergmann/version/tree/master"
- },
- "time": "2016-10-03T07:35:21+00:00"
- },
- {
- "name": "theseer/tokenizer",
- "version": "1.2.1",
- "source": {
- "type": "git",
- "url": "https://github.com/theseer/tokenizer.git",
- "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
- "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
- "shasum": ""
- },
- "require": {
- "ext-dom": "*",
- "ext-tokenizer": "*",
- "ext-xmlwriter": "*",
- "php": "^7.2 || ^8.0"
- },
- "type": "library",
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Arne Blankerts",
- "email": "arne@blankerts.de",
- "role": "Developer"
- }
- ],
- "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
- "support": {
- "issues": "https://github.com/theseer/tokenizer/issues",
- "source": "https://github.com/theseer/tokenizer/tree/1.2.1"
- },
- "funding": [
- {
- "url": "https://github.com/theseer",
- "type": "github"
- }
- ],
- "time": "2021-07-28T10:34:58+00:00"
- }
- ],
- "aliases": [],
- "minimum-stability": "dev",
- "stability-flags": {
- "saltus/framework": 20
- },
- "prefer-stable": false,
- "prefer-lowest": false,
- "platform": [],
- "platform-dev": [],
- "plugin-api-version": "2.3.0"
-}
diff --git a/build/grunt/config/config.json b/build/grunt/config/config.json
deleted file mode 100644
index ebfaacf4..00000000
--- a/build/grunt/config/config.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "i18n": {
- "author": "Saltus
Date: Sat, 20 Jun 2026 22:34:58 +0800
Subject: [PATCH 02/86] infra(project): migrate build from Grunt to Composer
workflow
Replace legacy .gitignore patterns with generated-artifact entries.
Remove blanket-silenced PHPCS rules in favour of targeted inline ignores.
Add composer.json with PSR-4 autoloading, dev dependencies
(PHPUnit 11, WPCS 3), scripts (lint, test, package, make-pot),
and lock file pinning saltus/framework plus PHPUnit and PHPCS packages.
Add phpunit.xml.dist and bin/package.php CLI for distributable ZIPs.
Remove obsolete package-lock.json as Node/Grunt is no longer used.
---
.gitignore | 26 +-
bin/package.php | 55 ++
composer.json | 64 ++
composer.lock | 2365 +++++++++++++++++++++++++++++++++++++++++++++
package-lock.json | 91 --
phpcs.xml | 7 +-
phpunit.xml.dist | 8 +
7 files changed, 2513 insertions(+), 103 deletions(-)
create mode 100644 bin/package.php
create mode 100644 composer.json
create mode 100644 composer.lock
delete mode 100644 package-lock.json
create mode 100644 phpunit.xml.dist
diff --git a/.gitignore b/.gitignore
index ecb91256..b8c4eda0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,19 +1,23 @@
-# Composer
-vendor/*
-!vendor/.gitkeep
+# Dependencies
+/vendor/
+/node_modules/
+/build/node_modules/
-# dev
-bower_components
-node_modules
-npm-debug.log
-yarn-error.log
-vendor
+# Generated artifacts
+/dist/
+/release/
+/build/dist/
+/build/release/
+/*.zip
*.map
*.log
reports/
-dist/
-release/
+npm-debug.log
+yarn-error.log
+.phpunit.cache/
+.phpunit.result.cache
+.phpcs-cache
# Editor
.vscode
diff --git a/bin/package.php b/bin/package.php
new file mode 100644
index 00000000..ffe80479
--- /dev/null
+++ b/bin/package.php
@@ -0,0 +1,55 @@
+open( $zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE ) ) {
+ fwrite( STDERR, "Could not open {$zip_path}.\n" ); // phpcs:ignore WordPress.WP.AlternativeFunctions
+ exit( 1 );
+}
+
+$excluded_dirs = array( '.git', '.codex', '.agents', 'node_modules', 'build', 'dist', 'release', 'reports' );
+$excluded_files = array( 'composer.lock', 'package-lock.json' );
+
+$iterator = new RecursiveIteratorIterator(
+ new RecursiveDirectoryIterator( $root, FilesystemIterator::SKIP_DOTS )
+);
+
+foreach ( $iterator as $file ) {
+ if ( ! $file instanceof SplFileInfo || ! $file->isFile() ) {
+ continue;
+ }
+
+ $relative = ltrim( str_replace( $root, '', $file->getPathname() ), DIRECTORY_SEPARATOR );
+ $parts = explode( DIRECTORY_SEPARATOR, $relative );
+
+ if ( array_intersect( $parts, $excluded_dirs ) ) {
+ continue;
+ }
+
+ if ( in_array( basename( $relative ), $excluded_files, true ) || preg_match( '/\.(zip|log|map|cache)$/', basename( $relative ) ) ) {
+ continue;
+ }
+
+ $zip->addFile( $file->getPathname(), $slug . '/' . str_replace( DIRECTORY_SEPARATOR, '/', $relative ) );
+}
+
+$zip->close();
+
+echo "Created {$zip_path}\n"; // phpcs:ignore WordPress.Security.EscapeOutput
diff --git a/composer.json b/composer.json
new file mode 100644
index 00000000..82bb7632
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,64 @@
+{
+ "name": "saltus/framework-demo",
+ "description": "Modern demo plugin for the Saltus Framework for WordPress.",
+ "type": "wordpress-plugin",
+ "license": "GPL-2.0-or-later",
+ "homepage": "https://saltus.io/",
+ "authors": [
+ {
+ "name": "Saltus",
+ "email": "web@saltus.dev",
+ "homepage": "https://saltus.dev"
+ }
+ ],
+ "keywords": [
+ "wordpress",
+ "plugin",
+ "saltus",
+ "framework"
+ ],
+ "repositories": [
+ {
+ "type": "composer",
+ "url": "https://wpackagist.org"
+ },
+ {
+ "type": "vcs",
+ "url": "https://github.com/SaltusDev/saltus-framework.git"
+ }
+ ],
+ "require": {
+ "php": ">=8.3",
+ "saltus/framework": "dev-main"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0",
+ "wp-coding-standards/wpcs": "^3.1",
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0"
+ },
+ "autoload": {
+ "psr-4": {
+ "Saltus\\WP\\Plugin\\Saltus\\PluginFrameworkDemo\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Saltus\\WP\\Plugin\\Saltus\\PluginFrameworkDemo\\Tests\\": "tests/"
+ }
+ },
+ "config": {
+ "allow-plugins": {
+ "dealerdirect/phpcodesniffer-composer-installer": true
+ },
+ "sort-packages": true
+ },
+ "scripts": {
+ "validate-project": "composer validate --strict",
+ "lint": "phpcs",
+ "test": "phpunit",
+ "make-pot": "wp i18n make-pot . languages/framework-demo.pot --exclude=vendor,node_modules,dist,release,build",
+ "package": "php bin/package.php"
+ },
+ "minimum-stability": "dev",
+ "prefer-stable": true
+}
diff --git a/composer.lock b/composer.lock
new file mode 100644
index 00000000..0da33116
--- /dev/null
+++ b/composer.lock
@@ -0,0 +1,2365 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+ "This file is @generated automatically"
+ ],
+ "content-hash": "136628a128f86379ce50be2b78f37700",
+ "packages": [
+ {
+ "name": "hassankhan/config",
+ "version": "3.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/hassankhan/config.git",
+ "reference": "cf63da451c4d226df983017932b9cef1b6d49db5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/hassankhan/config/zipball/cf63da451c4d226df983017932b9cef1b6d49db5",
+ "reference": "cf63da451c4d226df983017932b9cef1b6d49db5",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.4"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.5",
+ "scrutinizer/ocular": "^1.9",
+ "squizlabs/php_codesniffer": "^3.6",
+ "symfony/yaml": "^5.4"
+ },
+ "suggest": {
+ "symfony/yaml": "^5.4"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Noodlehaus\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Hassan Khan",
+ "homepage": "http://hassankhan.me/",
+ "role": "Developer"
+ }
+ ],
+ "description": "Lightweight configuration file loader that supports PHP, INI, XML, JSON, and YAML files",
+ "homepage": "http://hassankhan.me/config/",
+ "keywords": [
+ "config",
+ "configuration",
+ "ini",
+ "json",
+ "microphp",
+ "unframework",
+ "xml",
+ "yaml",
+ "yml"
+ ],
+ "support": {
+ "issues": "https://github.com/hassankhan/config/issues",
+ "source": "https://github.com/hassankhan/config/tree/3.2.0"
+ },
+ "time": "2024-12-09T16:20:44+00:00"
+ },
+ {
+ "name": "saltus/framework",
+ "version": "dev-main",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/SaltusDev/saltus-framework.git",
+ "reference": "c552751ae408b3da9ff3309520da134f2f12a701"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/SaltusDev/saltus-framework/zipball/c552751ae408b3da9ff3309520da134f2f12a701",
+ "reference": "c552751ae408b3da9ff3309520da134f2f12a701",
+ "shasum": ""
+ },
+ "require": {
+ "hassankhan/config": "^3.2.0",
+ "php": ">=7.4"
+ },
+ "require-dev": {
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
+ "digitalrevolution/php-codesniffer-baseline": "^1.1.2",
+ "php-stubs/woocommerce-stubs": "^10.6.2",
+ "php-stubs/wordpress-stubs": "^6.7",
+ "phpcompatibility/phpcompatibility-wp": "*",
+ "phpstan/extension-installer": "^1.3",
+ "phpunit/phpunit": "^12.5.15",
+ "squizlabs/php_codesniffer": "^3.9",
+ "szepeviktor/phpstan-wordpress": "^2.1",
+ "wp-coding-standards/wpcs": "^3.1",
+ "yoast/phpunit-polyfills": "^4.0"
+ },
+ "default-branch": true,
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Saltus\\WP\\Framework\\": "src/"
+ },
+ "classmap": [
+ "lib/codestar-framework/"
+ ]
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "Saltus\\WP\\Framework\\Tests\\": "tests/"
+ }
+ },
+ "scripts": {
+ "phpstan": [
+ "./vendor/bin/phpstan analyse --memory-limit=2G"
+ ],
+ "phpcs": [
+ "./vendor/bin/phpcs --standard=phpcs.xml"
+ ]
+ },
+ "license": [
+ "GPL-3.0-only"
+ ],
+ "authors": [
+ {
+ "name": "Saltus Plugin Framework",
+ "email": "web@goodomens.studio",
+ "homepage": "https://saltus.dev/"
+ }
+ ],
+ "description": "A WordPress framework for building plugins around custom post types, taxonomies, meta boxes, settings pages, and admin tooling.",
+ "homepage": "https://saltus.dev/",
+ "keywords": [
+ "admin",
+ "custom-post-types",
+ "framework",
+ "meta-boxes",
+ "settings",
+ "taxonomies",
+ "wordpress"
+ ],
+ "support": {
+ "source": "https://github.com/SaltusDev/saltus-framework",
+ "issues": "https://github.com/SaltusDev/saltus-framework/issues",
+ "docs": "https://github.com/SaltusDev/saltus-framework/wiki"
+ },
+ "time": "2026-06-20T06:01:09+00:00"
+ }
+ ],
+ "packages-dev": [
+ {
+ "name": "dealerdirect/phpcodesniffer-composer-installer",
+ "version": "v1.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCSStandards/composer-installer.git",
+ "reference": "963f0c67bffde0eac41b56be71ac0e8ba132f0bd"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/963f0c67bffde0eac41b56be71ac0e8ba132f0bd",
+ "reference": "963f0c67bffde0eac41b56be71ac0e8ba132f0bd",
+ "shasum": ""
+ },
+ "require": {
+ "composer-plugin-api": "^2.2",
+ "php": ">=5.4",
+ "squizlabs/php_codesniffer": "^3.1.0 || ^4.0"
+ },
+ "require-dev": {
+ "composer/composer": "^2.2",
+ "ext-json": "*",
+ "ext-zip": "*",
+ "php-parallel-lint/php-parallel-lint": "^1.4.0",
+ "phpcompatibility/php-compatibility": "^9.0 || ^10.0.0@dev",
+ "yoast/phpunit-polyfills": "^1.0"
+ },
+ "type": "composer-plugin",
+ "extra": {
+ "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
+ },
+ "autoload": {
+ "psr-4": {
+ "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Franck Nijhof",
+ "email": "opensource@frenck.dev",
+ "homepage": "https://frenck.dev",
+ "role": "Open source developer"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors"
+ }
+ ],
+ "description": "PHP_CodeSniffer Standards Composer Installer Plugin",
+ "keywords": [
+ "PHPCodeSniffer",
+ "PHP_CodeSniffer",
+ "code quality",
+ "codesniffer",
+ "composer",
+ "installer",
+ "phpcbf",
+ "phpcs",
+ "plugin",
+ "qa",
+ "quality",
+ "standard",
+ "standards",
+ "style guide",
+ "stylecheck",
+ "tests"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPCSStandards/composer-installer/issues",
+ "security": "https://github.com/PHPCSStandards/composer-installer/security/policy",
+ "source": "https://github.com/PHPCSStandards/composer-installer"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/PHPCSStandards",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jrfnl",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/phpcsstandards",
+ "type": "thanks_dev"
+ }
+ ],
+ "time": "2026-05-06T08:26:05+00:00"
+ },
+ {
+ "name": "myclabs/deep-copy",
+ "version": "1.13.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/myclabs/DeepCopy.git",
+ "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a",
+ "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1 || ^8.0"
+ },
+ "conflict": {
+ "doctrine/collections": "<1.6.8",
+ "doctrine/common": "<2.13.3 || >=3 <3.2.2"
+ },
+ "require-dev": {
+ "doctrine/collections": "^1.6.8",
+ "doctrine/common": "^2.13.3 || ^3.2.2",
+ "phpspec/prophecy": "^1.10",
+ "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/DeepCopy/deep_copy.php"
+ ],
+ "psr-4": {
+ "DeepCopy\\": "src/DeepCopy/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Create deep copies (clones) of your objects",
+ "keywords": [
+ "clone",
+ "copy",
+ "duplicate",
+ "object",
+ "object graph"
+ ],
+ "support": {
+ "issues": "https://github.com/myclabs/DeepCopy/issues",
+ "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4"
+ },
+ "funding": [
+ {
+ "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-08-01T08:46:24+00:00"
+ },
+ {
+ "name": "nikic/php-parser",
+ "version": "v5.7.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nikic/PHP-Parser.git",
+ "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82",
+ "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82",
+ "shasum": ""
+ },
+ "require": {
+ "ext-ctype": "*",
+ "ext-json": "*",
+ "ext-tokenizer": "*",
+ "php": ">=7.4"
+ },
+ "require-dev": {
+ "ircmaxell/php-yacc": "^0.0.7",
+ "phpunit/phpunit": "^9.0"
+ },
+ "bin": [
+ "bin/php-parse"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "PhpParser\\": "lib/PhpParser"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Nikita Popov"
+ }
+ ],
+ "description": "A PHP parser written in PHP",
+ "keywords": [
+ "parser",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/nikic/PHP-Parser/issues",
+ "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0"
+ },
+ "time": "2025-12-06T11:56:16+00:00"
+ },
+ {
+ "name": "phar-io/manifest",
+ "version": "2.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phar-io/manifest.git",
+ "reference": "54750ef60c58e43759730615a392c31c80e23176"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176",
+ "reference": "54750ef60c58e43759730615a392c31c80e23176",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-libxml": "*",
+ "ext-phar": "*",
+ "ext-xmlwriter": "*",
+ "phar-io/version": "^3.0.1",
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "sebastian@phpeople.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
+ "support": {
+ "issues": "https://github.com/phar-io/manifest/issues",
+ "source": "https://github.com/phar-io/manifest/tree/2.0.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/theseer",
+ "type": "github"
+ }
+ ],
+ "time": "2024-03-03T12:33:53+00:00"
+ },
+ {
+ "name": "phar-io/version",
+ "version": "3.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phar-io/version.git",
+ "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
+ "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "sebastian@phpeople.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Library for handling version information and constraints",
+ "support": {
+ "issues": "https://github.com/phar-io/version/issues",
+ "source": "https://github.com/phar-io/version/tree/3.2.1"
+ },
+ "time": "2022-02-21T01:04:05+00:00"
+ },
+ {
+ "name": "phpcsstandards/phpcsextra",
+ "version": "1.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCSStandards/PHPCSExtra.git",
+ "reference": "b598aa890815b8df16363271b659d73280129101"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCSStandards/PHPCSExtra/zipball/b598aa890815b8df16363271b659d73280129101",
+ "reference": "b598aa890815b8df16363271b659d73280129101",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4",
+ "phpcsstandards/phpcsutils": "^1.2.0",
+ "squizlabs/php_codesniffer": "^3.13.5 || ^4.0.1"
+ },
+ "require-dev": {
+ "php-parallel-lint/php-console-highlighter": "^1.0",
+ "php-parallel-lint/php-parallel-lint": "^1.4.0",
+ "phpcsstandards/phpcsdevcs": "^1.2.0",
+ "phpcsstandards/phpcsdevtools": "^1.2.1",
+ "phpunit/phpunit": "^4.5 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4"
+ },
+ "type": "phpcodesniffer-standard",
+ "extra": {
+ "branch-alias": {
+ "dev-stable": "1.x-dev",
+ "dev-develop": "1.x-dev"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL-3.0-or-later"
+ ],
+ "authors": [
+ {
+ "name": "Juliette Reinders Folmer",
+ "homepage": "https://github.com/jrfnl",
+ "role": "lead"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/PHPCSStandards/PHPCSExtra/graphs/contributors"
+ }
+ ],
+ "description": "A collection of sniffs and standards for use with PHP_CodeSniffer.",
+ "keywords": [
+ "PHP_CodeSniffer",
+ "phpcbf",
+ "phpcodesniffer-standard",
+ "phpcs",
+ "standards",
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPCSStandards/PHPCSExtra/issues",
+ "security": "https://github.com/PHPCSStandards/PHPCSExtra/security/policy",
+ "source": "https://github.com/PHPCSStandards/PHPCSExtra"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/PHPCSStandards",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jrfnl",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/phpcsstandards",
+ "type": "thanks_dev"
+ }
+ ],
+ "time": "2025-11-12T23:06:57+00:00"
+ },
+ {
+ "name": "phpcsstandards/phpcsutils",
+ "version": "1.2.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCSStandards/PHPCSUtils.git",
+ "reference": "c216317e96c8b3f5932808f9b0f1f7a14e3bbf55"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/c216317e96c8b3f5932808f9b0f1f7a14e3bbf55",
+ "reference": "c216317e96c8b3f5932808f9b0f1f7a14e3bbf55",
+ "shasum": ""
+ },
+ "require": {
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7 || ^1.0",
+ "php": ">=5.4",
+ "squizlabs/php_codesniffer": "^3.13.5 || ^4.0.1"
+ },
+ "require-dev": {
+ "ext-filter": "*",
+ "php-parallel-lint/php-console-highlighter": "^1.0",
+ "php-parallel-lint/php-parallel-lint": "^1.4.0",
+ "phpcsstandards/phpcsdevcs": "^1.2.0",
+ "yoast/phpunit-polyfills": "^1.1.0 || ^2.0.0 || ^3.0.0"
+ },
+ "type": "phpcodesniffer-standard",
+ "extra": {
+ "branch-alias": {
+ "dev-stable": "1.x-dev",
+ "dev-develop": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "PHPCSUtils/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL-3.0-or-later"
+ ],
+ "authors": [
+ {
+ "name": "Juliette Reinders Folmer",
+ "homepage": "https://github.com/jrfnl",
+ "role": "lead"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/PHPCSStandards/PHPCSUtils/graphs/contributors"
+ }
+ ],
+ "description": "A suite of utility functions for use with PHP_CodeSniffer",
+ "homepage": "https://phpcsutils.com/",
+ "keywords": [
+ "PHP_CodeSniffer",
+ "phpcbf",
+ "phpcodesniffer-standard",
+ "phpcs",
+ "phpcs3",
+ "phpcs4",
+ "standards",
+ "static analysis",
+ "tokens",
+ "utility"
+ ],
+ "support": {
+ "docs": "https://phpcsutils.com/",
+ "issues": "https://github.com/PHPCSStandards/PHPCSUtils/issues",
+ "security": "https://github.com/PHPCSStandards/PHPCSUtils/security/policy",
+ "source": "https://github.com/PHPCSStandards/PHPCSUtils"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/PHPCSStandards",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jrfnl",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/phpcsstandards",
+ "type": "thanks_dev"
+ }
+ ],
+ "time": "2025-12-08T14:27:58+00:00"
+ },
+ {
+ "name": "phpunit/php-code-coverage",
+ "version": "11.0.12",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
+ "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2c1ed04922802c15e1de5d7447b4856de949cf56",
+ "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-libxml": "*",
+ "ext-xmlwriter": "*",
+ "nikic/php-parser": "^5.7.0",
+ "php": ">=8.2",
+ "phpunit/php-file-iterator": "^5.1.0",
+ "phpunit/php-text-template": "^4.0.1",
+ "sebastian/code-unit-reverse-lookup": "^4.0.1",
+ "sebastian/complexity": "^4.0.1",
+ "sebastian/environment": "^7.2.1",
+ "sebastian/lines-of-code": "^3.0.1",
+ "sebastian/version": "^5.0.2",
+ "theseer/tokenizer": "^1.3.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "suggest": {
+ "ext-pcov": "PHP extension that provides line coverage",
+ "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "11.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
+ "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
+ "keywords": [
+ "coverage",
+ "testing",
+ "xunit"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
+ "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.12"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-12-24T07:01:01+00:00"
+ },
+ {
+ "name": "phpunit/php-file-iterator",
+ "version": "5.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
+ "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/2f3a64888c814fc235386b7387dd5b5ed92ad903",
+ "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "FilterIterator implementation that filters files based on a list of suffixes.",
+ "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
+ "keywords": [
+ "filesystem",
+ "iterator"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
+ "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpunit/php-file-iterator",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-02-02T13:52:54+00:00"
+ },
+ {
+ "name": "phpunit/php-invoker",
+ "version": "5.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-invoker.git",
+ "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2",
+ "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "ext-pcntl": "*",
+ "phpunit/phpunit": "^11.0"
+ },
+ "suggest": {
+ "ext-pcntl": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Invoke callables with a timeout",
+ "homepage": "https://github.com/sebastianbergmann/php-invoker/",
+ "keywords": [
+ "process"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-invoker/issues",
+ "security": "https://github.com/sebastianbergmann/php-invoker/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T05:07:44+00:00"
+ },
+ {
+ "name": "phpunit/php-text-template",
+ "version": "4.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-text-template.git",
+ "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964",
+ "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Simple template engine.",
+ "homepage": "https://github.com/sebastianbergmann/php-text-template/",
+ "keywords": [
+ "template"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-text-template/issues",
+ "security": "https://github.com/sebastianbergmann/php-text-template/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T05:08:43+00:00"
+ },
+ {
+ "name": "phpunit/php-timer",
+ "version": "7.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-timer.git",
+ "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3",
+ "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "7.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Utility class for timing",
+ "homepage": "https://github.com/sebastianbergmann/php-timer/",
+ "keywords": [
+ "timer"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-timer/issues",
+ "security": "https://github.com/sebastianbergmann/php-timer/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T05:09:35+00:00"
+ },
+ {
+ "name": "phpunit/phpunit",
+ "version": "11.5.55",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/phpunit.git",
+ "reference": "adc7262fccc12de2b30f12a8aa0b33775d814f00"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/adc7262fccc12de2b30f12a8aa0b33775d814f00",
+ "reference": "adc7262fccc12de2b30f12a8aa0b33775d814f00",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-json": "*",
+ "ext-libxml": "*",
+ "ext-mbstring": "*",
+ "ext-xml": "*",
+ "ext-xmlwriter": "*",
+ "myclabs/deep-copy": "^1.13.4",
+ "phar-io/manifest": "^2.0.4",
+ "phar-io/version": "^3.2.1",
+ "php": ">=8.2",
+ "phpunit/php-code-coverage": "^11.0.12",
+ "phpunit/php-file-iterator": "^5.1.1",
+ "phpunit/php-invoker": "^5.0.1",
+ "phpunit/php-text-template": "^4.0.1",
+ "phpunit/php-timer": "^7.0.1",
+ "sebastian/cli-parser": "^3.0.2",
+ "sebastian/code-unit": "^3.0.3",
+ "sebastian/comparator": "^6.3.3",
+ "sebastian/diff": "^6.0.2",
+ "sebastian/environment": "^7.2.1",
+ "sebastian/exporter": "^6.3.2",
+ "sebastian/global-state": "^7.0.2",
+ "sebastian/object-enumerator": "^6.0.1",
+ "sebastian/recursion-context": "^6.0.3",
+ "sebastian/type": "^5.1.3",
+ "sebastian/version": "^5.0.2",
+ "staabm/side-effects-detector": "^1.0.5"
+ },
+ "suggest": {
+ "ext-soap": "To be able to generate mocks based on WSDL files"
+ },
+ "bin": [
+ "phpunit"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "11.5-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/Framework/Assert/Functions.php"
+ ],
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "The PHP Unit Testing framework.",
+ "homepage": "https://phpunit.de/",
+ "keywords": [
+ "phpunit",
+ "testing",
+ "xunit"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/phpunit/issues",
+ "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.55"
+ },
+ "funding": [
+ {
+ "url": "https://phpunit.de/sponsors.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-02-18T12:37:06+00:00"
+ },
+ {
+ "name": "sebastian/cli-parser",
+ "version": "3.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/cli-parser.git",
+ "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180",
+ "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for parsing CLI options",
+ "homepage": "https://github.com/sebastianbergmann/cli-parser",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/cli-parser/issues",
+ "security": "https://github.com/sebastianbergmann/cli-parser/security/policy",
+ "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T04:41:36+00:00"
+ },
+ {
+ "name": "sebastian/code-unit",
+ "version": "3.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/code-unit.git",
+ "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64",
+ "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Collection of value objects that represent the PHP code units",
+ "homepage": "https://github.com/sebastianbergmann/code-unit",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/code-unit/issues",
+ "security": "https://github.com/sebastianbergmann/code-unit/security/policy",
+ "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2025-03-19T07:56:08+00:00"
+ },
+ {
+ "name": "sebastian/code-unit-reverse-lookup",
+ "version": "4.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
+ "reference": "183a9b2632194febd219bb9246eee421dad8d45e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e",
+ "reference": "183a9b2632194febd219bb9246eee421dad8d45e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Looks up which function or method a line of code belongs to",
+ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
+ "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy",
+ "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T04:45:54+00:00"
+ },
+ {
+ "name": "sebastian/comparator",
+ "version": "6.3.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/comparator.git",
+ "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2c95e1e86cb8dd41beb8d502057d1081ccc8eca9",
+ "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-mbstring": "*",
+ "php": ">=8.2",
+ "sebastian/diff": "^6.0",
+ "sebastian/exporter": "^6.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.4"
+ },
+ "suggest": {
+ "ext-bcmath": "For comparing BcMath\\Number objects"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.3-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@2bepublished.at"
+ }
+ ],
+ "description": "Provides the functionality to compare PHP values for equality",
+ "homepage": "https://github.com/sebastianbergmann/comparator",
+ "keywords": [
+ "comparator",
+ "compare",
+ "equality"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/comparator/issues",
+ "security": "https://github.com/sebastianbergmann/comparator/security/policy",
+ "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-01-24T09:26:40+00:00"
+ },
+ {
+ "name": "sebastian/complexity",
+ "version": "4.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/complexity.git",
+ "reference": "ee41d384ab1906c68852636b6de493846e13e5a0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0",
+ "reference": "ee41d384ab1906c68852636b6de493846e13e5a0",
+ "shasum": ""
+ },
+ "require": {
+ "nikic/php-parser": "^5.0",
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for calculating the complexity of PHP code units",
+ "homepage": "https://github.com/sebastianbergmann/complexity",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/complexity/issues",
+ "security": "https://github.com/sebastianbergmann/complexity/security/policy",
+ "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T04:49:50+00:00"
+ },
+ {
+ "name": "sebastian/diff",
+ "version": "6.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/diff.git",
+ "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544",
+ "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0",
+ "symfony/process": "^4.2 || ^5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Kore Nordmann",
+ "email": "mail@kore-nordmann.de"
+ }
+ ],
+ "description": "Diff implementation",
+ "homepage": "https://github.com/sebastianbergmann/diff",
+ "keywords": [
+ "diff",
+ "udiff",
+ "unidiff",
+ "unified diff"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/diff/issues",
+ "security": "https://github.com/sebastianbergmann/diff/security/policy",
+ "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T04:53:05+00:00"
+ },
+ {
+ "name": "sebastian/environment",
+ "version": "7.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/environment.git",
+ "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a5c75038693ad2e8d4b6c15ba2403532647830c4",
+ "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.3"
+ },
+ "suggest": {
+ "ext-posix": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "7.2-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Provides functionality to handle HHVM/PHP environments",
+ "homepage": "https://github.com/sebastianbergmann/environment",
+ "keywords": [
+ "Xdebug",
+ "environment",
+ "hhvm"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/environment/issues",
+ "security": "https://github.com/sebastianbergmann/environment/security/policy",
+ "source": "https://github.com/sebastianbergmann/environment/tree/7.2.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/environment",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-05-21T11:55:47+00:00"
+ },
+ {
+ "name": "sebastian/exporter",
+ "version": "6.3.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/exporter.git",
+ "reference": "70a298763b40b213ec087c51c739efcaa90bcd74"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/70a298763b40b213ec087c51c739efcaa90bcd74",
+ "reference": "70a298763b40b213ec087c51c739efcaa90bcd74",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*",
+ "php": ">=8.2",
+ "sebastian/recursion-context": "^6.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.3-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
+ }
+ ],
+ "description": "Provides the functionality to export PHP variables for visualization",
+ "homepage": "https://www.github.com/sebastianbergmann/exporter",
+ "keywords": [
+ "export",
+ "exporter"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/exporter/issues",
+ "security": "https://github.com/sebastianbergmann/exporter/security/policy",
+ "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-09-24T06:12:51+00:00"
+ },
+ {
+ "name": "sebastian/global-state",
+ "version": "7.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/global-state.git",
+ "reference": "3be331570a721f9a4b5917f4209773de17f747d7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7",
+ "reference": "3be331570a721f9a4b5917f4209773de17f747d7",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "sebastian/object-reflector": "^4.0",
+ "sebastian/recursion-context": "^6.0"
+ },
+ "require-dev": {
+ "ext-dom": "*",
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "7.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Snapshotting of global state",
+ "homepage": "https://www.github.com/sebastianbergmann/global-state",
+ "keywords": [
+ "global state"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/global-state/issues",
+ "security": "https://github.com/sebastianbergmann/global-state/security/policy",
+ "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T04:57:36+00:00"
+ },
+ {
+ "name": "sebastian/lines-of-code",
+ "version": "3.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/lines-of-code.git",
+ "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a",
+ "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a",
+ "shasum": ""
+ },
+ "require": {
+ "nikic/php-parser": "^5.0",
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for counting the lines of code in PHP source code",
+ "homepage": "https://github.com/sebastianbergmann/lines-of-code",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
+ "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy",
+ "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T04:58:38+00:00"
+ },
+ {
+ "name": "sebastian/object-enumerator",
+ "version": "6.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-enumerator.git",
+ "reference": "f5b498e631a74204185071eb41f33f38d64608aa"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa",
+ "reference": "f5b498e631a74204185071eb41f33f38d64608aa",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "sebastian/object-reflector": "^4.0",
+ "sebastian/recursion-context": "^6.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Traverses array structures and object graphs to enumerate all referenced objects",
+ "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
+ "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy",
+ "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T05:00:13+00:00"
+ },
+ {
+ "name": "sebastian/object-reflector",
+ "version": "4.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-reflector.git",
+ "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9",
+ "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Allows reflection of object attributes, including inherited and non-public ones",
+ "homepage": "https://github.com/sebastianbergmann/object-reflector/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/object-reflector/issues",
+ "security": "https://github.com/sebastianbergmann/object-reflector/security/policy",
+ "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T05:01:32+00:00"
+ },
+ {
+ "name": "sebastian/recursion-context",
+ "version": "6.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/recursion-context.git",
+ "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/f6458abbf32a6c8174f8f26261475dc133b3d9dc",
+ "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ }
+ ],
+ "description": "Provides functionality to recursively process PHP variables",
+ "homepage": "https://github.com/sebastianbergmann/recursion-context",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/recursion-context/issues",
+ "security": "https://github.com/sebastianbergmann/recursion-context/security/policy",
+ "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-08-13T04:42:22+00:00"
+ },
+ {
+ "name": "sebastian/type",
+ "version": "5.1.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/type.git",
+ "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/f77d2d4e78738c98d9a68d2596fe5e8fa380f449",
+ "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Collection of value objects that represent the types of the PHP type system",
+ "homepage": "https://github.com/sebastianbergmann/type",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/type/issues",
+ "security": "https://github.com/sebastianbergmann/type/security/policy",
+ "source": "https://github.com/sebastianbergmann/type/tree/5.1.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/type",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-08-09T06:55:48+00:00"
+ },
+ {
+ "name": "sebastian/version",
+ "version": "5.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/version.git",
+ "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874",
+ "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that helps with managing the version number of Git-hosted PHP projects",
+ "homepage": "https://github.com/sebastianbergmann/version",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/version/issues",
+ "security": "https://github.com/sebastianbergmann/version/security/policy",
+ "source": "https://github.com/sebastianbergmann/version/tree/5.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-10-09T05:16:32+00:00"
+ },
+ {
+ "name": "squizlabs/php_codesniffer",
+ "version": "3.13.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
+ "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0ca86845ce43291e8f5692c7356fccf3bcf02bf4",
+ "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4",
+ "shasum": ""
+ },
+ "require": {
+ "ext-simplexml": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlwriter": "*",
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4"
+ },
+ "bin": [
+ "bin/phpcbf",
+ "bin/phpcs"
+ ],
+ "type": "library",
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Greg Sherwood",
+ "role": "Former lead"
+ },
+ {
+ "name": "Juliette Reinders Folmer",
+ "role": "Current lead"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors"
+ }
+ ],
+ "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
+ "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
+ "keywords": [
+ "phpcs",
+ "standards",
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues",
+ "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy",
+ "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
+ "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/PHPCSStandards",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jrfnl",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/phpcsstandards",
+ "type": "thanks_dev"
+ }
+ ],
+ "time": "2025-11-04T16:30:35+00:00"
+ },
+ {
+ "name": "staabm/side-effects-detector",
+ "version": "1.0.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/staabm/side-effects-detector.git",
+ "reference": "d8334211a140ce329c13726d4a715adbddd0a163"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163",
+ "reference": "d8334211a140ce329c13726d4a715adbddd0a163",
+ "shasum": ""
+ },
+ "require": {
+ "ext-tokenizer": "*",
+ "php": "^7.4 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/extension-installer": "^1.4.3",
+ "phpstan/phpstan": "^1.12.6",
+ "phpunit/phpunit": "^9.6.21",
+ "symfony/var-dumper": "^5.4.43",
+ "tomasvotruba/type-coverage": "1.0.0",
+ "tomasvotruba/unused-public": "1.0.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "lib/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "A static analysis tool to detect side effects in PHP code",
+ "keywords": [
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/staabm/side-effects-detector/issues",
+ "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/staabm",
+ "type": "github"
+ }
+ ],
+ "time": "2024-10-20T05:08:20+00:00"
+ },
+ {
+ "name": "theseer/tokenizer",
+ "version": "1.3.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/theseer/tokenizer.git",
+ "reference": "b7489ce515e168639d17feec34b8847c326b0b3c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c",
+ "reference": "b7489ce515e168639d17feec34b8847c326b0b3c",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlwriter": "*",
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
+ "support": {
+ "issues": "https://github.com/theseer/tokenizer/issues",
+ "source": "https://github.com/theseer/tokenizer/tree/1.3.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/theseer",
+ "type": "github"
+ }
+ ],
+ "time": "2025-11-17T20:03:58+00:00"
+ },
+ {
+ "name": "wp-coding-standards/wpcs",
+ "version": "3.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/WordPress/WordPress-Coding-Standards.git",
+ "reference": "7795ec6fa05663d716a549d0b44e47ffc8b0d4a6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/7795ec6fa05663d716a549d0b44e47ffc8b0d4a6",
+ "reference": "7795ec6fa05663d716a549d0b44e47ffc8b0d4a6",
+ "shasum": ""
+ },
+ "require": {
+ "ext-filter": "*",
+ "ext-libxml": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlreader": "*",
+ "php": ">=7.2",
+ "phpcsstandards/phpcsextra": "^1.5.0",
+ "phpcsstandards/phpcsutils": "^1.1.0",
+ "squizlabs/php_codesniffer": "^3.13.4"
+ },
+ "require-dev": {
+ "php-parallel-lint/php-console-highlighter": "^1.0.0",
+ "php-parallel-lint/php-parallel-lint": "^1.4.0",
+ "phpcompatibility/php-compatibility": "^10.0.0@dev",
+ "phpcsstandards/phpcsdevtools": "^1.2.0",
+ "phpunit/phpunit": "^8.0 || ^9.0"
+ },
+ "suggest": {
+ "ext-iconv": "For improved results",
+ "ext-mbstring": "For improved results"
+ },
+ "type": "phpcodesniffer-standard",
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/WordPress/WordPress-Coding-Standards/graphs/contributors"
+ }
+ ],
+ "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress coding conventions",
+ "keywords": [
+ "phpcs",
+ "standards",
+ "static analysis",
+ "wordpress"
+ ],
+ "support": {
+ "issues": "https://github.com/WordPress/WordPress-Coding-Standards/issues",
+ "source": "https://github.com/WordPress/WordPress-Coding-Standards",
+ "wiki": "https://github.com/WordPress/WordPress-Coding-Standards/wiki"
+ },
+ "funding": [
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "custom"
+ }
+ ],
+ "time": "2025-11-25T12:08:04+00:00"
+ }
+ ],
+ "aliases": [],
+ "minimum-stability": "dev",
+ "stability-flags": {
+ "saltus/framework": 20
+ },
+ "prefer-stable": true,
+ "prefer-lowest": false,
+ "platform": {
+ "php": ">=8.3"
+ },
+ "platform-dev": {},
+ "plugin-api-version": "2.6.0"
+}
diff --git a/package-lock.json b/package-lock.json
deleted file mode 100644
index f4db8223..00000000
--- a/package-lock.json
+++ /dev/null
@@ -1,91 +0,0 @@
-{
- "requires": true,
- "lockfileVersion": 1,
- "dependencies": {
- "ansi-regex": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
- "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
- },
- "ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "requires": {
- "color-convert": "^1.9.0"
- }
- },
- "chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "requires": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- }
- },
- "color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "requires": {
- "color-name": "1.1.3"
- }
- },
- "color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
- },
- "escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
- },
- "grunt-shell": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/grunt-shell/-/grunt-shell-3.0.1.tgz",
- "integrity": "sha512-C8eR4frw/NmIFIwSvzSLS4wOQBUzC+z6QhrKPzwt/tlaIqlzH35i/O2MggVOBj2Sh1tbaAqpASWxGiGsi4JMIQ==",
- "requires": {
- "chalk": "^2.4.1",
- "npm-run-path": "^2.0.0",
- "strip-ansi": "^5.0.0"
- }
- },
- "has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
- },
- "npm-run-path": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
- "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
- "requires": {
- "path-key": "^2.0.0"
- }
- },
- "path-key": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
- "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
- "requires": {
- "ansi-regex": "^4.1.0"
- }
- },
- "supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "requires": {
- "has-flag": "^3.0.0"
- }
- }
- }
-}
diff --git a/phpcs.xml b/phpcs.xml
index d6215f1c..d52dcea4 100644
--- a/phpcs.xml
+++ b/phpcs.xml
@@ -8,6 +8,11 @@
Date: Sat, 20 Jun 2026 22:35:25 +0800
Subject: [PATCH 03/86] feature(renamer): introduce plugin rebranding engine
---
src/Plugin/Admin/RenamerPage.php | 148 +++++++++++++++++++
src/Plugin/Renamer/PluginIdentity.php | 118 +++++++++++++++
src/Plugin/Renamer/PluginRenamer.php | 158 +++++++++++++++++++++
src/Plugin/Renamer/ValidationException.php | 5 +
4 files changed, 429 insertions(+)
create mode 100644 src/Plugin/Admin/RenamerPage.php
create mode 100644 src/Plugin/Renamer/PluginIdentity.php
create mode 100644 src/Plugin/Renamer/PluginRenamer.php
create mode 100644 src/Plugin/Renamer/ValidationException.php
diff --git a/src/Plugin/Admin/RenamerPage.php b/src/Plugin/Admin/RenamerPage.php
new file mode 100644
index 00000000..91c14958
--- /dev/null
+++ b/src/Plugin/Admin/RenamerPage.php
@@ -0,0 +1,148 @@
+core = $core;
+ }
+
+ public function register(): void {
+ add_action( 'admin_menu', array( $this, 'add_page' ), 20 );
+ add_action( 'admin_post_framework_demo_generate_plugin', array( $this, 'generate_plugin' ) );
+ }
+
+ public function add_page(): void {
+ add_submenu_page(
+ 'framework-demo-settings',
+ __( 'Rename Plugin', 'framework-demo' ),
+ __( 'Rename Plugin', 'framework-demo' ),
+ 'manage_options',
+ self::PAGE_SLUG,
+ array( $this, 'render' )
+ );
+
+ add_submenu_page(
+ null,
+ __( 'Rename Plugin', 'framework-demo' ),
+ __( 'Rename Plugin', 'framework-demo' ),
+ 'manage_options',
+ self::PAGE_SLUG,
+ array( $this, 'render' )
+ );
+ }
+
+ public function render(): void {
+ if ( ! current_user_can( 'manage_options' ) ) {
+ wp_die( esc_html__( 'You do not have permission to access this page.', 'framework-demo' ) );
+ }
+
+ $defaults = PluginIdentity::defaults();
+ $error = isset( $_GET['framework_demo_error'] ) ? sanitize_text_field( wp_unslash( $_GET['framework_demo_error'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+ ?>
+ %s %s
Date: Sat, 20 Jun 2026 22:35:34 +0800
Subject: [PATCH 05/86] style(models): migrate from short to long array syntax
---
src/models/post-type-all.php | 175 ++++++++++++++++---------------
src/models/post-type-basic.php | 12 +--
src/models/taxonomy-multiple.php | 44 ++++----
3 files changed, 118 insertions(+), 113 deletions(-)
diff --git a/src/models/post-type-all.php b/src/models/post-type-all.php
index 528f5488..b5abc22b 100644
--- a/src/models/post-type-all.php
+++ b/src/models/post-type-all.php
@@ -1,10 +1,10 @@
true,
'type' => 'cpt',
'name' => 'book',
- 'features' => [
+ 'features' => array(
'dragAndDrop' => true,
'duplicate' => true,
'single_export' => true,
@@ -30,7 +30,7 @@
),
'shortcode' => array(
'title' => __( 'Shortcode', 'framework-demo' ),
- 'function' => function() {
+ 'function' => function () {
global $post;
echo esc_html( '[display-book id="' . $post->ID . '"]' );
},
@@ -44,8 +44,8 @@
'taxonomy' => 'writer',
),
),
- ],
- 'supports' => [
+ ),
+ 'supports' => array(
'title',
'author',
'excerpt',
@@ -53,16 +53,16 @@
'page-attributes',
'thumbnail',
'post-formats',
- ],
- 'labels' => [
+ ),
+ 'labels' => array(
'has_one' => 'Book',
'has_many' => 'Books',
'featured_image' => 'Book Cover',
'text_domain' => 'framework-demo',
// optional, but better for translation
- 'overrides' => [
- 'labels' => [
+ 'overrides' => array(
+ 'labels' => array(
'name' => __( 'Books', 'framework-demo' ),
'singular_name' => __( 'Book', 'framework-demo' ),
'menu_name' => __( 'Books', 'framework-demo' ),
@@ -82,10 +82,6 @@
'attributes' => __( 'Book Attributes', 'framework-demo' ),
'insert_into_item' => __( 'Insert into book', 'framework-demo' ),
'uploaded_to_this_item' => __( 'Uploaded to this book', 'framework-demo' ),
- 'featured_image' => __( 'Featured Image', 'framework-demo' ),
- 'set_featured_image' => __( 'Set featured image', 'framework-demo' ),
- 'remove_featured_image' => __( 'Remove featured image', 'framework-demo' ),
- 'use_featured_image' => __( 'Use featured image', 'framework-demo' ),
'filter_items_list' => __( 'Filter books list', 'framework-demo' ),
'items_list_navigation' => __( 'Books list navigation', 'framework-demo' ),
'items_list' => __( 'Books list', 'framework-demo' ),
@@ -93,9 +89,10 @@
'set_featured_image' => __( 'Set Book Cover Image', 'framework-demo' ),
'remove_featured_image' => __( 'Remove Book Cover', 'framework-demo' ),
'use_featured_image' => __( 'Use as Book Cover', 'framework-demo' ),
- ],
+ ),
// you can use the placeholders {permalink}, {preview_url}, {date}
- 'messages' => [
+ 'messages' => array(
+ /* translators: {permalink}: replaced by the book permalink. */
'post_updated' => __( 'Book information updated. View Book', 'framework-demo' ),
'post_updated_short' => __( 'Book info updated', 'framework-demo' ),
'custom_field_updated' => __( 'Custom field updated', 'framework-demo' ),
@@ -103,29 +100,37 @@
'restored_to_revision' => __( 'Book content restored from revision', 'framework-demo' ),
'post_published' => __( 'Book Published', 'framework-demo' ),
'post_saved' => __( 'Book information saved.', 'framework-demo' ),
+ /* translators: {preview_url}: replaced by the book preview URL. */
'post_submitted' => __( 'Book submitted. Preview', 'framework-demo' ),
+ /* translators: 1: {date}: scheduled publication date, 2: {preview_url}: replaced by the book preview URL. */
'post_schedulled' => __( 'Book scheduled for {date}. Preview', 'framework-demo' ),
+ /* translators: {preview_url}: replaced by the book preview URL. */
'post_draft_updated' => __( 'Book draft updated. Preview', 'framework-demo' ),
- ],
- 'bulk_messages' => [
+ ),
+ 'bulk_messages' => array(
'updated_singular' => __( 'Book updated. Yay!', 'framework-demo' ),
+ /* translators: %s: number of books updated. */
'updated_plural' => __( '%s Books updated. Yay!', 'framework-demo' ),
'locked_singular' => __( 'Book not updated, somebody is editing it', 'framework-demo' ),
+ /* translators: %s: number of books not updated because they are locked. */
'locked_plural' => __( '%s Books not updated, somebody is editing them', 'framework-demo' ),
'deleted_singular' => __( 'Book permanetly deleted. Fahrenheit 451 team was here?', 'framework-demo' ),
+ /* translators: %s: number of books permanently deleted. */
'deleted_plural' => __( '%s Books permanently deleted. Why? :(', 'framework-demo' ),
'trashed_singular' => __( 'Book moved to the trash. I\'m sad :(', 'framework-demo' ),
+ /* translators: %s: number of books moved to the trash. */
'trashed_plural' => __( '%s Books moved to the trash. Why? :(', 'framework-demo' ),
'untrashed_singular' => __( 'Book recovered from trash. Well done!', 'framework-demo' ),
+ /* translators: %s: number of books restored from the trash. */
'untrashed_plural' => __( '%s Books saved from the enemies!', 'framework-demo' ),
- ],
+ ),
// overrides some of the available button labels and placeholders
- 'ui' => [
+ 'ui' => array(
'enter_title_here' => __( 'Enter book name here', 'framework-demo' ),
- ],
- ],
- ],
- 'options' => [
+ ),
+ ),
+ ),
+ 'options' => array(
'public' => true,
'publicly_queryable' => true,
'show_in_rest' => true,
@@ -138,137 +143,137 @@
'can_export' => true,
'capability_type' => 'post',
'menu_icon' => 'dashicons-book',
- 'rewrite' => [
+ 'rewrite' => array(
'slug' => 'book',
'with_front' => true,
'feeds' => true,
'pages' => true,
- ],
- ],
+ ),
+ ),
'block_editor' => false,
- 'meta' => [
- 'ts_info' => [
+ 'meta' => array(
+ 'ts_info' => array(
'id' => 'information_metabox',
'title' => __( 'Information', 'framework-demo' ),
- 'sections' => [
- 'details' => [
+ 'sections' => array(
+ 'details' => array(
'title' => __( 'Details', 'framework-demo' ),
'desc' => __( 'Book details', 'framework-demo' ),
'icon' => 'fa fa-file-text-o',
- 'fields' => [
- 'paperback' => [
+ 'fields' => array(
+ 'paperback' => array(
'title' => __( 'Paperback', 'framework-demo' ),
'type' => 'text',
'desc' => __( 'Number of pages', 'framework-demo' ),
- ],
- 'isbn' => [
+ ),
+ 'isbn' => array(
'title' => __( 'ISBN', 'framework-demo' ),
'type' => 'text',
- ],
- 'desc' => [
+ ),
+ 'desc' => array(
'title' => __( 'Description', 'framework-demo' ),
'type' => 'textarea',
'desc' => __( 'Short description for this book', 'framework-demo' ),
- ],
- 'enabled' => [
+ ),
+ 'enabled' => array(
'type' => 'switcher',
'title' => __( 'Display more options', 'framework-demo' ),
'default' => false,
- ],
- 'icon' => [
+ ),
+ 'icon' => array(
'title' => __( 'Icon', 'framework-demo' ),
'type' => 'icon',
'desc' => __( 'Demo field', 'framework-demo' ),
'dependency' => array( 'enabled', '==', 'true' ),
- ],
- 'icon_color' => [
+ ),
+ 'icon_color' => array(
'title' => __( 'Icon Color', 'framework-demo' ),
'type' => 'color',
'desc' => __( 'Social network icon colour', 'framework-demo' ),
'dependency' => array( 'enabled', '==', 'true' ),
- ],
- ],
- ],
- 'gallery' => [
+ ),
+ ),
+ ),
+ 'gallery' => array(
'title' => __( 'Preview', 'framework-demo' ),
'icon' => 'fa fa-picture-o',
- 'fields' => [
- 'gallery' => [
+ 'fields' => array(
+ 'gallery' => array(
'title' => __( 'Gallery', 'framework-demo' ),
'type' => 'gallery',
'subtitle' => __( 'Images from the book.', 'framework-demo' ),
- ],
- ],
- ],
- 'notes' => [
+ ),
+ ),
+ ),
+ 'notes' => array(
'title' => __( 'Notes', 'framework-demo' ),
'desc' => __( 'Personal Notes', 'framework-demo' ),
'icon' => 'fa fa-sticky-note-o',
- 'fields' => [
- 'notes' => [
+ 'fields' => array(
+ 'notes' => array(
'title' => __( 'Notes', 'framework-demo' ),
'type' => 'wp_editor',
'subtitle' => __( 'Personal notes', 'framework-demo' ),
- ],
- ],
- ],
- ],
- ],
- ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
// settings page
- 'settings' => [
- 'framework-demo-settings' => [
+ 'settings' => array(
+ 'framework-demo-settings' => array(
'id' => 'framework-demo-settings',
'title' => __( 'Plugin Settings', 'framework-demo' ),
'capability' => 'manage_options',
'menu_title' => __( 'Settings', 'framework-demo' ),
- 'sections' => [
- 'general' => [
+ 'sections' => array(
+ 'general' => array(
'title' => __( 'General', 'framework-demo' ),
'desc' => __( 'Basic settings that affect the plugin behaviour', 'framework-demo' ),
'icon' => 'fa fa-cog fa-lg',
- 'fields' => [
- 'gen01' => [
+ 'fields' => array(
+ 'gen01' => array(
'type' => 'text',
'title' => __( 'Option 01', 'framework-demo' ),
'desc' => __( 'Description', 'framework-demo' ),
'default' => '',
- ],
+ ),
- 'gen02' => [
+ 'gen02' => array(
'title' => __( 'Option 02', 'framework-demo' ),
'desc' => __( 'description', 'framework-demo' ),
'subtitle' => __( 'subtitle', 'framework-demo' ),
'type' => 'textarea',
- ],
- 'gen04' => [
+ ),
+ 'gen04' => array(
'title' => __( 'Option 03', 'framework-demo' ),
'desc' => __( 'Description', 'framework-demo' ),
'type' => 'switcher',
- ],
- 'gen05' => [
+ ),
+ 'gen05' => array(
'title' => __( 'Checkbox', 'framework-demo' ),
'desc' => __( 'Description', 'framework-demo' ),
'type' => 'checkbox',
- ],
- ],
- ],
+ ),
+ ),
+ ),
- 'custom' => [
+ 'custom' => array(
'title' => __( 'CSS', 'framework-demo' ),
'desc' => __( 'Add custom styles to the pages loading the layouts.', 'framework-demo' ),
'icon' => 'fa fa-code fa-lg',
- 'fields' => [
- 'framework-demo_custom_css' => [
+ 'fields' => array(
+ 'framework-demo_custom_css' => array(
'title' => __( 'Custom CSS', 'framework-demo' ),
'desc' => __( 'Custom CSS to load with the layouts', 'framework-demo' ),
'type' => 'code_editor',
- ],
- ],
- ],
+ ),
+ ),
+ ),
- ],
- ],
- ],
-];
+ ),
+ ),
+ ),
+);
diff --git a/src/models/post-type-basic.php b/src/models/post-type-basic.php
index 15487625..48b2c0cc 100644
--- a/src/models/post-type-basic.php
+++ b/src/models/post-type-basic.php
@@ -1,17 +1,17 @@
'cpt',
'name' => 'movie',
- 'supports' => [
+ 'supports' => array(
'title',
'editor',
'thumbnail',
'page-attributes',
- ],
- 'labels' => [
+ ),
+ 'labels' => array(
'has_one' => 'Movie',
'has_many' => 'Movies',
'featured_image' => 'Movie Poster',
- ],
-];
+ ),
+);
diff --git a/src/models/taxonomy-multiple.php b/src/models/taxonomy-multiple.php
index 29477775..ee2b23a8 100644
--- a/src/models/taxonomy-multiple.php
+++ b/src/models/taxonomy-multiple.php
@@ -1,39 +1,39 @@
'category',
'name' => 'genre',
- 'associations' => [
+ 'associations' => array(
'book',
- ],
- ],
- [
+ ),
+ ),
+ array(
'type' => 'category',
'name' => 'writer',
'associations' => 'book',
- ],
- [
+ ),
+ array(
'type' => 'tag',
'name' => 'country',
- 'labels' => [
- 'has_one' => 'Country',
- 'has_many' => 'Countries',
- 'overrides' => [
- 'labels' => [
+ 'labels' => array(
+ 'has_one' => 'Country',
+ 'has_many' => 'Countries',
+ 'overrides' => array(
+ 'labels' => array(
'menu_name' => 'Places',
- ]
- ],
- ],
+ ),
+ ),
+ ),
// args - third parameter for register_taxonomy
- 'options' => [
+ 'options' => array(
'description' => 'Description for this taxonomy',
'public' => true,
'show_in_menu' => true,
- ],
+ ),
// object_type - second parameter for register_taxonomy
- 'associations' => [
+ 'associations' => array(
'book',
'post',
- ],
- ],
-];
+ ),
+ ),
+);
From 6f174652ebf13e346e9372fb40526144d65aab98 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sat, 20 Jun 2026 22:35:41 +0800
Subject: [PATCH 06/86] test(renamer): add unit tests for plugin rebranding
pipeline
---
tests/Plugin/Renamer/PluginIdentityTest.php | 44 +++++++++++
tests/Plugin/Renamer/PluginRenamerTest.php | 84 +++++++++++++++++++++
tests/bootstrap.php | 26 +++++++
3 files changed, 154 insertions(+)
create mode 100644 tests/Plugin/Renamer/PluginIdentityTest.php
create mode 100644 tests/Plugin/Renamer/PluginRenamerTest.php
create mode 100644 tests/bootstrap.php
diff --git a/tests/Plugin/Renamer/PluginIdentityTest.php b/tests/Plugin/Renamer/PluginIdentityTest.php
new file mode 100644
index 00000000..175a553e
--- /dev/null
+++ b/tests/Plugin/Renamer/PluginIdentityTest.php
@@ -0,0 +1,44 @@
+plugin_name );
+ self::assertSame( 'my-saltus-plugin', $identity->plugin_slug );
+ self::assertSame( 'MySaltusPlugin', $identity->namespace_segment );
+ }
+
+ public function test_invalid_slug_fails_validation(): void {
+ $data = PluginIdentity::defaults();
+ $data['plugin_slug'] = 'Bad Slug';
+
+ $this->expectException( ValidationException::class );
+
+ PluginIdentity::from_request( $data );
+ }
+
+ public function test_invalid_namespace_fails_validation(): void {
+ $data = PluginIdentity::defaults();
+ $data['namespace_segment'] = 'bad-plugin';
+
+ $this->expectException( ValidationException::class );
+
+ PluginIdentity::from_request( $data );
+ }
+
+ public function test_invalid_url_fails_validation(): void {
+ $data = PluginIdentity::defaults();
+ $data['plugin_uri'] = 'not a url';
+
+ $this->expectException( ValidationException::class );
+
+ PluginIdentity::from_request( $data );
+ }
+}
diff --git a/tests/Plugin/Renamer/PluginRenamerTest.php b/tests/Plugin/Renamer/PluginRenamerTest.php
new file mode 100644
index 00000000..e9505287
--- /dev/null
+++ b/tests/Plugin/Renamer/PluginRenamerTest.php
@@ -0,0 +1,84 @@
+make_source_fixture();
+ $output = tempnam( sys_get_temp_dir(), 'renamer-' );
+ $identity = PluginIdentity::from_request(
+ array_merge(
+ PluginIdentity::defaults(),
+ array(
+ 'plugin_name' => 'Acme Library',
+ 'plugin_slug' => 'acme-library',
+ 'main_file' => 'acme-library.php',
+ 'namespace_segment' => 'AcmeLibrary',
+ 'text_domain' => 'acme-library',
+ 'author' => 'Acme Inc',
+ 'prefix' => 'acme_library',
+ )
+ )
+ );
+
+ $renamer = new PluginRenamer( $source );
+ $renamer->build_zip( $identity, $output );
+
+ $zip = new ZipArchive();
+ self::assertTrue( true === $zip->open( $output ) );
+
+ self::assertNotFalse( $zip->locateName( 'acme-library/acme-library.php' ) );
+ self::assertFalse( $zip->locateName( 'acme-library/vendor/autoload.php' ) );
+ self::assertFalse( $zip->locateName( 'acme-library/build/Gruntfile.js' ) );
+
+ $contents = $zip->getFromName( 'acme-library/acme-library.php' );
+ self::assertIsString( $contents );
+ self::assertStringContainsString( 'Plugin Name: Acme Library', $contents );
+ self::assertStringContainsString( 'namespace Saltus\\WP\\Plugin\\Saltus\\AcmeLibrary;', $contents );
+ self::assertStringNotContainsString( 'framework-demo', $contents );
+
+ $zip->close();
+ @unlink( $output );
+ $this->remove_dir( $source );
+ }
+
+ private function make_source_fixture(): string {
+ $source = sys_get_temp_dir() . '/framework-demo-fixture-' . uniqid();
+ mkdir( $source . '/src', 0777, true );
+ mkdir( $source . '/vendor', 0777, true );
+ mkdir( $source . '/build', 0777, true );
+
+ file_put_contents(
+ $source . '/framework-demo.php',
+ "isDir() ) {
+ rmdir( $file->getPathname() );
+ continue;
+ }
+
+ unlink( $file->getPathname() );
+ }
+
+ rmdir( $dir );
+ }
+}
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
new file mode 100644
index 00000000..accb1694
--- /dev/null
+++ b/tests/bootstrap.php
@@ -0,0 +1,26 @@
+
Date: Sat, 20 Jun 2026 22:35:44 +0800
Subject: [PATCH 07/86] docs(readme): document modern Composer-based workflow
---
README.md | 82 +++++++++++++++++++++++++++++++++++++------------------
1 file changed, 56 insertions(+), 26 deletions(-)
diff --git a/README.md b/README.md
index 6ecfb112..2c04ed49 100644
--- a/README.md
+++ b/README.md
@@ -1,42 +1,72 @@
-This is the development repository of a demo plugin for WordPress built using the Saltus Framework for WordPress.
+# Saltus Framework Demo
-The following are needed to work with this project:
- 1. [Composer](https://getcomposer.org/) to manage PHP dependencies
- 2. [Node.js](https://nodejs.org/en/) to handle release tasks using [grunt](https://gruntjs.com/)
+This is a modern demo plugin for building WordPress plugins with the Saltus Framework.
-## How to use this Demo Plugin to create your own:
+It shows how to register custom post types, taxonomies, admin columns, filters, meta boxes, settings pages, assets, and translations using Saltus model configuration files.
-1. Download, fork or clone this repository
-2. Make the necessary name changes to the folder and main file ( framework-demo.php )
-3. Edit the header of the main file, so that the plugin has the proper information
-4. Replace the text domain used by the plugin ( You can do a find/replace for `‘framework-demo’` )
-5. Replace Namespace used (optional) ( You can do a find/replace for `PluginFrameworkDemo` for example)
-6. Optionally create a git repository for your project
+## Requirements
-## To start development:
+- PHP 8.3 or newer
+- WordPress with Composer-installed plugin dependencies
+- Composer 2
-1. Open the build folder in the terminal and run: `composer install` and `npm install`
-2. And now the fun part: edit the files in src/models to create your own model. Check [Saltus Framework Documentation](https://github.com/SaltusDev/saltus-framework) to understand how to use models.
+## Setup
-We are working on providing a more simple way to start using this demo for less experienced developers.
+From the plugin directory:
+```bash
+composer install
+```
-## Available Grunt Tasks
+Then activate **Saltus Framework Demo** in WordPress.
-All grunt tasks run inside the build folder.
+The demo models live in `src/models`:
-**Main Release Tasks:**
+- `post-type-basic.php` registers a small `movie` post type.
+- `post-type-all.php` registers the larger `book` demo, including meta fields and settings.
+- `taxonomy-multiple.php` registers demo taxonomies for books and posts.
+## Rename UI
-`grunt bump` - Will do a minor increase in the plugin version
+The plugin includes a generator UI for creating a renamed copy of the demo plugin.
+In wp-admin, open the plugin settings screen and choose **Rename Plugin**. Fill in the new plugin identity:
-`grunt release` - Runs multiple tasks to prepare your plugin for release, creating in the end a release folder and zip file inside the build/release folder. These files should be ready for distribution.
+- plugin name
+- slug and main file
+- namespace segment
+- text domain
+- description
+- author details
+- version
+- code prefix
+Submitting the form downloads a ZIP file for the renamed plugin. The installed demo plugin is not modified.
-**Other Development tasks:**
-`grunt bs` - browser sync
-`grunt i18n` - internationalization
-`grunt build` - compiles files
-`grunt dev` - compiles files
-`grunt prod` - compiles files
+## Development Commands
+
+```bash
+composer validate --strict
+vendor/bin/phpcs
+vendor/bin/phpunit
+composer package
+```
+
+`composer package` creates `dist/framework-demo.zip`.
+
+`composer make-pot` uses WP-CLI to rebuild `languages/framework-demo.pot` when WP-CLI is available.
+
+## Releasing
+
+Build the release ZIP with:
+
+```bash
+composer install --no-dev --optimize-autoloader
+composer package
+```
+
+The package script excludes development-only directories such as `.git`, `node_modules`, `build`, `dist`, `release`, and reports.
+
+## Notes
+
+This repository is intentionally a demo and starter. Keep the Saltus model files that help explain framework capabilities, and delete or rename demo models when generating a production plugin.
From 3e3d332f57725fdb04fded6bc6f1a66dae1c86c9 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sat, 20 Jun 2026 23:28:08 +0800
Subject: [PATCH 08/86] refactor(core): Remove framework dependency from Core
constructor
The Core class no longer needs the Saltus Framework reference. The framework is still instantiated and registered at the plugin level, but is no longer passed into Core. The unused unset() call in the constructor is removed.
---
framework-demo.php | 4 ++--
src/Core.php | 4 +---
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/framework-demo.php b/framework-demo.php
index 1c8b73a2..2cf6ae0d 100644
--- a/framework-demo.php
+++ b/framework-demo.php
@@ -88,8 +88,8 @@ static function (): void {
add_action(
'plugins_loaded',
- static function () use ( $framework ): void {
- $plugin = new Core( PLUGIN_SLUG, PLUGIN_VERSION, PLUGIN_FILE, $framework );
+ static function (): void {
+ $plugin = new Core( PLUGIN_SLUG, PLUGIN_VERSION, PLUGIN_FILE );
$plugin->init();
}
);
diff --git a/src/Core.php b/src/Core.php
index 8078b951..9c83b2e7 100644
--- a/src/Core.php
+++ b/src/Core.php
@@ -32,13 +32,11 @@ class Core {
* @param string $name Plugin name.
* @param string $version Plugin version. Use semver.
* @param string $file_path Plugin file path
- * @param \Saltus\WP\Framework\Core $framework Saltus Framework.
*/
- public function __construct( string $name, string $version, string $file_path, \Saltus\WP\Framework\Core $framework ) {
+ public function __construct( string $name, string $version, string $file_path ) {
$this->name = $name;
$this->version = $version;
$this->file_path = $file_path;
- unset( $framework );
}
/**
From 409d5e04fda907afa7629497c2beb6c3bf5c694f Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sat, 20 Jun 2026 23:28:51 +0800
Subject: [PATCH 09/86] fix(renamer): Clean output buffers before ZIP download
Clear all output buffers before sending ZIP headers to prevent "headers already sent" errors.
---
src/Plugin/Renamer/PluginRenamer.php | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/Plugin/Renamer/PluginRenamer.php b/src/Plugin/Renamer/PluginRenamer.php
index 9183eea6..fd744958 100644
--- a/src/Plugin/Renamer/PluginRenamer.php
+++ b/src/Plugin/Renamer/PluginRenamer.php
@@ -26,6 +26,10 @@ public function __construct( string $source_dir ) {
}
public function stream_zip( PluginIdentity $identity ): void {
+ while ( ob_get_level() ) {
+ ob_end_clean();
+ }
+
$tmp_file = wp_tempnam( $identity->plugin_slug . '.zip' );
if ( false === $tmp_file ) {
throw new \RuntimeException( 'Could not create a temporary ZIP file.' );
@@ -140,6 +144,7 @@ private function rewrite_contents( string $contents, PluginIdentity $identity ):
'Author URI: ' . self::ORIGINAL_AUTHOR_URI => 'Author URI: ' . $identity->author_uri,
'Author: ' . self::ORIGINAL_AUTHOR => 'Author: ' . $identity->author,
self::ORIGINAL_SLUG => $identity->plugin_slug,
+ "PLUGIN_VERSION', '" . self::ORIGINAL_VERSION . "'" => "PLUGIN_VERSION', '" . $identity->version . "'",
self::ORIGINAL_VERSION => $identity->version,
);
From d30e8e9435a1be35f40d7689a313e73ca255b62d Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sat, 20 Jun 2026 23:28:59 +0800
Subject: [PATCH 10/86] fix(renamer): Preserve uppercase letters in package
name conversion
The regex now allows uppercase letters to pass through before strtolower() runs. Previously, uppercase letters in author names were replaced with dashes, producing incorrect package name segments.
---
src/Plugin/Renamer/PluginRenamer.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Plugin/Renamer/PluginRenamer.php b/src/Plugin/Renamer/PluginRenamer.php
index fd744958..44a3bce3 100644
--- a/src/Plugin/Renamer/PluginRenamer.php
+++ b/src/Plugin/Renamer/PluginRenamer.php
@@ -152,7 +152,7 @@ private function rewrite_contents( string $contents, PluginIdentity $identity ):
}
private function package_name( PluginIdentity $identity ): string {
- return strtolower( preg_replace( '/[^a-z0-9-]+/', '-', $identity->author ) ) . '/' . $identity->plugin_slug;
+ return strtolower( preg_replace( '/[^a-zA-Z0-9-]+/', '-', $identity->author ) ) . '/' . $identity->plugin_slug;
}
private function delete_file( string $path ): void {
From 567f7c33db32463bea242ed79745a6f379e0c4ac Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sat, 20 Jun 2026 23:29:54 +0800
Subject: [PATCH 11/86] test(renamer): Add test for PLUGIN_VERSION constant
replacement
Verify that the renamer correctly replaces the PLUGIN_VERSION value in the main plugin file when a custom version is provided.
---
tests/Plugin/Renamer/PluginRenamerTest.php | 37 +++++++++++++++++++++-
1 file changed, 36 insertions(+), 1 deletion(-)
diff --git a/tests/Plugin/Renamer/PluginRenamerTest.php b/tests/Plugin/Renamer/PluginRenamerTest.php
index e9505287..cb41afbf 100644
--- a/tests/Plugin/Renamer/PluginRenamerTest.php
+++ b/tests/Plugin/Renamer/PluginRenamerTest.php
@@ -47,6 +47,41 @@ public function test_build_zip_creates_renamed_plugin_package(): void {
$this->remove_dir( $source );
}
+ public function test_build_zip_replaces_plugin_version_constant(): void {
+ $source = $this->make_source_fixture();
+ $output = tempnam( sys_get_temp_dir(), 'renamer-' );
+ $identity = PluginIdentity::from_request(
+ array_merge(
+ PluginIdentity::defaults(),
+ array(
+ 'plugin_name' => 'Acme Library',
+ 'plugin_slug' => 'acme-library',
+ 'main_file' => 'acme-library.php',
+ 'namespace_segment' => 'AcmeLibrary',
+ 'text_domain' => 'acme-library',
+ 'author' => 'Acme Inc',
+ 'prefix' => 'acme_library',
+ 'version' => '1.5.0',
+ )
+ )
+ );
+
+ $renamer = new PluginRenamer( $source );
+ $renamer->build_zip( $identity, $output );
+
+ $zip = new ZipArchive();
+ self::assertTrue( true === $zip->open( $output ) );
+
+ $contents = $zip->getFromName( 'acme-library/acme-library.php' );
+ self::assertIsString( $contents );
+ self::assertStringContainsString( "PLUGIN_VERSION', '1.5.0'", $contents );
+ self::assertStringNotContainsString( "PLUGIN_VERSION', '2.0.0'", $contents );
+
+ $zip->close();
+ @unlink( $output );
+ $this->remove_dir( $source );
+ }
+
private function make_source_fixture(): string {
$source = sys_get_temp_dir() . '/framework-demo-fixture-' . uniqid();
mkdir( $source . '/src', 0777, true );
@@ -55,7 +90,7 @@ private function make_source_fixture(): string {
file_put_contents(
$source . '/framework-demo.php',
- "
Date: Sat, 20 Jun 2026 23:30:14 +0800
Subject: [PATCH 12/86] test(renamer): Add test for package name replacement
Verify the renamer correctly rewrites the composer.json package name from saltus/framework-demo to the target author/slug combination. The test uses a mixed-case author name (Acme Inc) to verify the updated regex preserves uppercase letters before strtolower conversion.
---
tests/Plugin/Renamer/PluginRenamerTest.php | 44 +++++++++++++++++++++-
1 file changed, 43 insertions(+), 1 deletion(-)
diff --git a/tests/Plugin/Renamer/PluginRenamerTest.php b/tests/Plugin/Renamer/PluginRenamerTest.php
index cb41afbf..67249dc4 100644
--- a/tests/Plugin/Renamer/PluginRenamerTest.php
+++ b/tests/Plugin/Renamer/PluginRenamerTest.php
@@ -82,7 +82,42 @@ public function test_build_zip_replaces_plugin_version_constant(): void {
$this->remove_dir( $source );
}
- private function make_source_fixture(): string {
+ public function test_build_zip_replaces_package_name(): void {
+ $source = $this->make_source_fixture( true );
+ $output = tempnam( sys_get_temp_dir(), 'renamer-' );
+ $identity = PluginIdentity::from_request(
+ array_merge(
+ PluginIdentity::defaults(),
+ array(
+ 'plugin_name' => 'Acme Library',
+ 'plugin_slug' => 'acme-library',
+ 'main_file' => 'acme-library.php',
+ 'namespace_segment' => 'AcmeLibrary',
+ 'text_domain' => 'acme-library',
+ 'author' => 'Acme Inc',
+ 'prefix' => 'acme_library',
+ )
+ )
+ );
+
+ $renamer = new PluginRenamer( $source );
+ $renamer->build_zip( $identity, $output );
+
+ $zip = new ZipArchive();
+ self::assertTrue( true === $zip->open( $output ) );
+
+ self::assertNotFalse( $zip->locateName( 'acme-library/composer.json' ) );
+ $contents = $zip->getFromName( 'acme-library/composer.json' );
+ self::assertIsString( $contents );
+ self::assertStringContainsString( '"name": "acme-inc/acme-library"', $contents );
+ self::assertStringNotContainsString( 'saltus/framework-demo', $contents );
+
+ $zip->close();
+ @unlink( $output );
+ $this->remove_dir( $source );
+ }
+
+ private function make_source_fixture( bool $with_composer = false ): string {
$source = sys_get_temp_dir() . '/framework-demo-fixture-' . uniqid();
mkdir( $source . '/src', 0777, true );
mkdir( $source . '/vendor', 0777, true );
@@ -96,6 +131,13 @@ private function make_source_fixture(): string {
file_put_contents( $source . '/vendor/autoload.php', '
Date: Sun, 21 Jun 2026 10:06:00 +0800
Subject: [PATCH 13/86] Optimizations
---
src/Plugin/Admin/RenamerPage.php | 11 +----------
src/Plugin/Renamer/PluginRenamer.php | 8 +++++++-
2 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/src/Plugin/Admin/RenamerPage.php b/src/Plugin/Admin/RenamerPage.php
index 91c14958..3a7735a4 100644
--- a/src/Plugin/Admin/RenamerPage.php
+++ b/src/Plugin/Admin/RenamerPage.php
@@ -35,15 +35,6 @@ public function add_page(): void {
self::PAGE_SLUG,
array( $this, 'render' )
);
-
- add_submenu_page(
- null,
- __( 'Rename Plugin', 'framework-demo' ),
- __( 'Rename Plugin', 'framework-demo' ),
- 'manage_options',
- self::PAGE_SLUG,
- array( $this, 'render' )
- );
}
public function render(): void {
@@ -96,7 +87,7 @@ public function generate_plugin(): void {
check_admin_referer( self::NONCE_ACTION, self::NONCE_NAME );
try {
- $post_data = array_map( 'wp_unslash', $_POST );
+ $post_data = wp_unslash( $_POST );
$identity = PluginIdentity::from_request( $post_data );
$renamer = new PluginRenamer( $this->core->get_dir_path() );
$renamer->stream_zip( $identity );
diff --git a/src/Plugin/Renamer/PluginRenamer.php b/src/Plugin/Renamer/PluginRenamer.php
index 44a3bce3..33890fb5 100644
--- a/src/Plugin/Renamer/PluginRenamer.php
+++ b/src/Plugin/Renamer/PluginRenamer.php
@@ -31,10 +31,16 @@ public function stream_zip( PluginIdentity $identity ): void {
}
$tmp_file = wp_tempnam( $identity->plugin_slug . '.zip' );
- if ( false === $tmp_file ) {
+ if ( '' === $tmp_file ) {
throw new \RuntimeException( 'Could not create a temporary ZIP file.' );
}
+ register_shutdown_function( function () use ( $tmp_file ): void {
+ if ( is_file( $tmp_file ) ) {
+ unlink( $tmp_file ); // phpcs:ignore WordPress.WP.AlternativeFunctions
+ }
+ } );
+
$this->build_zip( $identity, $tmp_file );
if ( headers_sent() ) {
From b0091059a04f4aae56191d8fd4f17def30d66f61 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sun, 21 Jun 2026 17:25:07 +0800
Subject: [PATCH 14/86] fix(renamer): guard GET param against array input
Check that $_GET['framework_demo_error'] is a string before
passing it to sanitize_text_field(), which expects a string.
A malicious array parameter would otherwise trigger PHP warnings.
---
src/Plugin/Admin/RenamerPage.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Plugin/Admin/RenamerPage.php b/src/Plugin/Admin/RenamerPage.php
index 3a7735a4..c96caa48 100644
--- a/src/Plugin/Admin/RenamerPage.php
+++ b/src/Plugin/Admin/RenamerPage.php
@@ -43,7 +43,7 @@ public function render(): void {
}
$defaults = PluginIdentity::defaults();
- $error = isset( $_GET['framework_demo_error'] ) ? sanitize_text_field( wp_unslash( $_GET['framework_demo_error'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+ $error = isset( $_GET['framework_demo_error'] ) && is_string( $_GET['framework_demo_error'] ) ? sanitize_text_field( wp_unslash( $_GET['framework_demo_error'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
?>
Date: Sun, 21 Jun 2026 17:25:14 +0800
Subject: [PATCH 15/86] fix(renamer): validate URLs before esc_url_raw
sanitization
Run validation before esc_url_raw() to catch invalid URLs
before they are silently converted to empty strings.
Wrap validation error messages in __() for i18n support.
---
src/Plugin/Renamer/PluginIdentity.php | 19 ++++++++++++-------
1 file changed, 12 insertions(+), 7 deletions(-)
diff --git a/src/Plugin/Renamer/PluginIdentity.php b/src/Plugin/Renamer/PluginIdentity.php
index bf13f466..b79fdf54 100644
--- a/src/Plugin/Renamer/PluginIdentity.php
+++ b/src/Plugin/Renamer/PluginIdentity.php
@@ -65,6 +65,11 @@ public static function from_request( array $request ): self {
$data[ $key ] = sanitize_text_field( $value );
}
+ $data['author_uri'] = trim( $data['author_uri'] );
+ $data['plugin_uri'] = trim( $data['plugin_uri'] );
+
+ self::validate( $data );
+
$data['author_uri'] = esc_url_raw( $data['author_uri'] );
$data['plugin_uri'] = esc_url_raw( $data['plugin_uri'] );
@@ -81,33 +86,33 @@ private static function validate( array $data ): void {
foreach ( $required as $field ) {
if ( '' === trim( $data[ $field ] ) ) {
- throw new ValidationException( sprintf( '%s is required.', self::label( $field ) ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
+ throw new ValidationException( sprintf( __( '%s is required.', 'framework-demo' ), self::label( $field ) ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
}
if ( ! preg_match( '/^[a-z0-9]+(?:-[a-z0-9]+)*$/', $data['plugin_slug'] ) ) {
- throw new ValidationException( 'Plugin slug must contain only lowercase letters, numbers, and single dashes.' );
+ throw new ValidationException( __( 'Plugin slug must contain only lowercase letters, numbers, and single dashes.', 'framework-demo' ) );
}
if ( ! preg_match( '/^[a-z0-9]+(?:-[a-z0-9]+)*\.php$/', $data['main_file'] ) ) {
- throw new ValidationException( 'Main plugin file must be a lowercase dash-safe PHP filename.' );
+ throw new ValidationException( __( 'Main plugin file must be a lowercase dash-safe PHP filename.', 'framework-demo' ) );
}
if ( ! preg_match( '/^[A-Z][A-Za-z0-9]*$/', $data['namespace_segment'] ) ) {
- throw new ValidationException( 'Namespace segment must be a valid PHP namespace segment, such as MyPlugin.' );
+ throw new ValidationException( __( 'Namespace segment must be a valid PHP namespace segment, such as MyPlugin.', 'framework-demo' ) );
}
if ( ! preg_match( '/^[a-z0-9]+(?:-[a-z0-9]+)*$/', $data['text_domain'] ) ) {
- throw new ValidationException( 'Text domain must contain only lowercase letters, numbers, and single dashes.' );
+ throw new ValidationException( __( 'Text domain must contain only lowercase letters, numbers, and single dashes.', 'framework-demo' ) );
}
if ( ! preg_match( '/^[a-z][a-z0-9_]*$/', $data['prefix'] ) ) {
- throw new ValidationException( 'Code prefix must contain only lowercase letters, numbers, and underscores, and start with a letter.' );
+ throw new ValidationException( __( 'Code prefix must contain only lowercase letters, numbers, and underscores, and start with a letter.', 'framework-demo' ) );
}
foreach ( array( 'author_uri', 'plugin_uri' ) as $url_field ) {
if ( '' !== $data[ $url_field ] && false === filter_var( $data[ $url_field ], FILTER_VALIDATE_URL ) ) {
- throw new ValidationException( sprintf( '%s must be a valid URL or empty.', self::label( $url_field ) ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
+ throw new ValidationException( sprintf( __( '%s must be a valid URL or empty.', 'framework-demo' ), self::label( $url_field ) ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
}
}
From 786796b9ba02e44c18a1d816ea432921213058f6 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sun, 21 Jun 2026 17:25:17 +0800
Subject: [PATCH 16/86] fix(renamer): check ZipArchive return values for errors
ZipArchive::close() and addFromString() return false on
failure without throwing exceptions. Check their return
values and throw RuntimeException on failure to prevent
silently generating incomplete or corrupted ZIP files.
---
src/Plugin/Renamer/PluginRenamer.php | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/Plugin/Renamer/PluginRenamer.php b/src/Plugin/Renamer/PluginRenamer.php
index 33890fb5..a1bc50bb 100644
--- a/src/Plugin/Renamer/PluginRenamer.php
+++ b/src/Plugin/Renamer/PluginRenamer.php
@@ -70,7 +70,9 @@ public function build_zip( PluginIdentity $identity, string $destination ): void
}
$this->add_files( $zip, $identity );
- $zip->close();
+ if ( ! $zip->close() ) {
+ throw new \RuntimeException( 'Failed to write the ZIP file to disk.' );
+ }
}
private function add_files( \ZipArchive $zip, PluginIdentity $identity ): void {
@@ -101,7 +103,9 @@ private function add_files( \ZipArchive $zip, PluginIdentity $identity ): void {
$contents = $this->rewrite_contents( $contents, $identity );
}
- $zip->addFromString( $identity->plugin_slug . '/' . $target_path, $contents );
+ if ( ! $zip->addFromString( $identity->plugin_slug . '/' . $target_path, $contents ) ) {
+ throw new \RuntimeException( 'Failed to add ' . $relative_path . ' to the ZIP archive.' );
+ }
}
}
From 8c39c713b876bf0261b4b4052be0fd206ca55477 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sun, 21 Jun 2026 17:25:23 +0800
Subject: [PATCH 17/86] test(renamer): restore bootstrap stubs
Restore WordPress function stubs removed in prior cleanup.
Make esc_url_raw return empty string for invalid URLs
to match real WordPress behavior.
---
tests/bootstrap.php | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index accb1694..b95f801f 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -9,7 +9,17 @@ function sanitize_text_field( $value ) {
if ( ! function_exists( 'esc_url_raw' ) ) {
function esc_url_raw( $value ) {
- return trim( (string) $value );
+ $value = trim( (string) $value );
+ if ( false === filter_var( $value, FILTER_VALIDATE_URL ) ) {
+ return '';
+ }
+ return $value;
+ }
+}
+
+if ( ! function_exists( '__' ) ) {
+ function __( $text, $domain = '' ) {
+ return $text;
}
}
@@ -24,3 +34,4 @@ function sanitize_file_name( $filename ) {
return preg_replace( '/[^A-Za-z0-9_.-]/', '-', (string) $filename );
}
}
+
From a371a48d616ab225520a215d486822fe49e72492 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sun, 21 Jun 2026 18:26:32 +0800
Subject: [PATCH 18/86] Update phpcs
---
phpcs.xml | 119 ++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 89 insertions(+), 30 deletions(-)
diff --git a/phpcs.xml b/phpcs.xml
index d52dcea4..d2131d69 100644
--- a/phpcs.xml
+++ b/phpcs.xml
@@ -1,32 +1,91 @@
Date: Sun, 21 Jun 2026 18:26:51 +0800
Subject: [PATCH 19/86] Pass error msg by transient
---
src/Plugin/Admin/RenamerPage.php | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/src/Plugin/Admin/RenamerPage.php b/src/Plugin/Admin/RenamerPage.php
index c96caa48..f561fd1e 100644
--- a/src/Plugin/Admin/RenamerPage.php
+++ b/src/Plugin/Admin/RenamerPage.php
@@ -38,20 +38,28 @@ public function add_page(): void {
}
public function render(): void {
+ if (
+ empty( $_GET['framework_demo_nonce'] ) ||
+ ! wp_verify_nonce( $_GET['framework_demo_nonce'], 'framework_demo_error_redirect' )
+ ) {
+ return;
+ }
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'You do not have permission to access this page.', 'framework-demo' ) );
}
- $defaults = PluginIdentity::defaults();
- $error = isset( $_GET['framework_demo_error'] ) && is_string( $_GET['framework_demo_error'] ) ? sanitize_text_field( wp_unslash( $_GET['framework_demo_error'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+ $defaults = PluginIdentity::defaults();
+ $error_key = sanitize_text_field( $_GET['framework_demo_error'] ?? '' );
+ $error_message = get_transient( 'framework_demo_error_' . $error_key );
+ delete_transient( 'framework_demo_error_' . $error_key );
?>
Date: Sun, 21 Jun 2026 18:33:04 +0800
Subject: [PATCH 20/86] Include saltus by packagist
---
composer.json | 9 +-
composer.lock | 242 +++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 223 insertions(+), 28 deletions(-)
diff --git a/composer.json b/composer.json
index 82bb7632..0c9445e8 100644
--- a/composer.json
+++ b/composer.json
@@ -21,19 +21,16 @@
{
"type": "composer",
"url": "https://wpackagist.org"
- },
- {
- "type": "vcs",
- "url": "https://github.com/SaltusDev/saltus-framework.git"
}
],
"require": {
"php": ">=8.3",
- "saltus/framework": "dev-main"
+ "saltus/framework": "^1.3"
},
"require-dev": {
"phpunit/phpunit": "^11.0",
- "wp-coding-standards/wpcs": "^3.1",
+ "wp-coding-standards/wpcs": "^3.3",
+ "phpcompatibility/phpcompatibility-wp": "*",
"dealerdirect/phpcodesniffer-composer-installer": "^1.0"
},
"autoload": {
diff --git a/composer.lock b/composer.lock
index 0da33116..6da9c51c 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "136628a128f86379ce50be2b78f37700",
+ "content-hash": "93e61bdbf87e6f44fded6a2612e71654",
"packages": [
{
"name": "hassankhan/config",
@@ -70,7 +70,7 @@
},
{
"name": "saltus/framework",
- "version": "dev-main",
+ "version": "v1.3.5",
"source": {
"type": "git",
"url": "https://github.com/SaltusDev/saltus-framework.git",
@@ -99,7 +99,6 @@
"wp-coding-standards/wpcs": "^3.1",
"yoast/phpunit-polyfills": "^4.0"
},
- "default-branch": true,
"type": "library",
"autoload": {
"psr-4": {
@@ -109,19 +108,7 @@
"lib/codestar-framework/"
]
},
- "autoload-dev": {
- "psr-4": {
- "Saltus\\WP\\Framework\\Tests\\": "tests/"
- }
- },
- "scripts": {
- "phpstan": [
- "./vendor/bin/phpstan analyse --memory-limit=2G"
- ],
- "phpcs": [
- "./vendor/bin/phpcs --standard=phpcs.xml"
- ]
- },
+ "notification-url": "https://packagist.org/downloads/",
"license": [
"GPL-3.0-only"
],
@@ -135,18 +122,18 @@
"description": "A WordPress framework for building plugins around custom post types, taxonomies, meta boxes, settings pages, and admin tooling.",
"homepage": "https://saltus.dev/",
"keywords": [
+ "Settings",
"admin",
"custom-post-types",
"framework",
"meta-boxes",
- "settings",
"taxonomies",
"wordpress"
],
"support": {
- "source": "https://github.com/SaltusDev/saltus-framework",
+ "docs": "https://github.com/SaltusDev/saltus-framework/wiki",
"issues": "https://github.com/SaltusDev/saltus-framework/issues",
- "docs": "https://github.com/SaltusDev/saltus-framework/wiki"
+ "source": "https://github.com/SaltusDev/saltus-framework"
},
"time": "2026-06-20T06:01:09+00:00"
}
@@ -484,6 +471,219 @@
},
"time": "2022-02-21T01:04:05+00:00"
},
+ {
+ "name": "phpcompatibility/php-compatibility",
+ "version": "9.3.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCompatibility/PHPCompatibility.git",
+ "reference": "9fb324479acf6f39452e0655d2429cc0d3914243"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9fb324479acf6f39452e0655d2429cc0d3914243",
+ "reference": "9fb324479acf6f39452e0655d2429cc0d3914243",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3",
+ "squizlabs/php_codesniffer": "^2.3 || ^3.0.2"
+ },
+ "conflict": {
+ "squizlabs/php_codesniffer": "2.6.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0"
+ },
+ "suggest": {
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.",
+ "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues."
+ },
+ "type": "phpcodesniffer-standard",
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL-3.0-or-later"
+ ],
+ "authors": [
+ {
+ "name": "Wim Godden",
+ "homepage": "https://github.com/wimg",
+ "role": "lead"
+ },
+ {
+ "name": "Juliette Reinders Folmer",
+ "homepage": "https://github.com/jrfnl",
+ "role": "lead"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors"
+ }
+ ],
+ "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.",
+ "homepage": "http://techblog.wimgodden.be/tag/codesniffer/",
+ "keywords": [
+ "compatibility",
+ "phpcs",
+ "standards"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues",
+ "source": "https://github.com/PHPCompatibility/PHPCompatibility"
+ },
+ "time": "2019-12-27T09:44:58+00:00"
+ },
+ {
+ "name": "phpcompatibility/phpcompatibility-paragonie",
+ "version": "1.3.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git",
+ "reference": "244d7b04fc4bc2117c15f5abe23eb933b5f02bbf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/244d7b04fc4bc2117c15f5abe23eb933b5f02bbf",
+ "reference": "244d7b04fc4bc2117c15f5abe23eb933b5f02bbf",
+ "shasum": ""
+ },
+ "require": {
+ "phpcompatibility/php-compatibility": "^9.0"
+ },
+ "require-dev": {
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
+ "paragonie/random_compat": "dev-master",
+ "paragonie/sodium_compat": "dev-master"
+ },
+ "suggest": {
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.",
+ "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues."
+ },
+ "type": "phpcodesniffer-standard",
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL-3.0-or-later"
+ ],
+ "authors": [
+ {
+ "name": "Wim Godden",
+ "role": "lead"
+ },
+ {
+ "name": "Juliette Reinders Folmer",
+ "role": "lead"
+ }
+ ],
+ "description": "A set of rulesets for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by the Paragonie polyfill libraries.",
+ "homepage": "http://phpcompatibility.com/",
+ "keywords": [
+ "compatibility",
+ "paragonie",
+ "phpcs",
+ "polyfill",
+ "standards",
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues",
+ "security": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/security/policy",
+ "source": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/PHPCompatibility",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jrfnl",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/phpcompatibility",
+ "type": "thanks_dev"
+ }
+ ],
+ "time": "2025-09-19T17:43:28+00:00"
+ },
+ {
+ "name": "phpcompatibility/phpcompatibility-wp",
+ "version": "2.1.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git",
+ "reference": "7c8d18b4d90dac9e86b0869a608fa09158e168fa"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/7c8d18b4d90dac9e86b0869a608fa09158e168fa",
+ "reference": "7c8d18b4d90dac9e86b0869a608fa09158e168fa",
+ "shasum": ""
+ },
+ "require": {
+ "phpcompatibility/php-compatibility": "^9.0",
+ "phpcompatibility/phpcompatibility-paragonie": "^1.0",
+ "squizlabs/php_codesniffer": "^3.3"
+ },
+ "require-dev": {
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0"
+ },
+ "suggest": {
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.",
+ "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues."
+ },
+ "type": "phpcodesniffer-standard",
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL-3.0-or-later"
+ ],
+ "authors": [
+ {
+ "name": "Wim Godden",
+ "role": "lead"
+ },
+ {
+ "name": "Juliette Reinders Folmer",
+ "role": "lead"
+ }
+ ],
+ "description": "A ruleset for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by WordPress.",
+ "homepage": "http://phpcompatibility.com/",
+ "keywords": [
+ "compatibility",
+ "phpcs",
+ "standards",
+ "static analysis",
+ "wordpress"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues",
+ "security": "https://github.com/PHPCompatibility/PHPCompatibilityWP/security/policy",
+ "source": "https://github.com/PHPCompatibility/PHPCompatibilityWP"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/PHPCompatibility",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jrfnl",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/phpcompatibility",
+ "type": "thanks_dev"
+ }
+ ],
+ "time": "2025-10-18T00:05:59+00:00"
+ },
{
"name": "phpcsstandards/phpcsextra",
"version": "1.5.0",
@@ -2352,9 +2552,7 @@
],
"aliases": [],
"minimum-stability": "dev",
- "stability-flags": {
- "saltus/framework": 20
- },
+ "stability-flags": {},
"prefer-stable": true,
"prefer-lowest": false,
"platform": {
From b8078aecd5e616ba97795947c4ce5cae0a9b6504 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sun, 21 Jun 2026 18:33:21 +0800
Subject: [PATCH 21/86] Replace func
---
src/Plugin/Admin/RenamerPage.php | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/Plugin/Admin/RenamerPage.php b/src/Plugin/Admin/RenamerPage.php
index f561fd1e..d4b7ca88 100644
--- a/src/Plugin/Admin/RenamerPage.php
+++ b/src/Plugin/Admin/RenamerPage.php
@@ -125,7 +125,10 @@ private function render_text_field( string $id, string $label, string $value, bo
type=""
class="regular-text"
value=""
- required
+
+ required
>
From 5e66a9302ad3c9c8b806b2e517fc9f128b4d8e99 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Mon, 22 Jun 2026 00:13:01 +0800
Subject: [PATCH 22/86] fix(renamer): guard nonce check behind error parameter
Move the nonce verification out of the top-level page render
block so the page renders normally on first visit. Only verify
the error redirect nonce when an error token is present.
---
src/Plugin/Admin/RenamerPage.php | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/src/Plugin/Admin/RenamerPage.php b/src/Plugin/Admin/RenamerPage.php
index d4b7ca88..25654161 100644
--- a/src/Plugin/Admin/RenamerPage.php
+++ b/src/Plugin/Admin/RenamerPage.php
@@ -38,20 +38,22 @@ public function add_page(): void {
}
public function render(): void {
- if (
- empty( $_GET['framework_demo_nonce'] ) ||
- ! wp_verify_nonce( $_GET['framework_demo_nonce'], 'framework_demo_error_redirect' )
- ) {
- return;
- }
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'You do not have permission to access this page.', 'framework-demo' ) );
}
$defaults = PluginIdentity::defaults();
$error_key = sanitize_text_field( $_GET['framework_demo_error'] ?? '' );
- $error_message = get_transient( 'framework_demo_error_' . $error_key );
- delete_transient( 'framework_demo_error_' . $error_key );
+ $error_message = '';
+
+ if (
+ $error_key !== ''
+ && isset( $_GET['framework_demo_nonce'] )
+ && wp_verify_nonce( $_GET['framework_demo_nonce'], 'framework_demo_error_redirect' )
+ ) {
+ $error_message = get_transient( 'framework_demo_error_' . $error_key );
+ delete_transient( 'framework_demo_error_' . $error_key );
+ }
?>
Date: Mon, 22 Jun 2026 00:13:04 +0800
Subject: [PATCH 23/86] fix(assets): scope admin styles to plugin pages
Replace unset of the hook_suffix with an early return guard
that only loads styles when the suffix contains 'framework-demo'.
This avoids styling conflicts on other admin pages.
---
src/Plugin/Assets.php | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/Plugin/Assets.php b/src/Plugin/Assets.php
index 51b1682e..6610d709 100644
--- a/src/Plugin/Assets.php
+++ b/src/Plugin/Assets.php
@@ -37,7 +37,9 @@ public function load_assets(): void {
*
*/
public function load_admin_styles( string $hook_suffix = '' ): void {
- unset( $hook_suffix );
+ if ( ! $hook_suffix || strpos( $hook_suffix, 'framework-demo' ) === false ) {
+ return;
+ }
wp_register_style(
$this->core->get_name() . '_admin',
From 321ebd1ee1313d75d10d82e17a57e7624c9bf82b Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Mon, 22 Jun 2026 00:13:08 +0800
Subject: [PATCH 24/86] infra(phpcs): update testVersion to 8.3
The plugin uses PHP 8.0+ features such as mixed return types.
The previous testVersion of 7.4- caused false positive errors
from PHPCompatibility.
---
phpcs.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/phpcs.xml b/phpcs.xml
index d2131d69..f16ca26d 100644
--- a/phpcs.xml
+++ b/phpcs.xml
@@ -86,6 +86,6 @@
Date: Mon, 22 Jun 2026 00:36:32 +0800
Subject: [PATCH 25/86] fix(renamer): harden ZIP builder against edge cases
Check headers_sent() before disk I/O in stream_zip() so the application fails fast when streaming is impossible.
Trim leading and trailing dashes from the generated vendor name in package_name() to prevent malformed Composer package names such as 'acme-inc-/my-plugin'.
Existing tests for package_name verification are extended to cover the dash-trimming edge case.
---
src/Plugin/Renamer/PluginRenamer.php | 11 ++++---
tests/Plugin/Renamer/PluginRenamerTest.php | 34 ++++++++++++++++++++++
2 files changed, 39 insertions(+), 6 deletions(-)
diff --git a/src/Plugin/Renamer/PluginRenamer.php b/src/Plugin/Renamer/PluginRenamer.php
index a1bc50bb..39d6f26c 100644
--- a/src/Plugin/Renamer/PluginRenamer.php
+++ b/src/Plugin/Renamer/PluginRenamer.php
@@ -26,6 +26,10 @@ public function __construct( string $source_dir ) {
}
public function stream_zip( PluginIdentity $identity ): void {
+ if ( headers_sent() ) {
+ throw new \RuntimeException( 'Headers were already sent before the ZIP download could start.' );
+ }
+
while ( ob_get_level() ) {
ob_end_clean();
}
@@ -43,11 +47,6 @@ public function stream_zip( PluginIdentity $identity ): void {
$this->build_zip( $identity, $tmp_file );
- if ( headers_sent() ) {
- $this->delete_file( $tmp_file );
- throw new \RuntimeException( 'Headers were already sent before the ZIP download could start.' );
- }
-
header( 'Content-Type: application/zip' );
header( 'Content-Disposition: attachment; filename="' . $identity->plugin_slug . '.zip"' );
header( 'Content-Length: ' . (string) filesize( $tmp_file ) );
@@ -162,7 +161,7 @@ private function rewrite_contents( string $contents, PluginIdentity $identity ):
}
private function package_name( PluginIdentity $identity ): string {
- return strtolower( preg_replace( '/[^a-zA-Z0-9-]+/', '-', $identity->author ) ) . '/' . $identity->plugin_slug;
+ return trim( strtolower( preg_replace( '/[^a-zA-Z0-9-]+/', '-', $identity->author ) ), '-' ) . '/' . $identity->plugin_slug;
}
private function delete_file( string $path ): void {
diff --git a/tests/Plugin/Renamer/PluginRenamerTest.php b/tests/Plugin/Renamer/PluginRenamerTest.php
index 67249dc4..7ab7a5eb 100644
--- a/tests/Plugin/Renamer/PluginRenamerTest.php
+++ b/tests/Plugin/Renamer/PluginRenamerTest.php
@@ -117,6 +117,40 @@ public function test_build_zip_replaces_package_name(): void {
$this->remove_dir( $source );
}
+ public function test_package_name_trims_leading_trailing_dashes(): void {
+ $source = $this->make_source_fixture( true );
+ $output = tempnam( sys_get_temp_dir(), 'renamer-' );
+ $identity = PluginIdentity::from_request(
+ array_merge(
+ PluginIdentity::defaults(),
+ array(
+ 'plugin_name' => 'Acme Library',
+ 'plugin_slug' => 'acme-library',
+ 'main_file' => 'acme-library.php',
+ 'namespace_segment' => 'AcmeLibrary',
+ 'text_domain' => 'acme-library',
+ 'author' => 'Acme Inc -',
+ 'prefix' => 'acme_library',
+ )
+ )
+ );
+
+ $renamer = new PluginRenamer( $source );
+ $renamer->build_zip( $identity, $output );
+
+ $zip = new ZipArchive();
+ self::assertTrue( true === $zip->open( $output ) );
+
+ $contents = $zip->getFromName( 'acme-library/composer.json' );
+ self::assertIsString( $contents );
+ self::assertStringContainsString( '"name": "acme-inc/acme-library"', $contents );
+ self::assertStringNotContainsString( 'acme-inc-/', $contents );
+
+ $zip->close();
+ @unlink( $output );
+ $this->remove_dir( $source );
+ }
+
private function make_source_fixture( bool $with_composer = false ): string {
$source = sys_get_temp_dir() . '/framework-demo-fixture-' . uniqid();
mkdir( $source . '/src', 0777, true );
From 9ed5155ecdb66cf242bd7996f4e99f1c44b9ab6a Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Mon, 22 Jun 2026 00:36:36 +0800
Subject: [PATCH 26/86] fix(identity): guard string cast against array input
Defensively verify that request values are not arrays before casting
to string in from_request(), preventing PHP 8.x warnings when a
malformed or malicious request submits an array for a text field.
---
src/Plugin/Renamer/PluginIdentity.php | 2 +-
tests/Plugin/Renamer/PluginIdentityTest.php | 9 +++++++++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/Plugin/Renamer/PluginIdentity.php b/src/Plugin/Renamer/PluginIdentity.php
index b79fdf54..82c0eae2 100644
--- a/src/Plugin/Renamer/PluginIdentity.php
+++ b/src/Plugin/Renamer/PluginIdentity.php
@@ -61,7 +61,7 @@ public static function from_request( array $request ): self {
$data = array();
foreach ( array_keys( self::defaults() ) as $key ) {
- $value = isset( $request[ $key ] ) ? (string) $request[ $key ] : '';
+ $value = isset( $request[ $key ] ) && ! is_array( $request[ $key ] ) ? (string) $request[ $key ] : '';
$data[ $key ] = sanitize_text_field( $value );
}
diff --git a/tests/Plugin/Renamer/PluginIdentityTest.php b/tests/Plugin/Renamer/PluginIdentityTest.php
index 175a553e..4542027f 100644
--- a/tests/Plugin/Renamer/PluginIdentityTest.php
+++ b/tests/Plugin/Renamer/PluginIdentityTest.php
@@ -33,6 +33,15 @@ public function test_invalid_namespace_fails_validation(): void {
PluginIdentity::from_request( $data );
}
+ public function test_array_input_does_not_cause_php_warning(): void {
+ $data = PluginIdentity::defaults();
+ $data['plugin_name'] = [ 'malicious', 'array' ];
+
+ $this->expectException( ValidationException::class );
+
+ PluginIdentity::from_request( $data );
+ }
+
public function test_invalid_url_fails_validation(): void {
$data = PluginIdentity::defaults();
$data['plugin_uri'] = 'not a url';
From 90be4cc8de6c18f9380451b8739cc9737e596ab3 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Mon, 22 Jun 2026 00:36:39 +0800
Subject: [PATCH 27/86] fix(assets): migrate strpos to str_contains
Since this plugin requires PHP 8.3 or newer, use the more modern and
readable str_contains() function instead of strpos().
---
src/Plugin/Assets.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Plugin/Assets.php b/src/Plugin/Assets.php
index 6610d709..7fbc09e2 100644
--- a/src/Plugin/Assets.php
+++ b/src/Plugin/Assets.php
@@ -37,7 +37,7 @@ public function load_assets(): void {
*
*/
public function load_admin_styles( string $hook_suffix = '' ): void {
- if ( ! $hook_suffix || strpos( $hook_suffix, 'framework-demo' ) === false ) {
+ if ( ! $hook_suffix || ! str_contains( $hook_suffix, 'framework-demo' ) ) {
return;
}
From b4f583897012c8d53531ff7036e5d3f172c68f85 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Mon, 22 Jun 2026 00:36:43 +0800
Subject: [PATCH 28/86] fix(post-type): guard against null global post
Defensively verify that the global $post object is a valid WP_Post
instance before accessing its properties, preventing potential PHP
warnings or errors if the global is null or uninitialized.
---
src/models/post-type-all.php | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/models/post-type-all.php b/src/models/post-type-all.php
index b5abc22b..12ad0c89 100644
--- a/src/models/post-type-all.php
+++ b/src/models/post-type-all.php
@@ -32,6 +32,9 @@
'title' => __( 'Shortcode', 'framework-demo' ),
'function' => function () {
global $post;
+ if ( ! $post instanceof \WP_Post ) {
+ return;
+ }
echo esc_html( '[display-book id="' . $post->ID . '"]' );
},
),
From e13ecd539a1365e961a2648ed7a8b9fe02d3f581 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Mon, 22 Jun 2026 21:19:11 +0800
Subject: [PATCH 29/86] fix(path): use substr for reliable path stripping
Replace str_replace with substr for removing root/source directory
prefixes from file paths. str_replace can produce incorrect results when
the directory name appears elsewhere in the path. Using substr with the
length of the directory path is safer and more robust.
---
bin/package.php | 2 +-
src/Plugin/Renamer/PluginRenamer.php | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/bin/package.php b/bin/package.php
index ffe80479..3234c1fd 100644
--- a/bin/package.php
+++ b/bin/package.php
@@ -36,7 +36,7 @@
continue;
}
- $relative = ltrim( str_replace( $root, '', $file->getPathname() ), DIRECTORY_SEPARATOR );
+ $relative = substr( $file->getPathname(), strlen( $root ) + 1 );
$parts = explode( DIRECTORY_SEPARATOR, $relative );
if ( array_intersect( $parts, $excluded_dirs ) ) {
diff --git a/src/Plugin/Renamer/PluginRenamer.php b/src/Plugin/Renamer/PluginRenamer.php
index 39d6f26c..b6839500 100644
--- a/src/Plugin/Renamer/PluginRenamer.php
+++ b/src/Plugin/Renamer/PluginRenamer.php
@@ -109,7 +109,7 @@ private function add_files( \ZipArchive $zip, PluginIdentity $identity ): void {
}
private function relative_path( string $path ): string {
- return ltrim( str_replace( $this->source_dir, '', $path ), DIRECTORY_SEPARATOR );
+ return substr( $path, strlen( $this->source_dir ) + 1 );
}
private function target_path( string $relative_path, PluginIdentity $identity ): string {
From d71a4f6ae1040ce21c9b1523db88f2b4e6a17744 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Mon, 22 Jun 2026 21:19:49 +0800
Subject: [PATCH 30/86] fix(renamer): fallback vendor name for non-ASCII author
names
When the author name contains only non-ASCII characters (Cyrillic,
Chinese, Japanese, emoji), the sanitized vendor name becomes empty,
resulting in an invalid package name like '/plugin-slug'. Fall back
to 'local' to ensure composer.json remains valid.
---
src/Plugin/Renamer/PluginRenamer.php | 8 +++++-
tests/Plugin/Renamer/PluginRenamerTest.php | 33 ++++++++++++++++++++++
2 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/src/Plugin/Renamer/PluginRenamer.php b/src/Plugin/Renamer/PluginRenamer.php
index b6839500..25aa4d42 100644
--- a/src/Plugin/Renamer/PluginRenamer.php
+++ b/src/Plugin/Renamer/PluginRenamer.php
@@ -161,7 +161,13 @@ private function rewrite_contents( string $contents, PluginIdentity $identity ):
}
private function package_name( PluginIdentity $identity ): string {
- return trim( strtolower( preg_replace( '/[^a-zA-Z0-9-]+/', '-', $identity->author ) ), '-' ) . '/' . $identity->plugin_slug;
+ $vendor = trim( strtolower( preg_replace( '/[^a-zA-Z0-9-]+/', '-', $identity->author ) ), '-' );
+
+ if ( '' === $vendor ) {
+ $vendor = 'local';
+ }
+
+ return $vendor . '/' . $identity->plugin_slug;
}
private function delete_file( string $path ): void {
diff --git a/tests/Plugin/Renamer/PluginRenamerTest.php b/tests/Plugin/Renamer/PluginRenamerTest.php
index 7ab7a5eb..fe2c5720 100644
--- a/tests/Plugin/Renamer/PluginRenamerTest.php
+++ b/tests/Plugin/Renamer/PluginRenamerTest.php
@@ -151,6 +151,39 @@ public function test_package_name_trims_leading_trailing_dashes(): void {
$this->remove_dir( $source );
}
+ public function test_package_name_falls_back_to_local_when_author_has_no_ascii(): void {
+ $source = $this->make_source_fixture( true );
+ $output = tempnam( sys_get_temp_dir(), 'renamer-' );
+ $identity = PluginIdentity::from_request(
+ array_merge(
+ PluginIdentity::defaults(),
+ array(
+ 'plugin_name' => 'Acme Library',
+ 'plugin_slug' => 'acme-library',
+ 'main_file' => 'acme-library.php',
+ 'namespace_segment' => 'AcmeLibrary',
+ 'text_domain' => 'acme-library',
+ 'author' => 'Иван Петров',
+ 'prefix' => 'acme_library',
+ )
+ )
+ );
+
+ $renamer = new PluginRenamer( $source );
+ $renamer->build_zip( $identity, $output );
+
+ $zip = new ZipArchive();
+ self::assertTrue( true === $zip->open( $output ) );
+
+ $contents = $zip->getFromName( 'acme-library/composer.json' );
+ self::assertIsString( $contents );
+ self::assertStringContainsString( '"name": "local/acme-library"', $contents );
+
+ $zip->close();
+ @unlink( $output );
+ $this->remove_dir( $source );
+ }
+
private function make_source_fixture( bool $with_composer = false ): string {
$source = sys_get_temp_dir() . '/framework-demo-fixture-' . uniqid();
mkdir( $source . '/src', 0777, true );
From e5232bacd718b54e62133030e38ef7cd166eb9fa Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Mon, 22 Jun 2026 21:19:56 +0800
Subject: [PATCH 31/86] fix(renamer): guard ob_end_clean failure to prevent
infinite loop
If an active output buffer was started with flags preventing it from being
cleaned or removed, ob_end_clean() returns false and the buffer level
does not decrease. This could cause an infinite loop. Breaking when
ob_end_clean() fails prevents this.
---
src/Plugin/Renamer/PluginRenamer.php | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/Plugin/Renamer/PluginRenamer.php b/src/Plugin/Renamer/PluginRenamer.php
index 25aa4d42..b1b99546 100644
--- a/src/Plugin/Renamer/PluginRenamer.php
+++ b/src/Plugin/Renamer/PluginRenamer.php
@@ -31,7 +31,9 @@ public function stream_zip( PluginIdentity $identity ): void {
}
while ( ob_get_level() ) {
- ob_end_clean();
+ if ( false === ob_end_clean() ) {
+ break;
+ }
}
$tmp_file = wp_tempnam( $identity->plugin_slug . '.zip' );
From f6b65d7b38dc0443b005bfdc8582bef3e1fc9e78 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Mon, 22 Jun 2026 21:20:03 +0800
Subject: [PATCH 32/86] fix(identity): remove redundant validation call in
from_request
self::validate() was called twice in from_request(): once before and once
after esc_url_raw(). Since esc_url_raw() only sanitizes URLs and does not
make a valid URL invalid, the first call is unnecessary. Fix the test
bootstrap's esc_url_raw mock to match WordPress behavior (strip bad
characters rather than return empty for non-URLs).
---
src/Plugin/Renamer/PluginIdentity.php | 2 --
tests/bootstrap.php | 4 +---
2 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/src/Plugin/Renamer/PluginIdentity.php b/src/Plugin/Renamer/PluginIdentity.php
index 82c0eae2..b4c41063 100644
--- a/src/Plugin/Renamer/PluginIdentity.php
+++ b/src/Plugin/Renamer/PluginIdentity.php
@@ -68,8 +68,6 @@ public static function from_request( array $request ): self {
$data['author_uri'] = trim( $data['author_uri'] );
$data['plugin_uri'] = trim( $data['plugin_uri'] );
- self::validate( $data );
-
$data['author_uri'] = esc_url_raw( $data['author_uri'] );
$data['plugin_uri'] = esc_url_raw( $data['plugin_uri'] );
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index b95f801f..e9b4f855 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -10,9 +10,7 @@ function sanitize_text_field( $value ) {
if ( ! function_exists( 'esc_url_raw' ) ) {
function esc_url_raw( $value ) {
$value = trim( (string) $value );
- if ( false === filter_var( $value, FILTER_VALIDATE_URL ) ) {
- return '';
- }
+ $value = preg_replace( '/[\x00-\x20<>"\']/', '', $value );
return $value;
}
}
From e5a172c4a1347d9e004e785c698985e1734de468 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Mon, 22 Jun 2026 21:20:19 +0800
Subject: [PATCH 33/86] fix(post-type): correct post_schedulled to
post_scheduled message key
Fix the typo 'post_schedulled' -> 'post_scheduled'. The standard
WordPress post updated message key is 'post_scheduled' (one 'l').
---
src/models/post-type-all.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/models/post-type-all.php b/src/models/post-type-all.php
index 12ad0c89..1dd502c0 100644
--- a/src/models/post-type-all.php
+++ b/src/models/post-type-all.php
@@ -106,7 +106,7 @@
/* translators: {preview_url}: replaced by the book preview URL. */
'post_submitted' => __( 'Book submitted. Preview', 'framework-demo' ),
/* translators: 1: {date}: scheduled publication date, 2: {preview_url}: replaced by the book preview URL. */
- 'post_schedulled' => __( 'Book scheduled for {date}. Preview', 'framework-demo' ),
+ 'post_scheduled' => __( 'Book scheduled for {date}. Preview', 'framework-demo' ),
/* translators: {preview_url}: replaced by the book preview URL. */
'post_draft_updated' => __( 'Book draft updated. Preview', 'framework-demo' ),
),
From 12fc7717aca0193f321ae462f0e5fa346ff4b3d8 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Mon, 22 Jun 2026 21:20:30 +0800
Subject: [PATCH 34/86] fix(post-type): correct permanetly to permanently in
message
Fix the spelling 'permanetly' -> 'permanently' in the bulk delete
message for the book post type.
---
src/models/post-type-all.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/models/post-type-all.php b/src/models/post-type-all.php
index 1dd502c0..c2acc4c9 100644
--- a/src/models/post-type-all.php
+++ b/src/models/post-type-all.php
@@ -117,7 +117,7 @@
'locked_singular' => __( 'Book not updated, somebody is editing it', 'framework-demo' ),
/* translators: %s: number of books not updated because they are locked. */
'locked_plural' => __( '%s Books not updated, somebody is editing them', 'framework-demo' ),
- 'deleted_singular' => __( 'Book permanetly deleted. Fahrenheit 451 team was here?', 'framework-demo' ),
+ 'deleted_singular' => __( 'Book permanently deleted. Fahrenheit 451 team was here?', 'framework-demo' ),
/* translators: %s: number of books permanently deleted. */
'deleted_plural' => __( '%s Books permanently deleted. Why? :(', 'framework-demo' ),
'trashed_singular' => __( 'Book moved to the trash. I\'m sad :(', 'framework-demo' ),
From 71dd2b5cb86cd98222c77ea673d685507a8ea161 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Mon, 22 Jun 2026 23:26:27 +0800
Subject: [PATCH 35/86] fix(i18n): use plugin_basename for
load_plugin_textdomain path
plugin_basename() returns a relative path from WP_PLUGIN_DIR, preventing the invalid concatenation that occurs when passing an absolute path to load_plugin_textdomain.
---
src/Core.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Core.php b/src/Core.php
index 9c83b2e7..5a7f5f9a 100644
--- a/src/Core.php
+++ b/src/Core.php
@@ -85,7 +85,7 @@ public function init(): void {
*/
private function set_locale(): void {
$i18n = new I18n( $this->name );
- $i18n->load_plugin_textdomain( dirname( $this->file_path ) );
+ $i18n->load_plugin_textdomain( dirname( plugin_basename( $this->file_path ) ) );
}
/**
From ec9cdaa7004ce1136bd10b7b582f37085151a605 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Mon, 22 Jun 2026 23:26:32 +0800
Subject: [PATCH 36/86] feature(renamer): always use plugin_slug as text domain
Remove the standalone text_domain field from the generator UI. The text domain is now always derived from the plugin_slug per WordPress convention.
---
src/Plugin/Admin/RenamerPage.php | 1 -
src/Plugin/Renamer/PluginIdentity.php | 10 +++-------
src/Plugin/Renamer/PluginRenamer.php | 2 +-
tests/Plugin/Renamer/PluginRenamerTest.php | 5 -----
4 files changed, 4 insertions(+), 14 deletions(-)
diff --git a/src/Plugin/Admin/RenamerPage.php b/src/Plugin/Admin/RenamerPage.php
index 25654161..d0a4820a 100644
--- a/src/Plugin/Admin/RenamerPage.php
+++ b/src/Plugin/Admin/RenamerPage.php
@@ -74,7 +74,6 @@ public function render(): void {
render_text_field( 'plugin_slug', __( 'Plugin Slug', 'framework-demo' ), $defaults['plugin_slug'], true ); ?>
render_text_field( 'main_file', __( 'Main Plugin File', 'framework-demo' ), $defaults['main_file'], true ); ?>
render_text_field( 'namespace_segment', __( 'Namespace Segment', 'framework-demo' ), $defaults['namespace_segment'], true ); ?>
- render_text_field( 'text_domain', __( 'Text Domain', 'framework-demo' ), $defaults['text_domain'], true ); ?>
render_text_field( 'description', __( 'Description', 'framework-demo' ), $defaults['description'], true ); ?>
render_text_field( 'author', __( 'Author', 'framework-demo' ), $defaults['author'], true ); ?>
render_text_field( 'author_uri', __( 'Author URI', 'framework-demo' ), $defaults['author_uri'], false, 'url' ); ?>
diff --git a/src/Plugin/Renamer/PluginIdentity.php b/src/Plugin/Renamer/PluginIdentity.php
index b4c41063..92f3c71e 100644
--- a/src/Plugin/Renamer/PluginIdentity.php
+++ b/src/Plugin/Renamer/PluginIdentity.php
@@ -26,7 +26,7 @@ public function __construct( array $data ) {
$this->plugin_slug = $data['plugin_slug'];
$this->main_file = $data['main_file'];
$this->namespace_segment = $data['namespace_segment'];
- $this->text_domain = $data['text_domain'];
+ $this->text_domain = $this->plugin_slug;
$this->description = $data['description'];
$this->author = $data['author'];
$this->author_uri = $data['author_uri'];
@@ -44,7 +44,7 @@ public static function defaults(): array {
'plugin_slug' => 'my-saltus-plugin',
'main_file' => 'my-saltus-plugin.php',
'namespace_segment' => 'MySaltusPlugin',
- 'text_domain' => 'my-saltus-plugin',
+
'description' => 'A WordPress plugin built with the Saltus Framework.',
'author' => 'Your Name',
'author_uri' => 'https://example.com/',
@@ -80,7 +80,7 @@ public static function from_request( array $request ): self {
* @param array
Date: Sun, 28 Jun 2026 18:15:50 +0800
Subject: [PATCH 37/86] refactor: reorder plugin bootstrap autoload after PHP
version check
Move the vendor/autoload.php and src/Core.php require statements below the
PHP version compatibility check so that dependencies are only loaded
when the runtime meets the minimum PHP requirement.
Previously the autoload and Core bootstrap ran unconditionally before
the version guard, which could produce fatal errors on unsupported
PHP versions.
---
framework-demo.php | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/framework-demo.php b/framework-demo.php
index 2cf6ae0d..9fbf8d7b 100644
--- a/framework-demo.php
+++ b/framework-demo.php
@@ -39,14 +39,6 @@
define( __NAMESPACE__ . '\PLUGIN_MINIMUM_PHP', '8.3' );
}
-if ( file_exists( __DIR__ . '/vendor/autoload.php' ) ) {
- require_once __DIR__ . '/vendor/autoload.php';
-}
-
-if ( ! class_exists( Core::class ) && file_exists( __DIR__ . '/src/Core.php' ) ) {
- require_once __DIR__ . '/src/Core.php';
-}
-
if ( version_compare( PHP_VERSION, PLUGIN_MINIMUM_PHP, '<' ) ) {
add_action(
'admin_notices',
@@ -67,6 +59,14 @@ static function (): void {
return;
}
+if ( file_exists( __DIR__ . '/vendor/autoload.php' ) ) {
+ require_once __DIR__ . '/vendor/autoload.php';
+}
+
+if ( ! class_exists( Core::class ) && file_exists( __DIR__ . '/src/Core.php' ) ) {
+ require_once __DIR__ . '/src/Core.php';
+}
+
if ( ! class_exists( \Saltus\WP\Framework\Core::class ) || ! class_exists( Core::class ) ) {
add_action(
'admin_notices',
From f1067591e111578fc9d58920c174874ee7c10fa7 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sun, 28 Jun 2026 18:15:54 +0800
Subject: [PATCH 38/86] refactor: standardize comparison style in Renamer
module
Convert Yoda conditions ('' === ) to standard comparisons ( === '')
for consistency and readability.
In PluginIdentity:
- Add /* translators: */ comments for i18n context
- Annotate ValidationException throws with phpcs:ignore
In PluginRenamer:
- Split add_files() to handle text vs binary files separately,
avoiding unnecessary file_get_contents on binary files
- Scope version string replacement to 'Version: N.N.N' header format
instead of broad 'N.N.N' replacement
- Annotate RuntimeExceptions with phpcs:ignore
In post-type-all:
- Fix whitespace alignment in labels array
---
src/Plugin/Renamer/PluginIdentity.php | 14 +++++----
src/Plugin/Renamer/PluginRenamer.php | 43 ++++++++++++++-------------
src/models/post-type-all.php | 2 +-
3 files changed, 32 insertions(+), 27 deletions(-)
diff --git a/src/Plugin/Renamer/PluginIdentity.php b/src/Plugin/Renamer/PluginIdentity.php
index 92f3c71e..c5121dd7 100644
--- a/src/Plugin/Renamer/PluginIdentity.php
+++ b/src/Plugin/Renamer/PluginIdentity.php
@@ -83,29 +83,31 @@ private static function validate( array $data ): void {
$required = array( 'plugin_name', 'plugin_slug', 'main_file', 'namespace_segment', 'description', 'author', 'version', 'prefix' );
foreach ( $required as $field ) {
- if ( '' === trim( $data[ $field ] ) ) {
+ if ( trim( $data[ $field ] ) === '' ) {
+ /* translators: %s: field label */
throw new ValidationException( sprintf( __( '%s is required.', 'framework-demo' ), self::label( $field ) ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
}
if ( ! preg_match( '/^[a-z0-9]+(?:-[a-z0-9]+)*$/', $data['plugin_slug'] ) ) {
- throw new ValidationException( __( 'Plugin slug must contain only lowercase letters, numbers, and single dashes.', 'framework-demo' ) );
+ throw new ValidationException( __( 'Plugin slug must contain only lowercase letters, numbers, and single dashes.', 'framework-demo' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
if ( ! preg_match( '/^[a-z0-9]+(?:-[a-z0-9]+)*\.php$/', $data['main_file'] ) ) {
- throw new ValidationException( __( 'Main plugin file must be a lowercase dash-safe PHP filename.', 'framework-demo' ) );
+ throw new ValidationException( __( 'Main plugin file must be a lowercase dash-safe PHP filename.', 'framework-demo' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
if ( ! preg_match( '/^[A-Z][A-Za-z0-9]*$/', $data['namespace_segment'] ) ) {
- throw new ValidationException( __( 'Namespace segment must be a valid PHP namespace segment, such as MyPlugin.', 'framework-demo' ) );
+ throw new ValidationException( __( 'Namespace segment must be a valid PHP namespace segment, such as MyPlugin.', 'framework-demo' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
if ( ! preg_match( '/^[a-z][a-z0-9_]*$/', $data['prefix'] ) ) {
- throw new ValidationException( __( 'Code prefix must contain only lowercase letters, numbers, and underscores, and start with a letter.', 'framework-demo' ) );
+ throw new ValidationException( __( 'Code prefix must contain only lowercase letters, numbers, and underscores, and start with a letter.', 'framework-demo' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
foreach ( array( 'author_uri', 'plugin_uri' ) as $url_field ) {
- if ( '' !== $data[ $url_field ] && false === filter_var( $data[ $url_field ], FILTER_VALIDATE_URL ) ) {
+ if ( $data[ $url_field ] !== '' && filter_var( $data[ $url_field ], FILTER_VALIDATE_URL ) === false ) {
+ /* translators: %s: field label */
throw new ValidationException( sprintf( __( '%s must be a valid URL or empty.', 'framework-demo' ), self::label( $url_field ) ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
}
diff --git a/src/Plugin/Renamer/PluginRenamer.php b/src/Plugin/Renamer/PluginRenamer.php
index 1f4992f6..d5ffa496 100644
--- a/src/Plugin/Renamer/PluginRenamer.php
+++ b/src/Plugin/Renamer/PluginRenamer.php
@@ -31,13 +31,13 @@ public function stream_zip( PluginIdentity $identity ): void {
}
while ( ob_get_level() ) {
- if ( false === ob_end_clean() ) {
+ if ( ob_end_clean() === false ) {
break;
}
}
$tmp_file = wp_tempnam( $identity->plugin_slug . '.zip' );
- if ( '' === $tmp_file ) {
+ if ( $tmp_file === '' ) {
throw new \RuntimeException( 'Could not create a temporary ZIP file.' );
}
@@ -66,7 +66,7 @@ public function build_zip( PluginIdentity $identity, string $destination ): void
}
$zip = new \ZipArchive();
- if ( true !== $zip->open( $destination, \ZipArchive::CREATE | \ZipArchive::OVERWRITE ) ) {
+ if ( $zip->open( $destination, \ZipArchive::CREATE | \ZipArchive::OVERWRITE ) !== true ) {
throw new \RuntimeException( 'Could not open the temporary ZIP file.' );
}
@@ -94,18 +94,21 @@ private function add_files( \ZipArchive $zip, PluginIdentity $identity ): void {
continue;
}
- $target_path = $this->target_path( $relative_path, $identity );
- $contents = file_get_contents( $file->getPathname() ); // phpcs:ignore WordPress.WP.AlternativeFunctions
- if ( false === $contents ) {
- throw new \RuntimeException( 'Could not read ' . $relative_path ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
- }
+ $target_path = $identity->plugin_slug . '/' . $this->target_path( $relative_path, $identity );
if ( $this->is_text_file( $relative_path ) ) {
+ $contents = file_get_contents( $file->getPathname() ); // phpcs:ignore WordPress.WP.AlternativeFunctions
+ if ( $contents === false ) {
+ throw new \RuntimeException( 'Could not read ' . $relative_path ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
+ }
$contents = $this->rewrite_contents( $contents, $identity );
+ $added = $zip->addFromString( $target_path, $contents );
+ } else {
+ $added = $zip->addFile( $file->getPathname(), $target_path );
}
- if ( ! $zip->addFromString( $identity->plugin_slug . '/' . $target_path, $contents ) ) {
- throw new \RuntimeException( 'Failed to add ' . $relative_path . ' to the ZIP archive.' );
+ if ( ! $added ) {
+ throw new \RuntimeException( 'Failed to add ' . $relative_path . ' to the ZIP archive.' ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
}
}
@@ -144,19 +147,19 @@ private function is_text_file( string $relative_path ): bool {
private function rewrite_contents( string $contents, PluginIdentity $identity ): string {
$replacements = array(
- self::ORIGINAL_NAMESPACE_SEGMENT => $identity->namespace_segment,
- self::ORIGINAL_PACKAGE => $this->package_name( $identity ),
- self::ORIGINAL_MAIN_FILE => $identity->main_file,
- self::ORIGINAL_PREFIX_UPPER => strtoupper( $identity->prefix ),
- self::ORIGINAL_PREFIX => $identity->prefix,
- 'Plugin Name: ' . self::ORIGINAL_NAME => 'Plugin Name: ' . $identity->plugin_name,
+ self::ORIGINAL_NAMESPACE_SEGMENT => $identity->namespace_segment,
+ self::ORIGINAL_PACKAGE => $this->package_name( $identity ),
+ self::ORIGINAL_MAIN_FILE => $identity->main_file,
+ self::ORIGINAL_PREFIX_UPPER => strtoupper( $identity->prefix ),
+ self::ORIGINAL_PREFIX => $identity->prefix,
+ 'Plugin Name: ' . self::ORIGINAL_NAME => 'Plugin Name: ' . $identity->plugin_name,
'Description: ' . self::ORIGINAL_DESCRIPTION => 'Description: ' . $identity->description,
'Plugin URI: ' . self::ORIGINAL_PLUGIN_URI => 'Plugin URI: ' . $identity->plugin_uri,
'Author URI: ' . self::ORIGINAL_AUTHOR_URI => 'Author URI: ' . $identity->author_uri,
- 'Author: ' . self::ORIGINAL_AUTHOR => 'Author: ' . $identity->author,
- self::ORIGINAL_SLUG => $identity->plugin_slug,
+ 'Author: ' . self::ORIGINAL_AUTHOR => 'Author: ' . $identity->author,
+ self::ORIGINAL_SLUG => $identity->plugin_slug,
"PLUGIN_VERSION', '" . self::ORIGINAL_VERSION . "'" => "PLUGIN_VERSION', '" . $identity->version . "'",
- self::ORIGINAL_VERSION => $identity->version,
+ 'Version: ' . self::ORIGINAL_VERSION => 'Version: ' . $identity->version,
);
return strtr( $contents, $replacements );
@@ -165,7 +168,7 @@ private function rewrite_contents( string $contents, PluginIdentity $identity ):
private function package_name( PluginIdentity $identity ): string {
$vendor = trim( strtolower( preg_replace( '/[^a-zA-Z0-9-]+/', '-', $identity->author ) ), '-' );
- if ( '' === $vendor ) {
+ if ( $vendor === '' ) {
$vendor = 'local';
}
diff --git a/src/models/post-type-all.php b/src/models/post-type-all.php
index c2acc4c9..e0b8af00 100644
--- a/src/models/post-type-all.php
+++ b/src/models/post-type-all.php
@@ -106,7 +106,7 @@
/* translators: {preview_url}: replaced by the book preview URL. */
'post_submitted' => __( 'Book submitted. Preview', 'framework-demo' ),
/* translators: 1: {date}: scheduled publication date, 2: {preview_url}: replaced by the book preview URL. */
- 'post_scheduled' => __( 'Book scheduled for {date}. Preview', 'framework-demo' ),
+ 'post_scheduled' => __( 'Book scheduled for {date}. Preview', 'framework-demo' ),
/* translators: {preview_url}: replaced by the book preview URL. */
'post_draft_updated' => __( 'Book draft updated. Preview', 'framework-demo' ),
),
From 9e504a120be8ec495168c82c20bb232b1995bf7b Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sun, 28 Jun 2026 18:43:47 +0800
Subject: [PATCH 39/86] fix(renamer): harden plugin renamer input processing
- Strip both forward and backward slashes from source directory path
- Validate version against strict semver format
- Strip PHP comment closers from plugin name, description, and author
---
src/Plugin/Renamer/PluginIdentity.php | 8 ++++++
src/Plugin/Renamer/PluginRenamer.php | 2 +-
tests/Plugin/Renamer/PluginIdentityTest.php | 31 +++++++++++++++++++++
3 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/src/Plugin/Renamer/PluginIdentity.php b/src/Plugin/Renamer/PluginIdentity.php
index c5121dd7..d0b859b9 100644
--- a/src/Plugin/Renamer/PluginIdentity.php
+++ b/src/Plugin/Renamer/PluginIdentity.php
@@ -68,6 +68,10 @@ public static function from_request( array $request ): self {
$data['author_uri'] = trim( $data['author_uri'] );
$data['plugin_uri'] = trim( $data['plugin_uri'] );
+ foreach ( array( 'plugin_name', 'description', 'author' ) as $comment_field ) {
+ $data[ $comment_field ] = str_replace( '*/', '', $data[ $comment_field ] );
+ }
+
$data['author_uri'] = esc_url_raw( $data['author_uri'] );
$data['plugin_uri'] = esc_url_raw( $data['plugin_uri'] );
@@ -101,6 +105,10 @@ private static function validate( array $data ): void {
throw new ValidationException( __( 'Namespace segment must be a valid PHP namespace segment, such as MyPlugin.', 'framework-demo' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
+ if ( ! preg_match( '/^\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?(?:\+[a-zA-Z0-9.]+)?$/', $data['version'] ) ) {
+ throw new ValidationException( __( 'Version must be a valid semver string like 1.0.0 or 2.0.0-beta.1.', 'framework-demo' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
+ }
+
if ( ! preg_match( '/^[a-z][a-z0-9_]*$/', $data['prefix'] ) ) {
throw new ValidationException( __( 'Code prefix must contain only lowercase letters, numbers, and underscores, and start with a letter.', 'framework-demo' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
diff --git a/src/Plugin/Renamer/PluginRenamer.php b/src/Plugin/Renamer/PluginRenamer.php
index d5ffa496..97a81e78 100644
--- a/src/Plugin/Renamer/PluginRenamer.php
+++ b/src/Plugin/Renamer/PluginRenamer.php
@@ -22,7 +22,7 @@ class PluginRenamer {
private string $source_dir;
public function __construct( string $source_dir ) {
- $this->source_dir = rtrim( $source_dir, DIRECTORY_SEPARATOR );
+ $this->source_dir = rtrim( $source_dir, '/\\' );
}
public function stream_zip( PluginIdentity $identity ): void {
diff --git a/tests/Plugin/Renamer/PluginIdentityTest.php b/tests/Plugin/Renamer/PluginIdentityTest.php
index 4542027f..fe0dbb7a 100644
--- a/tests/Plugin/Renamer/PluginIdentityTest.php
+++ b/tests/Plugin/Renamer/PluginIdentityTest.php
@@ -50,4 +50,35 @@ public function test_invalid_url_fails_validation(): void {
PluginIdentity::from_request( $data );
}
+
+ public function test_invalid_version_fails_validation(): void {
+ $data = PluginIdentity::defaults();
+ $data['version'] = 'abc';
+
+ $this->expectException( ValidationException::class );
+
+ PluginIdentity::from_request( $data );
+ }
+
+ public function test_version_without_patch_fails_validation(): void {
+ $data = PluginIdentity::defaults();
+ $data['version'] = '1.0';
+
+ $this->expectException( ValidationException::class );
+
+ PluginIdentity::from_request( $data );
+ }
+
+ public function test_comment_breakout_is_sanitized(): void {
+ $data = PluginIdentity::defaults();
+ $data['plugin_name'] = 'Foo */ bar';
+ $data['description'] = 'Desc */ breakout';
+ $data['author'] = 'Auth */ test';
+
+ $identity = PluginIdentity::from_request( $data );
+
+ self::assertSame( 'Foo bar', $identity->plugin_name );
+ self::assertSame( 'Desc breakout', $identity->description );
+ self::assertSame( 'Auth test', $identity->author );
+ }
}
From a9af57c5f07b70ba48a9ed0f3046b8c85c76c8cb Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Mon, 29 Jun 2026 00:51:52 +0800
Subject: [PATCH 40/86] infra(build): Add Strauss namespace prefixing to
release pipeline
Add brianhenryie/strauss for prefixing production Composer
dependencies into vendor-prefixed/ during release builds.
Replace inline ZIP loop with staging pipeline: copy files,
composer install, prefix-namespaces, remove vendor, then zip.
Output filename now includes the plugin version.
Enable Strauss plugin in composer.json allow-plugins.
---
.gitignore | 1 +
bin/package.php | 234 +-
composer.json | 22 +-
composer.lock | 5993 ++++++++++++++++++++++++++++++++++++++---------
phpcs.xml | 3 +-
5 files changed, 5120 insertions(+), 1133 deletions(-)
diff --git a/.gitignore b/.gitignore
index b8c4eda0..104cb122 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
# Dependencies
/vendor/
+/vendor-prefixed/
/node_modules/
/build/node_modules/
diff --git a/bin/package.php b/bin/package.php
index 3234c1fd..fb35c9cc 100644
--- a/bin/package.php
+++ b/bin/package.php
@@ -5,8 +5,43 @@
$root = dirname( __DIR__ );
$slug = 'framework-demo';
+$stage = $root . '/build/release/' . $slug;
$dist = $root . '/dist';
-$zip_path = $dist . '/' . $slug . '.zip';
+
+/**
+ * Read the plugin version from the main plugin file.
+ *
+ * @param string $plugin_file Main plugin file.
+ * @return string
+ */
+function read_plugin_version( string $plugin_file ): string {
+ $contents = file_get_contents( $plugin_file ); // phpcs:ignore WordPress.WP.AlternativeFunctions
+
+ if ( false === $contents ) {
+ throw new RuntimeException( "Could not read {$plugin_file}." );
+ }
+
+ if ( 1 === preg_match( "/PLUGIN_VERSION', '([^']+)'/", $contents, $matches ) ) {
+ return $matches[1];
+ }
+
+ if ( 1 === preg_match( '/^\s*\*\s*Version:\s*([^\r\n]+)/mi', $contents, $matches ) ) {
+ return trim( $matches[1] );
+ }
+
+ throw new RuntimeException( 'Could not determine the plugin version.' );
+}
+
+try {
+ $version = read_plugin_version( $root . '/' . $slug . '.php' );
+ if ( 1 !== preg_match( '/^\d+\.\d+\.\d+(?:-[a-zA-Z0-9.]+)?(?:\+[a-zA-Z0-9.]+)?$/', $version ) ) {
+ throw new RuntimeException( "Invalid plugin version {$version}." );
+ }
+ $zip_path = $dist . '/' . $slug . '-' . $version . '.zip';
+} catch ( RuntimeException $exception ) {
+ fwrite( STDERR, $exception->getMessage() . "\n" ); // phpcs:ignore WordPress.WP.AlternativeFunctions
+ exit( 1 );
+}
if ( ! class_exists( ZipArchive::class ) ) {
fwrite( STDERR, "The PHP zip extension is required.\n" ); // phpcs:ignore WordPress.WP.AlternativeFunctions
@@ -18,38 +53,197 @@
exit( 1 );
}
-$zip = new ZipArchive();
-if ( true !== $zip->open( $zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE ) ) {
- fwrite( STDERR, "Could not open {$zip_path}.\n" ); // phpcs:ignore WordPress.WP.AlternativeFunctions
- exit( 1 );
-}
+/**
+ * Recursively remove a path.
+ *
+ * @param string $path Path to remove.
+ */
+function remove_path( string $path ): void {
+ if ( ! file_exists( $path ) ) {
+ return;
+ }
-$excluded_dirs = array( '.git', '.codex', '.agents', 'node_modules', 'build', 'dist', 'release', 'reports' );
-$excluded_files = array( 'composer.lock', 'package-lock.json' );
+ if ( is_file( $path ) || is_link( $path ) ) {
+ unlink( $path ); // phpcs:ignore WordPress.WP.AlternativeFunctions
+ return;
+ }
-$iterator = new RecursiveIteratorIterator(
- new RecursiveDirectoryIterator( $root, FilesystemIterator::SKIP_DOTS )
-);
+ $iterator = new RecursiveIteratorIterator(
+ new RecursiveDirectoryIterator( $path, FilesystemIterator::SKIP_DOTS ),
+ RecursiveIteratorIterator::CHILD_FIRST
+ );
-foreach ( $iterator as $file ) {
- if ( ! $file instanceof SplFileInfo || ! $file->isFile() ) {
- continue;
+ foreach ( $iterator as $item ) {
+ if ( $item->isDir() && ! $item->isLink() ) {
+ rmdir( $item->getPathname() ); // phpcs:ignore WordPress.WP.AlternativeFunctions
+ } else {
+ unlink( $item->getPathname() ); // phpcs:ignore WordPress.WP.AlternativeFunctions
+ }
}
- $relative = substr( $file->getPathname(), strlen( $root ) + 1 );
- $parts = explode( DIRECTORY_SEPARATOR, $relative );
+ rmdir( $path ); // phpcs:ignore WordPress.WP.AlternativeFunctions
+}
+
+/**
+ * Determine whether a relative path should be excluded from the release stage.
+ *
+ * @param string $relative Relative path.
+ * @return bool
+ */
+function is_excluded_from_release( string $relative ): bool {
+ $parts = explode( DIRECTORY_SEPARATOR, $relative );
+
+ $excluded_dirs = array(
+ '.agents',
+ '.codex',
+ '.git',
+ 'build',
+ 'dist',
+ 'node_modules',
+ 'release',
+ 'reports',
+ 'tests',
+ 'vendor',
+ 'vendor-prefixed',
+ );
if ( array_intersect( $parts, $excluded_dirs ) ) {
- continue;
+ return true;
+ }
+
+ $basename = basename( $relative );
+ $excluded_files = array(
+ '.gitignore',
+ '.phpunit.result.cache',
+ 'package-lock.json',
+ 'phpcs.xml',
+ 'phpunit.xml.dist',
+ );
+
+ return in_array( $basename, $excluded_files, true )
+ || 1 === preg_match( '/\.(zip|log|map|cache)$/', $basename );
+}
+
+/**
+ * Copy repository files into the release stage.
+ *
+ * @param string $source Source directory.
+ * @param string $target Target directory.
+ */
+function copy_release_files( string $source, string $target ): void {
+ $iterator = new RecursiveIteratorIterator(
+ new RecursiveDirectoryIterator( $source, FilesystemIterator::SKIP_DOTS ),
+ RecursiveIteratorIterator::SELF_FIRST
+ );
+
+ foreach ( $iterator as $item ) {
+ $relative = substr( $item->getPathname(), strlen( $source ) + 1 );
+
+ if ( is_excluded_from_release( $relative ) ) {
+ continue;
+ }
+
+ $destination = $target . DIRECTORY_SEPARATOR . $relative;
+
+ if ( $item->isDir() ) {
+ if ( ! is_dir( $destination ) && ! mkdir( $destination, 0775, true ) && ! is_dir( $destination ) ) { // phpcs:ignore WordPress.WP.AlternativeFunctions
+ throw new RuntimeException( "Could not create {$destination}." );
+ }
+ continue;
+ }
+
+ $destination_dir = dirname( $destination );
+ if ( ! is_dir( $destination_dir ) && ! mkdir( $destination_dir, 0775, true ) && ! is_dir( $destination_dir ) ) { // phpcs:ignore WordPress.WP.AlternativeFunctions
+ throw new RuntimeException( "Could not create {$destination_dir}." );
+ }
+
+ if ( ! copy( $item->getPathname(), $destination ) ) { // phpcs:ignore WordPress.WP.AlternativeFunctions
+ throw new RuntimeException( "Could not copy {$relative}." );
+ }
+ }
+}
+
+/**
+ * Run Composer in the release stage and prefix production dependencies.
+ *
+ * @param string $working_dir Composer working directory.
+ */
+function install_release_dependencies( string $working_dir ): void {
+ $composer = getenv( 'COMPOSER_BINARY' ) ?: 'composer';
+ if ( false === getenv( 'COMPOSER_CACHE_DIR' ) ) {
+ putenv( 'COMPOSER_CACHE_DIR=' . sys_get_temp_dir() . '/framework-demo-composer-cache' ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_putenv
+ }
+
+ $commands = array(
+ sprintf(
+ '%s install --optimize-autoloader --no-interaction --no-progress --working-dir=%s',
+ escapeshellcmd( $composer ),
+ escapeshellarg( $working_dir )
+ ),
+ sprintf(
+ '%s prefix-namespaces --working-dir=%s',
+ escapeshellcmd( $composer ),
+ escapeshellarg( $working_dir )
+ ),
+ );
+
+ foreach ( $commands as $command ) {
+ passthru( $command, $exit_code ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions
+
+ if ( 0 !== $exit_code ) {
+ throw new RuntimeException( 'Composer command failed while building the release package.' );
+ }
}
- if ( in_array( basename( $relative ), $excluded_files, true ) || preg_match( '/\.(zip|log|map|cache)$/', basename( $relative ) ) ) {
- continue;
+ remove_path( $working_dir . '/vendor' );
+}
+
+/**
+ * Add staged files to the release ZIP.
+ *
+ * @param ZipArchive $zip ZIP archive.
+ * @param string $source Source directory.
+ * @param string $prefix ZIP path prefix.
+ */
+function zip_release_files( ZipArchive $zip, string $source, string $prefix ): void {
+ $iterator = new RecursiveIteratorIterator(
+ new RecursiveDirectoryIterator( $source, FilesystemIterator::SKIP_DOTS )
+ );
+
+ foreach ( $iterator as $file ) {
+ if ( ! $file instanceof SplFileInfo || ! $file->isFile() ) {
+ continue;
+ }
+
+ $relative = substr( $file->getPathname(), strlen( $source ) + 1 );
+ $zip->addFile( $file->getPathname(), $prefix . '/' . str_replace( DIRECTORY_SEPARATOR, '/', $relative ) );
}
+}
- $zip->addFile( $file->getPathname(), $slug . '/' . str_replace( DIRECTORY_SEPARATOR, '/', $relative ) );
+try {
+ remove_path( $stage );
+
+ if ( ! mkdir( $stage, 0775, true ) && ! is_dir( $stage ) ) { // phpcs:ignore WordPress.WP.AlternativeFunctions
+ throw new RuntimeException( 'Could not create release staging directory.' );
+ }
+
+ copy_release_files( $root, $stage );
+ install_release_dependencies( $stage );
+ remove_path( $stage . '/composer.json' );
+ remove_path( $stage . '/composer.lock' );
+ remove_path( $zip_path );
+} catch ( RuntimeException $exception ) {
+ fwrite( STDERR, $exception->getMessage() . "\n" ); // phpcs:ignore WordPress.WP.AlternativeFunctions
+ exit( 1 );
+}
+
+$zip = new ZipArchive();
+if ( true !== $zip->open( $zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE ) ) {
+ fwrite( STDERR, "Could not open {$zip_path}.\n" ); // phpcs:ignore WordPress.WP.AlternativeFunctions
+ exit( 1 );
}
+zip_release_files( $zip, $stage, $slug );
$zip->close();
echo "Created {$zip_path}\n"; // phpcs:ignore WordPress.Security.EscapeOutput
diff --git a/composer.json b/composer.json
index 0c9445e8..b0ef846e 100644
--- a/composer.json
+++ b/composer.json
@@ -3,7 +3,7 @@
"description": "Modern demo plugin for the Saltus Framework for WordPress.",
"type": "wordpress-plugin",
"license": "GPL-2.0-or-later",
- "homepage": "https://saltus.io/",
+ "homepage": "https://saltus.dev/",
"authors": [
{
"name": "Saltus",
@@ -28,6 +28,7 @@
"saltus/framework": "^1.3"
},
"require-dev": {
+ "brianhenryie/strauss": "^0.22",
"phpunit/phpunit": "^11.0",
"wp-coding-standards/wpcs": "^3.3",
"phpcompatibility/phpcompatibility-wp": "*",
@@ -45,15 +46,34 @@
},
"config": {
"allow-plugins": {
+ "brianhenryie/strauss": true,
"dealerdirect/phpcodesniffer-composer-installer": true
},
"sort-packages": true
},
+ "extra": {
+ "strauss": {
+ "namespace_prefix": "Saltus\\WP\\Plugin\\Saltus\\PluginFrameworkDemo\\",
+ "classmap_prefix": "Saltus_WP_Plugin_Saltus_PluginFrameworkDemo_",
+ "target_directory": "vendor-prefixed",
+ "packages": [
+ "saltus/framework"
+ ],
+ "override_autoloader": true,
+ "delete_vendor_packages": true,
+ "class_alias": false
+ }
+ },
"scripts": {
"validate-project": "composer validate --strict",
"lint": "phpcs",
"test": "phpunit",
"make-pot": "wp i18n make-pot . languages/framework-demo.pot --exclude=vendor,node_modules,dist,release,build",
+ "prefix-namespaces": [
+ "strauss",
+ "@php composer dump-autoload --optimize"
+ ],
+ "build": "php bin/package.php",
"package": "php bin/package.php"
},
"minimum-stability": "dev",
diff --git a/composer.lock b/composer.lock
index 6da9c51c..b6ae8b04 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "93e61bdbf87e6f44fded6a2612e71654",
+ "content-hash": "1819c58db15db4903d2abcd00a1cdf61",
"packages": [
{
"name": "hassankhan/config",
@@ -140,709 +140,852 @@
],
"packages-dev": [
{
- "name": "dealerdirect/phpcodesniffer-composer-installer",
- "version": "v1.2.1",
+ "name": "brianhenryie/simple-php-code-parser",
+ "version": "0.15.6",
"source": {
"type": "git",
- "url": "https://github.com/PHPCSStandards/composer-installer.git",
- "reference": "963f0c67bffde0eac41b56be71ac0e8ba132f0bd"
+ "url": "https://github.com/BrianHenryIE/Simple-PHP-Code-Parser.git",
+ "reference": "f8ce87b92595b2770f23f89d2be9dd4e6129043f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/963f0c67bffde0eac41b56be71ac0e8ba132f0bd",
- "reference": "963f0c67bffde0eac41b56be71ac0e8ba132f0bd",
+ "url": "https://api.github.com/repos/BrianHenryIE/Simple-PHP-Code-Parser/zipball/f8ce87b92595b2770f23f89d2be9dd4e6129043f",
+ "reference": "f8ce87b92595b2770f23f89d2be9dd4e6129043f",
"shasum": ""
},
"require": {
- "composer-plugin-api": "^2.2",
- "php": ">=5.4",
- "squizlabs/php_codesniffer": "^3.1.0 || ^4.0"
+ "nikic/php-parser": "^4.18 || ^5",
+ "php": ">=7.4",
+ "phpdocumentor/reflection-common": "~2.2",
+ "phpdocumentor/reflection-docblock": "~5.3",
+ "phpdocumentor/type-resolver": "~1.7.2",
+ "phpstan/phpdoc-parser": "~1.23",
+ "voku/simple-cache": "^4.1|^5"
},
"require-dev": {
- "composer/composer": "^2.2",
- "ext-json": "*",
- "ext-zip": "*",
- "php-parallel-lint/php-parallel-lint": "^1.4.0",
- "phpcompatibility/php-compatibility": "^9.0 || ^10.0.0@dev",
- "yoast/phpunit-polyfills": "^1.0"
- },
- "type": "composer-plugin",
- "extra": {
- "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
+ "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0"
},
+ "type": "library",
"autoload": {
"psr-4": {
- "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
+ "BrianHenryIE\\SimplePhpParser\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "MIT"
+ "Apache-2.0"
],
"authors": [
{
- "name": "Franck Nijhof",
- "email": "opensource@frenck.dev",
- "homepage": "https://frenck.dev",
- "role": "Open source developer"
+ "name": "Lars Moelleken",
+ "homepage": "https://www.moelleken.org/"
},
{
- "name": "Contributors",
- "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors"
+ "name": "Brian Henry",
+ "homepage": "https://BrianHenry.ie"
}
],
- "description": "PHP_CodeSniffer Standards Composer Installer Plugin",
+ "description": "Get a simple data structure from your php code.",
+ "homepage": "https://github.com/BrianHenryIE/Simple-PHP-Code-Parser",
"keywords": [
- "PHPCodeSniffer",
- "PHP_CodeSniffer",
- "code quality",
- "codesniffer",
- "composer",
- "installer",
- "phpcbf",
- "phpcs",
- "plugin",
- "qa",
- "quality",
- "standard",
- "standards",
- "style guide",
- "stylecheck",
- "tests"
+ "parser",
+ "php",
+ "phpdoc"
],
"support": {
- "issues": "https://github.com/PHPCSStandards/composer-installer/issues",
- "security": "https://github.com/PHPCSStandards/composer-installer/security/policy",
- "source": "https://github.com/PHPCSStandards/composer-installer"
+ "source": "https://github.com/BrianHenryIE/Simple-PHP-Code-Parser/tree/0.15.6"
},
"funding": [
{
- "url": "https://github.com/PHPCSStandards",
- "type": "github"
+ "url": "https://www.paypal.me/moelleken",
+ "type": "custom"
},
{
- "url": "https://github.com/jrfnl",
+ "url": "https://github.com/voku",
"type": "github"
},
{
- "url": "https://opencollective.com/php_codesniffer",
- "type": "open_collective"
- },
- {
- "url": "https://thanks.dev/u/gh/phpcsstandards",
- "type": "thanks_dev"
+ "url": "https://www.patreon.com/voku",
+ "type": "patreon"
}
],
- "time": "2026-05-06T08:26:05+00:00"
+ "time": "2026-06-25T20:32:36+00:00"
},
{
- "name": "myclabs/deep-copy",
- "version": "1.13.4",
+ "name": "brianhenryie/strauss",
+ "version": "0.22.6",
"source": {
"type": "git",
- "url": "https://github.com/myclabs/DeepCopy.git",
- "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a"
+ "url": "https://github.com/BrianHenryIE/strauss.git",
+ "reference": "4b1653b5d3c3036732ad9247e2dc77f81e8d47a3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a",
- "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a",
+ "url": "https://api.github.com/repos/BrianHenryIE/strauss/zipball/4b1653b5d3c3036732ad9247e2dc77f81e8d47a3",
+ "reference": "4b1653b5d3c3036732ad9247e2dc77f81e8d47a3",
"shasum": ""
},
"require": {
- "php": "^7.1 || ^8.0"
- },
- "conflict": {
- "doctrine/collections": "<1.6.8",
- "doctrine/common": "<2.13.3 || >=3 <3.2.2"
+ "brianhenryie/simple-php-code-parser": "^0.15.2",
+ "composer-runtime-api": "^2.0",
+ "composer/class-map-generator": "^1.6.0",
+ "composer/composer": "^2.6.0",
+ "elazar/flystream": "^0.5.0|^1",
+ "json-mapper/json-mapper": ">=2.0.0 <=2.22.3",
+ "league/flysystem": "^2.1|^3.0",
+ "league/flysystem-memory": "*",
+ "monolog/monolog": "^2.10",
+ "nikic/php-parser": "^5.4.0",
+ "symfony/console": "^4|^5|^6|^7",
+ "symfony/finder": "^4|^5|^6|^7"
+ },
+ "replace": {
+ "coenjacobs/mozart": "*"
},
"require-dev": {
- "doctrine/collections": "^1.6.8",
- "doctrine/common": "^2.13.3 || ^3.2.2",
- "phpspec/prophecy": "^1.10",
- "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
+ "brianhenryie/color-logger": "^1.2",
+ "clue/phar-composer": "^1.2",
+ "ext-json": "*",
+ "jaschilz/php-coverage-badger": "^2.0",
+ "mheap/phpunit-github-actions-printer": "^1.4",
+ "mockery/mockery": "^1.6",
+ "php": "^7.4|^8.0",
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpcov": "*",
+ "phpunit/phpunit": "^9|^10",
+ "squizlabs/php_codesniffer": "^3.5"
},
+ "bin": [
+ "bin/strauss"
+ ],
"type": "library",
"autoload": {
"files": [
- "src/DeepCopy/deep_copy.php"
+ "bootstrap.php"
],
"psr-4": {
- "DeepCopy\\": "src/DeepCopy/"
+ "BrianHenryIE\\Strauss\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
- "description": "Create deep copies (clones) of your objects",
- "keywords": [
- "clone",
- "copy",
- "duplicate",
- "object",
- "object graph"
- ],
- "support": {
- "issues": "https://github.com/myclabs/DeepCopy/issues",
- "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4"
- },
- "funding": [
+ "authors": [
{
- "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
- "type": "tidelift"
+ "name": "Brian Henry",
+ "email": "BrianHenryIE@gmail.com"
+ },
+ {
+ "name": "Coen Jacobs",
+ "email": "coenjacobs@gmail.com"
}
],
- "time": "2025-08-01T08:46:24+00:00"
+ "description": "Prefixes dependencies namespaces so they are unique to your plugin",
+ "support": {
+ "issues": "https://github.com/BrianHenryIE/strauss/issues",
+ "source": "https://github.com/BrianHenryIE/strauss/tree/0.22.6"
+ },
+ "time": "2025-06-28T00:39:35+00:00"
},
{
- "name": "nikic/php-parser",
- "version": "v5.7.0",
+ "name": "composer/ca-bundle",
+ "version": "1.5.12",
"source": {
"type": "git",
- "url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82"
+ "url": "https://github.com/composer/ca-bundle.git",
+ "reference": "00a2f4201641d5c53f7fc0195e6c8d9fcc321a78"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82",
- "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82",
+ "url": "https://api.github.com/repos/composer/ca-bundle/zipball/00a2f4201641d5c53f7fc0195e6c8d9fcc321a78",
+ "reference": "00a2f4201641d5c53f7fc0195e6c8d9fcc321a78",
"shasum": ""
},
"require": {
- "ext-ctype": "*",
- "ext-json": "*",
- "ext-tokenizer": "*",
- "php": ">=7.4"
+ "ext-openssl": "*",
+ "ext-pcre": "*",
+ "php": "^7.2 || ^8.0"
},
"require-dev": {
- "ircmaxell/php-yacc": "^0.0.7",
- "phpunit/phpunit": "^9.0"
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^8 || ^9",
+ "psr/log": "^1.0 || ^2.0 || ^3.0",
+ "symfony/process": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
- "bin": [
- "bin/php-parse"
- ],
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.x-dev"
+ "dev-main": "1.x-dev"
}
},
"autoload": {
"psr-4": {
- "PhpParser\\": "lib/PhpParser"
+ "Composer\\CaBundle\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Nikita Popov"
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
}
],
- "description": "A PHP parser written in PHP",
+ "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
"keywords": [
- "parser",
- "php"
+ "cabundle",
+ "cacert",
+ "certificate",
+ "ssl",
+ "tls"
],
"support": {
- "issues": "https://github.com/nikic/PHP-Parser/issues",
- "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0"
+ "irc": "irc://irc.freenode.org/composer",
+ "issues": "https://github.com/composer/ca-bundle/issues",
+ "source": "https://github.com/composer/ca-bundle/tree/1.5.12"
},
- "time": "2025-12-06T11:56:16+00:00"
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ }
+ ],
+ "time": "2026-05-19T11:26:22+00:00"
},
{
- "name": "phar-io/manifest",
- "version": "2.0.4",
+ "name": "composer/class-map-generator",
+ "version": "1.7.3",
"source": {
"type": "git",
- "url": "https://github.com/phar-io/manifest.git",
- "reference": "54750ef60c58e43759730615a392c31c80e23176"
+ "url": "https://github.com/composer/class-map-generator.git",
+ "reference": "86d8208fc3c649a3a999daf1a63c25201be2990f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176",
- "reference": "54750ef60c58e43759730615a392c31c80e23176",
+ "url": "https://api.github.com/repos/composer/class-map-generator/zipball/86d8208fc3c649a3a999daf1a63c25201be2990f",
+ "reference": "86d8208fc3c649a3a999daf1a63c25201be2990f",
"shasum": ""
},
"require": {
- "ext-dom": "*",
- "ext-libxml": "*",
- "ext-phar": "*",
- "ext-xmlwriter": "*",
- "phar-io/version": "^3.0.1",
- "php": "^7.2 || ^8.0"
+ "composer/pcre": "^2.1 || ^3.1",
+ "php": "^7.2 || ^8.0",
+ "symfony/finder": "^4.4 || ^5.3 || ^6 || ^7 || ^8"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.12 || ^2",
+ "phpstan/phpstan-deprecation-rules": "^1 || ^2",
+ "phpstan/phpstan-phpunit": "^1 || ^2",
+ "phpstan/phpstan-strict-rules": "^1.1 || ^2",
+ "phpunit/phpunit": "^8",
+ "symfony/filesystem": "^5.4 || ^6 || ^7 || ^8"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.0.x-dev"
+ "dev-main": "1.x-dev"
}
},
"autoload": {
- "classmap": [
- "src/"
- ]
+ "psr-4": {
+ "Composer\\ClassMapGenerator\\": "src"
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Arne Blankerts",
- "email": "arne@blankerts.de",
- "role": "Developer"
- },
- {
- "name": "Sebastian Heuer",
- "email": "sebastian@phpeople.de",
- "role": "Developer"
- },
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "Developer"
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "https://seld.be"
}
],
- "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
+ "description": "Utilities to scan PHP code and generate class maps.",
+ "keywords": [
+ "classmap"
+ ],
"support": {
- "issues": "https://github.com/phar-io/manifest/issues",
- "source": "https://github.com/phar-io/manifest/tree/2.0.4"
+ "issues": "https://github.com/composer/class-map-generator/issues",
+ "source": "https://github.com/composer/class-map-generator/tree/1.7.3"
},
"funding": [
{
- "url": "https://github.com/theseer",
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
"type": "github"
}
],
- "time": "2024-03-03T12:33:53+00:00"
+ "time": "2026-05-05T09:17:07+00:00"
},
{
- "name": "phar-io/version",
- "version": "3.2.1",
+ "name": "composer/composer",
+ "version": "2.10.1",
"source": {
"type": "git",
- "url": "https://github.com/phar-io/version.git",
- "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
+ "url": "https://github.com/composer/composer.git",
+ "reference": "4120703b9bda8795075047b40361d7ec4d2abe49"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
- "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
+ "url": "https://api.github.com/repos/composer/composer/zipball/4120703b9bda8795075047b40361d7ec4d2abe49",
+ "reference": "4120703b9bda8795075047b40361d7ec4d2abe49",
"shasum": ""
},
"require": {
- "php": "^7.2 || ^8.0"
+ "composer/ca-bundle": "^1.5",
+ "composer/class-map-generator": "^1.4.0",
+ "composer/metadata-minifier": "^1.0",
+ "composer/pcre": "^2.3 || ^3.3",
+ "composer/semver": "^3.3",
+ "composer/spdx-licenses": "^1.5.7",
+ "composer/xdebug-handler": "^2.0.2 || ^3.0.3",
+ "ext-json": "*",
+ "justinrainbow/json-schema": "^6.5.1",
+ "php": "^7.2.5 || ^8.0",
+ "psr/log": "^1.0 || ^2.0 || ^3.0",
+ "react/promise": "^3.3",
+ "seld/jsonlint": "^1.4",
+ "seld/phar-utils": "^1.2",
+ "seld/signal-handler": "^2.0",
+ "symfony/console": "^5.4.47 || ^6.4.25 || ^7.1.10 || ^8.0",
+ "symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.1.10 || ^8.0",
+ "symfony/finder": "^5.4.45 || ^6.4.24 || ^7.1.10 || ^8.0",
+ "symfony/polyfill-php73": "^1.24",
+ "symfony/polyfill-php80": "^1.24",
+ "symfony/polyfill-php81": "^1.24",
+ "symfony/polyfill-php84": "^1.30",
+ "symfony/process": "^5.4.47 || ^6.4.25 || ^7.1.10 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.11.8",
+ "phpstan/phpstan-deprecation-rules": "^1.2.0",
+ "phpstan/phpstan-phpunit": "^1.4.0",
+ "phpstan/phpstan-strict-rules": "^1.6.0",
+ "phpstan/phpstan-symfony": "^1.4.0",
+ "symfony/phpunit-bridge": "^6.4.25 || ^7.3.3 || ^8.0"
+ },
+ "suggest": {
+ "ext-curl": "Provides HTTP support (will fallback to PHP streams if missing)",
+ "ext-openssl": "Enables access to repositories and packages over HTTPS",
+ "ext-zip": "Allows direct extraction of ZIP archives (unzip/7z binaries will be used instead if available)",
+ "ext-zlib": "Enables gzip for HTTP requests"
},
+ "bin": [
+ "bin/composer"
+ ],
"type": "library",
+ "extra": {
+ "phpstan": {
+ "includes": [
+ "phpstan/rules.neon"
+ ]
+ },
+ "branch-alias": {
+ "dev-main": "2.10-dev"
+ }
+ },
"autoload": {
- "classmap": [
- "src/"
- ]
+ "psr-4": {
+ "Composer\\": "src/Composer/"
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Arne Blankerts",
- "email": "arne@blankerts.de",
- "role": "Developer"
- },
- {
- "name": "Sebastian Heuer",
- "email": "sebastian@phpeople.de",
- "role": "Developer"
+ "name": "Nils Adermann",
+ "email": "naderman@naderman.de",
+ "homepage": "https://www.naderman.de"
},
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "Developer"
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "https://seld.be"
}
],
- "description": "Library for handling version information and constraints",
+ "description": "Composer helps you declare, manage and install dependencies of PHP projects. It ensures you have the right stack everywhere.",
+ "homepage": "https://getcomposer.org/",
+ "keywords": [
+ "autoload",
+ "dependency",
+ "package"
+ ],
"support": {
- "issues": "https://github.com/phar-io/version/issues",
- "source": "https://github.com/phar-io/version/tree/3.2.1"
+ "irc": "ircs://irc.libera.chat:6697/composer",
+ "issues": "https://github.com/composer/composer/issues",
+ "security": "https://github.com/composer/composer/security/policy",
+ "source": "https://github.com/composer/composer/tree/2.10.1"
},
- "time": "2022-02-21T01:04:05+00:00"
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ }
+ ],
+ "time": "2026-06-04T08:25:59+00:00"
},
{
- "name": "phpcompatibility/php-compatibility",
- "version": "9.3.5",
+ "name": "composer/metadata-minifier",
+ "version": "1.0.0",
"source": {
"type": "git",
- "url": "https://github.com/PHPCompatibility/PHPCompatibility.git",
- "reference": "9fb324479acf6f39452e0655d2429cc0d3914243"
+ "url": "https://github.com/composer/metadata-minifier.git",
+ "reference": "c549d23829536f0d0e984aaabbf02af91f443207"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9fb324479acf6f39452e0655d2429cc0d3914243",
- "reference": "9fb324479acf6f39452e0655d2429cc0d3914243",
+ "url": "https://api.github.com/repos/composer/metadata-minifier/zipball/c549d23829536f0d0e984aaabbf02af91f443207",
+ "reference": "c549d23829536f0d0e984aaabbf02af91f443207",
"shasum": ""
},
"require": {
- "php": ">=5.3",
- "squizlabs/php_codesniffer": "^2.3 || ^3.0.2"
- },
- "conflict": {
- "squizlabs/php_codesniffer": "2.6.2"
+ "php": "^5.3.2 || ^7.0 || ^8.0"
},
"require-dev": {
- "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0"
+ "composer/composer": "^2",
+ "phpstan/phpstan": "^0.12.55",
+ "symfony/phpunit-bridge": "^4.2 || ^5"
},
- "suggest": {
- "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.",
- "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues."
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\MetadataMinifier\\": "src"
+ }
},
- "type": "phpcodesniffer-standard",
"notification-url": "https://packagist.org/downloads/",
"license": [
- "LGPL-3.0-or-later"
+ "MIT"
],
"authors": [
{
- "name": "Wim Godden",
- "homepage": "https://github.com/wimg",
- "role": "lead"
- },
- {
- "name": "Juliette Reinders Folmer",
- "homepage": "https://github.com/jrfnl",
- "role": "lead"
- },
- {
- "name": "Contributors",
- "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors"
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
}
],
- "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.",
- "homepage": "http://techblog.wimgodden.be/tag/codesniffer/",
+ "description": "Small utility library that handles metadata minification and expansion.",
"keywords": [
- "compatibility",
- "phpcs",
- "standards"
+ "composer",
+ "compression"
],
"support": {
- "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues",
- "source": "https://github.com/PHPCompatibility/PHPCompatibility"
+ "issues": "https://github.com/composer/metadata-minifier/issues",
+ "source": "https://github.com/composer/metadata-minifier/tree/1.0.0"
},
- "time": "2019-12-27T09:44:58+00:00"
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2021-04-07T13:37:33+00:00"
},
{
- "name": "phpcompatibility/phpcompatibility-paragonie",
- "version": "1.3.4",
+ "name": "composer/pcre",
+ "version": "3.4.0",
"source": {
"type": "git",
- "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git",
- "reference": "244d7b04fc4bc2117c15f5abe23eb933b5f02bbf"
+ "url": "https://github.com/composer/pcre.git",
+ "reference": "d5a341b3fb61f3001970940afb1d332968a183ed"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/244d7b04fc4bc2117c15f5abe23eb933b5f02bbf",
- "reference": "244d7b04fc4bc2117c15f5abe23eb933b5f02bbf",
+ "url": "https://api.github.com/repos/composer/pcre/zipball/d5a341b3fb61f3001970940afb1d332968a183ed",
+ "reference": "d5a341b3fb61f3001970940afb1d332968a183ed",
"shasum": ""
},
"require": {
- "phpcompatibility/php-compatibility": "^9.0"
+ "php": "^7.4 || ^8.0"
+ },
+ "conflict": {
+ "phpstan/phpstan": "<2.2.2"
},
"require-dev": {
- "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
- "paragonie/random_compat": "dev-master",
- "paragonie/sodium_compat": "dev-master"
+ "phpstan/phpstan": "^2",
+ "phpstan/phpstan-deprecation-rules": "^2",
+ "phpstan/phpstan-strict-rules": "^2",
+ "phpunit/phpunit": "^9"
},
- "suggest": {
- "dealerdirect/phpcodesniffer-composer-installer": "^1.0 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.",
- "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues."
+ "type": "library",
+ "extra": {
+ "phpstan": {
+ "includes": [
+ "extension.neon"
+ ]
+ },
+ "branch-alias": {
+ "dev-main": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\Pcre\\": "src"
+ }
},
- "type": "phpcodesniffer-standard",
"notification-url": "https://packagist.org/downloads/",
"license": [
- "LGPL-3.0-or-later"
+ "MIT"
],
"authors": [
{
- "name": "Wim Godden",
- "role": "lead"
- },
- {
- "name": "Juliette Reinders Folmer",
- "role": "lead"
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
}
],
- "description": "A set of rulesets for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by the Paragonie polyfill libraries.",
- "homepage": "http://phpcompatibility.com/",
+ "description": "PCRE wrapping library that offers type-safe preg_* replacements.",
"keywords": [
- "compatibility",
- "paragonie",
- "phpcs",
- "polyfill",
- "standards",
- "static analysis"
+ "PCRE",
+ "preg",
+ "regex",
+ "regular expression"
],
"support": {
- "issues": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues",
- "security": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/security/policy",
- "source": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie"
+ "issues": "https://github.com/composer/pcre/issues",
+ "source": "https://github.com/composer/pcre/tree/3.4.0"
},
"funding": [
{
- "url": "https://github.com/PHPCompatibility",
- "type": "github"
+ "url": "https://packagist.com",
+ "type": "custom"
},
{
- "url": "https://github.com/jrfnl",
+ "url": "https://github.com/composer",
"type": "github"
- },
- {
- "url": "https://opencollective.com/php_codesniffer",
- "type": "open_collective"
- },
- {
- "url": "https://thanks.dev/u/gh/phpcompatibility",
- "type": "thanks_dev"
}
],
- "time": "2025-09-19T17:43:28+00:00"
+ "time": "2026-06-07T11:47:49+00:00"
},
{
- "name": "phpcompatibility/phpcompatibility-wp",
- "version": "2.1.8",
+ "name": "composer/semver",
+ "version": "3.4.4",
"source": {
"type": "git",
- "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git",
- "reference": "7c8d18b4d90dac9e86b0869a608fa09158e168fa"
+ "url": "https://github.com/composer/semver.git",
+ "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/7c8d18b4d90dac9e86b0869a608fa09158e168fa",
- "reference": "7c8d18b4d90dac9e86b0869a608fa09158e168fa",
+ "url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95",
+ "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95",
"shasum": ""
},
"require": {
- "phpcompatibility/php-compatibility": "^9.0",
- "phpcompatibility/phpcompatibility-paragonie": "^1.0",
- "squizlabs/php_codesniffer": "^3.3"
+ "php": "^5.3.2 || ^7.0 || ^8.0"
},
"require-dev": {
- "dealerdirect/phpcodesniffer-composer-installer": "^1.0"
+ "phpstan/phpstan": "^1.11",
+ "symfony/phpunit-bridge": "^3 || ^7"
},
- "suggest": {
- "dealerdirect/phpcodesniffer-composer-installer": "^1.0 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.",
- "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues."
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\Semver\\": "src"
+ }
},
- "type": "phpcodesniffer-standard",
"notification-url": "https://packagist.org/downloads/",
"license": [
- "LGPL-3.0-or-later"
+ "MIT"
],
"authors": [
{
- "name": "Wim Godden",
- "role": "lead"
+ "name": "Nils Adermann",
+ "email": "naderman@naderman.de",
+ "homepage": "http://www.naderman.de"
},
{
- "name": "Juliette Reinders Folmer",
- "role": "lead"
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ },
+ {
+ "name": "Rob Bast",
+ "email": "rob.bast@gmail.com",
+ "homepage": "http://robbast.nl"
}
],
- "description": "A ruleset for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by WordPress.",
- "homepage": "http://phpcompatibility.com/",
+ "description": "Semver library that offers utilities, version constraint parsing and validation.",
"keywords": [
- "compatibility",
- "phpcs",
- "standards",
- "static analysis",
- "wordpress"
+ "semantic",
+ "semver",
+ "validation",
+ "versioning"
],
"support": {
- "issues": "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues",
- "security": "https://github.com/PHPCompatibility/PHPCompatibilityWP/security/policy",
- "source": "https://github.com/PHPCompatibility/PHPCompatibilityWP"
+ "irc": "ircs://irc.libera.chat:6697/composer",
+ "issues": "https://github.com/composer/semver/issues",
+ "source": "https://github.com/composer/semver/tree/3.4.4"
},
"funding": [
{
- "url": "https://github.com/PHPCompatibility",
- "type": "github"
+ "url": "https://packagist.com",
+ "type": "custom"
},
{
- "url": "https://github.com/jrfnl",
+ "url": "https://github.com/composer",
"type": "github"
- },
- {
- "url": "https://opencollective.com/php_codesniffer",
- "type": "open_collective"
- },
- {
- "url": "https://thanks.dev/u/gh/phpcompatibility",
- "type": "thanks_dev"
}
],
- "time": "2025-10-18T00:05:59+00:00"
+ "time": "2025-08-20T19:15:30+00:00"
},
{
- "name": "phpcsstandards/phpcsextra",
- "version": "1.5.0",
+ "name": "composer/spdx-licenses",
+ "version": "1.6.0",
"source": {
"type": "git",
- "url": "https://github.com/PHPCSStandards/PHPCSExtra.git",
- "reference": "b598aa890815b8df16363271b659d73280129101"
+ "url": "https://github.com/composer/spdx-licenses.git",
+ "reference": "5ecd0cb4177696f9fd48f1605dda81db3dee7889"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPCSStandards/PHPCSExtra/zipball/b598aa890815b8df16363271b659d73280129101",
- "reference": "b598aa890815b8df16363271b659d73280129101",
+ "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/5ecd0cb4177696f9fd48f1605dda81db3dee7889",
+ "reference": "5ecd0cb4177696f9fd48f1605dda81db3dee7889",
"shasum": ""
},
"require": {
- "php": ">=5.4",
- "phpcsstandards/phpcsutils": "^1.2.0",
- "squizlabs/php_codesniffer": "^3.13.5 || ^4.0.1"
+ "php": "^7.2 || ^8.0"
},
"require-dev": {
- "php-parallel-lint/php-console-highlighter": "^1.0",
- "php-parallel-lint/php-parallel-lint": "^1.4.0",
- "phpcsstandards/phpcsdevcs": "^1.2.0",
- "phpcsstandards/phpcsdevtools": "^1.2.1",
- "phpunit/phpunit": "^4.5 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4"
+ "phpstan/phpstan": "^1.11",
+ "symfony/phpunit-bridge": "^6.4.25 || ^7.3.3 || ^8.0"
},
- "type": "phpcodesniffer-standard",
+ "type": "library",
"extra": {
"branch-alias": {
- "dev-stable": "1.x-dev",
- "dev-develop": "1.x-dev"
+ "dev-main": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\Spdx\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "LGPL-3.0-or-later"
+ "MIT"
],
"authors": [
{
- "name": "Juliette Reinders Folmer",
- "homepage": "https://github.com/jrfnl",
- "role": "lead"
+ "name": "Nils Adermann",
+ "email": "naderman@naderman.de",
+ "homepage": "http://www.naderman.de"
},
{
- "name": "Contributors",
- "homepage": "https://github.com/PHPCSStandards/PHPCSExtra/graphs/contributors"
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ },
+ {
+ "name": "Rob Bast",
+ "email": "rob.bast@gmail.com",
+ "homepage": "http://robbast.nl"
}
],
- "description": "A collection of sniffs and standards for use with PHP_CodeSniffer.",
+ "description": "SPDX licenses list and validation library.",
"keywords": [
- "PHP_CodeSniffer",
- "phpcbf",
- "phpcodesniffer-standard",
- "phpcs",
- "standards",
- "static analysis"
+ "license",
+ "spdx",
+ "validator"
],
"support": {
- "issues": "https://github.com/PHPCSStandards/PHPCSExtra/issues",
- "security": "https://github.com/PHPCSStandards/PHPCSExtra/security/policy",
- "source": "https://github.com/PHPCSStandards/PHPCSExtra"
+ "irc": "ircs://irc.libera.chat:6697/composer",
+ "issues": "https://github.com/composer/spdx-licenses/issues",
+ "source": "https://github.com/composer/spdx-licenses/tree/1.6.0"
},
"funding": [
{
- "url": "https://github.com/PHPCSStandards",
- "type": "github"
+ "url": "https://packagist.com",
+ "type": "custom"
},
{
- "url": "https://github.com/jrfnl",
+ "url": "https://github.com/composer",
"type": "github"
- },
- {
- "url": "https://opencollective.com/php_codesniffer",
- "type": "open_collective"
- },
- {
- "url": "https://thanks.dev/u/gh/phpcsstandards",
- "type": "thanks_dev"
}
],
- "time": "2025-11-12T23:06:57+00:00"
+ "time": "2026-04-08T20:18:39+00:00"
},
{
- "name": "phpcsstandards/phpcsutils",
- "version": "1.2.2",
+ "name": "composer/xdebug-handler",
+ "version": "3.0.5",
"source": {
"type": "git",
- "url": "https://github.com/PHPCSStandards/PHPCSUtils.git",
- "reference": "c216317e96c8b3f5932808f9b0f1f7a14e3bbf55"
+ "url": "https://github.com/composer/xdebug-handler.git",
+ "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/c216317e96c8b3f5932808f9b0f1f7a14e3bbf55",
- "reference": "c216317e96c8b3f5932808f9b0f1f7a14e3bbf55",
+ "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef",
+ "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef",
"shasum": ""
},
"require": {
- "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7 || ^1.0",
- "php": ">=5.4",
- "squizlabs/php_codesniffer": "^3.13.5 || ^4.0.1"
+ "composer/pcre": "^1 || ^2 || ^3",
+ "php": "^7.2.5 || ^8.0",
+ "psr/log": "^1 || ^2 || ^3"
},
"require-dev": {
- "ext-filter": "*",
- "php-parallel-lint/php-console-highlighter": "^1.0",
- "php-parallel-lint/php-parallel-lint": "^1.4.0",
- "phpcsstandards/phpcsdevcs": "^1.2.0",
- "yoast/phpunit-polyfills": "^1.1.0 || ^2.0.0 || ^3.0.0"
- },
- "type": "phpcodesniffer-standard",
- "extra": {
- "branch-alias": {
- "dev-stable": "1.x-dev",
- "dev-develop": "1.x-dev"
- }
+ "phpstan/phpstan": "^1.0",
+ "phpstan/phpstan-strict-rules": "^1.1",
+ "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5"
},
+ "type": "library",
"autoload": {
- "classmap": [
- "PHPCSUtils/"
- ]
+ "psr-4": {
+ "Composer\\XdebugHandler\\": "src"
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "LGPL-3.0-or-later"
+ "MIT"
],
"authors": [
{
- "name": "Juliette Reinders Folmer",
- "homepage": "https://github.com/jrfnl",
- "role": "lead"
- },
- {
- "name": "Contributors",
- "homepage": "https://github.com/PHPCSStandards/PHPCSUtils/graphs/contributors"
+ "name": "John Stevenson",
+ "email": "john-stevenson@blueyonder.co.uk"
}
],
- "description": "A suite of utility functions for use with PHP_CodeSniffer",
- "homepage": "https://phpcsutils.com/",
+ "description": "Restarts a process without Xdebug.",
"keywords": [
- "PHP_CodeSniffer",
- "phpcbf",
- "phpcodesniffer-standard",
- "phpcs",
- "phpcs3",
- "phpcs4",
- "standards",
- "static analysis",
- "tokens",
- "utility"
+ "Xdebug",
+ "performance"
],
"support": {
- "docs": "https://phpcsutils.com/",
- "issues": "https://github.com/PHPCSStandards/PHPCSUtils/issues",
- "security": "https://github.com/PHPCSStandards/PHPCSUtils/security/policy",
- "source": "https://github.com/PHPCSStandards/PHPCSUtils"
+ "irc": "ircs://irc.libera.chat:6697/composer",
+ "issues": "https://github.com/composer/xdebug-handler/issues",
+ "source": "https://github.com/composer/xdebug-handler/tree/3.0.5"
},
"funding": [
{
- "url": "https://github.com/PHPCSStandards",
- "type": "github"
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-05-06T16:37:16+00:00"
+ },
+ {
+ "name": "dealerdirect/phpcodesniffer-composer-installer",
+ "version": "v1.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCSStandards/composer-installer.git",
+ "reference": "963f0c67bffde0eac41b56be71ac0e8ba132f0bd"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/963f0c67bffde0eac41b56be71ac0e8ba132f0bd",
+ "reference": "963f0c67bffde0eac41b56be71ac0e8ba132f0bd",
+ "shasum": ""
+ },
+ "require": {
+ "composer-plugin-api": "^2.2",
+ "php": ">=5.4",
+ "squizlabs/php_codesniffer": "^3.1.0 || ^4.0"
+ },
+ "require-dev": {
+ "composer/composer": "^2.2",
+ "ext-json": "*",
+ "ext-zip": "*",
+ "php-parallel-lint/php-parallel-lint": "^1.4.0",
+ "phpcompatibility/php-compatibility": "^9.0 || ^10.0.0@dev",
+ "yoast/phpunit-polyfills": "^1.0"
+ },
+ "type": "composer-plugin",
+ "extra": {
+ "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin"
+ },
+ "autoload": {
+ "psr-4": {
+ "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Franck Nijhof",
+ "email": "opensource@frenck.dev",
+ "homepage": "https://frenck.dev",
+ "role": "Open source developer"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors"
+ }
+ ],
+ "description": "PHP_CodeSniffer Standards Composer Installer Plugin",
+ "keywords": [
+ "PHPCodeSniffer",
+ "PHP_CodeSniffer",
+ "code quality",
+ "codesniffer",
+ "composer",
+ "installer",
+ "phpcbf",
+ "phpcs",
+ "plugin",
+ "qa",
+ "quality",
+ "standard",
+ "standards",
+ "style guide",
+ "stylecheck",
+ "tests"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPCSStandards/composer-installer/issues",
+ "security": "https://github.com/PHPCSStandards/composer-installer/security/policy",
+ "source": "https://github.com/PHPCSStandards/composer-installer"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/PHPCSStandards",
+ "type": "github"
},
{
"url": "https://github.com/jrfnl",
@@ -857,48 +1000,3114 @@
"type": "thanks_dev"
}
],
- "time": "2025-12-08T14:27:58+00:00"
+ "time": "2026-05-06T08:26:05+00:00"
},
{
- "name": "phpunit/php-code-coverage",
- "version": "11.0.12",
+ "name": "doctrine/deprecations",
+ "version": "1.1.6",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56"
+ "url": "https://github.com/doctrine/deprecations.git",
+ "reference": "d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2c1ed04922802c15e1de5d7447b4856de949cf56",
- "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56",
+ "url": "https://api.github.com/repos/doctrine/deprecations/zipball/d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca",
+ "reference": "d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca",
"shasum": ""
},
"require": {
- "ext-dom": "*",
- "ext-libxml": "*",
- "ext-xmlwriter": "*",
- "nikic/php-parser": "^5.7.0",
- "php": ">=8.2",
- "phpunit/php-file-iterator": "^5.1.0",
- "phpunit/php-text-template": "^4.0.1",
- "sebastian/code-unit-reverse-lookup": "^4.0.1",
- "sebastian/complexity": "^4.0.1",
- "sebastian/environment": "^7.2.1",
- "sebastian/lines-of-code": "^3.0.1",
- "sebastian/version": "^5.0.2",
- "theseer/tokenizer": "^1.3.1"
+ "php": "^7.1 || ^8.0"
+ },
+ "conflict": {
+ "phpunit/phpunit": "<=7.5 || >=14"
},
"require-dev": {
- "phpunit/phpunit": "^11.5.46"
+ "doctrine/coding-standard": "^9 || ^12 || ^14",
+ "phpstan/phpstan": "1.4.10 || 2.1.30",
+ "phpstan/phpstan-phpunit": "^1.0 || ^2",
+ "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12.4 || ^13.0",
+ "psr/log": "^1 || ^2 || ^3"
},
"suggest": {
- "ext-pcov": "PHP extension that provides line coverage",
- "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage"
+ "psr/log": "Allows logging deprecations via PSR-3 logger implementation"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Deprecations\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.",
+ "homepage": "https://www.doctrine-project.org/",
+ "support": {
+ "issues": "https://github.com/doctrine/deprecations/issues",
+ "source": "https://github.com/doctrine/deprecations/tree/1.1.6"
+ },
+ "time": "2026-02-07T07:09:04+00:00"
+ },
+ {
+ "name": "elazar/flystream",
+ "version": "1.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/elazar/flystream.git",
+ "reference": "5f4233b3f20e17bba474dd6c631ed347d23ff98c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/elazar/flystream/zipball/5f4233b3f20e17bba474dd6c631ed347d23ff98c",
+ "reference": "5f4233b3f20e17bba474dd6c631ed347d23ff98c",
+ "shasum": ""
+ },
+ "require": {
+ "league/flysystem": "^2.1 || ^3.0",
+ "php": "^8.1",
+ "psr/container": "^2.0",
+ "psr/log": "^2.0 || ^3.0"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^3.0",
+ "league/flysystem-memory": "^2.0 || ^3.0",
+ "monolog/monolog": "^3.0",
+ "nunomaduro/collision": "^6 || ^7 || ^8",
+ "pestphp/pest": "^1 || ^2 || ^3"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Elazar\\Flystream\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Matthew Turland",
+ "email": "me@matthewturland.com"
+ }
+ ],
+ "description": "PHP stream wrapper for Flysystem v2 and v3",
+ "support": {
+ "issues": "https://github.com/elazar/flystream/issues",
+ "source": "https://github.com/elazar/flystream/tree/1.4.0"
+ },
+ "time": "2025-05-17T14:10:53+00:00"
+ },
+ {
+ "name": "json-mapper/json-mapper",
+ "version": "2.22.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/JsonMapper/JsonMapper.git",
+ "reference": "a0ca67d3201f1379a2df9ef43cd3db5b70421274"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/JsonMapper/JsonMapper/zipball/a0ca67d3201f1379a2df9ef43cd3db5b70421274",
+ "reference": "a0ca67d3201f1379a2df9ef43cd3db5b70421274",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "myclabs/php-enum": "^1.7",
+ "nikic/php-parser": "^4.13 || ^5.0",
+ "php": "^7.1 || ^8.0",
+ "psr/log": "^1.1 || ^2.0 || ^3.0",
+ "psr/simple-cache": " ^1.0 || ^2.0 || ^3.0",
+ "symfony/cache": "^4.4 || ^5.0 || ^6.0 || ^7.0",
+ "symfony/polyfill-php73": "^1.18"
+ },
+ "require-dev": {
+ "guzzlehttp/guzzle": "^6.5 || ^7.0",
+ "php-coveralls/php-coveralls": "^2.4",
+ "phpstan/phpstan": "^0.12.14",
+ "phpstan/phpstan-phpunit": "^0.12.17",
+ "phpunit/phpunit": "^7.5 || ^8.5 || ^9.0",
+ "squizlabs/php_codesniffer": "^3.5",
+ "symfony/console": "^2.1 || ^3.0 || ^4.0 || ^5.0",
+ "vimeo/psalm": "^4.10 || ^5.0"
+ },
+ "suggest": {
+ "json-mapper/laravel-package": "Use JsonMapper directly with Laravel",
+ "json-mapper/symfony-bundle": "Use JsonMapper directly with Symfony"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "JsonMapper\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Map JSON structures to PHP classes",
+ "homepage": "https://jsonmapper.net",
+ "keywords": [
+ "json",
+ "jsonmapper",
+ "mapper",
+ "middleware"
+ ],
+ "support": {
+ "docs": "https://jsonmapper.net",
+ "issues": "https://github.com/JsonMapper/JsonMapper/issues",
+ "source": "https://github.com/JsonMapper/JsonMapper"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/DannyvdSluijs",
+ "type": "github"
+ }
+ ],
+ "time": "2025-02-03T11:54:11+00:00"
+ },
+ {
+ "name": "justinrainbow/json-schema",
+ "version": "6.10.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/jsonrainbow/json-schema.git",
+ "reference": "8b1308a9d7bdbdb20ce87ef920f82b4564bb2d33"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/8b1308a9d7bdbdb20ce87ef920f82b4564bb2d33",
+ "reference": "8b1308a9d7bdbdb20ce87ef920f82b4564bb2d33",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "marc-mabe/php-enum": "^4.4",
+ "php": "^7.2 || ^8.0"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "3.3.0",
+ "json-schema/json-schema-test-suite": "dev-main",
+ "marc-mabe/php-enum-phpstan": "^2.0",
+ "phpspec/prophecy": "^1.19",
+ "phpstan/phpstan": "^1.12",
+ "phpunit/phpunit": "^8.5"
+ },
+ "bin": [
+ "bin/validate-json"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "6.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "JsonSchema\\": "src/JsonSchema/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Bruno Prieto Reis",
+ "email": "bruno.p.reis@gmail.com"
+ },
+ {
+ "name": "Justin Rainbow",
+ "email": "justin.rainbow@gmail.com"
+ },
+ {
+ "name": "Igor Wiedler",
+ "email": "igor@wiedler.ch"
+ },
+ {
+ "name": "Robert Schönthal",
+ "email": "seroscho@googlemail.com"
+ }
+ ],
+ "description": "A library to validate a json schema.",
+ "homepage": "https://github.com/jsonrainbow/json-schema",
+ "keywords": [
+ "json",
+ "schema"
+ ],
+ "support": {
+ "issues": "https://github.com/jsonrainbow/json-schema/issues",
+ "source": "https://github.com/jsonrainbow/json-schema/tree/6.10.0"
+ },
+ "time": "2026-06-16T20:50:26+00:00"
+ },
+ {
+ "name": "league/flysystem",
+ "version": "3.35.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/flysystem.git",
+ "reference": "f23af6c5aafd958a7593029a271d77baf5ed793c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/f23af6c5aafd958a7593029a271d77baf5ed793c",
+ "reference": "f23af6c5aafd958a7593029a271d77baf5ed793c",
+ "shasum": ""
+ },
+ "require": {
+ "league/flysystem-local": "^3.0.0",
+ "league/mime-type-detection": "^1.0.0",
+ "php": "^8.0.2"
+ },
+ "conflict": {
+ "async-aws/core": "<1.19.0",
+ "async-aws/s3": "<1.14.0",
+ "aws/aws-sdk-php": "3.209.31 || 3.210.0",
+ "guzzlehttp/guzzle": "<7.0",
+ "guzzlehttp/ringphp": "<1.1.1",
+ "phpseclib/phpseclib": "3.0.15",
+ "symfony/http-client": "<5.2"
+ },
+ "require-dev": {
+ "async-aws/s3": "^1.5 || ^2.0",
+ "async-aws/simple-s3": "^1.1 || ^2.0",
+ "aws/aws-sdk-php": "^3.295.10",
+ "composer/semver": "^3.0",
+ "ext-fileinfo": "*",
+ "ext-ftp": "*",
+ "ext-mongodb": "^1.3|^2",
+ "ext-zip": "*",
+ "friendsofphp/php-cs-fixer": "^3.5",
+ "google/cloud-storage": "^1.23",
+ "guzzlehttp/psr7": "^2.6",
+ "microsoft/azure-storage-blob": "^1.1",
+ "mongodb/mongodb": "^1.2|^2",
+ "phpseclib/phpseclib": "^3.0.36",
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^9.5.11|^10.0",
+ "sabre/dav": "^4.6.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "League\\Flysystem\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Frank de Jonge",
+ "email": "info@frankdejonge.nl"
+ }
+ ],
+ "description": "File storage abstraction for PHP",
+ "keywords": [
+ "WebDAV",
+ "aws",
+ "cloud",
+ "file",
+ "files",
+ "filesystem",
+ "filesystems",
+ "ftp",
+ "s3",
+ "sftp",
+ "storage"
+ ],
+ "support": {
+ "issues": "https://github.com/thephpleague/flysystem/issues",
+ "source": "https://github.com/thephpleague/flysystem/tree/3.35.1"
+ },
+ "time": "2026-06-25T06:52:23+00:00"
+ },
+ {
+ "name": "league/flysystem-local",
+ "version": "3.31.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/flysystem-local.git",
+ "reference": "2f669db18a4c20c755c2bb7d3a7b0b2340488079"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/2f669db18a4c20c755c2bb7d3a7b0b2340488079",
+ "reference": "2f669db18a4c20c755c2bb7d3a7b0b2340488079",
+ "shasum": ""
+ },
+ "require": {
+ "ext-fileinfo": "*",
+ "league/flysystem": "^3.0.0",
+ "league/mime-type-detection": "^1.0.0",
+ "php": "^8.0.2"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "League\\Flysystem\\Local\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Frank de Jonge",
+ "email": "info@frankdejonge.nl"
+ }
+ ],
+ "description": "Local filesystem adapter for Flysystem.",
+ "keywords": [
+ "Flysystem",
+ "file",
+ "files",
+ "filesystem",
+ "local"
+ ],
+ "support": {
+ "source": "https://github.com/thephpleague/flysystem-local/tree/3.31.0"
+ },
+ "time": "2026-01-23T15:30:45+00:00"
+ },
+ {
+ "name": "league/flysystem-memory",
+ "version": "3.31.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/flysystem-memory.git",
+ "reference": "b2d1700ed1215684e7276e55bcacf350e0e06ff9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/flysystem-memory/zipball/b2d1700ed1215684e7276e55bcacf350e0e06ff9",
+ "reference": "b2d1700ed1215684e7276e55bcacf350e0e06ff9",
+ "shasum": ""
+ },
+ "require": {
+ "ext-fileinfo": "*",
+ "league/flysystem": "^3.0.0",
+ "php": "^8.0.2"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "League\\Flysystem\\InMemory\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Frank de Jonge",
+ "email": "info@frankdejonge.nl"
+ }
+ ],
+ "description": "In-memory filesystem adapter for Flysystem.",
+ "keywords": [
+ "Flysystem",
+ "file",
+ "files",
+ "filesystem",
+ "memory"
+ ],
+ "support": {
+ "source": "https://github.com/thephpleague/flysystem-memory/tree/3.31.0"
+ },
+ "time": "2026-01-23T15:30:45+00:00"
+ },
+ {
+ "name": "league/mime-type-detection",
+ "version": "1.16.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/mime-type-detection.git",
+ "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/2d6702ff215bf922936ccc1ad31007edc76451b9",
+ "reference": "2d6702ff215bf922936ccc1ad31007edc76451b9",
+ "shasum": ""
+ },
+ "require": {
+ "ext-fileinfo": "*",
+ "php": "^7.4 || ^8.0"
+ },
+ "require-dev": {
+ "friendsofphp/php-cs-fixer": "^3.2",
+ "phpstan/phpstan": "^0.12.68",
+ "phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "League\\MimeTypeDetection\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Frank de Jonge",
+ "email": "info@frankdejonge.nl"
+ }
+ ],
+ "description": "Mime-type detection for Flysystem",
+ "support": {
+ "issues": "https://github.com/thephpleague/mime-type-detection/issues",
+ "source": "https://github.com/thephpleague/mime-type-detection/tree/1.16.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/frankdejonge",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/league/flysystem",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-09-21T08:32:55+00:00"
+ },
+ {
+ "name": "marc-mabe/php-enum",
+ "version": "v4.7.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/marc-mabe/php-enum.git",
+ "reference": "bb426fcdd65c60fb3638ef741e8782508fda7eef"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/marc-mabe/php-enum/zipball/bb426fcdd65c60fb3638ef741e8782508fda7eef",
+ "reference": "bb426fcdd65c60fb3638ef741e8782508fda7eef",
+ "shasum": ""
+ },
+ "require": {
+ "ext-reflection": "*",
+ "php": "^7.1 | ^8.0"
+ },
+ "require-dev": {
+ "phpbench/phpbench": "^0.16.10 || ^1.0.4",
+ "phpstan/phpstan": "^1.3.1",
+ "phpunit/phpunit": "^7.5.20 | ^8.5.22 | ^9.5.11",
+ "vimeo/psalm": "^4.17.0 | ^5.26.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-3.x": "3.2-dev",
+ "dev-master": "4.7-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "MabeEnum\\": "src/"
+ },
+ "classmap": [
+ "stubs/Stringable.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Marc Bennewitz",
+ "email": "dev@mabe.berlin",
+ "homepage": "https://mabe.berlin/",
+ "role": "Lead"
+ }
+ ],
+ "description": "Simple and fast implementation of enumerations with native PHP",
+ "homepage": "https://github.com/marc-mabe/php-enum",
+ "keywords": [
+ "enum",
+ "enum-map",
+ "enum-set",
+ "enumeration",
+ "enumerator",
+ "enummap",
+ "enumset",
+ "map",
+ "set",
+ "type",
+ "type-hint",
+ "typehint"
+ ],
+ "support": {
+ "issues": "https://github.com/marc-mabe/php-enum/issues",
+ "source": "https://github.com/marc-mabe/php-enum/tree/v4.7.2"
+ },
+ "time": "2025-09-14T11:18:39+00:00"
+ },
+ {
+ "name": "monolog/monolog",
+ "version": "2.11.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Seldaek/monolog.git",
+ "reference": "37308608e599f34a1a4845b16440047ec98a172a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Seldaek/monolog/zipball/37308608e599f34a1a4845b16440047ec98a172a",
+ "reference": "37308608e599f34a1a4845b16440047ec98a172a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2",
+ "psr/log": "^1.0.1 || ^2.0 || ^3.0"
+ },
+ "provide": {
+ "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0"
+ },
+ "require-dev": {
+ "aws/aws-sdk-php": "^2.4.9 || ^3.0",
+ "doctrine/couchdb": "~1.0@dev",
+ "elasticsearch/elasticsearch": "^7 || ^8",
+ "ext-json": "*",
+ "graylog2/gelf-php": "^1.4.2 || ^2@dev",
+ "guzzlehttp/guzzle": "^7.4",
+ "guzzlehttp/psr7": "^2.2",
+ "mongodb/mongodb": "^1.8 || ^2.0",
+ "php-amqplib/php-amqplib": "~2.4 || ^3",
+ "phpspec/prophecy": "^1.15",
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^8.5.38 || ^9.6.19",
+ "predis/predis": "^1.1 || ^2.0",
+ "rollbar/rollbar": "^1.3 || ^2 || ^3",
+ "ruflin/elastica": "^7",
+ "swiftmailer/swiftmailer": "^5.3|^6.0",
+ "symfony/mailer": "^5.4 || ^6",
+ "symfony/mime": "^5.4 || ^6"
+ },
+ "suggest": {
+ "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
+ "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
+ "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",
+ "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
+ "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler",
+ "ext-mbstring": "Allow to work properly with unicode symbols",
+ "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
+ "ext-openssl": "Required to send log messages using SSL",
+ "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)",
+ "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
+ "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
+ "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
+ "rollbar/rollbar": "Allow sending log messages to Rollbar",
+ "ruflin/elastica": "Allow sending log messages to an Elastic Search server"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Monolog\\": "src/Monolog"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "https://seld.be"
+ }
+ ],
+ "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
+ "homepage": "https://github.com/Seldaek/monolog",
+ "keywords": [
+ "log",
+ "logging",
+ "psr-3"
+ ],
+ "support": {
+ "issues": "https://github.com/Seldaek/monolog/issues",
+ "source": "https://github.com/Seldaek/monolog/tree/2.11.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/Seldaek",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/monolog/monolog",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-01-01T13:05:00+00:00"
+ },
+ {
+ "name": "myclabs/deep-copy",
+ "version": "1.13.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/myclabs/DeepCopy.git",
+ "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a",
+ "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1 || ^8.0"
+ },
+ "conflict": {
+ "doctrine/collections": "<1.6.8",
+ "doctrine/common": "<2.13.3 || >=3 <3.2.2"
+ },
+ "require-dev": {
+ "doctrine/collections": "^1.6.8",
+ "doctrine/common": "^2.13.3 || ^3.2.2",
+ "phpspec/prophecy": "^1.10",
+ "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/DeepCopy/deep_copy.php"
+ ],
+ "psr-4": {
+ "DeepCopy\\": "src/DeepCopy/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Create deep copies (clones) of your objects",
+ "keywords": [
+ "clone",
+ "copy",
+ "duplicate",
+ "object",
+ "object graph"
+ ],
+ "support": {
+ "issues": "https://github.com/myclabs/DeepCopy/issues",
+ "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4"
+ },
+ "funding": [
+ {
+ "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-08-01T08:46:24+00:00"
+ },
+ {
+ "name": "myclabs/php-enum",
+ "version": "1.8.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/myclabs/php-enum.git",
+ "reference": "e7be26966b7398204a234f8673fdad5ac6277802"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/myclabs/php-enum/zipball/e7be26966b7398204a234f8673fdad5ac6277802",
+ "reference": "e7be26966b7398204a234f8673fdad5ac6277802",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "php": "^7.3 || ^8.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.5",
+ "squizlabs/php_codesniffer": "1.*",
+ "vimeo/psalm": "^4.6.2 || ^5.2"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "MyCLabs\\Enum\\": "src/"
+ },
+ "classmap": [
+ "stubs/Stringable.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP Enum contributors",
+ "homepage": "https://github.com/myclabs/php-enum/graphs/contributors"
+ }
+ ],
+ "description": "PHP Enum implementation",
+ "homepage": "https://github.com/myclabs/php-enum",
+ "keywords": [
+ "enum"
+ ],
+ "support": {
+ "issues": "https://github.com/myclabs/php-enum/issues",
+ "source": "https://github.com/myclabs/php-enum/tree/1.8.5"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/mnapoli",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/myclabs/php-enum",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-01-14T11:49:03+00:00"
+ },
+ {
+ "name": "nikic/php-parser",
+ "version": "v5.7.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nikic/PHP-Parser.git",
+ "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82",
+ "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82",
+ "shasum": ""
+ },
+ "require": {
+ "ext-ctype": "*",
+ "ext-json": "*",
+ "ext-tokenizer": "*",
+ "php": ">=7.4"
+ },
+ "require-dev": {
+ "ircmaxell/php-yacc": "^0.0.7",
+ "phpunit/phpunit": "^9.0"
+ },
+ "bin": [
+ "bin/php-parse"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "PhpParser\\": "lib/PhpParser"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Nikita Popov"
+ }
+ ],
+ "description": "A PHP parser written in PHP",
+ "keywords": [
+ "parser",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/nikic/PHP-Parser/issues",
+ "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0"
+ },
+ "time": "2025-12-06T11:56:16+00:00"
+ },
+ {
+ "name": "phar-io/manifest",
+ "version": "2.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phar-io/manifest.git",
+ "reference": "54750ef60c58e43759730615a392c31c80e23176"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176",
+ "reference": "54750ef60c58e43759730615a392c31c80e23176",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-libxml": "*",
+ "ext-phar": "*",
+ "ext-xmlwriter": "*",
+ "phar-io/version": "^3.0.1",
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "sebastian@phpeople.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
+ "support": {
+ "issues": "https://github.com/phar-io/manifest/issues",
+ "source": "https://github.com/phar-io/manifest/tree/2.0.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/theseer",
+ "type": "github"
+ }
+ ],
+ "time": "2024-03-03T12:33:53+00:00"
+ },
+ {
+ "name": "phar-io/version",
+ "version": "3.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phar-io/version.git",
+ "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
+ "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "sebastian@phpeople.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Library for handling version information and constraints",
+ "support": {
+ "issues": "https://github.com/phar-io/version/issues",
+ "source": "https://github.com/phar-io/version/tree/3.2.1"
+ },
+ "time": "2022-02-21T01:04:05+00:00"
+ },
+ {
+ "name": "phpcompatibility/php-compatibility",
+ "version": "9.3.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCompatibility/PHPCompatibility.git",
+ "reference": "9fb324479acf6f39452e0655d2429cc0d3914243"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9fb324479acf6f39452e0655d2429cc0d3914243",
+ "reference": "9fb324479acf6f39452e0655d2429cc0d3914243",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3",
+ "squizlabs/php_codesniffer": "^2.3 || ^3.0.2"
+ },
+ "conflict": {
+ "squizlabs/php_codesniffer": "2.6.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0"
+ },
+ "suggest": {
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.",
+ "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues."
+ },
+ "type": "phpcodesniffer-standard",
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL-3.0-or-later"
+ ],
+ "authors": [
+ {
+ "name": "Wim Godden",
+ "homepage": "https://github.com/wimg",
+ "role": "lead"
+ },
+ {
+ "name": "Juliette Reinders Folmer",
+ "homepage": "https://github.com/jrfnl",
+ "role": "lead"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors"
+ }
+ ],
+ "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.",
+ "homepage": "http://techblog.wimgodden.be/tag/codesniffer/",
+ "keywords": [
+ "compatibility",
+ "phpcs",
+ "standards"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues",
+ "source": "https://github.com/PHPCompatibility/PHPCompatibility"
+ },
+ "time": "2019-12-27T09:44:58+00:00"
+ },
+ {
+ "name": "phpcompatibility/phpcompatibility-paragonie",
+ "version": "1.3.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git",
+ "reference": "244d7b04fc4bc2117c15f5abe23eb933b5f02bbf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/244d7b04fc4bc2117c15f5abe23eb933b5f02bbf",
+ "reference": "244d7b04fc4bc2117c15f5abe23eb933b5f02bbf",
+ "shasum": ""
+ },
+ "require": {
+ "phpcompatibility/php-compatibility": "^9.0"
+ },
+ "require-dev": {
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
+ "paragonie/random_compat": "dev-master",
+ "paragonie/sodium_compat": "dev-master"
+ },
+ "suggest": {
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.",
+ "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues."
+ },
+ "type": "phpcodesniffer-standard",
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL-3.0-or-later"
+ ],
+ "authors": [
+ {
+ "name": "Wim Godden",
+ "role": "lead"
+ },
+ {
+ "name": "Juliette Reinders Folmer",
+ "role": "lead"
+ }
+ ],
+ "description": "A set of rulesets for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by the Paragonie polyfill libraries.",
+ "homepage": "http://phpcompatibility.com/",
+ "keywords": [
+ "compatibility",
+ "paragonie",
+ "phpcs",
+ "polyfill",
+ "standards",
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues",
+ "security": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/security/policy",
+ "source": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/PHPCompatibility",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jrfnl",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/phpcompatibility",
+ "type": "thanks_dev"
+ }
+ ],
+ "time": "2025-09-19T17:43:28+00:00"
+ },
+ {
+ "name": "phpcompatibility/phpcompatibility-wp",
+ "version": "2.1.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git",
+ "reference": "7c8d18b4d90dac9e86b0869a608fa09158e168fa"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/7c8d18b4d90dac9e86b0869a608fa09158e168fa",
+ "reference": "7c8d18b4d90dac9e86b0869a608fa09158e168fa",
+ "shasum": ""
+ },
+ "require": {
+ "phpcompatibility/php-compatibility": "^9.0",
+ "phpcompatibility/phpcompatibility-paragonie": "^1.0",
+ "squizlabs/php_codesniffer": "^3.3"
+ },
+ "require-dev": {
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0"
+ },
+ "suggest": {
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.",
+ "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues."
+ },
+ "type": "phpcodesniffer-standard",
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL-3.0-or-later"
+ ],
+ "authors": [
+ {
+ "name": "Wim Godden",
+ "role": "lead"
+ },
+ {
+ "name": "Juliette Reinders Folmer",
+ "role": "lead"
+ }
+ ],
+ "description": "A ruleset for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by WordPress.",
+ "homepage": "http://phpcompatibility.com/",
+ "keywords": [
+ "compatibility",
+ "phpcs",
+ "standards",
+ "static analysis",
+ "wordpress"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues",
+ "security": "https://github.com/PHPCompatibility/PHPCompatibilityWP/security/policy",
+ "source": "https://github.com/PHPCompatibility/PHPCompatibilityWP"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/PHPCompatibility",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jrfnl",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/phpcompatibility",
+ "type": "thanks_dev"
+ }
+ ],
+ "time": "2025-10-18T00:05:59+00:00"
+ },
+ {
+ "name": "phpcsstandards/phpcsextra",
+ "version": "1.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCSStandards/PHPCSExtra.git",
+ "reference": "b598aa890815b8df16363271b659d73280129101"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCSStandards/PHPCSExtra/zipball/b598aa890815b8df16363271b659d73280129101",
+ "reference": "b598aa890815b8df16363271b659d73280129101",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4",
+ "phpcsstandards/phpcsutils": "^1.2.0",
+ "squizlabs/php_codesniffer": "^3.13.5 || ^4.0.1"
+ },
+ "require-dev": {
+ "php-parallel-lint/php-console-highlighter": "^1.0",
+ "php-parallel-lint/php-parallel-lint": "^1.4.0",
+ "phpcsstandards/phpcsdevcs": "^1.2.0",
+ "phpcsstandards/phpcsdevtools": "^1.2.1",
+ "phpunit/phpunit": "^4.5 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4"
+ },
+ "type": "phpcodesniffer-standard",
+ "extra": {
+ "branch-alias": {
+ "dev-stable": "1.x-dev",
+ "dev-develop": "1.x-dev"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL-3.0-or-later"
+ ],
+ "authors": [
+ {
+ "name": "Juliette Reinders Folmer",
+ "homepage": "https://github.com/jrfnl",
+ "role": "lead"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/PHPCSStandards/PHPCSExtra/graphs/contributors"
+ }
+ ],
+ "description": "A collection of sniffs and standards for use with PHP_CodeSniffer.",
+ "keywords": [
+ "PHP_CodeSniffer",
+ "phpcbf",
+ "phpcodesniffer-standard",
+ "phpcs",
+ "standards",
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPCSStandards/PHPCSExtra/issues",
+ "security": "https://github.com/PHPCSStandards/PHPCSExtra/security/policy",
+ "source": "https://github.com/PHPCSStandards/PHPCSExtra"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/PHPCSStandards",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jrfnl",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/phpcsstandards",
+ "type": "thanks_dev"
+ }
+ ],
+ "time": "2025-11-12T23:06:57+00:00"
+ },
+ {
+ "name": "phpcsstandards/phpcsutils",
+ "version": "1.2.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCSStandards/PHPCSUtils.git",
+ "reference": "c216317e96c8b3f5932808f9b0f1f7a14e3bbf55"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/c216317e96c8b3f5932808f9b0f1f7a14e3bbf55",
+ "reference": "c216317e96c8b3f5932808f9b0f1f7a14e3bbf55",
+ "shasum": ""
+ },
+ "require": {
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7 || ^1.0",
+ "php": ">=5.4",
+ "squizlabs/php_codesniffer": "^3.13.5 || ^4.0.1"
+ },
+ "require-dev": {
+ "ext-filter": "*",
+ "php-parallel-lint/php-console-highlighter": "^1.0",
+ "php-parallel-lint/php-parallel-lint": "^1.4.0",
+ "phpcsstandards/phpcsdevcs": "^1.2.0",
+ "yoast/phpunit-polyfills": "^1.1.0 || ^2.0.0 || ^3.0.0"
+ },
+ "type": "phpcodesniffer-standard",
+ "extra": {
+ "branch-alias": {
+ "dev-stable": "1.x-dev",
+ "dev-develop": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "PHPCSUtils/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "LGPL-3.0-or-later"
+ ],
+ "authors": [
+ {
+ "name": "Juliette Reinders Folmer",
+ "homepage": "https://github.com/jrfnl",
+ "role": "lead"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/PHPCSStandards/PHPCSUtils/graphs/contributors"
+ }
+ ],
+ "description": "A suite of utility functions for use with PHP_CodeSniffer",
+ "homepage": "https://phpcsutils.com/",
+ "keywords": [
+ "PHP_CodeSniffer",
+ "phpcbf",
+ "phpcodesniffer-standard",
+ "phpcs",
+ "phpcs3",
+ "phpcs4",
+ "standards",
+ "static analysis",
+ "tokens",
+ "utility"
+ ],
+ "support": {
+ "docs": "https://phpcsutils.com/",
+ "issues": "https://github.com/PHPCSStandards/PHPCSUtils/issues",
+ "security": "https://github.com/PHPCSStandards/PHPCSUtils/security/policy",
+ "source": "https://github.com/PHPCSStandards/PHPCSUtils"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/PHPCSStandards",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jrfnl",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/phpcsstandards",
+ "type": "thanks_dev"
+ }
+ ],
+ "time": "2025-12-08T14:27:58+00:00"
+ },
+ {
+ "name": "phpdocumentor/reflection-common",
+ "version": "2.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
+ "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b",
+ "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-2.x": "2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "phpDocumentor\\Reflection\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jaap van Otterdijk",
+ "email": "opensource@ijaap.nl"
+ }
+ ],
+ "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
+ "homepage": "http://www.phpdoc.org",
+ "keywords": [
+ "FQSEN",
+ "phpDocumentor",
+ "phpdoc",
+ "reflection",
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues",
+ "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x"
+ },
+ "time": "2020-06-27T09:03:43+00:00"
+ },
+ {
+ "name": "phpdocumentor/reflection-docblock",
+ "version": "5.6.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
+ "reference": "31a105931bc8ffa3a123383829772e832fd8d903"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/31a105931bc8ffa3a123383829772e832fd8d903",
+ "reference": "31a105931bc8ffa3a123383829772e832fd8d903",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/deprecations": "^1.1",
+ "ext-filter": "*",
+ "php": "^7.4 || ^8.0",
+ "phpdocumentor/reflection-common": "^2.2",
+ "phpdocumentor/type-resolver": "^1.7",
+ "phpstan/phpdoc-parser": "^1.7|^2.0",
+ "webmozart/assert": "^1.9.1 || ^2"
+ },
+ "require-dev": {
+ "mockery/mockery": "~1.3.5 || ~1.6.0",
+ "phpstan/extension-installer": "^1.1",
+ "phpstan/phpstan": "^1.8",
+ "phpstan/phpstan-mockery": "^1.1",
+ "phpstan/phpstan-webmozart-assert": "^1.2",
+ "phpunit/phpunit": "^9.5",
+ "psalm/phar": "^5.26"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "phpDocumentor\\Reflection\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Mike van Riel",
+ "email": "me@mikevanriel.com"
+ },
+ {
+ "name": "Jaap van Otterdijk",
+ "email": "opensource@ijaap.nl"
+ }
+ ],
+ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
+ "support": {
+ "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
+ "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.7"
+ },
+ "time": "2026-03-18T20:47:46+00:00"
+ },
+ {
+ "name": "phpdocumentor/type-resolver",
+ "version": "1.7.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpDocumentor/TypeResolver.git",
+ "reference": "8430ca5c93b5b933ef1aaf8dd93f80d0c55d2349"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/8430ca5c93b5b933ef1aaf8dd93f80d0c55d2349",
+ "reference": "8430ca5c93b5b933ef1aaf8dd93f80d0c55d2349",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/deprecations": "^1.0",
+ "php": "^7.4 || ^8.0",
+ "phpdocumentor/reflection-common": "^2.0",
+ "phpstan/phpdoc-parser": "^1.13"
+ },
+ "require-dev": {
+ "ext-tokenizer": "*",
+ "phpbench/phpbench": "^1.2",
+ "phpstan/extension-installer": "^1.1",
+ "phpstan/phpstan": "^1.8",
+ "phpstan/phpstan-phpunit": "^1.1",
+ "phpunit/phpunit": "^9.5",
+ "rector/rector": "^0.13.9",
+ "vimeo/psalm": "^4.25"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-1.x": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "phpDocumentor\\Reflection\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Mike van Riel",
+ "email": "me@mikevanriel.com"
+ }
+ ],
+ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
+ "support": {
+ "issues": "https://github.com/phpDocumentor/TypeResolver/issues",
+ "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.4"
+ },
+ "time": "2024-01-11T11:21:11+00:00"
+ },
+ {
+ "name": "phpstan/phpdoc-parser",
+ "version": "1.33.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpstan/phpdoc-parser.git",
+ "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/82a311fd3690fb2bf7b64d5c98f912b3dd746140",
+ "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "require-dev": {
+ "doctrine/annotations": "^2.0",
+ "nikic/php-parser": "^4.15",
+ "php-parallel-lint/php-parallel-lint": "^1.2",
+ "phpstan/extension-installer": "^1.0",
+ "phpstan/phpstan": "^1.5",
+ "phpstan/phpstan-phpunit": "^1.1",
+ "phpstan/phpstan-strict-rules": "^1.0",
+ "phpunit/phpunit": "^9.5",
+ "symfony/process": "^5.2"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "PHPStan\\PhpDocParser\\": [
+ "src/"
+ ]
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "PHPDoc parser with support for nullable, intersection and generic types",
+ "support": {
+ "issues": "https://github.com/phpstan/phpdoc-parser/issues",
+ "source": "https://github.com/phpstan/phpdoc-parser/tree/1.33.0"
+ },
+ "time": "2024-10-13T11:25:22+00:00"
+ },
+ {
+ "name": "phpunit/php-code-coverage",
+ "version": "11.0.12",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
+ "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2c1ed04922802c15e1de5d7447b4856de949cf56",
+ "reference": "2c1ed04922802c15e1de5d7447b4856de949cf56",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-libxml": "*",
+ "ext-xmlwriter": "*",
+ "nikic/php-parser": "^5.7.0",
+ "php": ">=8.2",
+ "phpunit/php-file-iterator": "^5.1.0",
+ "phpunit/php-text-template": "^4.0.1",
+ "sebastian/code-unit-reverse-lookup": "^4.0.1",
+ "sebastian/complexity": "^4.0.1",
+ "sebastian/environment": "^7.2.1",
+ "sebastian/lines-of-code": "^3.0.1",
+ "sebastian/version": "^5.0.2",
+ "theseer/tokenizer": "^1.3.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.5.46"
+ },
+ "suggest": {
+ "ext-pcov": "PHP extension that provides line coverage",
+ "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "11.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
+ "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
+ "keywords": [
+ "coverage",
+ "testing",
+ "xunit"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
+ "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.12"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-12-24T07:01:01+00:00"
+ },
+ {
+ "name": "phpunit/php-file-iterator",
+ "version": "5.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
+ "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/2f3a64888c814fc235386b7387dd5b5ed92ad903",
+ "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "FilterIterator implementation that filters files based on a list of suffixes.",
+ "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
+ "keywords": [
+ "filesystem",
+ "iterator"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
+ "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpunit/php-file-iterator",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-02-02T13:52:54+00:00"
+ },
+ {
+ "name": "phpunit/php-invoker",
+ "version": "5.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-invoker.git",
+ "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2",
+ "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "ext-pcntl": "*",
+ "phpunit/phpunit": "^11.0"
+ },
+ "suggest": {
+ "ext-pcntl": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Invoke callables with a timeout",
+ "homepage": "https://github.com/sebastianbergmann/php-invoker/",
+ "keywords": [
+ "process"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-invoker/issues",
+ "security": "https://github.com/sebastianbergmann/php-invoker/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T05:07:44+00:00"
+ },
+ {
+ "name": "phpunit/php-text-template",
+ "version": "4.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-text-template.git",
+ "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964",
+ "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Simple template engine.",
+ "homepage": "https://github.com/sebastianbergmann/php-text-template/",
+ "keywords": [
+ "template"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-text-template/issues",
+ "security": "https://github.com/sebastianbergmann/php-text-template/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T05:08:43+00:00"
+ },
+ {
+ "name": "phpunit/php-timer",
+ "version": "7.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-timer.git",
+ "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3",
+ "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "7.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Utility class for timing",
+ "homepage": "https://github.com/sebastianbergmann/php-timer/",
+ "keywords": [
+ "timer"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-timer/issues",
+ "security": "https://github.com/sebastianbergmann/php-timer/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T05:09:35+00:00"
+ },
+ {
+ "name": "phpunit/phpunit",
+ "version": "11.5.55",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/phpunit.git",
+ "reference": "adc7262fccc12de2b30f12a8aa0b33775d814f00"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/adc7262fccc12de2b30f12a8aa0b33775d814f00",
+ "reference": "adc7262fccc12de2b30f12a8aa0b33775d814f00",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-json": "*",
+ "ext-libxml": "*",
+ "ext-mbstring": "*",
+ "ext-xml": "*",
+ "ext-xmlwriter": "*",
+ "myclabs/deep-copy": "^1.13.4",
+ "phar-io/manifest": "^2.0.4",
+ "phar-io/version": "^3.2.1",
+ "php": ">=8.2",
+ "phpunit/php-code-coverage": "^11.0.12",
+ "phpunit/php-file-iterator": "^5.1.1",
+ "phpunit/php-invoker": "^5.0.1",
+ "phpunit/php-text-template": "^4.0.1",
+ "phpunit/php-timer": "^7.0.1",
+ "sebastian/cli-parser": "^3.0.2",
+ "sebastian/code-unit": "^3.0.3",
+ "sebastian/comparator": "^6.3.3",
+ "sebastian/diff": "^6.0.2",
+ "sebastian/environment": "^7.2.1",
+ "sebastian/exporter": "^6.3.2",
+ "sebastian/global-state": "^7.0.2",
+ "sebastian/object-enumerator": "^6.0.1",
+ "sebastian/recursion-context": "^6.0.3",
+ "sebastian/type": "^5.1.3",
+ "sebastian/version": "^5.0.2",
+ "staabm/side-effects-detector": "^1.0.5"
+ },
+ "suggest": {
+ "ext-soap": "To be able to generate mocks based on WSDL files"
+ },
+ "bin": [
+ "phpunit"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "11.5-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/Framework/Assert/Functions.php"
+ ],
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "The PHP Unit Testing framework.",
+ "homepage": "https://phpunit.de/",
+ "keywords": [
+ "phpunit",
+ "testing",
+ "xunit"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/phpunit/issues",
+ "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.55"
+ },
+ "funding": [
+ {
+ "url": "https://phpunit.de/sponsors.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-02-18T12:37:06+00:00"
+ },
+ {
+ "name": "psr/cache",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/cache.git",
+ "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
+ "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Cache\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for caching libraries",
+ "keywords": [
+ "cache",
+ "psr",
+ "psr-6"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/cache/tree/3.0.0"
+ },
+ "time": "2021-02-03T23:26:27+00:00"
+ },
+ {
+ "name": "psr/container",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
+ "keywords": [
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/container/issues",
+ "source": "https://github.com/php-fig/container/tree/2.0.2"
+ },
+ "time": "2021-11-05T16:47:00+00:00"
+ },
+ {
+ "name": "psr/log",
+ "version": "3.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
+ "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/log/tree/3.0.2"
+ },
+ "time": "2024-09-11T13:17:53+00:00"
+ },
+ {
+ "name": "psr/simple-cache",
+ "version": "2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/simple-cache.git",
+ "reference": "8707bf3cea6f710bf6ef05491234e3ab06f6432a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/8707bf3cea6f710bf6ef05491234e3ab06f6432a",
+ "reference": "8707bf3cea6f710bf6ef05491234e3ab06f6432a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\SimpleCache\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interfaces for simple caching",
+ "keywords": [
+ "cache",
+ "caching",
+ "psr",
+ "psr-16",
+ "simple-cache"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/simple-cache/tree/2.0.0"
+ },
+ "time": "2021-10-29T13:22:09+00:00"
+ },
+ {
+ "name": "react/promise",
+ "version": "v3.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/reactphp/promise.git",
+ "reference": "23444f53a813a3296c1368bb104793ce8d88f04a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/reactphp/promise/zipball/23444f53a813a3296c1368bb104793ce8d88f04a",
+ "reference": "23444f53a813a3296c1368bb104793ce8d88f04a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "1.12.28 || 1.4.10",
+ "phpunit/phpunit": "^9.6 || ^7.5"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/functions_include.php"
+ ],
+ "psr-4": {
+ "React\\Promise\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jan Sorgalla",
+ "email": "jsorgalla@gmail.com",
+ "homepage": "https://sorgalla.com/"
+ },
+ {
+ "name": "Christian Lück",
+ "email": "christian@clue.engineering",
+ "homepage": "https://clue.engineering/"
+ },
+ {
+ "name": "Cees-Jan Kiewiet",
+ "email": "reactphp@ceesjankiewiet.nl",
+ "homepage": "https://wyrihaximus.net/"
+ },
+ {
+ "name": "Chris Boden",
+ "email": "cboden@gmail.com",
+ "homepage": "https://cboden.dev/"
+ }
+ ],
+ "description": "A lightweight implementation of CommonJS Promises/A for PHP",
+ "keywords": [
+ "promise",
+ "promises"
+ ],
+ "support": {
+ "issues": "https://github.com/reactphp/promise/issues",
+ "source": "https://github.com/reactphp/promise/tree/v3.3.0"
+ },
+ "funding": [
+ {
+ "url": "https://opencollective.com/reactphp",
+ "type": "open_collective"
+ }
+ ],
+ "time": "2025-08-19T18:57:03+00:00"
+ },
+ {
+ "name": "sebastian/cli-parser",
+ "version": "3.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/cli-parser.git",
+ "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180",
+ "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for parsing CLI options",
+ "homepage": "https://github.com/sebastianbergmann/cli-parser",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/cli-parser/issues",
+ "security": "https://github.com/sebastianbergmann/cli-parser/security/policy",
+ "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T04:41:36+00:00"
+ },
+ {
+ "name": "sebastian/code-unit",
+ "version": "3.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/code-unit.git",
+ "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64",
+ "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Collection of value objects that represent the PHP code units",
+ "homepage": "https://github.com/sebastianbergmann/code-unit",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/code-unit/issues",
+ "security": "https://github.com/sebastianbergmann/code-unit/security/policy",
+ "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2025-03-19T07:56:08+00:00"
+ },
+ {
+ "name": "sebastian/code-unit-reverse-lookup",
+ "version": "4.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
+ "reference": "183a9b2632194febd219bb9246eee421dad8d45e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e",
+ "reference": "183a9b2632194febd219bb9246eee421dad8d45e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Looks up which function or method a line of code belongs to",
+ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
+ "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy",
+ "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T04:45:54+00:00"
+ },
+ {
+ "name": "sebastian/comparator",
+ "version": "6.3.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/comparator.git",
+ "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2c95e1e86cb8dd41beb8d502057d1081ccc8eca9",
+ "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-mbstring": "*",
+ "php": ">=8.2",
+ "sebastian/diff": "^6.0",
+ "sebastian/exporter": "^6.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.4"
+ },
+ "suggest": {
+ "ext-bcmath": "For comparing BcMath\\Number objects"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.3-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@2bepublished.at"
+ }
+ ],
+ "description": "Provides the functionality to compare PHP values for equality",
+ "homepage": "https://github.com/sebastianbergmann/comparator",
+ "keywords": [
+ "comparator",
+ "compare",
+ "equality"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/comparator/issues",
+ "security": "https://github.com/sebastianbergmann/comparator/security/policy",
+ "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-01-24T09:26:40+00:00"
+ },
+ {
+ "name": "sebastian/complexity",
+ "version": "4.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/complexity.git",
+ "reference": "ee41d384ab1906c68852636b6de493846e13e5a0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0",
+ "reference": "ee41d384ab1906c68852636b6de493846e13e5a0",
+ "shasum": ""
+ },
+ "require": {
+ "nikic/php-parser": "^5.0",
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for calculating the complexity of PHP code units",
+ "homepage": "https://github.com/sebastianbergmann/complexity",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/complexity/issues",
+ "security": "https://github.com/sebastianbergmann/complexity/security/policy",
+ "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T04:49:50+00:00"
+ },
+ {
+ "name": "sebastian/diff",
+ "version": "6.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/diff.git",
+ "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544",
+ "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0",
+ "symfony/process": "^4.2 || ^5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Kore Nordmann",
+ "email": "mail@kore-nordmann.de"
+ }
+ ],
+ "description": "Diff implementation",
+ "homepage": "https://github.com/sebastianbergmann/diff",
+ "keywords": [
+ "diff",
+ "udiff",
+ "unidiff",
+ "unified diff"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/diff/issues",
+ "security": "https://github.com/sebastianbergmann/diff/security/policy",
+ "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T04:53:05+00:00"
+ },
+ {
+ "name": "sebastian/environment",
+ "version": "7.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/environment.git",
+ "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a5c75038693ad2e8d4b6c15ba2403532647830c4",
+ "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.3"
+ },
+ "suggest": {
+ "ext-posix": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "7.2-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Provides functionality to handle HHVM/PHP environments",
+ "homepage": "https://github.com/sebastianbergmann/environment",
+ "keywords": [
+ "Xdebug",
+ "environment",
+ "hhvm"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/environment/issues",
+ "security": "https://github.com/sebastianbergmann/environment/security/policy",
+ "source": "https://github.com/sebastianbergmann/environment/tree/7.2.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/environment",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-05-21T11:55:47+00:00"
+ },
+ {
+ "name": "sebastian/exporter",
+ "version": "6.3.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/exporter.git",
+ "reference": "70a298763b40b213ec087c51c739efcaa90bcd74"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/70a298763b40b213ec087c51c739efcaa90bcd74",
+ "reference": "70a298763b40b213ec087c51c739efcaa90bcd74",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*",
+ "php": ">=8.2",
+ "sebastian/recursion-context": "^6.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.3-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
+ }
+ ],
+ "description": "Provides the functionality to export PHP variables for visualization",
+ "homepage": "https://www.github.com/sebastianbergmann/exporter",
+ "keywords": [
+ "export",
+ "exporter"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/exporter/issues",
+ "security": "https://github.com/sebastianbergmann/exporter/security/policy",
+ "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-09-24T06:12:51+00:00"
+ },
+ {
+ "name": "sebastian/global-state",
+ "version": "7.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/global-state.git",
+ "reference": "3be331570a721f9a4b5917f4209773de17f747d7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7",
+ "reference": "3be331570a721f9a4b5917f4209773de17f747d7",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "sebastian/object-reflector": "^4.0",
+ "sebastian/recursion-context": "^6.0"
+ },
+ "require-dev": {
+ "ext-dom": "*",
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "7.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Snapshotting of global state",
+ "homepage": "https://www.github.com/sebastianbergmann/global-state",
+ "keywords": [
+ "global state"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/global-state/issues",
+ "security": "https://github.com/sebastianbergmann/global-state/security/policy",
+ "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T04:57:36+00:00"
+ },
+ {
+ "name": "sebastian/lines-of-code",
+ "version": "3.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/lines-of-code.git",
+ "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a",
+ "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a",
+ "shasum": ""
+ },
+ "require": {
+ "nikic/php-parser": "^5.0",
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for counting the lines of code in PHP source code",
+ "homepage": "https://github.com/sebastianbergmann/lines-of-code",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
+ "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy",
+ "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T04:58:38+00:00"
+ },
+ {
+ "name": "sebastian/object-enumerator",
+ "version": "6.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-enumerator.git",
+ "reference": "f5b498e631a74204185071eb41f33f38d64608aa"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa",
+ "reference": "f5b498e631a74204185071eb41f33f38d64608aa",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "sebastian/object-reflector": "^4.0",
+ "sebastian/recursion-context": "^6.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Traverses array structures and object graphs to enumerate all referenced objects",
+ "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
+ "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy",
+ "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T05:00:13+00:00"
+ },
+ {
+ "name": "sebastian/object-reflector",
+ "version": "4.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-reflector.git",
+ "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9",
+ "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Allows reflection of object attributes, including inherited and non-public ones",
+ "homepage": "https://github.com/sebastianbergmann/object-reflector/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/object-reflector/issues",
+ "security": "https://github.com/sebastianbergmann/object-reflector/security/policy",
+ "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-07-03T05:01:32+00:00"
+ },
+ {
+ "name": "sebastian/recursion-context",
+ "version": "6.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/recursion-context.git",
+ "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/f6458abbf32a6c8174f8f26261475dc133b3d9dc",
+ "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.3"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "11.0.x-dev"
+ "dev-main": "6.0-dev"
}
},
"autoload": {
@@ -913,21 +4122,23 @@
"authors": [
{
"name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
}
],
- "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
- "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
- "keywords": [
- "coverage",
- "testing",
- "xunit"
- ],
+ "description": "Provides functionality to recursively process PHP variables",
+ "homepage": "https://github.com/sebastianbergmann/recursion-context",
"support": {
- "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
- "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
- "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.12"
+ "issues": "https://github.com/sebastianbergmann/recursion-context/issues",
+ "security": "https://github.com/sebastianbergmann/recursion-context/security/policy",
+ "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.3"
},
"funding": [
{
@@ -943,24 +4154,24 @@
"type": "thanks_dev"
},
{
- "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage",
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context",
"type": "tidelift"
}
],
- "time": "2025-12-24T07:01:01+00:00"
+ "time": "2025-08-13T04:42:22+00:00"
},
{
- "name": "phpunit/php-file-iterator",
- "version": "5.1.1",
+ "name": "sebastian/type",
+ "version": "5.1.3",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
- "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903"
+ "url": "https://github.com/sebastianbergmann/type.git",
+ "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/2f3a64888c814fc235386b7387dd5b5ed92ad903",
- "reference": "2f3a64888c814fc235386b7387dd5b5ed92ad903",
+ "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/f77d2d4e78738c98d9a68d2596fe5e8fa380f449",
+ "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449",
"shasum": ""
},
"require": {
@@ -991,16 +4202,12 @@
"role": "lead"
}
],
- "description": "FilterIterator implementation that filters files based on a list of suffixes.",
- "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
- "keywords": [
- "filesystem",
- "iterator"
- ],
+ "description": "Collection of value objects that represent the types of the PHP type system",
+ "homepage": "https://github.com/sebastianbergmann/type",
"support": {
- "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
- "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy",
- "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.1"
+ "issues": "https://github.com/sebastianbergmann/type/issues",
+ "security": "https://github.com/sebastianbergmann/type/security/policy",
+ "source": "https://github.com/sebastianbergmann/type/tree/5.1.3"
},
"funding": [
{
@@ -1016,36 +4223,29 @@
"type": "thanks_dev"
},
{
- "url": "https://tidelift.com/funding/github/packagist/phpunit/php-file-iterator",
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/type",
"type": "tidelift"
}
],
- "time": "2026-02-02T13:52:54+00:00"
+ "time": "2025-08-09T06:55:48+00:00"
},
{
- "name": "phpunit/php-invoker",
- "version": "5.0.1",
+ "name": "sebastian/version",
+ "version": "5.0.2",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/php-invoker.git",
- "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2"
+ "url": "https://github.com/sebastianbergmann/version.git",
+ "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2",
- "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2",
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874",
+ "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874",
"shasum": ""
},
"require": {
"php": ">=8.2"
},
- "require-dev": {
- "ext-pcntl": "*",
- "phpunit/phpunit": "^11.0"
- },
- "suggest": {
- "ext-pcntl": "*"
- },
"type": "library",
"extra": {
"branch-alias": {
@@ -1068,1370 +4268,1798 @@
"role": "lead"
}
],
- "description": "Invoke callables with a timeout",
- "homepage": "https://github.com/sebastianbergmann/php-invoker/",
+ "description": "Library that helps with managing the version number of Git-hosted PHP projects",
+ "homepage": "https://github.com/sebastianbergmann/version",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/version/issues",
+ "security": "https://github.com/sebastianbergmann/version/security/policy",
+ "source": "https://github.com/sebastianbergmann/version/tree/5.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-10-09T05:16:32+00:00"
+ },
+ {
+ "name": "seld/jsonlint",
+ "version": "1.12.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Seldaek/jsonlint.git",
+ "reference": "9a90eb5d32d5a500296bf43f946d60246444d5f7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/9a90eb5d32d5a500296bf43f946d60246444d5f7",
+ "reference": "9a90eb5d32d5a500296bf43f946d60246444d5f7",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.11",
+ "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^8.5.13"
+ },
+ "bin": [
+ "bin/jsonlint"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Seld\\JsonLint\\": "src/Seld/JsonLint/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "https://seld.be"
+ }
+ ],
+ "description": "JSON Linter",
"keywords": [
- "process"
+ "json",
+ "linter",
+ "parser",
+ "validator"
],
"support": {
- "issues": "https://github.com/sebastianbergmann/php-invoker/issues",
- "security": "https://github.com/sebastianbergmann/php-invoker/security/policy",
- "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1"
+ "issues": "https://github.com/Seldaek/jsonlint/issues",
+ "source": "https://github.com/Seldaek/jsonlint/tree/1.12.1"
},
"funding": [
{
- "url": "https://github.com/sebastianbergmann",
+ "url": "https://github.com/Seldaek",
"type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/seld/jsonlint",
+ "type": "tidelift"
}
],
- "time": "2024-07-03T05:07:44+00:00"
+ "time": "2026-06-12T11:32:29+00:00"
},
{
- "name": "phpunit/php-text-template",
- "version": "4.0.1",
+ "name": "seld/phar-utils",
+ "version": "1.2.1",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/php-text-template.git",
- "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964"
+ "url": "https://github.com/Seldaek/phar-utils.git",
+ "reference": "ea2f4014f163c1be4c601b9b7bd6af81ba8d701c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964",
- "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964",
+ "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/ea2f4014f163c1be4c601b9b7bd6af81ba8d701c",
+ "reference": "ea2f4014f163c1be4c601b9b7bd6af81ba8d701c",
"shasum": ""
},
"require": {
- "php": ">=8.2"
+ "php": ">=5.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Seld\\PharUtils\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be"
+ }
+ ],
+ "description": "PHAR file format utilities, for when PHP phars you up",
+ "keywords": [
+ "phar"
+ ],
+ "support": {
+ "issues": "https://github.com/Seldaek/phar-utils/issues",
+ "source": "https://github.com/Seldaek/phar-utils/tree/1.2.1"
+ },
+ "time": "2022-08-31T10:31:18+00:00"
+ },
+ {
+ "name": "seld/signal-handler",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Seldaek/signal-handler.git",
+ "reference": "04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Seldaek/signal-handler/zipball/04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98",
+ "reference": "04a6112e883ad76c0ada8e4a9f7520bbfdb6bb98",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.0"
},
"require-dev": {
- "phpunit/phpunit": "^11.0"
+ "phpstan/phpstan": "^1",
+ "phpstan/phpstan-deprecation-rules": "^1.0",
+ "phpstan/phpstan-phpunit": "^1",
+ "phpstan/phpstan-strict-rules": "^1.3",
+ "phpunit/phpunit": "^7.5.20 || ^8.5.23",
+ "psr/log": "^1 || ^2 || ^3"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "4.0-dev"
+ "dev-main": "2.x-dev"
}
},
"autoload": {
- "classmap": [
- "src/"
- ]
+ "psr-4": {
+ "Seld\\Signal\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "Simple unix signal handler that silently fails where signals are not supported for easy cross-platform development",
+ "keywords": [
+ "posix",
+ "sigint",
+ "signal",
+ "sigterm",
+ "unix"
+ ],
+ "support": {
+ "issues": "https://github.com/Seldaek/signal-handler/issues",
+ "source": "https://github.com/Seldaek/signal-handler/tree/2.0.2"
+ },
+ "time": "2023-09-03T09:24:00+00:00"
+ },
+ {
+ "name": "squizlabs/php_codesniffer",
+ "version": "3.13.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
+ "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0ca86845ce43291e8f5692c7356fccf3bcf02bf4",
+ "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4",
+ "shasum": ""
+ },
+ "require": {
+ "ext-simplexml": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlwriter": "*",
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4"
},
+ "bin": [
+ "bin/phpcbf",
+ "bin/phpcs"
+ ],
+ "type": "library",
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
+ "name": "Greg Sherwood",
+ "role": "Former lead"
+ },
+ {
+ "name": "Juliette Reinders Folmer",
+ "role": "Current lead"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors"
}
],
- "description": "Simple template engine.",
- "homepage": "https://github.com/sebastianbergmann/php-text-template/",
+ "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
+ "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
"keywords": [
- "template"
+ "phpcs",
+ "standards",
+ "static analysis"
],
"support": {
- "issues": "https://github.com/sebastianbergmann/php-text-template/issues",
- "security": "https://github.com/sebastianbergmann/php-text-template/security/policy",
- "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1"
+ "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues",
+ "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy",
+ "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
+ "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki"
},
"funding": [
{
- "url": "https://github.com/sebastianbergmann",
+ "url": "https://github.com/PHPCSStandards",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/jrfnl",
"type": "github"
+ },
+ {
+ "url": "https://opencollective.com/php_codesniffer",
+ "type": "open_collective"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/phpcsstandards",
+ "type": "thanks_dev"
}
],
- "time": "2024-07-03T05:08:43+00:00"
+ "time": "2025-11-04T16:30:35+00:00"
},
{
- "name": "phpunit/php-timer",
- "version": "7.0.1",
+ "name": "staabm/side-effects-detector",
+ "version": "1.0.5",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/php-timer.git",
- "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3"
+ "url": "https://github.com/staabm/side-effects-detector.git",
+ "reference": "d8334211a140ce329c13726d4a715adbddd0a163"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3",
- "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3",
+ "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163",
+ "reference": "d8334211a140ce329c13726d4a715adbddd0a163",
"shasum": ""
},
"require": {
- "php": ">=8.2"
+ "ext-tokenizer": "*",
+ "php": "^7.4 || ^8.0"
},
"require-dev": {
- "phpunit/phpunit": "^11.0"
+ "phpstan/extension-installer": "^1.4.3",
+ "phpstan/phpstan": "^1.12.6",
+ "phpunit/phpunit": "^9.6.21",
+ "symfony/var-dumper": "^5.4.43",
+ "tomasvotruba/type-coverage": "1.0.0",
+ "tomasvotruba/unused-public": "1.0.0"
},
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "7.0-dev"
- }
- },
"autoload": {
"classmap": [
- "src/"
+ "lib/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
- }
+ "MIT"
],
- "description": "Utility class for timing",
- "homepage": "https://github.com/sebastianbergmann/php-timer/",
+ "description": "A static analysis tool to detect side effects in PHP code",
"keywords": [
- "timer"
+ "static analysis"
],
"support": {
- "issues": "https://github.com/sebastianbergmann/php-timer/issues",
- "security": "https://github.com/sebastianbergmann/php-timer/security/policy",
- "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1"
+ "issues": "https://github.com/staabm/side-effects-detector/issues",
+ "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5"
},
"funding": [
{
- "url": "https://github.com/sebastianbergmann",
+ "url": "https://github.com/staabm",
"type": "github"
}
],
- "time": "2024-07-03T05:09:35+00:00"
+ "time": "2024-10-20T05:08:20+00:00"
},
{
- "name": "phpunit/phpunit",
- "version": "11.5.55",
+ "name": "symfony/cache",
+ "version": "v7.4.14",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "adc7262fccc12de2b30f12a8aa0b33775d814f00"
+ "url": "https://github.com/symfony/cache.git",
+ "reference": "9adfcb2a7fc3924473b09f5a0b058dcc2cc7be9a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/adc7262fccc12de2b30f12a8aa0b33775d814f00",
- "reference": "adc7262fccc12de2b30f12a8aa0b33775d814f00",
+ "url": "https://api.github.com/repos/symfony/cache/zipball/9adfcb2a7fc3924473b09f5a0b058dcc2cc7be9a",
+ "reference": "9adfcb2a7fc3924473b09f5a0b058dcc2cc7be9a",
"shasum": ""
},
"require": {
- "ext-dom": "*",
- "ext-json": "*",
- "ext-libxml": "*",
- "ext-mbstring": "*",
- "ext-xml": "*",
- "ext-xmlwriter": "*",
- "myclabs/deep-copy": "^1.13.4",
- "phar-io/manifest": "^2.0.4",
- "phar-io/version": "^3.2.1",
"php": ">=8.2",
- "phpunit/php-code-coverage": "^11.0.12",
- "phpunit/php-file-iterator": "^5.1.1",
- "phpunit/php-invoker": "^5.0.1",
- "phpunit/php-text-template": "^4.0.1",
- "phpunit/php-timer": "^7.0.1",
- "sebastian/cli-parser": "^3.0.2",
- "sebastian/code-unit": "^3.0.3",
- "sebastian/comparator": "^6.3.3",
- "sebastian/diff": "^6.0.2",
- "sebastian/environment": "^7.2.1",
- "sebastian/exporter": "^6.3.2",
- "sebastian/global-state": "^7.0.2",
- "sebastian/object-enumerator": "^6.0.1",
- "sebastian/recursion-context": "^6.0.3",
- "sebastian/type": "^5.1.3",
- "sebastian/version": "^5.0.2",
- "staabm/side-effects-detector": "^1.0.5"
+ "psr/cache": "^2.0|^3.0",
+ "psr/log": "^1.1|^2|^3",
+ "symfony/cache-contracts": "^3.6",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/var-exporter": "^6.4|^7.0|^8.0"
},
- "suggest": {
- "ext-soap": "To be able to generate mocks based on WSDL files"
+ "conflict": {
+ "doctrine/dbal": "<3.6",
+ "ext-redis": "<6.1",
+ "ext-relay": "<0.12.1",
+ "symfony/dependency-injection": "<6.4",
+ "symfony/http-kernel": "<6.4",
+ "symfony/var-dumper": "<6.4"
+ },
+ "provide": {
+ "psr/cache-implementation": "2.0|3.0",
+ "psr/simple-cache-implementation": "1.0|2.0|3.0",
+ "symfony/cache-implementation": "1.1|2.0|3.0"
},
- "bin": [
- "phpunit"
- ],
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "11.5-dev"
- }
+ "require-dev": {
+ "cache/integration-tests": "dev-master",
+ "doctrine/dbal": "^3.6|^4",
+ "predis/predis": "^1.1|^2.0",
+ "psr/simple-cache": "^1.0|^2.0|^3.0",
+ "symfony/clock": "^6.4|^7.0|^8.0",
+ "symfony/config": "^6.4|^7.0|^8.0",
+ "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+ "symfony/filesystem": "^6.4|^7.0|^8.0",
+ "symfony/http-kernel": "^6.4|^7.0|^8.0",
+ "symfony/messenger": "^6.4|^7.0|^8.0",
+ "symfony/var-dumper": "^6.4|^7.0|^8.0"
},
+ "type": "library",
"autoload": {
- "files": [
- "src/Framework/Assert/Functions.php"
- ],
+ "psr-4": {
+ "Symfony\\Component\\Cache\\": ""
+ },
"classmap": [
- "src/"
+ "Traits/ValueWrapper.php"
+ ],
+ "exclude-from-classmap": [
+ "/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "The PHP Unit Testing framework.",
- "homepage": "https://phpunit.de/",
+ "description": "Provides extended PSR-6, PSR-16 (and tags) implementations",
+ "homepage": "https://symfony.com",
"keywords": [
- "phpunit",
- "testing",
- "xunit"
+ "caching",
+ "psr6"
],
"support": {
- "issues": "https://github.com/sebastianbergmann/phpunit/issues",
- "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.55"
+ "source": "https://github.com/symfony/cache/tree/v7.4.14"
},
"funding": [
{
- "url": "https://phpunit.de/sponsors.html",
+ "url": "https://symfony.com/sponsor",
"type": "custom"
},
{
- "url": "https://github.com/sebastianbergmann",
+ "url": "https://github.com/fabpot",
"type": "github"
},
{
- "url": "https://liberapay.com/sebastianbergmann",
- "type": "liberapay"
- },
- {
- "url": "https://thanks.dev/u/gh/sebastianbergmann",
- "type": "thanks_dev"
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
},
{
- "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2026-02-18T12:37:06+00:00"
+ "time": "2026-06-17T14:44:48+00:00"
},
{
- "name": "sebastian/cli-parser",
- "version": "3.0.2",
+ "name": "symfony/cache-contracts",
+ "version": "v3.7.1",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/cli-parser.git",
- "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180"
+ "url": "https://github.com/symfony/cache-contracts.git",
+ "reference": "9789738bc19af1106dc54d6afba9a0b467516cf2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180",
- "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180",
+ "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/9789738bc19af1106dc54d6afba9a0b467516cf2",
+ "reference": "9789738bc19af1106dc54d6afba9a0b467516cf2",
"shasum": ""
},
"require": {
- "php": ">=8.2"
- },
- "require-dev": {
- "phpunit/phpunit": "^11.0"
+ "php": ">=8.1",
+ "psr/cache": "^3.0"
},
"type": "library",
"extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
"branch-alias": {
- "dev-main": "3.0-dev"
+ "dev-main": "3.7-dev"
}
},
"autoload": {
- "classmap": [
- "src/"
- ]
+ "psr-4": {
+ "Symfony\\Contracts\\Cache\\": ""
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Library for parsing CLI options",
- "homepage": "https://github.com/sebastianbergmann/cli-parser",
+ "description": "Generic abstractions related to caching",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
"support": {
- "issues": "https://github.com/sebastianbergmann/cli-parser/issues",
- "security": "https://github.com/sebastianbergmann/cli-parser/security/policy",
- "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2"
+ "source": "https://github.com/symfony/cache-contracts/tree/v3.7.1"
},
"funding": [
{
- "url": "https://github.com/sebastianbergmann",
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
"type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
}
],
- "time": "2024-07-03T04:41:36+00:00"
+ "time": "2026-06-05T06:23:12+00:00"
},
{
- "name": "sebastian/code-unit",
- "version": "3.0.3",
+ "name": "symfony/console",
+ "version": "v7.4.14",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/code-unit.git",
- "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64"
+ "url": "https://github.com/symfony/console.git",
+ "reference": "92f58bc4bf97a92ed1b9f367f0cd44f20bde0e87"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/54391c61e4af8078e5b276ab082b6d3c54c9ad64",
- "reference": "54391c61e4af8078e5b276ab082b6d3c54c9ad64",
+ "url": "https://api.github.com/repos/symfony/console/zipball/92f58bc4bf97a92ed1b9f367f0cd44f20bde0e87",
+ "reference": "92f58bc4bf97a92ed1b9f367f0cd44f20bde0e87",
"shasum": ""
},
"require": {
- "php": ">=8.2"
+ "php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/string": "^7.2|^8.0"
+ },
+ "conflict": {
+ "symfony/dependency-injection": "<6.4",
+ "symfony/dotenv": "<6.4",
+ "symfony/event-dispatcher": "<6.4",
+ "symfony/lock": "<6.4",
+ "symfony/process": "<6.4"
+ },
+ "provide": {
+ "psr/log-implementation": "1.0|2.0|3.0"
},
"require-dev": {
- "phpunit/phpunit": "^11.5"
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^6.4|^7.0|^8.0",
+ "symfony/dependency-injection": "^6.4|^7.0|^8.0",
+ "symfony/event-dispatcher": "^6.4|^7.0|^8.0",
+ "symfony/http-foundation": "^6.4|^7.0|^8.0",
+ "symfony/http-kernel": "^6.4|^7.0|^8.0",
+ "symfony/lock": "^6.4|^7.0|^8.0",
+ "symfony/messenger": "^6.4|^7.0|^8.0",
+ "symfony/process": "^6.4|^7.0|^8.0",
+ "symfony/stopwatch": "^6.4|^7.0|^8.0",
+ "symfony/var-dumper": "^6.4|^7.0|^8.0"
},
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "3.0-dev"
- }
- },
"autoload": {
- "classmap": [
- "src/"
+ "psr-4": {
+ "Symfony\\Component\\Console\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Collection of value objects that represent the PHP code units",
- "homepage": "https://github.com/sebastianbergmann/code-unit",
+ "description": "Eases the creation of beautiful and testable command line interfaces",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "cli",
+ "command-line",
+ "console",
+ "terminal"
+ ],
"support": {
- "issues": "https://github.com/sebastianbergmann/code-unit/issues",
- "security": "https://github.com/sebastianbergmann/code-unit/security/policy",
- "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.3"
+ "source": "https://github.com/symfony/console/tree/v7.4.14"
},
"funding": [
{
- "url": "https://github.com/sebastianbergmann",
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
"type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
}
],
- "time": "2025-03-19T07:56:08+00:00"
+ "time": "2026-06-16T11:50:14+00:00"
},
{
- "name": "sebastian/code-unit-reverse-lookup",
- "version": "4.0.1",
+ "name": "symfony/deprecation-contracts",
+ "version": "v3.7.1",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
- "reference": "183a9b2632194febd219bb9246eee421dad8d45e"
+ "url": "https://github.com/symfony/deprecation-contracts.git",
+ "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e",
- "reference": "183a9b2632194febd219bb9246eee421dad8d45e",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/f3202fa1b5097b0af062dc978b32ecf63404e31d",
+ "reference": "f3202fa1b5097b0af062dc978b32ecf63404e31d",
"shasum": ""
},
"require": {
- "php": ">=8.2"
- },
- "require-dev": {
- "phpunit/phpunit": "^11.0"
+ "php": ">=8.1"
},
"type": "library",
"extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
"branch-alias": {
- "dev-main": "4.0-dev"
+ "dev-main": "3.7-dev"
}
},
"autoload": {
- "classmap": [
- "src/"
+ "files": [
+ "function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Looks up which function or method a line of code belongs to",
- "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
+ "description": "A generic function and convention to trigger deprecation notices",
+ "homepage": "https://symfony.com",
"support": {
- "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
- "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy",
- "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1"
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.1"
},
"funding": [
{
- "url": "https://github.com/sebastianbergmann",
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
"type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
}
],
- "time": "2024-07-03T04:45:54+00:00"
+ "time": "2026-06-05T06:23:12+00:00"
},
{
- "name": "sebastian/comparator",
- "version": "6.3.3",
+ "name": "symfony/filesystem",
+ "version": "v7.4.11",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/comparator.git",
- "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9"
+ "url": "https://github.com/symfony/filesystem.git",
+ "reference": "d721ea61b4a5fba8c5b6e7c1feda19efea144b50"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2c95e1e86cb8dd41beb8d502057d1081ccc8eca9",
- "reference": "2c95e1e86cb8dd41beb8d502057d1081ccc8eca9",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/d721ea61b4a5fba8c5b6e7c1feda19efea144b50",
+ "reference": "d721ea61b4a5fba8c5b6e7c1feda19efea144b50",
"shasum": ""
},
"require": {
- "ext-dom": "*",
- "ext-mbstring": "*",
"php": ">=8.2",
- "sebastian/diff": "^6.0",
- "sebastian/exporter": "^6.0"
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-mbstring": "~1.8"
},
"require-dev": {
- "phpunit/phpunit": "^11.4"
- },
- "suggest": {
- "ext-bcmath": "For comparing BcMath\\Number objects"
+ "symfony/process": "^6.4|^7.0|^8.0"
},
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "6.3-dev"
- }
- },
"autoload": {
- "classmap": [
- "src/"
+ "psr-4": {
+ "Symfony\\Component\\Filesystem\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- },
- {
- "name": "Jeff Welch",
- "email": "whatthejeff@gmail.com"
- },
- {
- "name": "Volker Dusch",
- "email": "github@wallbash.com"
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
},
{
- "name": "Bernhard Schussek",
- "email": "bschussek@2bepublished.at"
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Provides the functionality to compare PHP values for equality",
- "homepage": "https://github.com/sebastianbergmann/comparator",
- "keywords": [
- "comparator",
- "compare",
- "equality"
- ],
+ "description": "Provides basic utilities for the filesystem",
+ "homepage": "https://symfony.com",
"support": {
- "issues": "https://github.com/sebastianbergmann/comparator/issues",
- "security": "https://github.com/sebastianbergmann/comparator/security/policy",
- "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.3"
+ "source": "https://github.com/symfony/filesystem/tree/v7.4.11"
},
"funding": [
{
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
},
{
- "url": "https://liberapay.com/sebastianbergmann",
- "type": "liberapay"
+ "url": "https://github.com/fabpot",
+ "type": "github"
},
{
- "url": "https://thanks.dev/u/gh/sebastianbergmann",
- "type": "thanks_dev"
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
},
{
- "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator",
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2026-01-24T09:26:40+00:00"
+ "time": "2026-05-11T16:38:44+00:00"
},
{
- "name": "sebastian/complexity",
- "version": "4.0.1",
+ "name": "symfony/finder",
+ "version": "v7.4.14",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/complexity.git",
- "reference": "ee41d384ab1906c68852636b6de493846e13e5a0"
+ "url": "https://github.com/symfony/finder.git",
+ "reference": "13b38720174286f55d1761152b575a8d1436fc25"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0",
- "reference": "ee41d384ab1906c68852636b6de493846e13e5a0",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/13b38720174286f55d1761152b575a8d1436fc25",
+ "reference": "13b38720174286f55d1761152b575a8d1436fc25",
"shasum": ""
},
"require": {
- "nikic/php-parser": "^5.0",
"php": ">=8.2"
},
"require-dev": {
- "phpunit/phpunit": "^11.0"
+ "symfony/filesystem": "^6.4|^7.0|^8.0"
},
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "4.0-dev"
- }
- },
"autoload": {
- "classmap": [
- "src/"
+ "psr-4": {
+ "Symfony\\Component\\Finder\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Library for calculating the complexity of PHP code units",
- "homepage": "https://github.com/sebastianbergmann/complexity",
+ "description": "Finds files and directories via an intuitive fluent interface",
+ "homepage": "https://symfony.com",
"support": {
- "issues": "https://github.com/sebastianbergmann/complexity/issues",
- "security": "https://github.com/sebastianbergmann/complexity/security/policy",
- "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1"
+ "source": "https://github.com/symfony/finder/tree/v7.4.14"
},
"funding": [
{
- "url": "https://github.com/sebastianbergmann",
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
"type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
}
],
- "time": "2024-07-03T04:49:50+00:00"
+ "time": "2026-06-27T08:31:18+00:00"
},
{
- "name": "sebastian/diff",
- "version": "6.0.2",
+ "name": "symfony/polyfill-ctype",
+ "version": "v1.37.0",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/diff.git",
- "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544"
+ "url": "https://github.com/symfony/polyfill-ctype.git",
+ "reference": "141046a8f9477948ff284fa65be2095baafb94f2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544",
- "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2",
+ "reference": "141046a8f9477948ff284fa65be2095baafb94f2",
"shasum": ""
},
"require": {
- "php": ">=8.2"
+ "php": ">=7.2"
},
- "require-dev": {
- "phpunit/phpunit": "^11.0",
- "symfony/process": "^4.2 || ^5"
+ "provide": {
+ "ext-ctype": "*"
+ },
+ "suggest": {
+ "ext-ctype": "For best performance"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-main": "6.0-dev"
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
- "classmap": [
- "src/"
- ]
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Ctype\\": ""
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
+ "name": "Gert de Pagter",
+ "email": "BackEndTea@gmail.com"
},
{
- "name": "Kore Nordmann",
- "email": "mail@kore-nordmann.de"
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Diff implementation",
- "homepage": "https://github.com/sebastianbergmann/diff",
+ "description": "Symfony polyfill for ctype functions",
+ "homepage": "https://symfony.com",
"keywords": [
- "diff",
- "udiff",
- "unidiff",
- "unified diff"
+ "compatibility",
+ "ctype",
+ "polyfill",
+ "portable"
],
"support": {
- "issues": "https://github.com/sebastianbergmann/diff/issues",
- "security": "https://github.com/sebastianbergmann/diff/security/policy",
- "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2"
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.37.0"
},
"funding": [
{
- "url": "https://github.com/sebastianbergmann",
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
"type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
}
],
- "time": "2024-07-03T04:53:05+00:00"
+ "time": "2026-04-10T16:19:22+00:00"
},
{
- "name": "sebastian/environment",
- "version": "7.2.1",
+ "name": "symfony/polyfill-intl-grapheme",
+ "version": "v1.38.1",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/environment.git",
- "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4"
+ "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
+ "reference": "e9247d281d694a5120554d9afaf54e070e88a603"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/a5c75038693ad2e8d4b6c15ba2403532647830c4",
- "reference": "a5c75038693ad2e8d4b6c15ba2403532647830c4",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/e9247d281d694a5120554d9afaf54e070e88a603",
+ "reference": "e9247d281d694a5120554d9afaf54e070e88a603",
"shasum": ""
},
"require": {
- "php": ">=8.2"
- },
- "require-dev": {
- "phpunit/phpunit": "^11.3"
+ "php": ">=7.2"
},
"suggest": {
- "ext-posix": "*"
+ "ext-intl": "For best performance"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-main": "7.2-dev"
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
- "classmap": [
- "src/"
- ]
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Provides functionality to handle HHVM/PHP environments",
- "homepage": "https://github.com/sebastianbergmann/environment",
+ "description": "Symfony polyfill for intl's grapheme_* functions",
+ "homepage": "https://symfony.com",
"keywords": [
- "Xdebug",
- "environment",
- "hhvm"
+ "compatibility",
+ "grapheme",
+ "intl",
+ "polyfill",
+ "portable",
+ "shim"
],
"support": {
- "issues": "https://github.com/sebastianbergmann/environment/issues",
- "security": "https://github.com/sebastianbergmann/environment/security/policy",
- "source": "https://github.com/sebastianbergmann/environment/tree/7.2.1"
+ "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.38.1"
},
"funding": [
{
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
},
{
- "url": "https://liberapay.com/sebastianbergmann",
- "type": "liberapay"
+ "url": "https://github.com/fabpot",
+ "type": "github"
},
{
- "url": "https://thanks.dev/u/gh/sebastianbergmann",
- "type": "thanks_dev"
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
},
{
- "url": "https://tidelift.com/funding/github/packagist/sebastian/environment",
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2025-05-21T11:55:47+00:00"
+ "time": "2026-05-26T05:58:03+00:00"
},
{
- "name": "sebastian/exporter",
- "version": "6.3.2",
+ "name": "symfony/polyfill-intl-normalizer",
+ "version": "v1.38.0",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/exporter.git",
- "reference": "70a298763b40b213ec087c51c739efcaa90bcd74"
+ "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
+ "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/70a298763b40b213ec087c51c739efcaa90bcd74",
- "reference": "70a298763b40b213ec087c51c739efcaa90bcd74",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/2d446c214bdbe5b71bde5011b060a05fece3ae6b",
+ "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b",
"shasum": ""
},
"require": {
- "ext-mbstring": "*",
- "php": ">=8.2",
- "sebastian/recursion-context": "^6.0"
+ "php": ">=7.2"
},
- "require-dev": {
- "phpunit/phpunit": "^11.3"
+ "suggest": {
+ "ext-intl": "For best performance"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-main": "6.3-dev"
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
+ },
"classmap": [
- "src/"
+ "Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- },
- {
- "name": "Jeff Welch",
- "email": "whatthejeff@gmail.com"
- },
- {
- "name": "Volker Dusch",
- "email": "github@wallbash.com"
- },
- {
- "name": "Adam Harvey",
- "email": "aharvey@php.net"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
},
{
- "name": "Bernhard Schussek",
- "email": "bschussek@gmail.com"
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Provides the functionality to export PHP variables for visualization",
- "homepage": "https://www.github.com/sebastianbergmann/exporter",
+ "description": "Symfony polyfill for intl's Normalizer class and related functions",
+ "homepage": "https://symfony.com",
"keywords": [
- "export",
- "exporter"
+ "compatibility",
+ "intl",
+ "normalizer",
+ "polyfill",
+ "portable",
+ "shim"
],
"support": {
- "issues": "https://github.com/sebastianbergmann/exporter/issues",
- "security": "https://github.com/sebastianbergmann/exporter/security/policy",
- "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.2"
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.38.0"
},
"funding": [
{
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
},
{
- "url": "https://liberapay.com/sebastianbergmann",
- "type": "liberapay"
+ "url": "https://github.com/fabpot",
+ "type": "github"
},
{
- "url": "https://thanks.dev/u/gh/sebastianbergmann",
- "type": "thanks_dev"
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
},
{
- "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter",
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2025-09-24T06:12:51+00:00"
+ "time": "2026-05-25T13:48:31+00:00"
},
{
- "name": "sebastian/global-state",
- "version": "7.0.2",
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.38.2",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/global-state.git",
- "reference": "3be331570a721f9a4b5917f4209773de17f747d7"
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7",
- "reference": "3be331570a721f9a4b5917f4209773de17f747d7",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6",
+ "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "sebastian/object-reflector": "^4.0",
- "sebastian/recursion-context": "^6.0"
+ "ext-iconv": "*",
+ "php": ">=7.2"
},
- "require-dev": {
- "ext-dom": "*",
- "phpunit/phpunit": "^11.0"
+ "provide": {
+ "ext-mbstring": "*"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-main": "7.0-dev"
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
- "classmap": [
- "src/"
- ]
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Snapshotting of global state",
- "homepage": "https://www.github.com/sebastianbergmann/global-state",
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
"keywords": [
- "global state"
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
],
"support": {
- "issues": "https://github.com/sebastianbergmann/global-state/issues",
- "security": "https://github.com/sebastianbergmann/global-state/security/policy",
- "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2"
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.2"
},
"funding": [
{
- "url": "https://github.com/sebastianbergmann",
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
"type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
}
],
- "time": "2024-07-03T04:57:36+00:00"
+ "time": "2026-05-27T06:59:30+00:00"
},
{
- "name": "sebastian/lines-of-code",
- "version": "3.0.1",
+ "name": "symfony/polyfill-php73",
+ "version": "v1.37.0",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/lines-of-code.git",
- "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a"
+ "url": "https://github.com/symfony/polyfill-php73.git",
+ "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a",
- "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a",
+ "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb",
+ "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb",
"shasum": ""
},
"require": {
- "nikic/php-parser": "^5.0",
- "php": ">=8.2"
- },
- "require-dev": {
- "phpunit/phpunit": "^11.0"
+ "php": ">=7.2"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-main": "3.0-dev"
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php73\\": ""
+ },
"classmap": [
- "src/"
+ "Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Library for counting the lines of code in PHP source code",
- "homepage": "https://github.com/sebastianbergmann/lines-of-code",
+ "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
"support": {
- "issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
- "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy",
- "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1"
+ "source": "https://github.com/symfony/polyfill-php73/tree/v1.37.0"
},
"funding": [
{
- "url": "https://github.com/sebastianbergmann",
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
"type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
}
],
- "time": "2024-07-03T04:58:38+00:00"
+ "time": "2024-09-09T11:45:10+00:00"
},
{
- "name": "sebastian/object-enumerator",
- "version": "6.0.1",
+ "name": "symfony/polyfill-php80",
+ "version": "v1.37.0",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/object-enumerator.git",
- "reference": "f5b498e631a74204185071eb41f33f38d64608aa"
+ "url": "https://github.com/symfony/polyfill-php80.git",
+ "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa",
- "reference": "f5b498e631a74204185071eb41f33f38d64608aa",
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dfb55726c3a76ea3b6459fcfda1ec2d80a682411",
+ "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "sebastian/object-reflector": "^4.0",
- "sebastian/recursion-context": "^6.0"
- },
- "require-dev": {
- "phpunit/phpunit": "^11.0"
+ "php": ">=7.2"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-main": "6.0-dev"
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php80\\": ""
+ },
"classmap": [
- "src/"
+ "Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
+ "name": "Ion Bazan",
+ "email": "ion.bazan@gmail.com"
+ },
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Traverses array structures and object graphs to enumerate all referenced objects",
- "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
+ "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
"support": {
- "issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
- "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy",
- "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1"
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.37.0"
},
"funding": [
{
- "url": "https://github.com/sebastianbergmann",
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
"type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
}
],
- "time": "2024-07-03T05:00:13+00:00"
+ "time": "2026-04-10T16:19:22+00:00"
},
{
- "name": "sebastian/object-reflector",
- "version": "4.0.1",
+ "name": "symfony/polyfill-php81",
+ "version": "v1.38.1",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/object-reflector.git",
- "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9"
+ "url": "https://github.com/symfony/polyfill-php81.git",
+ "reference": "6bfb9c766cacffbc8e118cb87217d08ed84e5cd7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9",
- "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9",
+ "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/6bfb9c766cacffbc8e118cb87217d08ed84e5cd7",
+ "reference": "6bfb9c766cacffbc8e118cb87217d08ed84e5cd7",
"shasum": ""
},
"require": {
- "php": ">=8.2"
- },
- "require-dev": {
- "phpunit/phpunit": "^11.0"
+ "php": ">=7.2"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-main": "4.0-dev"
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php81\\": ""
+ },
"classmap": [
- "src/"
+ "Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Allows reflection of object attributes, including inherited and non-public ones",
- "homepage": "https://github.com/sebastianbergmann/object-reflector/",
+ "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
"support": {
- "issues": "https://github.com/sebastianbergmann/object-reflector/issues",
- "security": "https://github.com/sebastianbergmann/object-reflector/security/policy",
- "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1"
+ "source": "https://github.com/symfony/polyfill-php81/tree/v1.38.1"
},
"funding": [
{
- "url": "https://github.com/sebastianbergmann",
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
"type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
}
],
- "time": "2024-07-03T05:01:32+00:00"
+ "time": "2026-05-26T12:45:58+00:00"
},
{
- "name": "sebastian/recursion-context",
- "version": "6.0.3",
+ "name": "symfony/polyfill-php84",
+ "version": "v1.38.1",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/recursion-context.git",
- "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc"
+ "url": "https://github.com/symfony/polyfill-php84.git",
+ "reference": "f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/f6458abbf32a6c8174f8f26261475dc133b3d9dc",
- "reference": "f6458abbf32a6c8174f8f26261475dc133b3d9dc",
+ "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa",
+ "reference": "f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa",
"shasum": ""
},
"require": {
- "php": ">=8.2"
- },
- "require-dev": {
- "phpunit/phpunit": "^11.3"
+ "php": ">=7.2"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-main": "6.0-dev"
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php84\\": ""
+ },
"classmap": [
- "src/"
+ "Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- },
- {
- "name": "Jeff Welch",
- "email": "whatthejeff@gmail.com"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
},
{
- "name": "Adam Harvey",
- "email": "aharvey@php.net"
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Provides functionality to recursively process PHP variables",
- "homepage": "https://github.com/sebastianbergmann/recursion-context",
+ "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
"support": {
- "issues": "https://github.com/sebastianbergmann/recursion-context/issues",
- "security": "https://github.com/sebastianbergmann/recursion-context/security/policy",
- "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.3"
+ "source": "https://github.com/symfony/polyfill-php84/tree/v1.38.1"
},
"funding": [
{
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
},
{
- "url": "https://liberapay.com/sebastianbergmann",
- "type": "liberapay"
+ "url": "https://github.com/fabpot",
+ "type": "github"
},
{
- "url": "https://thanks.dev/u/gh/sebastianbergmann",
- "type": "thanks_dev"
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
},
{
- "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context",
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2025-08-13T04:42:22+00:00"
+ "time": "2026-05-26T12:51:13+00:00"
},
{
- "name": "sebastian/type",
- "version": "5.1.3",
+ "name": "symfony/process",
+ "version": "v7.4.13",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/type.git",
- "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449"
+ "url": "https://github.com/symfony/process.git",
+ "reference": "f5804be144caceb570f6747519999636b664f24c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/f77d2d4e78738c98d9a68d2596fe5e8fa380f449",
- "reference": "f77d2d4e78738c98d9a68d2596fe5e8fa380f449",
+ "url": "https://api.github.com/repos/symfony/process/zipball/f5804be144caceb570f6747519999636b664f24c",
+ "reference": "f5804be144caceb570f6747519999636b664f24c",
"shasum": ""
},
- "require": {
- "php": ">=8.2"
- },
- "require-dev": {
- "phpunit/phpunit": "^11.3"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "5.1-dev"
- }
+ "require": {
+ "php": ">=8.2"
},
+ "type": "library",
"autoload": {
- "classmap": [
- "src/"
+ "psr-4": {
+ "Symfony\\Component\\Process\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Collection of value objects that represent the types of the PHP type system",
- "homepage": "https://github.com/sebastianbergmann/type",
+ "description": "Executes commands in sub-processes",
+ "homepage": "https://symfony.com",
"support": {
- "issues": "https://github.com/sebastianbergmann/type/issues",
- "security": "https://github.com/sebastianbergmann/type/security/policy",
- "source": "https://github.com/sebastianbergmann/type/tree/5.1.3"
+ "source": "https://github.com/symfony/process/tree/v7.4.13"
},
"funding": [
{
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
},
{
- "url": "https://liberapay.com/sebastianbergmann",
- "type": "liberapay"
+ "url": "https://github.com/fabpot",
+ "type": "github"
},
{
- "url": "https://thanks.dev/u/gh/sebastianbergmann",
- "type": "thanks_dev"
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
},
{
- "url": "https://tidelift.com/funding/github/packagist/sebastian/type",
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2025-08-09T06:55:48+00:00"
+ "time": "2026-05-23T16:05:06+00:00"
},
{
- "name": "sebastian/version",
- "version": "5.0.2",
+ "name": "symfony/service-contracts",
+ "version": "v3.7.1",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/version.git",
- "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874"
+ "url": "https://github.com/symfony/service-contracts.git",
+ "reference": "c0a284bab1ed8aa0417e3d69250ab437739563a0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874",
- "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/c0a284bab1ed8aa0417e3d69250ab437739563a0",
+ "reference": "c0a284bab1ed8aa0417e3d69250ab437739563a0",
"shasum": ""
},
"require": {
- "php": ">=8.2"
+ "php": ">=8.1",
+ "psr/container": "^1.1|^2.0",
+ "symfony/deprecation-contracts": "^2.5|^3"
+ },
+ "conflict": {
+ "ext-psr": "<1.1|>=2"
},
"type": "library",
"extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
"branch-alias": {
- "dev-main": "5.0-dev"
+ "dev-main": "3.7-dev"
}
},
"autoload": {
- "classmap": [
- "src/"
+ "psr-4": {
+ "Symfony\\Contracts\\Service\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Test/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Library that helps with managing the version number of Git-hosted PHP projects",
- "homepage": "https://github.com/sebastianbergmann/version",
+ "description": "Generic abstractions related to writing services",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
"support": {
- "issues": "https://github.com/sebastianbergmann/version/issues",
- "security": "https://github.com/sebastianbergmann/version/security/policy",
- "source": "https://github.com/sebastianbergmann/version/tree/5.0.2"
+ "source": "https://github.com/symfony/service-contracts/tree/v3.7.1"
},
"funding": [
{
- "url": "https://github.com/sebastianbergmann",
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
"type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
}
],
- "time": "2024-10-09T05:16:32+00:00"
+ "time": "2026-06-16T09:55:08+00:00"
},
{
- "name": "squizlabs/php_codesniffer",
- "version": "3.13.5",
+ "name": "symfony/string",
+ "version": "v7.4.13",
"source": {
"type": "git",
- "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
- "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4"
+ "url": "https://github.com/symfony/string.git",
+ "reference": "961683010db3b27ec6ebcd7308e6e1ee8fa7ffde"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0ca86845ce43291e8f5692c7356fccf3bcf02bf4",
- "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4",
+ "url": "https://api.github.com/repos/symfony/string/zipball/961683010db3b27ec6ebcd7308e6e1ee8fa7ffde",
+ "reference": "961683010db3b27ec6ebcd7308e6e1ee8fa7ffde",
"shasum": ""
},
"require": {
- "ext-simplexml": "*",
- "ext-tokenizer": "*",
- "ext-xmlwriter": "*",
- "php": ">=5.4.0"
+ "php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3.0",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-intl-grapheme": "~1.33",
+ "symfony/polyfill-intl-normalizer": "~1.0",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "conflict": {
+ "symfony/translation-contracts": "<2.5"
},
"require-dev": {
- "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4"
+ "symfony/emoji": "^7.1|^8.0",
+ "symfony/http-client": "^6.4|^7.0|^8.0",
+ "symfony/intl": "^6.4|^7.0|^8.0",
+ "symfony/translation-contracts": "^2.5|^3.0",
+ "symfony/var-exporter": "^6.4|^7.0|^8.0"
},
- "bin": [
- "bin/phpcbf",
- "bin/phpcs"
- ],
"type": "library",
+ "autoload": {
+ "files": [
+ "Resources/functions.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\String\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Greg Sherwood",
- "role": "Former lead"
- },
- {
- "name": "Juliette Reinders Folmer",
- "role": "Current lead"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
},
{
- "name": "Contributors",
- "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors"
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
- "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
+ "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
+ "homepage": "https://symfony.com",
"keywords": [
- "phpcs",
- "standards",
- "static analysis"
+ "grapheme",
+ "i18n",
+ "string",
+ "unicode",
+ "utf-8",
+ "utf8"
],
"support": {
- "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues",
- "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy",
- "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
- "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki"
+ "source": "https://github.com/symfony/string/tree/v7.4.13"
},
"funding": [
{
- "url": "https://github.com/PHPCSStandards",
- "type": "github"
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
},
{
- "url": "https://github.com/jrfnl",
+ "url": "https://github.com/fabpot",
"type": "github"
},
{
- "url": "https://opencollective.com/php_codesniffer",
- "type": "open_collective"
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
},
{
- "url": "https://thanks.dev/u/gh/phpcsstandards",
- "type": "thanks_dev"
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
}
],
- "time": "2025-11-04T16:30:35+00:00"
+ "time": "2026-05-23T15:23:29+00:00"
},
{
- "name": "staabm/side-effects-detector",
- "version": "1.0.5",
+ "name": "symfony/var-exporter",
+ "version": "v7.4.14",
"source": {
"type": "git",
- "url": "https://github.com/staabm/side-effects-detector.git",
- "reference": "d8334211a140ce329c13726d4a715adbddd0a163"
+ "url": "https://github.com/symfony/var-exporter.git",
+ "reference": "0118811b1d59f323bf131250b3fb919febfece28"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163",
- "reference": "d8334211a140ce329c13726d4a715adbddd0a163",
+ "url": "https://api.github.com/repos/symfony/var-exporter/zipball/0118811b1d59f323bf131250b3fb919febfece28",
+ "reference": "0118811b1d59f323bf131250b3fb919febfece28",
"shasum": ""
},
"require": {
- "ext-tokenizer": "*",
- "php": "^7.4 || ^8.0"
+ "php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3"
},
"require-dev": {
- "phpstan/extension-installer": "^1.4.3",
- "phpstan/phpstan": "^1.12.6",
- "phpunit/phpunit": "^9.6.21",
- "symfony/var-dumper": "^5.4.43",
- "tomasvotruba/type-coverage": "1.0.0",
- "tomasvotruba/unused-public": "1.0.0"
+ "symfony/property-access": "^6.4|^7.0|^8.0",
+ "symfony/serializer": "^6.4|^7.0|^8.0",
+ "symfony/var-dumper": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
- "classmap": [
- "lib/"
+ "psr-4": {
+ "Symfony\\Component\\VarExporter\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
- "description": "A static analysis tool to detect side effects in PHP code",
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Allows exporting any serializable PHP data structure to plain PHP code",
+ "homepage": "https://symfony.com",
"keywords": [
- "static analysis"
+ "clone",
+ "construct",
+ "export",
+ "hydrate",
+ "instantiate",
+ "lazy-loading",
+ "proxy",
+ "serialize"
],
"support": {
- "issues": "https://github.com/staabm/side-effects-detector/issues",
- "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5"
+ "source": "https://github.com/symfony/var-exporter/tree/v7.4.14"
},
"funding": [
{
- "url": "https://github.com/staabm",
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
"type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
}
],
- "time": "2024-10-20T05:08:20+00:00"
+ "time": "2026-06-27T08:41:53+00:00"
},
{
"name": "theseer/tokenizer",
@@ -2483,6 +6111,149 @@
],
"time": "2025-11-17T20:03:58+00:00"
},
+ {
+ "name": "voku/simple-cache",
+ "version": "5.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/voku/simple-cache.git",
+ "reference": "71531e9a8f4bfb75a120a986ac12867af15c65be"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/voku/simple-cache/zipball/71531e9a8f4bfb75a120a986ac12867af15c65be",
+ "reference": "71531e9a8f4bfb75a120a986ac12867af15c65be",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.0.0",
+ "psr/simple-cache": "~1.0 || ~2.0"
+ },
+ "provide": {
+ "psr/simple-cache-implementation": "1.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0"
+ },
+ "suggest": {
+ "predis/predis": "~1.1 || ~2.0 || ~3.0",
+ "symfony/var-exporter": "~3.0 || ~4.0 || ~5.0 || ~6.0 || ~7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "voku\\cache\\": "src/voku/cache/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Lars Moelleken",
+ "homepage": "https://www.moelleken.org/",
+ "role": "Developer"
+ }
+ ],
+ "description": "Simple Cache library",
+ "homepage": "https://github.com/voku/simple-cache",
+ "keywords": [
+ "cache",
+ "caching",
+ "php",
+ "simple cache"
+ ],
+ "support": {
+ "issues": "https://github.com/voku/simple-cache/issues",
+ "source": "https://github.com/voku/simple-cache/tree/5.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://www.paypal.me/moelleken",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/voku",
+ "type": "github"
+ },
+ {
+ "url": "https://www.patreon.com/voku",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/voku/simple-cache",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2025-10-29T13:00:29+00:00"
+ },
+ {
+ "name": "webmozart/assert",
+ "version": "2.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/webmozarts/assert.git",
+ "reference": "2ccb7c2e821038c03a3e6e1700c570c158c55f70"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/webmozarts/assert/zipball/2ccb7c2e821038c03a3e6e1700c570c158c55f70",
+ "reference": "2ccb7c2e821038c03a3e6e1700c570c158c55f70",
+ "shasum": ""
+ },
+ "require": {
+ "ext-ctype": "*",
+ "ext-date": "*",
+ "ext-filter": "*",
+ "php": "^8.2"
+ },
+ "suggest": {
+ "ext-intl": "",
+ "ext-simplexml": "",
+ "ext-spl": ""
+ },
+ "type": "library",
+ "extra": {
+ "psalm": {
+ "pluginClass": "Webmozart\\Assert\\PsalmPlugin"
+ },
+ "branch-alias": {
+ "dev-master": "2.0-dev",
+ "dev-feature/2-0": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Webmozart\\Assert\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
+ },
+ {
+ "name": "Woody Gilk",
+ "email": "woody.gilk@gmail.com"
+ }
+ ],
+ "description": "Assertions to validate method input/output with nice error messages.",
+ "keywords": [
+ "assert",
+ "check",
+ "validate"
+ ],
+ "support": {
+ "issues": "https://github.com/webmozarts/assert/issues",
+ "source": "https://github.com/webmozarts/assert/tree/2.4.1"
+ },
+ "time": "2026-06-15T15:31:57+00:00"
+ },
{
"name": "wp-coding-standards/wpcs",
"version": "3.3.0",
diff --git a/phpcs.xml b/phpcs.xml
index f16ca26d..fda3cffe 100644
--- a/phpcs.xml
+++ b/phpcs.xml
@@ -7,6 +7,7 @@
Date: Mon, 29 Jun 2026 00:52:43 +0800
Subject: [PATCH 41/86] feature(renamer): Rewrite plugin header via docblock
replacement
Remove the ORIGINAL_NAME ORIGINAL_DESCRIPTION ORIGINAL_AUTHOR
ORIGINAL_AUTHOR_URI ORIGINAL_PLUGIN_URI constants. Replace
string-by-string header edits with a preg_replace-based docblock
swap targeting the @wordpress-plugin annotation.
Add dedicated add_main_file method that reads the main plugin file
rewrites the full header docblock then adds it to the ZIP separately
from the file iterator.
Add rewrite_composer_autoloader_classes to recompute
ComposerAutoloaderInit and ComposerStaticInit hashes from a
deterministic value derived from the new plugin identity.
Update default author URI and plugin URI to saltus.dev.
---
src/Plugin/Renamer/PluginIdentity.php | 6 +-
src/Plugin/Renamer/PluginRenamer.php | 106 ++++++++++++++++++++------
2 files changed, 86 insertions(+), 26 deletions(-)
diff --git a/src/Plugin/Renamer/PluginIdentity.php b/src/Plugin/Renamer/PluginIdentity.php
index d0b859b9..5eb38b65 100644
--- a/src/Plugin/Renamer/PluginIdentity.php
+++ b/src/Plugin/Renamer/PluginIdentity.php
@@ -44,11 +44,10 @@ public static function defaults(): array {
'plugin_slug' => 'my-saltus-plugin',
'main_file' => 'my-saltus-plugin.php',
'namespace_segment' => 'MySaltusPlugin',
-
'description' => 'A WordPress plugin built with the Saltus Framework.',
'author' => 'Your Name',
- 'author_uri' => 'https://example.com/',
- 'plugin_uri' => 'https://example.com/my-saltus-plugin/',
+ 'author_uri' => 'https://saltus.dev/',
+ 'plugin_uri' => 'https://saltus.dev/my-saltus-plugin/',
'version' => '1.0.0',
'prefix' => 'my_saltus_plugin',
);
@@ -76,7 +75,6 @@ public static function from_request( array $request ): self {
$data['plugin_uri'] = esc_url_raw( $data['plugin_uri'] );
self::validate( $data );
-
return new self( $data );
}
diff --git a/src/Plugin/Renamer/PluginRenamer.php b/src/Plugin/Renamer/PluginRenamer.php
index 97a81e78..b8b59de5 100644
--- a/src/Plugin/Renamer/PluginRenamer.php
+++ b/src/Plugin/Renamer/PluginRenamer.php
@@ -12,11 +12,6 @@ class PluginRenamer {
private const ORIGINAL_PACKAGE = 'saltus/framework-demo';
private const ORIGINAL_PREFIX = 'framework_demo';
private const ORIGINAL_PREFIX_UPPER = 'FRAMEWORK_DEMO';
- private const ORIGINAL_NAME = 'Saltus Framework Demo';
- private const ORIGINAL_DESCRIPTION = 'Saltus Plugin Framework Demo.';
- private const ORIGINAL_AUTHOR = 'Saltus';
- private const ORIGINAL_AUTHOR_URI = 'https://saltus.io/';
- private const ORIGINAL_PLUGIN_URI = 'https://saltus.io/';
private const ORIGINAL_VERSION = '2.0.0';
private string $source_dir;
@@ -69,13 +64,32 @@ public function build_zip( PluginIdentity $identity, string $destination ): void
if ( $zip->open( $destination, \ZipArchive::CREATE | \ZipArchive::OVERWRITE ) !== true ) {
throw new \RuntimeException( 'Could not open the temporary ZIP file.' );
}
-
+ $this->add_main_file( $zip, $identity );
$this->add_files( $zip, $identity );
if ( ! $zip->close() ) {
throw new \RuntimeException( 'Failed to write the ZIP file to disk.' );
}
}
+ private function add_main_file( \ZipArchive $zip, PluginIdentity $identity ): void {
+ $main_file_path = $this->source_dir . '/' . self::ORIGINAL_MAIN_FILE;
+ if ( ! is_file( $main_file_path ) ) {
+ throw new \RuntimeException( 'Main plugin file not found: ' . self::ORIGINAL_MAIN_FILE ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
+ }
+
+ $contents = file_get_contents( $main_file_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions
+ if ( $contents === false ) {
+ throw new \RuntimeException( 'Could not read the main plugin file.' );
+ }
+
+ $contents = $this->rewrite_main_file_contents( $contents, $identity );
+
+ $target_path = $identity->plugin_slug . '/' . $identity->main_file;
+ if ( ! $zip->addFromString( $target_path, $contents ) ) {
+ throw new \RuntimeException( 'Failed to add the main plugin file to the ZIP archive.' );
+ }
+ }
+
private function add_files( \ZipArchive $zip, PluginIdentity $identity ): void {
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator(
@@ -94,8 +108,11 @@ private function add_files( \ZipArchive $zip, PluginIdentity $identity ): void {
continue;
}
- $target_path = $identity->plugin_slug . '/' . $this->target_path( $relative_path, $identity );
+ if ( $relative_path === self::ORIGINAL_MAIN_FILE ) {
+ continue;
+ }
+ $target_path = $identity->plugin_slug . '/' . $this->target_path( $relative_path, $identity );
if ( $this->is_text_file( $relative_path ) ) {
$contents = file_get_contents( $file->getPathname() ); // phpcs:ignore WordPress.WP.AlternativeFunctions
if ( $contents === false ) {
@@ -128,7 +145,7 @@ private function should_exclude( string $relative_path ): bool {
$normalized = str_replace( '\\', '/', $relative_path );
$parts = explode( '/', $normalized );
- $excluded_dirs = array( '.git', '.codex', '.agents', 'vendor', 'node_modules', 'build', 'dist', 'release', 'reports' );
+ $excluded_dirs = array( '.git', '.codex', '.agents', 'node_modules', 'build', 'dist', 'release', 'reports', 'vendor' );
if ( array_intersect( $parts, $excluded_dirs ) ) {
return true;
}
@@ -147,22 +164,67 @@ private function is_text_file( string $relative_path ): bool {
private function rewrite_contents( string $contents, PluginIdentity $identity ): string {
$replacements = array(
- self::ORIGINAL_NAMESPACE_SEGMENT => $identity->namespace_segment,
- self::ORIGINAL_PACKAGE => $this->package_name( $identity ),
- self::ORIGINAL_MAIN_FILE => $identity->main_file,
- self::ORIGINAL_PREFIX_UPPER => strtoupper( $identity->prefix ),
- self::ORIGINAL_PREFIX => $identity->prefix,
- 'Plugin Name: ' . self::ORIGINAL_NAME => 'Plugin Name: ' . $identity->plugin_name,
- 'Description: ' . self::ORIGINAL_DESCRIPTION => 'Description: ' . $identity->description,
- 'Plugin URI: ' . self::ORIGINAL_PLUGIN_URI => 'Plugin URI: ' . $identity->plugin_uri,
- 'Author URI: ' . self::ORIGINAL_AUTHOR_URI => 'Author URI: ' . $identity->author_uri,
- 'Author: ' . self::ORIGINAL_AUTHOR => 'Author: ' . $identity->author,
- self::ORIGINAL_SLUG => $identity->plugin_slug,
- "PLUGIN_VERSION', '" . self::ORIGINAL_VERSION . "'" => "PLUGIN_VERSION', '" . $identity->version . "'",
- 'Version: ' . self::ORIGINAL_VERSION => 'Version: ' . $identity->version,
+ self::ORIGINAL_NAMESPACE_SEGMENT => $identity->namespace_segment,
+ self::ORIGINAL_PACKAGE => $this->package_name( $identity ),
+ self::ORIGINAL_MAIN_FILE => $identity->main_file,
+ self::ORIGINAL_PREFIX_UPPER => strtoupper( $identity->prefix ),
+ self::ORIGINAL_PREFIX => $identity->prefix,
+ self::ORIGINAL_SLUG => $identity->plugin_slug,
);
- return strtr( $contents, $replacements );
+ $contents = strtr( $contents, $replacements );
+
+ return $this->rewrite_composer_autoloader_classes( $contents, $identity );
+ }
+
+ private function rewrite_composer_autoloader_classes( string $contents, PluginIdentity $identity ): string {
+ $suffix = substr( md5( $identity->plugin_slug . '|' . $identity->namespace_segment . '|' . $identity->prefix ), 0, 32 );
+
+ $contents = preg_replace( '/ComposerAutoloaderInit[a-f0-9]{32}/', 'ComposerAutoloaderInit' . $suffix, $contents ) ?? $contents;
+ $contents = preg_replace( '/ComposerStaticInit[a-f0-9]{32}/', 'ComposerStaticInit' . $suffix, $contents ) ?? $contents;
+
+ return $contents;
+ }
+
+ private function rewrite_main_file_contents( string $contents, PluginIdentity $identity ): string {
+ $contents = $this->replace_plugin_header( $contents, $identity );
+ $contents = str_replace(
+ "PLUGIN_VERSION', '" . self::ORIGINAL_VERSION . "'",
+ "PLUGIN_VERSION', '" . $identity->version . "'",
+ $contents
+ );
+
+ return $this->rewrite_contents( $contents, $identity );
+ }
+
+ private function replace_plugin_header( string $contents, PluginIdentity $identity ): string {
+ $header = $this->plugin_header( $identity );
+ $result = preg_replace( '/\/\*\*[\s\S]*?@wordpress-plugin[\s\S]*?\*\/\s*/', $header, $contents, 1 );
+
+ if ( $result !== null && $result !== $contents ) {
+ return $result;
+ }
+
+ return preg_replace( '/^<\?php\s*/', "plugin_name}\n"
+ . " *\n"
+ . " * @wordpress-plugin\n"
+ . " * Plugin Name: {$identity->plugin_name}\n"
+ . " * Plugin URI: {$identity->plugin_uri}\n"
+ . " * Description: {$identity->description}\n"
+ . " * Version: {$identity->version}\n"
+ . " * Author: {$identity->author}\n"
+ . " * Author URI: {$identity->author_uri}\n"
+ . " * License: GPL-2.0-or-later\n"
+ . " * License URI: http://www.gnu.org/licenses/gpl-2.0.txt\n"
+ . " * Text Domain: {$identity->text_domain}\n"
+ . " * Domain Path: /languages\n"
+ . " * Requires PHP: 8.3\n"
+ . " */\n\n";
}
private function package_name( PluginIdentity $identity ): string {
From 1489d013915e1e7ce316a8506fe63327b69e5bad Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Mon, 29 Jun 2026 00:52:54 +0800
Subject: [PATCH 42/86] feature(admin): Add direct plugin activation delivery
modes
Add copy-activate delivery path to generate_plugin that builds
the renamed plugin into a ZIP extracts it to WP_PLUGIN_DIR
activates the new plugin then deactivates the source demo.
Show activation notice on plugin activation with a link to the
rebrand tool. Add a plugin row quick-action link for one-click
access to the rebrand page.
Restore submitted form values on validation errors via transient.
Show success messages from transient. Add sidebar guide explaining
the rebrand workflow steps. Refactor redirect_with_error to accept
form data for value persistence. Add notice dismiss action.
---
framework-demo.php | 28 ++-
src/Plugin/Admin/RenamerPage.php | 367 +++++++++++++++++++++++++++----
2 files changed, 352 insertions(+), 43 deletions(-)
diff --git a/framework-demo.php b/framework-demo.php
index 9fbf8d7b..2a900eef 100644
--- a/framework-demo.php
+++ b/framework-demo.php
@@ -4,11 +4,11 @@
*
* @wordpress-plugin
* Plugin Name: Saltus Framework Demo
- * Plugin URI: https://saltus.io/
+ * Plugin URI: https://saltus.dev/
* Description: Saltus Plugin Framework Demo.
* Version: 2.0.0
* Author: Saltus
- * Author URI: https://saltus.io/
+ * Author URI: https://saltus.dev/
* License: GPL-2.0-or-later
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
* Text Domain: framework-demo
@@ -39,6 +39,15 @@
define( __NAMESPACE__ . '\PLUGIN_MINIMUM_PHP', '8.3' );
}
+register_activation_hook(
+ PLUGIN_FILE,
+ static function (): void {
+ if ( ! get_option( 'framework_demo_rebrand_notice_dismissed', false ) ) {
+ update_option( 'framework_demo_rebrand_notice_pending', '1', false );
+ }
+ }
+);
+
if ( version_compare( PHP_VERSION, PLUGIN_MINIMUM_PHP, '<' ) ) {
add_action(
'admin_notices',
@@ -59,6 +68,10 @@ static function (): void {
return;
}
+if ( file_exists( __DIR__ . '/vendor-prefixed/autoload.php' ) ) {
+ require_once __DIR__ . '/vendor-prefixed/autoload.php';
+}
+
if ( file_exists( __DIR__ . '/vendor/autoload.php' ) ) {
require_once __DIR__ . '/vendor/autoload.php';
}
@@ -67,7 +80,12 @@ static function (): void {
require_once __DIR__ . '/src/Core.php';
}
-if ( ! class_exists( \Saltus\WP\Framework\Core::class ) || ! class_exists( Core::class ) ) {
+$framework_core_class = __NAMESPACE__ . '\\Saltus\\WP\\Framework\\Core';
+if ( ! class_exists( $framework_core_class ) ) {
+ $framework_core_class = '\\Saltus\\WP\\Framework\\Core';
+}
+
+if ( ! class_exists( $framework_core_class ) || ! class_exists( Core::class ) ) {
add_action(
'admin_notices',
static function (): void {
@@ -83,8 +101,8 @@ static function (): void {
/*
* The framework needs the plugin root path so it can load the model files.
*/
-$framework = new \Saltus\WP\Framework\Core( __DIR__ );
-$framework->register();
+$saltus_framework = new $framework_core_class( __DIR__ );
+$saltus_framework->register();
add_action(
'plugins_loaded',
diff --git a/src/Plugin/Admin/RenamerPage.php b/src/Plugin/Admin/RenamerPage.php
index d0a4820a..7533c8bd 100644
--- a/src/Plugin/Admin/RenamerPage.php
+++ b/src/Plugin/Admin/RenamerPage.php
@@ -11,9 +11,11 @@
*/
class RenamerPage {
- private const PAGE_SLUG = 'framework-demo-renamer';
- private const NONCE_ACTION = 'framework_demo_generate_plugin';
- private const NONCE_NAME = 'framework_demo_renamer_nonce';
+ private const PAGE_SLUG = 'framework-demo-renamer';
+ private const NONCE_ACTION = 'framework_demo_generate_plugin';
+ private const NONCE_NAME = 'framework_demo_renamer_nonce';
+ private const NOTICE_ACTION = 'framework_demo_dismiss_rebrand_notice';
+ private const NOTICE_NONCE = 'framework_demo_rebrand_notice_nonce';
private Core $core;
@@ -23,41 +25,132 @@ public function __construct( Core $core ) {
public function register(): void {
add_action( 'admin_menu', array( $this, 'add_page' ), 20 );
+ add_action( 'admin_notices', array( $this, 'render_activation_notice' ) );
add_action( 'admin_post_framework_demo_generate_plugin', array( $this, 'generate_plugin' ) );
+ add_action( 'admin_post_framework_demo_dismiss_rebrand_notice', array( $this, 'dismiss_activation_notice' ) );
+ add_filter(
+ 'plugin_action_links_' . plugin_basename( $this->core->get_file_path() ),
+ array( $this, 'add_plugin_action_link' )
+ );
}
public function add_page(): void {
add_submenu_page(
'framework-demo-settings',
- __( 'Rename Plugin', 'framework-demo' ),
- __( 'Rename Plugin', 'framework-demo' ),
+ __( 'Rebrand This Demo', 'framework-demo' ),
+ __( 'Rebrand This Demo', 'framework-demo' ),
'manage_options',
self::PAGE_SLUG,
array( $this, 'render' )
);
+
+ add_management_page(
+ __( 'Rebrand This Demo', 'framework-demo' ),
+ __( 'Rebrand This Demo', 'framework-demo' ),
+ 'manage_options',
+ self::PAGE_SLUG,
+ array( $this, 'render' )
+ );
+ }
+
+ /**
+ * Add a shortcut to the plugin row quick actions.
+ *
+ * @param array
Date: Mon, 29 Jun 2026 00:52:59 +0800
Subject: [PATCH 43/86] feature(css): Style renamer form guide sidebar layout
Add grid layout for the renamer page with two-column form-plus-guide
arrangement on wide screens collapsing to single column on narrow.
Style the form and guide panels with white background and border.
---
assets/css/admin-style.css | 41 ++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/assets/css/admin-style.css b/assets/css/admin-style.css
index e69de29b..4da9dc29 100644
--- a/assets/css/admin-style.css
+++ b/assets/css/admin-style.css
@@ -0,0 +1,41 @@
+.framework-demo-renamer__layout {
+ display: grid;
+ grid-template-columns: minmax(0, 1fr) 360px;
+ gap: 24px;
+ align-items: start;
+ max-width: 1180px;
+}
+
+.framework-demo-renamer__form,
+.framework-demo-renamer__guide {
+ background: #fff;
+ border: 1px solid #c3c4c7;
+ box-sizing: border-box;
+ padding: 16px 20px;
+}
+
+.framework-demo-renamer__form .form-table {
+ margin-top: 0;
+}
+
+.framework-demo-renamer__guide h2 {
+ margin-top: 0;
+}
+
+.framework-demo-renamer__guide h3 {
+ margin: 18px 0 8px;
+}
+
+.framework-demo-renamer__guide ol {
+ margin-left: 20px;
+}
+
+.framework-demo-renamer__guide li {
+ margin-bottom: 8px;
+}
+
+@media (max-width: 960px) {
+ .framework-demo-renamer__layout {
+ grid-template-columns: 1fr;
+ }
+}
From 7c48f644c6eba46d626e5b8415c9f1646b85da3f Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Mon, 29 Jun 2026 00:53:03 +0800
Subject: [PATCH 44/86] i18n: Update translation template for rebrand strings
Sync the POT file after renaming "Rename Plugin" to "Rebrand This
Demo" and adding the new UI strings for copy-activate delivery
activation notice and guide sidebar.
---
languages/framework-demo.pot | 624 +++++++++++++++++++++++------------
1 file changed, 410 insertions(+), 214 deletions(-)
diff --git a/languages/framework-demo.pot b/languages/framework-demo.pot
index 5e794196..55471c54 100644
--- a/languages/framework-demo.pot
+++ b/languages/framework-demo.pot
@@ -1,384 +1,580 @@
-# Copyright (C) 2020 Saltus
-# This file is distributed under the GPL-2.0+.
+# Copyright (C) 2026 Saltus
+# This file is distributed under the GPL-2.0-or-later.
msgid ""
msgstr ""
-"Project-Id-Version: Saltus Framework Demo 1.0.11\n"
-"Report-Msgid-Bugs-To: https://saltus.dev/\n"
-"POT-Creation-Date: 2020-01-19 01:17:20+00:00\n"
+"Project-Id-Version: Saltus Framework Demo 2.0.0\n"
+"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/framework-demo\n"
+"Last-Translator: FULL NAME
Date: Mon, 29 Jun 2026 00:53:12 +0800
Subject: [PATCH 45/86] test(renamer): Cover header replacement autoloader
prefixing
Add assertions for plugin URI Author URI and Text Domain fields
in the generated ZIP main file. Verify the source header docblock
is fully replaced not just overlaid.
Add assertions for vendor-prefixed autoload.php and composer
autoload_real.php: verify ComposerAutoloaderInit and
ComposerStaticInit hashes are rewritten and the original hashes
are absent. Verify PluginFrameworkDemo namespace is absent from
prefixed files.
Include vendor-prefixed fixture files (autoload.php
autoload_real.php autoload_static.php) in the test fixture.
---
tests/Plugin/Renamer/PluginRenamerTest.php | 35 +++++++++++++++++++++-
1 file changed, 34 insertions(+), 1 deletion(-)
diff --git a/tests/Plugin/Renamer/PluginRenamerTest.php b/tests/Plugin/Renamer/PluginRenamerTest.php
index 62dca7cc..103be773 100644
--- a/tests/Plugin/Renamer/PluginRenamerTest.php
+++ b/tests/Plugin/Renamer/PluginRenamerTest.php
@@ -33,14 +33,33 @@ public function test_build_zip_creates_renamed_plugin_package(): void {
self::assertNotFalse( $zip->locateName( 'acme-library/acme-library.php' ) );
self::assertFalse( $zip->locateName( 'acme-library/vendor/autoload.php' ) );
+ self::assertNotFalse( $zip->locateName( 'acme-library/vendor-prefixed/autoload.php' ) );
self::assertFalse( $zip->locateName( 'acme-library/build/Gruntfile.js' ) );
$contents = $zip->getFromName( 'acme-library/acme-library.php' );
self::assertIsString( $contents );
self::assertStringContainsString( 'Plugin Name: Acme Library', $contents );
+ self::assertStringContainsString( 'Plugin URI: https://saltus.dev/my-saltus-plugin/', $contents );
+ self::assertStringContainsString( 'Author URI: https://saltus.dev/', $contents );
+ self::assertStringContainsString( 'Text Domain: acme-library', $contents );
self::assertStringContainsString( 'namespace Saltus\\WP\\Plugin\\Saltus\\AcmeLibrary;', $contents );
+ self::assertStringNotContainsString( 'Source Header That Should Not Matter', $contents );
self::assertStringNotContainsString( 'framework-demo', $contents );
+ $prefixed_autoload = $zip->getFromName( 'acme-library/vendor-prefixed/autoload.php' );
+ self::assertIsString( $prefixed_autoload );
+ self::assertStringContainsString( 'Saltus\\\\WP\\\\Plugin\\\\Saltus\\\\AcmeLibrary', $prefixed_autoload );
+ self::assertMatchesRegularExpression( '/ComposerAutoloaderInit[a-f0-9]{32}/', $prefixed_autoload );
+ self::assertStringNotContainsString( 'ComposerAutoloaderInit0515b56810b0a42fc7dbe10cb02ee1c8', $prefixed_autoload );
+ self::assertStringNotContainsString( 'PluginFrameworkDemo', $prefixed_autoload );
+
+ $autoload_real = $zip->getFromName( 'acme-library/vendor-prefixed/composer/autoload_real.php' );
+ self::assertIsString( $autoload_real );
+ self::assertMatchesRegularExpression( '/ComposerAutoloaderInit[a-f0-9]{32}/', $autoload_real );
+ self::assertMatchesRegularExpression( '/ComposerStaticInit[a-f0-9]{32}/', $autoload_real );
+ self::assertStringNotContainsString( 'ComposerAutoloaderInit0515b56810b0a42fc7dbe10cb02ee1c8', $autoload_real );
+ self::assertStringNotContainsString( 'ComposerStaticInit0515b56810b0a42fc7dbe10cb02ee1c8', $autoload_real );
+
$zip->close();
@unlink( $output );
$this->remove_dir( $source );
@@ -183,14 +202,28 @@ private function make_source_fixture( bool $with_composer = false ): string {
$source = sys_get_temp_dir() . '/framework-demo-fixture-' . uniqid();
mkdir( $source . '/src', 0777, true );
mkdir( $source . '/vendor', 0777, true );
+ mkdir( $source . '/vendor-prefixed', 0777, true );
+ mkdir( $source . '/vendor-prefixed/composer', 0777, true );
mkdir( $source . '/build', 0777, true );
file_put_contents(
$source . '/framework-demo.php',
- "
Date: Mon, 29 Jun 2026 00:53:16 +0800
Subject: [PATCH 46/86] docs(readme): Update for rebrand UI changes
Replace the "Rename UI" section with "Rebrand This Demo" covering
the new copy-activate delivery mode and the two install paths.
Present field descriptions as a bullet list for clarity.
---
README.md | 31 ++++++++++++++++++-------------
1 file changed, 18 insertions(+), 13 deletions(-)
diff --git a/README.md b/README.md
index 2c04ed49..903115db 100644
--- a/README.md
+++ b/README.md
@@ -26,22 +26,27 @@ The demo models live in `src/models`:
- `post-type-all.php` registers the larger `book` demo, including meta fields and settings.
- `taxonomy-multiple.php` registers demo taxonomies for books and posts.
-## Rename UI
+## Rebrand This Demo
-The plugin includes a generator UI for creating a renamed copy of the demo plugin.
+The plugin includes a generator UI for creating your own branded copy of the demo plugin. In wp-admin, open **Tools > Rebrand This Demo** or use the **Rebrand This Demo** quick action on the plugin row.
-In wp-admin, open the plugin settings screen and choose **Rename Plugin**. Fill in the new plugin identity:
+Fill in the form with the identity your new plugin should use:
-- plugin name
-- slug and main file
-- namespace segment
-- text domain
-- description
-- author details
-- version
-- code prefix
+- **Plugin Name**: the public name shown in WordPress.
+- **Plugin Slug**: a lowercase folder-safe slug, such as `my-saltus-plugin`.
+- **Main Plugin File**: the main PHP file, usually matching the slug, such as `my-saltus-plugin.php`.
+- **Namespace Segment**: a PHP namespace segment like `MySaltusPlugin`.
+- **Description**: the plugin summary shown in wp-admin.
+- **Author details**: the author name and optional author/plugin URLs.
+- **Version**: a semver value such as `1.0.0`.
+- **Code Prefix**: a lowercase PHP-safe prefix like `my_saltus_plugin`.
-Submitting the form downloads a ZIP file for the renamed plugin. The installed demo plugin is not modified.
+After filling in the form, choose one of two install paths:
+
+- **Download Rebranded Plugin ZIP**: download the ZIP, then upload it from **Plugins > Add New > Upload Plugin** and activate it.
+- **Copy & Activate Plugin**: copy the generated plugin directly into this WordPress site's plugins directory and activate it automatically.
+
+The generated plugin is a separate copy. The installed demo plugin is not modified.
## Development Commands
@@ -52,7 +57,7 @@ vendor/bin/phpunit
composer package
```
-`composer package` creates `dist/framework-demo.zip`.
+`composer package` creates `dist/framework-demo-
Date: Mon, 29 Jun 2026 03:30:02 +0800
Subject: [PATCH 47/86] fix(renamer): Strip */ from URI header fields
preventing comment breakout
The author_uri and plugin_uri fields were sanitized with esc_url_raw()
and validated with FILTER_VALIDATE_URL, but neither check strips the
multi-line comment closing sequence */. Since these fields are written
directly into the generated plugin's /** */ header block, an attacker
could inject a URL like https://example.com?a=1*/system(current());/*
to close the comment early and execute arbitrary PHP code.
Add author_uri and plugin_uri to the existing str_replace('*/', '', ...)
loop that already covers plugin_name, description, and author.
---
src/Plugin/Renamer/PluginIdentity.php | 2 +-
tests/Plugin/Renamer/PluginIdentityTest.php | 13 +++++++++++++
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/src/Plugin/Renamer/PluginIdentity.php b/src/Plugin/Renamer/PluginIdentity.php
index 5eb38b65..6210a9a8 100644
--- a/src/Plugin/Renamer/PluginIdentity.php
+++ b/src/Plugin/Renamer/PluginIdentity.php
@@ -67,7 +67,7 @@ public static function from_request( array $request ): self {
$data['author_uri'] = trim( $data['author_uri'] );
$data['plugin_uri'] = trim( $data['plugin_uri'] );
- foreach ( array( 'plugin_name', 'description', 'author' ) as $comment_field ) {
+ foreach ( array( 'plugin_name', 'description', 'author', 'author_uri', 'plugin_uri' ) as $comment_field ) {
$data[ $comment_field ] = str_replace( '*/', '', $data[ $comment_field ] );
}
diff --git a/tests/Plugin/Renamer/PluginIdentityTest.php b/tests/Plugin/Renamer/PluginIdentityTest.php
index fe0dbb7a..0a16eb92 100644
--- a/tests/Plugin/Renamer/PluginIdentityTest.php
+++ b/tests/Plugin/Renamer/PluginIdentityTest.php
@@ -81,4 +81,17 @@ public function test_comment_breakout_is_sanitized(): void {
self::assertSame( 'Desc breakout', $identity->description );
self::assertSame( 'Auth test', $identity->author );
}
+
+ public function test_uri_comment_breakout_is_sanitized(): void {
+ $data = PluginIdentity::defaults();
+ $data['author_uri'] = 'https://example.com?a=1*/system(current($_GET));/*';
+ $data['plugin_uri'] = 'https://example.com?b=2*/phpinfo();/*';
+
+ $identity = PluginIdentity::from_request( $data );
+
+ self::assertStringNotContainsString( '*/', $identity->author_uri );
+ self::assertStringNotContainsString( '*/', $identity->plugin_uri );
+ self::assertSame( 'https://example.com?a=1system(current($_GET));/*', $identity->author_uri );
+ self::assertSame( 'https://example.com?b=2phpinfo();/*', $identity->plugin_uri );
+ }
}
From 23d69152e2e59ac86a68e9619cf28a1b18efe68f Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Mon, 29 Jun 2026 04:07:35 +0800
Subject: [PATCH 48/86] fix(renamer): Add composerRequire to renamed autoloader
patterns
Composer generates a composerRequire[hash] global helper function in autoload_real.php. Without renaming, activating multiple rebranded plugins causes a fatal "Cannot redeclare composerRequire[hash]()" error.
Adds the pattern to the existing set of renamed Composer autoloader identifiers (ComposerAutoloaderInit, ComposerStaticInit) and extends the test fixture and assertions to cover it.
---
src/Plugin/Renamer/PluginRenamer.php | 1 +
tests/Plugin/Renamer/PluginRenamerTest.php | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/Plugin/Renamer/PluginRenamer.php b/src/Plugin/Renamer/PluginRenamer.php
index b8b59de5..8f106960 100644
--- a/src/Plugin/Renamer/PluginRenamer.php
+++ b/src/Plugin/Renamer/PluginRenamer.php
@@ -182,6 +182,7 @@ private function rewrite_composer_autoloader_classes( string $contents, PluginId
$contents = preg_replace( '/ComposerAutoloaderInit[a-f0-9]{32}/', 'ComposerAutoloaderInit' . $suffix, $contents ) ?? $contents;
$contents = preg_replace( '/ComposerStaticInit[a-f0-9]{32}/', 'ComposerStaticInit' . $suffix, $contents ) ?? $contents;
+ $contents = preg_replace( '/composerRequire[a-f0-9]{32}/', 'composerRequire' . $suffix, $contents ) ?? $contents;
return $contents;
}
diff --git a/tests/Plugin/Renamer/PluginRenamerTest.php b/tests/Plugin/Renamer/PluginRenamerTest.php
index 103be773..94ec7880 100644
--- a/tests/Plugin/Renamer/PluginRenamerTest.php
+++ b/tests/Plugin/Renamer/PluginRenamerTest.php
@@ -57,8 +57,10 @@ public function test_build_zip_creates_renamed_plugin_package(): void {
self::assertIsString( $autoload_real );
self::assertMatchesRegularExpression( '/ComposerAutoloaderInit[a-f0-9]{32}/', $autoload_real );
self::assertMatchesRegularExpression( '/ComposerStaticInit[a-f0-9]{32}/', $autoload_real );
+ self::assertMatchesRegularExpression( '/composerRequire[a-f0-9]{32}/', $autoload_real );
self::assertStringNotContainsString( 'ComposerAutoloaderInit0515b56810b0a42fc7dbe10cb02ee1c8', $autoload_real );
self::assertStringNotContainsString( 'ComposerStaticInit0515b56810b0a42fc7dbe10cb02ee1c8', $autoload_real );
+ self::assertStringNotContainsString( 'composerRequire0515b56810b0a42fc7dbe10cb02ee1c8', $autoload_real );
$zip->close();
@unlink( $output );
@@ -218,7 +220,7 @@ private function make_source_fixture( bool $with_composer = false ): string {
);
file_put_contents(
$source . '/vendor-prefixed/composer/autoload_real.php',
- "
Date: Mon, 29 Jun 2026 04:07:38 +0800
Subject: [PATCH 49/86] fix(admin): Check WP_PLUGIN_DIR writability before zip
extraction
Fails early with a clear error message when the plugin directory is not writable, rather than throwing a generic error during ZipArchive::extractTo.
---
src/Plugin/Admin/RenamerPage.php | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/Plugin/Admin/RenamerPage.php b/src/Plugin/Admin/RenamerPage.php
index 7533c8bd..c13b12bf 100644
--- a/src/Plugin/Admin/RenamerPage.php
+++ b/src/Plugin/Admin/RenamerPage.php
@@ -242,6 +242,10 @@ private function copy_and_activate_plugin( PluginRenamer $renamer, PluginIdentit
throw new \RuntimeException( __( 'The WordPress plugin directory could not be found.', 'framework-demo' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
+ if ( ! wp_is_writable( WP_PLUGIN_DIR ) ) {
+ throw new \RuntimeException( __( 'The WordPress plugin directory is not writable.', 'framework-demo' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
+ }
+
$plugin_dir = trailingslashit( WP_PLUGIN_DIR ) . $identity->plugin_slug;
if ( file_exists( $plugin_dir ) ) {
throw new ValidationException( __( 'A plugin folder with that slug already exists. Choose a different slug or remove the existing plugin first.', 'framework-demo' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
From 0110cc6466f340cfc8a656981a4690d96ec40c8b Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Fri, 3 Jul 2026 01:18:02 +0800
Subject: [PATCH 50/86] fix(renamer): Strip PHP close/open tags from identity
comment fields
Extend the dangerous token list from */ alone to include ?> and the
PHP open tag variants (', 'author_uri );
self::assertSame( 'https://example.com?b=2phpinfo();/*', $identity->plugin_uri );
}
+
+ public function test_php_close_tag_is_sanitized(): void {
+ $data = PluginIdentity::defaults();
+ $data['plugin_name'] = 'Foo ?> breakout';
+ $data['description'] = 'Desc ?> injection';
+ $data['author'] = 'Auth ?> test';
+ $data['author_uri'] = 'https://example.com?>path';
+ $data['plugin_uri'] = 'https://example.com?x?>y';
+
+ $identity = PluginIdentity::from_request( $data );
+
+ self::assertSame( 'Foo breakout', $identity->plugin_name );
+ self::assertSame( 'Desc injection', $identity->description );
+ self::assertSame( 'Auth test', $identity->author );
+ self::assertStringNotContainsString( '?>', $identity->author_uri );
+ self::assertStringNotContainsString( '?>', $identity->plugin_uri );
+ }
+
+ public function test_php_open_tags_are_sanitized_in_uris(): void {
+ $data = PluginIdentity::defaults();
+ $data['author_uri'] = 'https://example.com';
+ $data['plugin_uri'] = 'https://example.com?x=y?>z';
+
+ $identity = PluginIdentity::from_request( $data );
+
+ self::assertStringNotContainsString( 'author_uri );
+ self::assertStringNotContainsString( '=', $identity->plugin_uri );
+ }
+
+ public function test_multiple_dangerous_tokens_are_all_stripped(): void {
+ $data = PluginIdentity::defaults();
+ $data['plugin_name'] = 'A*/B?>C';
+
+ $identity = PluginIdentity::from_request( $data );
+
+ self::assertSame( 'ABC', $identity->plugin_name );
+ }
}
From b878fa646c9f952c1204b5f6e74e597f13314d46 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Fri, 3 Jul 2026 02:47:16 +0800
Subject: [PATCH 51/86] infra(build): add CSS minification via PostCSS cssnano
Add PostCSS with cssnano for CSS minification.
- package.json declares postcss, cssnano, postcss-cli as devDependencies.
- postcss.config.js wires cssnano as the PostCSS plugin.
- bin/package.php gains minify_stage_css(), called during the build
pipeline to minify CSS in the staging directory before zipping.
- composer.json adds a minify-css script for standalone use.
---
bin/package.php | 35 +++++++++++++++++++++++++++++++++++
package.json | 13 +++++++++++++
postcss.config.js | 5 +++++
3 files changed, 53 insertions(+)
create mode 100644 package.json
create mode 100644 postcss.config.js
diff --git a/bin/package.php b/bin/package.php
index fb35c9cc..23c1c7e0 100644
--- a/bin/package.php
+++ b/bin/package.php
@@ -163,6 +163,40 @@ function copy_release_files( string $source, string $target ): void {
}
}
+/**
+ * Minify CSS files in the release stage using PostCSS + cssnano.
+ *
+ * @param string $working_dir Staging directory.
+ */
+function minify_stage_css( string $working_dir ): void {
+ $css_dir = $working_dir . '/assets/css';
+
+ if ( ! is_dir( $css_dir ) ) {
+ return;
+ }
+
+ $css_files = glob( $css_dir . '/*.css' );
+
+ if ( empty( $css_files ) ) {
+ return;
+ }
+
+ $npx = PHP_OS_FAMILY === 'WINNT' ? 'npx.cmd' : 'npx';
+ $files = implode( ' ', array_map( 'escapeshellarg', $css_files ) );
+ $command = sprintf(
+ '%s postcss %s --dir %s --no-map 2>&1',
+ escapeshellcmd( $npx ),
+ $files,
+ escapeshellarg( $css_dir )
+ );
+
+ passthru( $command, $exit_code );
+
+ if ( 0 !== $exit_code ) {
+ throw new RuntimeException( 'CSS minification failed.' );
+ }
+}
+
/**
* Run Composer in the release stage and prefix production dependencies.
*
@@ -228,6 +262,7 @@ function zip_release_files( ZipArchive $zip, string $source, string $prefix ): v
}
copy_release_files( $root, $stage );
+ minify_stage_css( $stage );
install_release_dependencies( $stage );
remove_path( $stage . '/composer.json' );
remove_path( $stage . '/composer.lock' );
diff --git a/package.json b/package.json
new file mode 100644
index 00000000..5ade6ec8
--- /dev/null
+++ b/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "saltus-framework-demo",
+ "private": true,
+ "description": "Build tooling for the Saltus Framework Demo WordPress plugin.",
+ "scripts": {
+ "minify-css": "postcss assets/css/*.css --dir assets/css/ --no-map"
+ },
+ "devDependencies": {
+ "cssnano": "^7.0.0",
+ "postcss": "^8.5.0",
+ "postcss-cli": "^11.0.0"
+ }
+}
diff --git a/postcss.config.js b/postcss.config.js
new file mode 100644
index 00000000..de79e02e
--- /dev/null
+++ b/postcss.config.js
@@ -0,0 +1,5 @@
+module.exports = {
+ plugins: [
+ require( 'cssnano' ),
+ ],
+};
From 28d6b7972226dd29f67a187a4c98ef856279cd2c Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Fri, 3 Jul 2026 02:47:42 +0800
Subject: [PATCH 52/86] infra(build): add composer build scripts
Register three new Composer scripts:
- minify-css runs PostCSS cssnano on assets/css
- check-i18n validates text domains across PHP sources
- version-bump automates semver bump, commit, and git tag
---
composer.json | 3 +++
1 file changed, 3 insertions(+)
diff --git a/composer.json b/composer.json
index b0ef846e..84890e45 100644
--- a/composer.json
+++ b/composer.json
@@ -73,6 +73,9 @@
"strauss",
"@php composer dump-autoload --optimize"
],
+ "minify-css": "npx postcss assets/css/*.css --dir assets/css/ --no-map",
+ "check-i18n": "php bin/check-textdomains.php",
+ "version-bump": "php bin/bump.php",
"build": "php bin/package.php",
"package": "php bin/package.php"
},
From fd365fea3f86470543d23010658c13ff92a65c22 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Fri, 3 Jul 2026 02:47:46 +0800
Subject: [PATCH 53/86] infra(build): add text domain validation script
Introduce bin/check-textdomains.php to scan PHP source files and
verify all i18n function calls use the "framework-demo" text domain.
Exits with code 0 if all domains are correct, 1 with error details
on mismatch. Can be run standalone or via composer check-i18n.
---
bin/check-textdomains.php | 90 +++++++++++++++++++++++++++++++++++++++
1 file changed, 90 insertions(+)
create mode 100644 bin/check-textdomains.php
diff --git a/bin/check-textdomains.php b/bin/check-textdomains.php
new file mode 100644
index 00000000..93307a58
--- /dev/null
+++ b/bin/check-textdomains.php
@@ -0,0 +1,90 @@
+isFile() || ! str_ends_with( $item->getFilename(), '.php' ) ) {
+ continue;
+ }
+
+ $relative = substr( $item->getPathname(), strlen( $root ) + 1 );
+ $parts = explode( DIRECTORY_SEPARATOR, $relative );
+
+ if ( array_intersect( $parts, $excluded_dirs ) ) {
+ continue;
+ }
+
+ $contents = file_get_contents( $item->getPathname() );
+
+ if ( false === preg_match_all( $pattern, $contents, $matches, PREG_OFFSET_CAPTURE ) ) {
+ continue;
+ }
+
+ foreach ( $matches[3] as $i => $domain_match ) {
+ $domain = $domain_match[0];
+ if ( $domain !== $text_domain ) {
+ $line_number = substr_count( substr( $contents, 0, $matches[0][ $i ][1] ), "\n" ) + 1;
+ $errors[] = sprintf(
+ '%s:%d — "%s" uses text domain "%s", expected "%s"',
+ $relative,
+ $line_number,
+ $matches[1][ $i ][0] . '()',
+ $domain,
+ $text_domain
+ );
+ }
+ }
+}
+
+if ( empty( $errors ) ) {
+ echo "All i18n calls use the correct text domain.\n";
+ exit( 0 );
+}
+
+foreach ( $errors as $error ) {
+ fwrite( STDERR, $error . "\n" );
+}
+
+fwrite( STDERR, sprintf( "\n%d i18n call(s) with incorrect text domain found.\n", count( $errors ) ) );
+exit( 1 );
From 1de898452baf5e08e7b08c80bcbf4b0866e41418 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Fri, 3 Jul 2026 02:47:53 +0800
Subject: [PATCH 54/86] infra(build): add version bump git-tagging script
Introduce bin/bump.php that reads the current semver from the plugin
header, increments it (patch/minor/major or explicit semver), updates
the plugin file, commits, and creates a git tag.
Usage: php bin/bump.php
Date: Fri, 3 Jul 2026 02:47:56 +0800
Subject: [PATCH 55/86] infra(ci): add GitHub Actions CI workflow
Run validate, lint, test, check-i18n, and build on push (main,
feature/*, fix/*) and pull requests. PHP 8.3 and 8.4 matrix with
Composer and npm dependency caching.
---
.github/workflows/ci.yml | 61 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
create mode 100644 .github/workflows/ci.yml
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000..f2b41d54
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,61 @@
+name: CI
+
+on:
+ push:
+ branches:
+ - main
+ - 'feature/**'
+ - 'fix/**'
+ pull_request:
+
+jobs:
+ ci:
+ name: Validate, lint, test, and build
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ php: ['8.3', '8.4']
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php }}
+ tools: composer:v2
+ coverage: none
+
+ - name: Validate composer.json
+ run: composer validate --strict
+
+ - name: Cache Composer dependencies
+ uses: actions/cache@v4
+ with:
+ path: vendor
+ key: composer-${{ runner.os }}-${{ matrix.php }}-${{ hashFiles('composer.lock') }}
+
+ - name: Install Composer dependencies
+ run: composer install --prefer-dist --no-progress
+
+ - name: Install Node dependencies
+ run: npm ci
+
+ - name: Lint
+ run: composer lint
+
+ - name: Test
+ run: composer test
+
+ - name: Check i18n text domains
+ run: composer check-i18n
+
+ - name: Build release ZIP
+ run: composer build
+
+ - name: Upload ZIP artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: framework-demo-${{ matrix.php }}
+ path: dist/*.zip
From d3999144ffd71a790e2803c163f638a654aaf186 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Fri, 3 Jul 2026 02:48:06 +0800
Subject: [PATCH 56/86] infra(build): add npm lockfile for reproducible CI
installs
The package-lock.json pins PostCSS and cssnano dependency versions,
enabling npm ci in the CI workflow.
---
package-lock.json | 1717 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 1717 insertions(+)
create mode 100644 package-lock.json
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 00000000..7987a7d3
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,1717 @@
+{
+ "name": "saltus-framework-demo",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "saltus-framework-demo",
+ "devDependencies": {
+ "cssnano": "^7.0.0",
+ "postcss": "^8.5.0",
+ "postcss-cli": "^11.0.0"
+ }
+ },
+ "node_modules/@colordx/core": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/@colordx/core/-/core-5.5.0.tgz",
+ "integrity": "sha512-3PxTH8itZzltK0U9jTwVVnjLXvnDYuq3m+QXsHkENxWiPRh4WaoLcs1SQjqgZ55kS+QyirpH5BVwzP2gMVG6EQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.10.41",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.41.tgz",
+ "integrity": "sha512-WwS7MHhqGHHlaVsqRZnhvCEMS0owDX+SxRlve7JkuH7My1Ara3ZriTmCQupPfYjxMZ8I/tgxtJYr2t7taHaH4A==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.28.4",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz",
+ "integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "baseline-browser-mapping": "^2.10.38",
+ "caniuse-lite": "^1.0.30001799",
+ "electron-to-chromium": "^1.5.376",
+ "node-releases": "^2.0.48",
+ "update-browserslist-db": "^1.2.3"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/caniuse-api": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
+ "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "browserslist": "^4.0.0",
+ "caniuse-lite": "^1.0.0",
+ "lodash.memoize": "^4.1.2",
+ "lodash.uniq": "^4.5.0"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001800",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001800.tgz",
+ "integrity": "sha512-MMHtuAz9Ys840zAY5F4k6fV5GaivZ9sPk+nz0mY+GYVzRBnYkN0mpqkSR92oWRQ19yQWo4HvBV/FnC16AJX8MA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "CC-BY-4.0"
+ },
+ "node_modules/chokidar": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/commander": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
+ "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/css-declaration-sorter": {
+ "version": "7.4.0",
+ "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.4.0.tgz",
+ "integrity": "sha512-LTuzjPoyA2vMGKKcaOqKSp7Ub2eGrNfKiZH4LpezxpNrsICGCSFvsQOI29psISxNZtaXibkC2CXzrQ5enMeGGw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.0.9"
+ }
+ },
+ "node_modules/css-select": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz",
+ "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-what": "^6.1.0",
+ "domhandler": "^5.0.2",
+ "domutils": "^3.0.1",
+ "nth-check": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/css-tree": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz",
+ "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mdn-data": "2.27.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
+ }
+ },
+ "node_modules/css-what": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
+ "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/cssnano": {
+ "version": "7.1.9",
+ "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-7.1.9.tgz",
+ "integrity": "sha512-uPR75+5Dk/WJ/YSPR1/YDHdwMM9c5FsaARljfKWgeCKLKOtJ0we21xy/RcCjn53fZnD/f6yYEIZ8pu18+GnbNQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cssnano-preset-default": "^7.0.17",
+ "lilconfig": "^3.1.3"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/cssnano"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/cssnano-preset-default": {
+ "version": "7.0.17",
+ "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-7.0.17.tgz",
+ "integrity": "sha512-11qO63A+czwguQFJCaTdICvbaxn0pJzz/XghLlv+OT7WyToDxAMR0Xb3/26/l0y0hQJywwNbj/SLSQlGBHE1OA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "browserslist": "^4.28.2",
+ "css-declaration-sorter": "^7.2.0",
+ "cssnano-utils": "^5.0.3",
+ "postcss-calc": "^10.1.1",
+ "postcss-colormin": "^7.0.10",
+ "postcss-convert-values": "^7.0.12",
+ "postcss-discard-comments": "^7.0.8",
+ "postcss-discard-duplicates": "^7.0.4",
+ "postcss-discard-empty": "^7.0.3",
+ "postcss-discard-overridden": "^7.0.3",
+ "postcss-merge-longhand": "^7.0.7",
+ "postcss-merge-rules": "^7.0.11",
+ "postcss-minify-font-values": "^7.0.3",
+ "postcss-minify-gradients": "^7.0.5",
+ "postcss-minify-params": "^7.0.9",
+ "postcss-minify-selectors": "^7.1.2",
+ "postcss-normalize-charset": "^7.0.3",
+ "postcss-normalize-display-values": "^7.0.3",
+ "postcss-normalize-positions": "^7.0.4",
+ "postcss-normalize-repeat-style": "^7.0.4",
+ "postcss-normalize-string": "^7.0.3",
+ "postcss-normalize-timing-functions": "^7.0.3",
+ "postcss-normalize-unicode": "^7.0.9",
+ "postcss-normalize-url": "^7.0.3",
+ "postcss-normalize-whitespace": "^7.0.3",
+ "postcss-ordered-values": "^7.0.4",
+ "postcss-reduce-initial": "^7.0.9",
+ "postcss-reduce-transforms": "^7.0.3",
+ "postcss-svgo": "^7.1.3",
+ "postcss-unique-selectors": "^7.0.7"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/cssnano-utils": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-5.0.3.tgz",
+ "integrity": "sha512-ynIREMICLxkxm7e9bCR9sh75s4Q5drICi0ua1yxo5jH2XPBqSKkl4dOh4EbFqtUmnTMhRffHgYL0EKKkMjtJTg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/csso": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz",
+ "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "css-tree": "~2.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
+ "npm": ">=7.0.0"
+ }
+ },
+ "node_modules/csso/node_modules/css-tree": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz",
+ "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mdn-data": "2.0.28",
+ "source-map-js": "^1.0.1"
+ },
+ "engines": {
+ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0",
+ "npm": ">=7.0.0"
+ }
+ },
+ "node_modules/csso/node_modules/mdn-data": {
+ "version": "2.0.28",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz",
+ "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==",
+ "dev": true,
+ "license": "CC0-1.0"
+ },
+ "node_modules/dependency-graph": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-1.0.0.tgz",
+ "integrity": "sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/domutils": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
+ "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.384",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.384.tgz",
+ "integrity": "sha512-g6KAKY1vkYsADvSPWvdJsuYT0ixdcu6lUtD9P/wJKGBEDlZVXh2AX42j1mPqqaQPDluWjara9ziQ7xqAeXCt5A==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/fs-extra": {
+ "version": "11.3.6",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.6.tgz",
+ "integrity": "sha512-w8ZNZr2mKIc7qeNaQ9AVPT1+iFaI+Avd4xudVOvdDJ8VytREi1Ft5Ih7hd9jjehod8vAM5GMsfQ/TpPf4EyoEA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=14.14"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/jsonfile": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz",
+ "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/lilconfig": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
+ "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antonk52"
+ }
+ },
+ "node_modules/lodash.memoize": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
+ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/lodash.uniq": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
+ "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/mdn-data": {
+ "version": "2.27.1",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz",
+ "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==",
+ "dev": true,
+ "license": "CC0-1.0"
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.15",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz",
+ "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.50",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.50.tgz",
+ "integrity": "sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/nth-check": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/nth-check?sponsor=1"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.5.16",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.16.tgz",
+ "integrity": "sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.12",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-calc": {
+ "version": "10.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-10.1.1.tgz",
+ "integrity": "sha512-NYEsLHh8DgG/PRH2+G9BTuUdtf9ViS+vdoQ0YA5OQdGsfN4ztiwtDWNtBl9EKeqNMFnIu8IKZ0cLxEQ5r5KVMw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-selector-parser": "^7.0.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.12 || ^20.9 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4.38"
+ }
+ },
+ "node_modules/postcss-cli": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-11.0.1.tgz",
+ "integrity": "sha512-0UnkNPSayHKRe/tc2YGW6XnSqqOA9eqpiRMgRlV1S6HdGi16vwJBx7lviARzbV1HpQHqLLRH3o8vTcB0cLc+5g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chokidar": "^3.3.0",
+ "dependency-graph": "^1.0.0",
+ "fs-extra": "^11.0.0",
+ "picocolors": "^1.0.0",
+ "postcss-load-config": "^5.0.0",
+ "postcss-reporter": "^7.0.0",
+ "pretty-hrtime": "^1.0.3",
+ "read-cache": "^1.0.0",
+ "slash": "^5.0.0",
+ "tinyglobby": "^0.2.12",
+ "yargs": "^17.0.0"
+ },
+ "bin": {
+ "postcss": "index.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.0.0"
+ }
+ },
+ "node_modules/postcss-colormin": {
+ "version": "7.0.10",
+ "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-7.0.10.tgz",
+ "integrity": "sha512-yFr6JezOolHLta/buLE71VKPh2mXursp4saVe98/ol8ZnEWhL+racShqPKlvd/DKWLre/39B6HhcMXf7RZ3hxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@colordx/core": "^5.4.3",
+ "browserslist": "^4.28.2",
+ "caniuse-api": "^3.0.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-convert-values": {
+ "version": "7.0.12",
+ "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-7.0.12.tgz",
+ "integrity": "sha512-xurKu5qqk4viR3Cp3p4xBR4KfnZm4w4ys6+UBwBmeuBSNkH7+DtLnYOYnOffgtE4yx8sH9S1VZ6RAAvROXzP2Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "browserslist": "^4.28.2",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-discard-comments": {
+ "version": "7.0.8",
+ "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-7.0.8.tgz",
+ "integrity": "sha512-CvvS5S9WrXblFXCEJ9nVo+4z+eA7zSC7Z88V1HEJuwlQhlFnYTIjg1xJY+BCUiG2bvICap2tXii4mP22BD108Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-selector-parser": "^7.1.1"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-discard-duplicates": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-7.0.4.tgz",
+ "integrity": "sha512-VBNn1+EuMZkeGVVtz0gRfbNGtx9IFgAsAV+E2pHtXPrp4qfGBkhTIiAuE/wrb+Y6Pakg9NewAlfTpYIFAWODtw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-discard-empty": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-7.0.3.tgz",
+ "integrity": "sha512-M2pyjQCU+/7cMHVtL6bKTHjv0lZnPLMpicgr67Dlth7AbuV9gjVTtUqaRwn6Pp6BwSDspUzhz8SaUrRykJU5Dw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-discard-overridden": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-7.0.3.tgz",
+ "integrity": "sha512-aNovXo9UsZuRNLzHJtp13lHIvinDPfiXBPePpXkSjCbgp++iU2FqE+YxvjIsg6EdyPZsASFbfu+JcBFVsErXIQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-load-config": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-5.1.0.tgz",
+ "integrity": "sha512-G5AJ+IX0aD0dygOE0yFZQ/huFFMSNneyfp0e3/bT05a8OfPC5FUoZRPfGijUdGOJNMewJiwzcHJXFafFzeKFVA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "lilconfig": "^3.1.1",
+ "yaml": "^2.4.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "jiti": ">=1.21.0",
+ "postcss": ">=8.0.9",
+ "tsx": "^4.8.1"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ },
+ "postcss": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/postcss-merge-longhand": {
+ "version": "7.0.7",
+ "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-7.0.7.tgz",
+ "integrity": "sha512-b3mfYUxR388u5Pt0HPcVIUtUDn/k15UfTY9M+ORW+meCR6JLNxoZffiYvXyOYQoRYQNZyX/UFkMCM/mNHxe1qA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0",
+ "stylehacks": "^7.0.11"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-merge-rules": {
+ "version": "7.0.11",
+ "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-7.0.11.tgz",
+ "integrity": "sha512-SJUPM18g2BmPhf8BVlbwqWz4aK3pLu6u6xjfwEzra7xL6IBR10sUaiB++EzqcVfadPHrKBSMlNdP+XieykhI+Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "browserslist": "^4.28.2",
+ "caniuse-api": "^3.0.0",
+ "cssnano-utils": "^5.0.3",
+ "postcss-selector-parser": "^7.1.1"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-minify-font-values": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-7.0.3.tgz",
+ "integrity": "sha512-yilG/VOaNI74IylQvAQQxm3/wZVBkXyYUqNUAdxqwtbWUXPsbK1q8Ms0mL83v+f8YicgcyfYCRZtWACUdYajpA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-minify-gradients": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-7.0.5.tgz",
+ "integrity": "sha512-YraROyQRg3BI1+Hg8E05B/JPdnTm8EDSVu4P2BxdM+CRiOyfmou809+chGIqo6fQqwjPGQ947nbGncSjmTU1WQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@colordx/core": "^5.4.3",
+ "cssnano-utils": "^5.0.3",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-minify-params": {
+ "version": "7.0.9",
+ "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-7.0.9.tgz",
+ "integrity": "sha512-R8itbB8BhlpoYyBm1ou0dD+vJnQ3F6adQipR4UnkCHUwlo+S9WXJaDRg1RHjC8YVAtIdrQzSWvJl40HnGDTKjA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "browserslist": "^4.28.2",
+ "cssnano-utils": "^5.0.3",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-minify-selectors": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-7.1.2.tgz",
+ "integrity": "sha512-aQtrEWKwqafNlExcKHQvPGsXR2+vlUqqJtf5XsCQcgsSb5PL4wlujWBYDJuWsP4UnQX1YHDHU8qRlD+1PzTQ+Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "browserslist": "^4.28.1",
+ "caniuse-api": "^3.0.0",
+ "cssesc": "^3.0.0",
+ "postcss-selector-parser": "^7.1.1"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-normalize-charset": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-7.0.3.tgz",
+ "integrity": "sha512-NoBfZu8PR4c2NlmjvrqQTzCzLY79hwcSRgNQ3ZiNK0ABzf9kYKloE/jNj+/8GQY1wsm8pRRgANk6ydLH8cwo0Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-normalize-display-values": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-7.0.3.tgz",
+ "integrity": "sha512-ldsCX0QIt05pKIOobZtVQ48wXJecr+czw4+e1/YjVhLMqslShgpVxgPtI2CefURR8oyVoYaU/l829MMwExDMLw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-normalize-positions": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-7.0.4.tgz",
+ "integrity": "sha512-VEvlpeGd3Ju1Hqa/oN4jaP3+ms4laYwkEL9N9u+B6k54PZjXbW1n6wI+aVprf1BQXlCYpS5+1pl/7/vHiKgARg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-normalize-repeat-style": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-7.0.4.tgz",
+ "integrity": "sha512-6mPKlY/8cSaDHxX502wERADarJsccwlky6yIrOapHH2ZgfoKAV94SbiTKfKEs4EEpdazuc3J72WsqeYk7hp9+Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-normalize-string": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-7.0.3.tgz",
+ "integrity": "sha512-HnEQPUchi1eznmDKEYrKUTqrprEq97SrpUYClgUkv7V2zRODD9DFoUsYU+m9ZOetmD5ku7fEMZB/lwy8IT6xVQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-normalize-timing-functions": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-7.0.3.tgz",
+ "integrity": "sha512-zmEzHdvpZBZu0OKlbJSfgASQvaayyAoVuWtvyr34IJ/LyS+DaOKvvR3EvFJ9RWWtNIx+CMvO125OVophaxNYew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-normalize-unicode": {
+ "version": "7.0.9",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-7.0.9.tgz",
+ "integrity": "sha512-DRAdWfeh/TjmhLJsw91vdiWCnUod9iwvM7xyS02/nF/sLsCR3A8l3pztrSUrWG8DSBqfX7yEk9FM0USaVJ2mSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "browserslist": "^4.28.2",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-normalize-url": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-7.0.3.tgz",
+ "integrity": "sha512-CL93wmloq5qsffmFv+bw24MIRbmhHrp53qoh1LDAb/5TtjWEXI/np4xcP/Gw9oWCb2XyWnqHYLDUwiKRoJBA1Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-normalize-whitespace": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-7.0.3.tgz",
+ "integrity": "sha512-FdHjjn+Ht5Z2ZRjNOmeCbNq6lq09sUYKpmlF/Aq0XjVNSLTL6fmHlA/3swN2wP2caY9GV/tjSDcIIyS7aN7W0A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-ordered-values": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-7.0.4.tgz",
+ "integrity": "sha512-nubSi49hDHQk4E8KIj+IbLY8Bg+8OcSUEhgyolgM+atnOvXjV7EjaR6bac4YGZoFyPa9mWoAF3EaYbWdFkKqVg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cssnano-utils": "^5.0.3",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-reduce-initial": {
+ "version": "7.0.9",
+ "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-7.0.9.tgz",
+ "integrity": "sha512-ztTNPdIxXTxtBcG03E9u8v44M4ElXbMIRT7pf2onlquGula0Y83nKKxqM22FA/hMgkfCjN7ohevkVlaNwI8iOQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "browserslist": "^4.28.2",
+ "caniuse-api": "^3.0.0"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-reduce-transforms": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-7.0.3.tgz",
+ "integrity": "sha512-FXsnN9ZwcZTT8Yf8cAHA8qIGUXcX6WfLd9JoYhrdDfmvsVhhfqkkv7m4AC3rwFOfz+GzkUa87OCKF9dUcicd+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-reporter": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-7.1.0.tgz",
+ "integrity": "sha512-/eoEylGWyy6/DOiMP5lmFRdmDKThqgn7D6hP2dXKJI/0rJSO1ADFNngZfDzxL0YAxFvws+Rtpuji1YIHj4mySA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "picocolors": "^1.0.0",
+ "thenby": "^1.3.4"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/postcss-selector-parser": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.4.tgz",
+ "integrity": "sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postcss-svgo": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-7.1.3.tgz",
+ "integrity": "sha512-2QfoFOYMcj8lwcVEf9WeTlkVIAm7u2QvOEhMzkQU3KUhhGX/l8hVV9EtjMv4iq3E9iI3OeeMN0YoMLbGusuigw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0",
+ "svgo": "^4.0.1"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >= 18"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-unique-selectors": {
+ "version": "7.0.7",
+ "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-7.0.7.tgz",
+ "integrity": "sha512-d+sCkaRnSefghOUdH8CMJZV9yUQhj2ojpe8Nw/lA+LV1UOfeleGkLTl6XdCFFSai9UJ+DJPb69FFuqthXYsY8w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-selector-parser": "^7.1.1"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/postcss-value-parser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/pretty-hrtime": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz",
+ "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/read-cache": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+ "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pify": "^2.3.0"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sax": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz",
+ "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=11.0.0"
+ }
+ },
+ "node_modules/slash": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz",
+ "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/stylehacks": {
+ "version": "7.0.11",
+ "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-7.0.11.tgz",
+ "integrity": "sha512-iODNfhXVLqc5LADs+Y6Oh5wJuK5ZcHbVng8aiK3y9pjMQdc5hLrBW0eFU6FtnpNrE6PoEg/MmFTU4waotj5WNg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "browserslist": "^4.28.2",
+ "postcss-selector-parser": "^7.1.1"
+ },
+ "engines": {
+ "node": "^18.12.0 || ^20.9.0 || >=22.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.5.13"
+ }
+ },
+ "node_modules/svgo": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.1.tgz",
+ "integrity": "sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "commander": "^11.1.0",
+ "css-select": "^5.1.0",
+ "css-tree": "^3.0.1",
+ "css-what": "^6.1.0",
+ "csso": "^5.0.5",
+ "picocolors": "^1.1.1",
+ "sax": "^1.5.0"
+ },
+ "bin": {
+ "svgo": "bin/svgo.js"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/svgo"
+ }
+ },
+ "node_modules/thenby": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/thenby/-/thenby-1.4.1.tgz",
+ "integrity": "sha512-D5a/bO0KdalOE3q8MlrRmSxjbKZHT3MQmXkJP+r97Vw8MMwOZKOwUSEyTtK7eSMj2y0kyAjpYMRMZmmLw1FtNQ==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.17",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
+ "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/tinyglobby/node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tinyglobby/node_modules/picomatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz",
+ "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/universalify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
+ "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yaml": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
+ "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/eemeli"
+ }
+ },
+ "node_modules/yargs": {
+ "version": "17.7.3",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz",
+ "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ }
+ }
+}
From 5c3d790a5e782960f6c3273d2cbef35818e3d0bd Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Fri, 3 Jul 2026 03:29:01 +0800
Subject: [PATCH 57/86] fix(renamer): Translate validation field labels via
i18n map
The label() method dynamically generated field labels via ucwords(), producing English-only strings in validation error messages regardless of site locale. Replace with a translation map so every label is passed through __() for full i18n support.
---
src/Plugin/Renamer/PluginIdentity.php | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/src/Plugin/Renamer/PluginIdentity.php b/src/Plugin/Renamer/PluginIdentity.php
index 5c81525a..36ba03d5 100644
--- a/src/Plugin/Renamer/PluginIdentity.php
+++ b/src/Plugin/Renamer/PluginIdentity.php
@@ -126,6 +126,18 @@ private static function validate( array $data ): void {
}
private static function label( string $field ): string {
- return ucwords( str_replace( '_', ' ', $field ) );
+ $labels = array(
+ 'plugin_name' => __( 'Plugin Name', 'framework-demo' ),
+ 'plugin_slug' => __( 'Plugin Slug', 'framework-demo' ),
+ 'main_file' => __( 'Main Plugin File', 'framework-demo' ),
+ 'namespace_segment' => __( 'Namespace Segment', 'framework-demo' ),
+ 'description' => __( 'Description', 'framework-demo' ),
+ 'author' => __( 'Author', 'framework-demo' ),
+ 'author_uri' => __( 'Author URI', 'framework-demo' ),
+ 'plugin_uri' => __( 'Plugin URI', 'framework-demo' ),
+ 'version' => __( 'Version', 'framework-demo' ),
+ 'prefix' => __( 'Code Prefix', 'framework-demo' ),
+ );
+ return $labels[ $field ] ?? ucwords( str_replace( '_', ' ', $field ) );
}
}
From c11bbfc7e4a52265d4511182c87f345cc21eed76 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Fri, 3 Jul 2026 03:29:07 +0800
Subject: [PATCH 58/86] fix(admin): Use unique slug for tools submenu page
The add_management_page() call used the same slug (framework-demo-renamer) as the settings submenu page, which can cause WordPress menu conflicts. Add a dedicated TOOLS_PAGE_SLUG constant and update tool_url() to use it, giving each menu registration its own unique slug.
---
src/Plugin/Admin/RenamerPage.php | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/Plugin/Admin/RenamerPage.php b/src/Plugin/Admin/RenamerPage.php
index c13b12bf..8c0636df 100644
--- a/src/Plugin/Admin/RenamerPage.php
+++ b/src/Plugin/Admin/RenamerPage.php
@@ -11,7 +11,8 @@
*/
class RenamerPage {
- private const PAGE_SLUG = 'framework-demo-renamer';
+ private const PAGE_SLUG = 'framework-demo-renamer';
+ private const TOOLS_PAGE_SLUG = 'framework-demo-renamer-tools';
private const NONCE_ACTION = 'framework_demo_generate_plugin';
private const NONCE_NAME = 'framework_demo_renamer_nonce';
private const NOTICE_ACTION = 'framework_demo_dismiss_rebrand_notice';
@@ -48,7 +49,7 @@ public function add_page(): void {
__( 'Rebrand This Demo', 'framework-demo' ),
__( 'Rebrand This Demo', 'framework-demo' ),
'manage_options',
- self::PAGE_SLUG,
+ self::TOOLS_PAGE_SLUG,
array( $this, 'render' )
);
}
@@ -355,7 +356,7 @@ private function render_guide(): void {
private function tool_url(): string {
return add_query_arg(
- array( 'page' => self::PAGE_SLUG ),
+ array( 'page' => self::TOOLS_PAGE_SLUG ),
admin_url( 'tools.php' )
);
}
From ce7a62f3a60f8911b051eb34757acc1c0a88393a Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Fri, 3 Jul 2026 03:32:31 +0800
Subject: [PATCH 59/86] fix(renamer): Include .js files in text file detection
The is_text_file() regex did not match .js files, so custom JavaScript files (e.g. block editor blocks, admin scripts) were skipped during namespace/prefix replacement. Add js to the extension whitelist so they are processed during rebranding.
---
src/Plugin/Renamer/PluginRenamer.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Plugin/Renamer/PluginRenamer.php b/src/Plugin/Renamer/PluginRenamer.php
index 8f106960..3a814e9a 100644
--- a/src/Plugin/Renamer/PluginRenamer.php
+++ b/src/Plugin/Renamer/PluginRenamer.php
@@ -159,7 +159,7 @@ private function should_exclude( string $relative_path ): bool {
}
private function is_text_file( string $relative_path ): bool {
- return (bool) preg_match( '/\.(php|json|md|txt|xml|css|pot)$/', $relative_path );
+ return (bool) preg_match( '/\.(php|json|md|txt|xml|css|js|pot)$/', $relative_path );
}
private function rewrite_contents( string $contents, PluginIdentity $identity ): string {
From 0710095617d77af30548601bd1086a2c4d0af538 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Fri, 3 Jul 2026 18:39:38 +0800
Subject: [PATCH 60/86] Fix CS
---
src/Plugin/Admin/RenamerPage.php | 25 ++++++-------------------
1 file changed, 6 insertions(+), 19 deletions(-)
diff --git a/src/Plugin/Admin/RenamerPage.php b/src/Plugin/Admin/RenamerPage.php
index 8c0636df..d6f4c00d 100644
--- a/src/Plugin/Admin/RenamerPage.php
+++ b/src/Plugin/Admin/RenamerPage.php
@@ -11,12 +11,12 @@
*/
class RenamerPage {
- private const PAGE_SLUG = 'framework-demo-renamer';
- private const TOOLS_PAGE_SLUG = 'framework-demo-renamer-tools';
- private const NONCE_ACTION = 'framework_demo_generate_plugin';
- private const NONCE_NAME = 'framework_demo_renamer_nonce';
- private const NOTICE_ACTION = 'framework_demo_dismiss_rebrand_notice';
- private const NOTICE_NONCE = 'framework_demo_rebrand_notice_nonce';
+ private const PAGE_SLUG = 'framework-demo-renamer';
+ private const TOOLS_PAGE_SLUG = 'framework-demo-renamer-tools';
+ private const NONCE_ACTION = 'framework_demo_generate_plugin';
+ private const NONCE_NAME = 'framework_demo_renamer_nonce';
+ private const NOTICE_ACTION = 'framework_demo_dismiss_rebrand_notice';
+ private const NOTICE_NONCE = 'framework_demo_rebrand_notice_nonce';
private Core $core;
@@ -361,19 +361,6 @@ private function tool_url(): string {
);
}
- private function redirect_with_success( string $message ): void {
- $token = wp_generate_uuid4();
- set_transient( 'framework_demo_success_' . $token, $message, 30 );
-
- wp_safe_redirect(
- add_query_arg(
- array( 'framework_demo_success' => $token ),
- $this->tool_url()
- )
- );
- exit;
- }
-
/**
* @param array
Date: Fri, 3 Jul 2026 18:40:19 +0800
Subject: [PATCH 61/86] Detect case for dangerous tokens
---
src/Plugin/Renamer/PluginIdentity.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Plugin/Renamer/PluginIdentity.php b/src/Plugin/Renamer/PluginIdentity.php
index 36ba03d5..ef7369b3 100644
--- a/src/Plugin/Renamer/PluginIdentity.php
+++ b/src/Plugin/Renamer/PluginIdentity.php
@@ -73,7 +73,7 @@ public static function from_request( array $request ): self {
do {
$before = $data[ $comment_field ];
- $data[ $comment_field ] = str_replace( $dangerous_tokens, '', $before );
+ $data[ $comment_field ] = str_ireplace( $dangerous_tokens, '', $before );
} while ( $data[ $comment_field ] !== $before );
}
From 5b114d351f3751d151b7356bd3e2721d9e04aa06 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Fri, 3 Jul 2026 18:40:43 +0800
Subject: [PATCH 62/86] Use empty array when registering asset
---
src/Plugin/Assets.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Plugin/Assets.php b/src/Plugin/Assets.php
index 7fbc09e2..25a6bba4 100644
--- a/src/Plugin/Assets.php
+++ b/src/Plugin/Assets.php
@@ -44,7 +44,7 @@ public function load_admin_styles( string $hook_suffix = '' ): void {
wp_register_style(
$this->core->get_name() . '_admin',
plugins_url( 'assets/css/admin-style.css', $this->core->get_file_path() ),
- false,
+ array(),
$this->core->get_version()
);
From 2d78684f274ea593f4fcff26a0318cb354f90b6e Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Fri, 3 Jul 2026 18:41:11 +0800
Subject: [PATCH 63/86] Detect empty content before running
---
bin/bump.php | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/bin/bump.php b/bin/bump.php
index de40a88f..0fcd95a3 100644
--- a/bin/bump.php
+++ b/bin/bump.php
@@ -15,6 +15,10 @@
function read_version( string $file ): string {
$contents = file_get_contents( $file );
+ if ( false === $contents ) {
+ throw new RuntimeException( "Could not read file: {$file}" );
+ }
+
if ( 1 === preg_match( "/PLUGIN_VERSION', '([^']+)'/", $contents, $matches ) ) {
return $matches[1];
}
@@ -70,6 +74,10 @@ function bump_version( string $version, string $type ): string {
function update_version( string $file, string $old_version, string $new_version ): void {
$contents = file_get_contents( $file );
+ if ( false === $contents ) {
+ throw new RuntimeException( "Could not read file: {$file}" );
+ }
+
$contents = str_replace(
"PLUGIN_VERSION', '{$old_version}'",
"PLUGIN_VERSION', '{$new_version}'",
From 5c8b9390c73096ad8b7e0a96dbfeb0396c715938 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sat, 4 Jul 2026 01:54:44 +0800
Subject: [PATCH 64/86] Fix(i18n): migrate textdomain checker from regex to
token_get_all
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The old regex approach had two bugs:
1. Strings containing commas (e.g. "Hello, world") broke [^,]+,
causing false negatives — translation strings with commas were
silently skipped from validation.
2. The regex assumed the text domain was always the 2nd argument,
causing false positives for _x(), _n(), _nx(), and similar
functions where the domain is the 3rd, 4th, or 5th argument.
Switch to token_get_all() which parses string boundaries correctly,
and introduce per-function argument position mapping via
$domain_arg_map for all 18 supported i18n functions.
---
bin/check-textdomains.php | 144 ++++++++++++++++++++++++++++++++++----
1 file changed, 132 insertions(+), 12 deletions(-)
diff --git a/bin/check-textdomains.php b/bin/check-textdomains.php
index 93307a58..f623bc58 100644
--- a/bin/check-textdomains.php
+++ b/bin/check-textdomains.php
@@ -2,6 +2,12 @@
/**
* Validate that all i18n calls use the correct text domain.
*
+ * Uses PHP's built-in token_get_all() which handles:
+ * - Multi-line strings
+ * - Commas inside translation strings
+ * - Escaped quotes
+ * - Variable argument positions per function
+ *
* Usage: php bin/check-textdomains.php
*/
@@ -29,7 +35,28 @@
'ngettext_with_context',
);
-$pattern = '/\b(' . implode( '|', array_map( 'preg_quote', $i18n_functions ) ) . ')\s*\(\s*[^,]+,\s*([\'"])([^\'"]+)\2\s*[),]/';
+$domain_arg_map = array(
+ '__' => 2,
+ '_e' => 2,
+ '_n' => 4,
+ '_x' => 3,
+ '_ex' => 3,
+ '_nx' => 5,
+ 'esc_html__' => 2,
+ 'esc_html_e' => 2,
+ 'esc_html_x' => 3,
+ 'esc_attr__' => 2,
+ 'esc_attr_e' => 2,
+ 'esc_attr_x' => 3,
+ '_n_noop' => 3,
+ '_nx_noop' => 4,
+ 'translate' => 2,
+ 'translate_with_gettext_context' => 3,
+ 'ngettext' => 4,
+ 'ngettext_with_context' => 5,
+);
+
+$function_names = array_flip( $i18n_functions );
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator( $root, FilesystemIterator::SKIP_DOTS ),
@@ -55,22 +82,115 @@
continue;
}
- $contents = file_get_contents( $item->getPathname() );
+ $source = file_get_contents( $item->getPathname() );
+ $tokens = @token_get_all( $source );
+ $t_count = count( $tokens );
- if ( false === preg_match_all( $pattern, $contents, $matches, PREG_OFFSET_CAPTURE ) ) {
- continue;
- }
+ for ( $i = 0; $i < $t_count; $i++ ) {
+ if ( ! is_array( $tokens[ $i ] ) || $tokens[ $i ][0] !== T_STRING ) {
+ continue;
+ }
+
+ $function = $tokens[ $i ][1];
+
+ if ( ! isset( $function_names[ $function ] ) ) {
+ continue;
+ }
+
+ // Skip method calls and static calls: $obj->method() or Class::method()
+ if ( $i > 0 ) {
+ $prev = $tokens[ $i - 1 ];
+ if ( ( is_array( $prev ) && ( $prev[0] === T_OBJECT_OPERATOR || $prev[0] === T_DOUBLE_COLON ) )
+ || $prev === '->' || $prev === '::'
+ ) {
+ continue;
+ }
+ }
+
+ // Locate opening parenthesis (skipping whitespace/comments).
+ $j = $i + 1;
+ while ( $j < $t_count && is_array( $tokens[ $j ] )
+ && in_array( $tokens[ $j ][0], array( T_WHITESPACE, T_COMMENT, T_DOC_COMMENT ), true ) ) {
+ $j++;
+ }
+
+ if ( $j >= $t_count || $tokens[ $j ] !== '(' ) {
+ continue;
+ }
+
+ $func_line = $tokens[ $i ][2];
+ $expected_arg = $domain_arg_map[ $function ];
+ $depth = 1;
+ $args = array( '' );
+ $arg_idx = 0;
+
+ for ( $k = $j + 1; $k < $t_count && $depth > 0; $k++ ) {
+ $token = $tokens[ $k ];
+
+ if ( is_array( $token ) ) {
+ $type = $token[0];
+
+ if ( $type === T_WHITESPACE || $type === T_COMMENT || $type === T_DOC_COMMENT ) {
+ continue;
+ }
+
+ // Skip heredoc/nowdoc body entirely.
+ if ( $type === T_START_HEREDOC ) {
+ while ( $k < $t_count ) {
+ $k++;
+ if ( is_array( $tokens[ $k ] ) && $tokens[ $k ][0] === T_END_HEREDOC ) {
+ break;
+ }
+ }
+ continue;
+ }
+
+ $args[ $arg_idx ] .= $token[1];
+ } else {
+ if ( $token === '(' || $token === '[' || $token === '{' ) {
+ $depth++;
+ $args[ $arg_idx ] .= $token;
+ } elseif ( $token === ')' || $token === ']' || $token === '}' ) {
+ $depth--;
+ if ( $depth === 0 ) { // End of the i18n function call.
+ break;
+ }
+ $args[ $arg_idx ] .= $token;
+ } elseif ( $token === ',' && $depth === 1 ) {
+ $arg_idx++;
+ $args[ $arg_idx ] = '';
+ } else {
+ $args[ $arg_idx ] .= $token;
+ }
+ }
+ }
+
+ $domain_pos = $expected_arg - 1;
+
+ if ( ! isset( $args[ $domain_pos ] ) ) {
+ continue;
+ }
+
+ $domain_arg = trim( $args[ $domain_pos ] );
+
+ if ( $domain_arg === '' ) {
+ continue;
+ }
+
+ $domain_value = null;
+
+ // Check if the domain argument is a simple single/double-quoted string literal.
+ if ( preg_match( '/^(\'|")(.*)\1$/s', $domain_arg, $m ) ) {
+ $domain_value = $m[2];
+ }
- foreach ( $matches[3] as $i => $domain_match ) {
- $domain = $domain_match[0];
- if ( $domain !== $text_domain ) {
- $line_number = substr_count( substr( $contents, 0, $matches[0][ $i ][1] ), "\n" ) + 1;
+ if ( $domain_value !== null && $domain_value !== $text_domain ) {
$errors[] = sprintf(
'%s:%d — "%s" uses text domain "%s", expected "%s"',
$relative,
- $line_number,
- $matches[1][ $i ][0] . '()',
- $domain,
+ $func_line,
+ $function . '()',
+ $domain_value,
$text_domain
);
}
From 160e00241e1d7bb76d77c5f998a41536b88b462c Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sat, 4 Jul 2026 03:10:32 +0800
Subject: [PATCH 65/86] fix(renamer): correct wp_tempnam() failure check
wp_tempnam() wraps PHP's native tempnam(), which returns false on
failure, not an empty string. Use ! instead of === '' to
properly catch creation errors and avoid a TypeError when passing
false to functions expecting a string.
---
src/Plugin/Admin/RenamerPage.php | 2 +-
src/Plugin/Renamer/PluginRenamer.php | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Plugin/Admin/RenamerPage.php b/src/Plugin/Admin/RenamerPage.php
index d6f4c00d..daec1c3b 100644
--- a/src/Plugin/Admin/RenamerPage.php
+++ b/src/Plugin/Admin/RenamerPage.php
@@ -253,7 +253,7 @@ private function copy_and_activate_plugin( PluginRenamer $renamer, PluginIdentit
}
$tmp_file = wp_tempnam( $identity->plugin_slug . '.zip' );
- if ( $tmp_file === '' ) {
+ if ( ! $tmp_file ) {
throw new \RuntimeException( __( 'Could not create a temporary ZIP file.', 'framework-demo' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
diff --git a/src/Plugin/Renamer/PluginRenamer.php b/src/Plugin/Renamer/PluginRenamer.php
index 3a814e9a..b4afb814 100644
--- a/src/Plugin/Renamer/PluginRenamer.php
+++ b/src/Plugin/Renamer/PluginRenamer.php
@@ -32,7 +32,7 @@ public function stream_zip( PluginIdentity $identity ): void {
}
$tmp_file = wp_tempnam( $identity->plugin_slug . '.zip' );
- if ( $tmp_file === '' ) {
+ if ( ! $tmp_file ) {
throw new \RuntimeException( 'Could not create a temporary ZIP file.' );
}
From 143aac0f63f47efa52dd68f6a7acd83d5eb852d4 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sat, 4 Jul 2026 03:26:56 +0800
Subject: [PATCH 66/86] fix(check-textdomains): add defensive guards in token
parsing
- Guard against file_get_contents returning false before tokenizing
- Handle PHP 8.0+ nullsafe object operator (?->) to prevent false
positives on nullsafe method calls like $obj?->__('text', 'domain')
---
bin/check-textdomains.php | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/bin/check-textdomains.php b/bin/check-textdomains.php
index f623bc58..cc1eaf9f 100644
--- a/bin/check-textdomains.php
+++ b/bin/check-textdomains.php
@@ -83,6 +83,9 @@
}
$source = file_get_contents( $item->getPathname() );
+ if ( false === $source ) {
+ continue;
+ }
$tokens = @token_get_all( $source );
$t_count = count( $tokens );
@@ -100,8 +103,14 @@
// Skip method calls and static calls: $obj->method() or Class::method()
if ( $i > 0 ) {
$prev = $tokens[ $i - 1 ];
- if ( ( is_array( $prev ) && ( $prev[0] === T_OBJECT_OPERATOR || $prev[0] === T_DOUBLE_COLON ) )
- || $prev === '->' || $prev === '::'
+ if ( ( is_array( $prev ) && (
+ $prev[0] === T_OBJECT_OPERATOR
+ || $prev[0] === T_DOUBLE_COLON
+ || ( defined( 'T_NULLSAFE_OBJECT_OPERATOR' ) && $prev[0] === T_NULLSAFE_OBJECT_OPERATOR )
+ ) )
+ || $prev === '->'
+ || $prev === '::'
+ || $prev === '?->'
) {
continue;
}
From d2b24dfa739c9aec2f3aad9c3c651399c49c76ad Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sat, 4 Jul 2026 03:27:08 +0800
Subject: [PATCH 67/86] fix(renamer-page): suppress cleanup exceptions to avoid
masking primary failure
Wrap recursive directory removal in try-catch with @ error suppression
so that cleanup failures do not mask the primary exception when
remove_path() is called from a catch block.
---
src/Plugin/Admin/RenamerPage.php | 26 +++++++++++++++-----------
1 file changed, 15 insertions(+), 11 deletions(-)
diff --git a/src/Plugin/Admin/RenamerPage.php b/src/Plugin/Admin/RenamerPage.php
index daec1c3b..26b09ed8 100644
--- a/src/Plugin/Admin/RenamerPage.php
+++ b/src/Plugin/Admin/RenamerPage.php
@@ -419,20 +419,24 @@ private function remove_path( string $path ): void {
return;
}
- $iterator = new \RecursiveIteratorIterator(
- new \RecursiveDirectoryIterator( $path, \FilesystemIterator::SKIP_DOTS ),
- \RecursiveIteratorIterator::CHILD_FIRST
- );
+ try {
+ $iterator = new \RecursiveIteratorIterator(
+ new \RecursiveDirectoryIterator( $path, \FilesystemIterator::SKIP_DOTS ),
+ \RecursiveIteratorIterator::CHILD_FIRST
+ );
- foreach ( $iterator as $item ) {
- if ( $item->isDir() && ! $item->isLink() ) {
- rmdir( $item->getPathname() ); // phpcs:ignore WordPress.WP.AlternativeFunctions
- continue;
+ foreach ( $iterator as $item ) {
+ if ( $item->isDir() && ! $item->isLink() ) {
+ @rmdir( $item->getPathname() ); // phpcs:ignore WordPress.WP.AlternativeFunctions
+ continue;
+ }
+
+ @unlink( $item->getPathname() ); // phpcs:ignore WordPress.WP.AlternativeFunctions
}
- unlink( $item->getPathname() ); // phpcs:ignore WordPress.WP.AlternativeFunctions
+ @rmdir( $path ); // phpcs:ignore WordPress.WP.AlternativeFunctions
+ } catch ( \Throwable $e ) {
+ // Fail silently to avoid masking the primary exception during cleanup.
}
-
- rmdir( $path ); // phpcs:ignore WordPress.WP.AlternativeFunctions
}
}
From 92ff29c29ae1a5363c7a5ed4b56266ad0077b9a4 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sat, 4 Jul 2026 03:49:53 +0800
Subject: [PATCH 68/86] fix: address PHPCS lint errors in defensive fixes
- Change Yoda condition to standard comparison (false === -> === false)
- Add phpcs:ignore for NoSilencedErrors warnings in cleanup block
- Suppress empty catch sniff on intentional empty catch
---
bin/check-textdomains.php | 2 +-
src/Plugin/Admin/RenamerPage.php | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/bin/check-textdomains.php b/bin/check-textdomains.php
index cc1eaf9f..66f32e71 100644
--- a/bin/check-textdomains.php
+++ b/bin/check-textdomains.php
@@ -83,7 +83,7 @@
}
$source = file_get_contents( $item->getPathname() );
- if ( false === $source ) {
+ if ( $source === false ) {
continue;
}
$tokens = @token_get_all( $source );
diff --git a/src/Plugin/Admin/RenamerPage.php b/src/Plugin/Admin/RenamerPage.php
index 26b09ed8..66825e98 100644
--- a/src/Plugin/Admin/RenamerPage.php
+++ b/src/Plugin/Admin/RenamerPage.php
@@ -427,15 +427,15 @@ private function remove_path( string $path ): void {
foreach ( $iterator as $item ) {
if ( $item->isDir() && ! $item->isLink() ) {
- @rmdir( $item->getPathname() ); // phpcs:ignore WordPress.WP.AlternativeFunctions
+ @rmdir( $item->getPathname() ); // phpcs:ignore WordPress.WP.AlternativeFunctions,WordPress.PHP.NoSilencedErrors.Discouraged
continue;
}
- @unlink( $item->getPathname() ); // phpcs:ignore WordPress.WP.AlternativeFunctions
+ @unlink( $item->getPathname() ); // phpcs:ignore WordPress.WP.AlternativeFunctions,WordPress.PHP.NoSilencedErrors.Discouraged
}
- @rmdir( $path ); // phpcs:ignore WordPress.WP.AlternativeFunctions
- } catch ( \Throwable $e ) {
+ @rmdir( $path ); // phpcs:ignore WordPress.WP.AlternativeFunctions,WordPress.PHP.NoSilencedErrors.Discouraged
+ } catch ( \Throwable $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
// Fail silently to avoid masking the primary exception during cleanup.
}
}
From c6ea12f76b5d08f5acc9dc7a46ac51e7b5b24ab8 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sat, 4 Jul 2026 03:52:18 +0800
Subject: [PATCH 69/86] Add all command
---
composer.json | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/composer.json b/composer.json
index 84890e45..83b37be8 100644
--- a/composer.json
+++ b/composer.json
@@ -77,6 +77,10 @@
"check-i18n": "php bin/check-textdomains.php",
"version-bump": "php bin/bump.php",
"build": "php bin/package.php",
+ "all": [
+ "@lint",
+ "@test"
+ ],
"package": "php bin/package.php"
},
"minimum-stability": "dev",
From 390a9d2054e146d826e90b2372742db2630895da Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sat, 4 Jul 2026 03:53:18 +0800
Subject: [PATCH 70/86] Add all command
---
composer.json | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/composer.json b/composer.json
index 83b37be8..41ce7762 100644
--- a/composer.json
+++ b/composer.json
@@ -66,8 +66,12 @@
},
"scripts": {
"validate-project": "composer validate --strict",
- "lint": "phpcs",
- "test": "phpunit",
+ "test:lint": "phpcs",
+ "test:unit": "phpunit",
+ "tests": [
+ "@lint",
+ "@test"
+ ],
"make-pot": "wp i18n make-pot . languages/framework-demo.pot --exclude=vendor,node_modules,dist,release,build",
"prefix-namespaces": [
"strauss",
@@ -77,10 +81,6 @@
"check-i18n": "php bin/check-textdomains.php",
"version-bump": "php bin/bump.php",
"build": "php bin/package.php",
- "all": [
- "@lint",
- "@test"
- ],
"package": "php bin/package.php"
},
"minimum-stability": "dev",
From 45142b0d4434246bf3ea22c90a723caf04463c75 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sat, 4 Jul 2026 13:42:13 +0800
Subject: [PATCH 71/86] Fix test calls
---
.github/workflows/ci.yml | 4 ++--
composer.json | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f2b41d54..5bdf40ec 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -43,10 +43,10 @@ jobs:
run: npm ci
- name: Lint
- run: composer lint
+ run: composer test:lint
- name: Test
- run: composer test
+ run: composer test:unit
- name: Check i18n text domains
run: composer check-i18n
diff --git a/composer.json b/composer.json
index 41ce7762..8d48ce19 100644
--- a/composer.json
+++ b/composer.json
@@ -69,8 +69,8 @@
"test:lint": "phpcs",
"test:unit": "phpunit",
"tests": [
- "@lint",
- "@test"
+ "@test:lint",
+ "@test:unit"
],
"make-pot": "wp i18n make-pot . languages/framework-demo.pot --exclude=vendor,node_modules,dist,release,build",
"prefix-namespaces": [
From e97c6d93e6b22a946e2591428d5c9c0f00fea181 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sat, 4 Jul 2026 16:13:10 +0800
Subject: [PATCH 72/86] fix(assets): use dynamic slug for admin style hook
---
src/Plugin/Assets.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Plugin/Assets.php b/src/Plugin/Assets.php
index 25a6bba4..c82f6102 100644
--- a/src/Plugin/Assets.php
+++ b/src/Plugin/Assets.php
@@ -37,7 +37,7 @@ public function load_assets(): void {
*
*/
public function load_admin_styles( string $hook_suffix = '' ): void {
- if ( ! $hook_suffix || ! str_contains( $hook_suffix, 'framework-demo' ) ) {
+ if ( ! $hook_suffix || ! str_contains( $hook_suffix, $this->core->get_name() ) ) {
return;
}
From 30887eba9030e2004dc32ab41f422e195c23fd44 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
Date: Sat, 4 Jul 2026 16:13:23 +0800
Subject: [PATCH 73/86] feature(renamer): rewrite composer.json author fields
Rebrand composer.json author metadata with user-supplied values.
- Replace "Saltus" author name and "saltus.dev" homepage URLs
- Suppress unlink warnings in delete_file helpers
- Add Saltus contributor checkbox on the rebrand form
When the contributor checkbox is checked, inject Saltus as
a second author in the generated plugin.
---
src/Plugin/Admin/RenamerPage.php | 26 ++++++++++++++++++++++-
src/Plugin/Renamer/PluginIdentity.php | 29 ++++++++++++++------------
src/Plugin/Renamer/PluginRenamer.php | 30 ++++++++++++++++++++-------
3 files changed, 63 insertions(+), 22 deletions(-)
diff --git a/src/Plugin/Admin/RenamerPage.php b/src/Plugin/Admin/RenamerPage.php
index 66825e98..62ce2bba 100644
--- a/src/Plugin/Admin/RenamerPage.php
+++ b/src/Plugin/Admin/RenamerPage.php
@@ -181,6 +181,7 @@ public function render(): void {
render_text_field( 'plugin_uri', __( 'Plugin URI', 'framework-demo' ), $values['plugin_uri'], false, 'url' ); ?>
render_text_field( 'version', __( 'Version', 'framework-demo' ), $values['version'], true ); ?>
render_text_field( 'prefix', __( 'Code Prefix', 'framework-demo' ), $values['prefix'], true ); ?>
+ render_checkbox_field( 'saltus_contributor', __( 'Credit Saltus as contributor', 'framework-demo' ), __( 'Include Saltus as a co-author in the generated plugin\'s composer.json', 'framework-demo' ) ); ?>
@@ -329,6 +330,29 @@ class="regular-text"
+
+
+ self::PAGE_SLUG,
+ 'framework_demo_error' => rawurlencode( $message ),
+ ),
+ admin_url( 'admin.php' )
+ )
+ );
+ exit;
+ }
+}
diff --git a/src/Plugin/Renamer/PluginIdentity.php b/src/Plugin/Renamer/PluginIdentity.php
new file mode 100644
index 00000000..bf13f466
--- /dev/null
+++ b/src/Plugin/Renamer/PluginIdentity.php
@@ -0,0 +1,118 @@
+ $data Renamer field values.
+ */
+ public function __construct( array $data ) {
+ $this->plugin_name = $data['plugin_name'];
+ $this->plugin_slug = $data['plugin_slug'];
+ $this->main_file = $data['main_file'];
+ $this->namespace_segment = $data['namespace_segment'];
+ $this->text_domain = $data['text_domain'];
+ $this->description = $data['description'];
+ $this->author = $data['author'];
+ $this->author_uri = $data['author_uri'];
+ $this->plugin_uri = $data['plugin_uri'];
+ $this->version = $data['version'];
+ $this->prefix = $data['prefix'];
+ }
+
+ /**
+ * @return array
+
+
+
+
+ >
+
+
@@ -136,9 +324,79 @@ class="regular-text"
+
+ self::PAGE_SLUG ),
+ admin_url( 'tools.php' )
+ );
+ }
+
+ private function redirect_with_success( string $message ): void {
+ $token = wp_generate_uuid4();
+ set_transient( 'framework_demo_success_' . $token, $message, 30 );
+
+ wp_safe_redirect(
+ add_query_arg(
+ array( 'framework_demo_success' => $token ),
+ $this->tool_url()
+ )
+ );
+ exit;
+ }
+
+ /**
+ * @param array
Hierarchical taxonomies will "
-"behave the same way as categories. Non-hierarchical taxonomies will behave "
-"like tags."
+#: src/Plugin/Admin/RenamerPage.php:182
+msgid "Code Prefix"
msgstr ""
-#: src/models/post-type-basic.php:228 src/models/post-type-basic.php:271
-#: src/models/post-type-basic.php:329
-msgid "Entry {#}"
+#: src/Plugin/Admin/RenamerPage.php:187
+msgid "Download Rebranded Plugin ZIP"
msgstr ""
-#: src/models/post-type-basic.php:229
-msgid "Add Another Taxonomy"
+#: src/Plugin/Admin/RenamerPage.php:190
+msgid "Copy & Activate Plugin"
msgstr ""
-#: src/models/post-type-basic.php:237
-msgid "Singular name for this taxonomy"
+#: src/Plugin/Admin/RenamerPage.php:203
+msgid "You do not have permission to generate plugins."
msgstr ""
-#: src/models/post-type-basic.php:245
-msgid "Plural name"
+#. translators: %s: error message.
+#: src/Plugin/Admin/RenamerPage.php:228
+#, php-format
+msgid "Could not generate the plugin ZIP: %s"
msgstr ""
-#: src/models/post-type-basic.php:247
-msgid "Plural name for this taxonomy"
+#: src/Plugin/Admin/RenamerPage.php:238
+msgid "You do not have permission to activate plugins."
msgstr ""
-#: src/models/post-type-basic.php:251
-msgid "Unique Identifier (slug)"
+#: src/Plugin/Admin/RenamerPage.php:242
+msgid "The WordPress plugin directory could not be found."
msgstr ""
-#: src/models/post-type-basic.php:253
-msgid ""
-"Unique word to identify this taxonomy. When changed a new taxonomy will be "
-"created. No spaces are allowed.
If empty, it will default to the "
-"singular name of this taxonomy."
+#: src/Plugin/Admin/RenamerPage.php:247
+msgid "A plugin folder with that slug already exists. Choose a different slug or remove the existing plugin first."
msgstr ""
-#: src/models/post-type-basic.php:257
-msgid "Hierarchical?"
+#: src/Plugin/Admin/RenamerPage.php:252
+msgid "Could not create a temporary ZIP file."
msgstr ""
-#: src/models/post-type-basic.php:259
-msgid "Can the terms in this taxonomy have parent-child relationship?"
+#. translators: %s: plugin name.
+#: src/Plugin/Admin/RenamerPage.php:269
+#, php-format
+msgid "%s was copied and activated."
msgstr ""
-#: src/models/post-type-basic.php:267
-msgid "Information Fields"
+#: src/Plugin/Admin/RenamerPage.php:278
+msgid "Could not open the generated ZIP file."
msgstr ""
-#: src/models/post-type-basic.php:269
-msgid "Fields that will display when adding new entries."
+#: src/Plugin/Admin/RenamerPage.php:285
+msgid "Could not copy the generated plugin into the plugins directory."
msgstr ""
-#: src/models/post-type-basic.php:272
-msgid "Add Another Field"
+#: src/Plugin/Admin/RenamerPage.php:326
+msgid "How to rebrand this demo"
msgstr ""
-#: src/models/post-type-basic.php:279
-msgid "Name this field"
+#: src/Plugin/Admin/RenamerPage.php:328
+msgid "1. Fill in your plugin identity"
msgstr ""
-#: src/models/post-type-basic.php:293
-msgid "Field type"
+#: src/Plugin/Admin/RenamerPage.php:330
+msgid "Use the public plugin name users should see in WordPress."
msgstr ""
-#: src/models/post-type-basic.php:295
-msgid "Type of field"
+#: src/Plugin/Admin/RenamerPage.php:331
+msgid "Choose a lowercase slug, then match the main file to it, such as my-plugin and my-plugin.php."
msgstr ""
-#: src/models/post-type-basic.php:298
-msgid "Text"
+#: src/Plugin/Admin/RenamerPage.php:332
+msgid "Use a PHP-safe namespace segment like MyPlugin and a lowercase code prefix like my_plugin."
msgstr ""
-#: src/models/post-type-basic.php:299
-msgid "Textarea"
+#: src/Plugin/Admin/RenamerPage.php:333
+msgid "Add the description, author details, URLs, and semver version for the first release."
msgstr ""
-#: src/models/post-type-basic.php:300
-msgid "User select"
+#: src/Plugin/Admin/RenamerPage.php:336
+msgid "2. Choose an install path"
msgstr ""
-#: src/models/post-type-basic.php:310
-msgid "Template"
+#: src/Plugin/Admin/RenamerPage.php:338
+msgid "Download the ZIP, then upload it from Plugins > Add New > Upload Plugin and activate it."
msgstr ""
-#: src/models/post-type-basic.php:312
-msgid ""
-"HTML template when the content for this field is displayed. The placeholder "
-"{value} must be present."
+#: src/Plugin/Admin/RenamerPage.php:339
+msgid "Or use Copy & Activate Plugin to install it directly on this site when the slug is not already in use."
msgstr ""
-#: src/models/post-type-basic.php:317
-msgid "Unique ID"
+#: src/Plugin/Admin/RenamerPage.php:342
+msgid "3. Continue from your new plugin"
msgstr ""
-#: src/models/post-type-basic.php:319
-msgid ""
-"Unique identifier for this field. Should not be changed once you have added "
-"data.
If left blank, it will default to a sanitized version of the name "
-"of this field."
+#: src/Plugin/Admin/RenamerPage.php:343
+msgid "The generated plugin is a separate copy. Keep this demo around for reference, or deactivate it after confirming your new plugin works."
msgstr ""
-#: src/models/post-type-basic.php:327
-msgid "Social Networks fields that will display when adding new entries."
+#. translators: %s: field label
+#: src/Plugin/Renamer/PluginIdentity.php:90
+#, php-format
+msgid "%s is required."
msgstr ""
-#: src/models/post-type-basic.php:330
-msgid "Add Another Social Network"
+#: src/Plugin/Renamer/PluginIdentity.php:95
+msgid "Plugin slug must contain only lowercase letters, numbers, and single dashes."
msgstr ""
-#. Plugin Name of the plugin/theme
-msgid "Saltus Framework Demo"
+#: src/Plugin/Renamer/PluginIdentity.php:99
+msgid "Main plugin file must be a lowercase dash-safe PHP filename."
msgstr ""
-#. Author URI of the plugin/theme
-msgid "https://saltus.io/"
+#: src/Plugin/Renamer/PluginIdentity.php:103
+msgid "Namespace segment must be a valid PHP namespace segment, such as MyPlugin."
msgstr ""
-#. Description of the plugin/theme
-msgid "Saltus Plugin Framework Demo."
+#: src/Plugin/Renamer/PluginIdentity.php:107
+msgid "Version must be a valid semver string like 1.0.0 or 2.0.0-beta.1."
msgstr ""
-#. Author of the plugin/theme
-msgid "Saltus"
-msgstr ""
\ No newline at end of file
+#: src/Plugin/Renamer/PluginIdentity.php:111
+msgid "Code prefix must contain only lowercase letters, numbers, and underscores, and start with a letter."
+msgstr ""
+
+#. translators: %s: field label
+#: src/Plugin/Renamer/PluginIdentity.php:117
+#, php-format
+msgid "%s must be a valid URL or empty."
+msgstr ""
From 60bc6de4d77b9c787a51cb6c1ec1972cc4f202e0 Mon Sep 17 00:00:00 2001
From: Pedro de Carvalho
+
+
+
+
+
+
+
+