COPYRIGHT.md000064400000000133144760112670006443 0ustar00Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. (https://getlaminas.org/) LICENSE.md000064400000002732144760112670006164 0ustar00Copyright (c) 2020 Laminas Project a Series of LF Projects, LLC. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of Laminas Foundation nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. README.md000064400000001612144760112670006033 0ustar00# laminas-code [![Build Status](https://travis-ci.com/laminas/laminas-code.svg?branch=master)](https://travis-ci.com/laminas/laminas-code) [![Coverage Status](https://coveralls.io/repos/github/laminas/laminas-code/badge.svg?branch=master)](https://coveralls.io/github/laminas/laminas-code?branch=master) `Laminas\Code\Generator` provides facilities to generate arbitrary code using an object-oriented interface, both to create new code as well as to update existing code. While the current implementation is limited to generating PHP code, you can easily extend the base class in order to provide code generation for other tasks: JavaScript, configuration files, apache vhosts, etc. - File issues at https://github.com/laminas/laminas-code/issues - Documentation is at https://docs.laminas.dev/laminas-code/ - Migration documentation from v2 to v3 is at https://docs.laminas.dev/laminas-code/migration/ composer.json000064400000003622144760112670007301 0ustar00{ "name": "laminas/laminas-code", "description": "Extensions to the PHP Reflection API, static code scanning, and code generation", "keywords": [ "laminas", "laminasframework", "code" ], "homepage": "https://laminas.dev", "license": "BSD-3-Clause", "require": { "php": "^7.4 || ~8.0.0" }, "conflict": { "phpspec/prophecy": "<1.9.0" }, "require-dev": { "ext-phar": "*", "doctrine/annotations": "^1.10.4", "laminas/laminas-coding-standard": "^2.1.4", "laminas/laminas-stdlib": "^3.3.0", "phpunit/phpunit": "^9.4.2", "psalm/plugin-phpunit": "^0.14.0", "vimeo/psalm": "^4.3.1" }, "suggest": { "doctrine/annotations": "Doctrine\\Common\\Annotations >=1.0 for annotation features", "laminas/laminas-stdlib": "Laminas\\Stdlib component", "laminas/laminas-zendframework-bridge": "A bridge with Zend Framework" }, "config": { "sort-packages": true }, "autoload": { "psr-4": { "Laminas\\Code\\": "src/" } }, "autoload-dev": { "psr-4": { "LaminasTest\\Code\\": "test/" } }, "scripts": { "check": [ "@cs-check", "@test" ], "cs-check": "phpcs", "cs-fix": "phpcbf", "static-analysis": "psalm --shepherd --stats", "test": "phpunit --colors=always", "test-coverage": "phpunit --colors=always --coverage-clover clover.xml" }, "support": { "issues": "https://github.com/laminas/laminas-code/issues", "forum": "https://discourse.laminas.dev", "chat": "https://laminas.dev/chat", "source": "https://github.com/laminas/laminas-code", "docs": "https://docs.laminas.dev/laminas-code/", "rss": "https://github.com/laminas/laminas-code/releases.atom" } } composer.lock000064400000462067144760112670007274 0ustar00{ "_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": "0dc801ff3a6de9be0727fe15155ef2e9", "packages": [], "packages-dev": [ { "name": "amphp/amp", "version": "v2.5.1", "source": { "type": "git", "url": "https://github.com/amphp/amp.git", "reference": "ecdc3c476b3ccff02f8e5d5bcc04f7ccfd18751c" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/amphp/amp/zipball/ecdc3c476b3ccff02f8e5d5bcc04f7ccfd18751c", "reference": "ecdc3c476b3ccff02f8e5d5bcc04f7ccfd18751c", "shasum": "" }, "require": { "php": ">=7" }, "require-dev": { "amphp/php-cs-fixer-config": "dev-master", "amphp/phpunit-util": "^1", "ext-json": "*", "jetbrains/phpstorm-stubs": "^2019.3", "phpunit/phpunit": "^6.0.9 | ^7", "psalm/phar": "^3.11@dev", "react/promise": "^2" }, "type": "library", "extra": { "branch-alias": { "dev-master": "2.x-dev" } }, "autoload": { "psr-4": { "Amp\\": "lib" }, "files": [ "lib/functions.php", "lib/Internal/functions.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Daniel Lowrey", "email": "rdlowrey@php.net" }, { "name": "Aaron Piotrowski", "email": "aaron@trowski.com" }, { "name": "Bob Weinand", "email": "bobwei9@hotmail.com" }, { "name": "Niklas Keller", "email": "me@kelunik.com" } ], "description": "A non-blocking concurrency framework for PHP applications.", "homepage": "http://amphp.org/amp", "keywords": [ "async", "asynchronous", "awaitable", "concurrency", "event", "event-loop", "future", "non-blocking", "promise" ], "support": { "irc": "irc://irc.freenode.org/amphp", "issues": "https://github.com/amphp/amp/issues", "source": "https://github.com/amphp/amp/tree/v2.5.1" }, "funding": [ { "url": "https://github.com/amphp", "type": "github" } ], "time": "2020-11-03T16:23:45+00:00" }, { "name": "amphp/byte-stream", "version": "v1.8.0", "source": { "type": "git", "url": "https://github.com/amphp/byte-stream.git", "reference": "f0c20cf598a958ba2aa8c6e5a71c697d652c7088" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/amphp/byte-stream/zipball/f0c20cf598a958ba2aa8c6e5a71c697d652c7088", "reference": "f0c20cf598a958ba2aa8c6e5a71c697d652c7088", "shasum": "" }, "require": { "amphp/amp": "^2", "php": ">=7.1" }, "require-dev": { "amphp/php-cs-fixer-config": "dev-master", "amphp/phpunit-util": "^1.4", "friendsofphp/php-cs-fixer": "^2.3", "jetbrains/phpstorm-stubs": "^2019.3", "phpunit/phpunit": "^6 || ^7 || ^8", "psalm/phar": "^3.11.4" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.x-dev" } }, "autoload": { "psr-4": { "Amp\\ByteStream\\": "lib" }, "files": [ "lib/functions.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Aaron Piotrowski", "email": "aaron@trowski.com" }, { "name": "Niklas Keller", "email": "me@kelunik.com" } ], "description": "A stream abstraction to make working with non-blocking I/O simple.", "homepage": "http://amphp.org/byte-stream", "keywords": [ "amp", "amphp", "async", "io", "non-blocking", "stream" ], "support": { "irc": "irc://irc.freenode.org/amphp", "issues": "https://github.com/amphp/byte-stream/issues", "source": "https://github.com/amphp/byte-stream/tree/master" }, "time": "2020-06-29T18:35:05+00:00" }, { "name": "composer/package-versions-deprecated", "version": "1.11.99.1", "source": { "type": "git", "url": "https://github.com/composer/package-versions-deprecated.git", "reference": "7413f0b55a051e89485c5cb9f765fe24bb02a7b6" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/7413f0b55a051e89485c5cb9f765fe24bb02a7b6", "reference": "7413f0b55a051e89485c5cb9f765fe24bb02a7b6", "shasum": "" }, "require": { "composer-plugin-api": "^1.1.0 || ^2.0", "php": "^7 || ^8" }, "replace": { "ocramius/package-versions": "1.11.99" }, "require-dev": { "composer/composer": "^1.9.3 || ^2.0@dev", "ext-zip": "^1.13", "phpunit/phpunit": "^6.5 || ^7" }, "type": "composer-plugin", "extra": { "class": "PackageVersions\\Installer", "branch-alias": { "dev-master": "1.x-dev" } }, "autoload": { "psr-4": { "PackageVersions\\": "src/PackageVersions" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Marco Pivetta", "email": "ocramius@gmail.com" }, { "name": "Jordi Boggiano", "email": "j.boggiano@seld.be" } ], "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", "support": { "issues": "https://github.com/composer/package-versions-deprecated/issues", "source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.1" }, "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": "2020-11-11T10:22:58+00:00" }, { "name": "composer/semver", "version": "3.2.4", "source": { "type": "git", "url": "https://github.com/composer/semver.git", "reference": "a02fdf930a3c1c3ed3a49b5f63859c0c20e10464" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/composer/semver/zipball/a02fdf930a3c1c3ed3a49b5f63859c0c20e10464", "reference": "a02fdf930a3c1c3ed3a49b5f63859c0c20e10464", "shasum": "" }, "require": { "php": "^5.3.2 || ^7.0 || ^8.0" }, "require-dev": { "phpstan/phpstan": "^0.12.54", "symfony/phpunit-bridge": "^4.2 || ^5" }, "type": "library", "extra": { "branch-alias": { "dev-main": "3.x-dev" } }, "autoload": { "psr-4": { "Composer\\Semver\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Nils Adermann", "email": "naderman@naderman.de", "homepage": "http://www.naderman.de" }, { "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": "Semver library that offers utilities, version constraint parsing and validation.", "keywords": [ "semantic", "semver", "validation", "versioning" ], "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/semver/issues", "source": "https://github.com/composer/semver/tree/3.2.4" }, "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": "2020-11-13T08:59:24+00:00" }, { "name": "composer/xdebug-handler", "version": "1.4.5", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", "reference": "f28d44c286812c714741478d968104c5e604a1d4" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/f28d44c286812c714741478d968104c5e604a1d4", "reference": "f28d44c286812c714741478d968104c5e604a1d4", "shasum": "" }, "require": { "php": "^5.3.2 || ^7.0 || ^8.0", "psr/log": "^1.0" }, "require-dev": { "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8" }, "type": "library", "autoload": { "psr-4": { "Composer\\XdebugHandler\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "John Stevenson", "email": "john-stevenson@blueyonder.co.uk" } ], "description": "Restarts a process without Xdebug.", "keywords": [ "Xdebug", "performance" ], "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/xdebug-handler/issues", "source": "https://github.com/composer/xdebug-handler/tree/1.4.5" }, "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": "2020-11-13T08:04:11+00:00" }, { "name": "dealerdirect/phpcodesniffer-composer-installer", "version": "v0.7.1", "source": { "type": "git", "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", "reference": "fe390591e0241955f22eb9ba327d137e501c771c" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/fe390591e0241955f22eb9ba327d137e501c771c", "reference": "fe390591e0241955f22eb9ba327d137e501c771c", "shasum": "" }, "require": { "composer-plugin-api": "^1.0 || ^2.0", "php": ">=5.3", "squizlabs/php_codesniffer": "^2.0 || ^3.0 || ^4.0" }, "require-dev": { "composer/composer": "*", "phpcompatibility/php-compatibility": "^9.0", "sensiolabs/security-checker": "^4.1.0" }, "type": "composer-plugin", "extra": { "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" }, "autoload": { "psr-4": { "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Franck Nijhof", "email": "franck.nijhof@dealerdirect.com", "homepage": "http://www.frenck.nl", "role": "Developer / IT Manager" } ], "description": "PHP_CodeSniffer Standards Composer Installer Plugin", "homepage": "http://www.dealerdirect.com", "keywords": [ "PHPCodeSniffer", "PHP_CodeSniffer", "code quality", "codesniffer", "composer", "installer", "phpcs", "plugin", "qa", "quality", "standard", "standards", "style guide", "stylecheck", "tests" ], "support": { "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" }, "time": "2020-12-07T18:04:37+00:00" }, { "name": "dnoegel/php-xdg-base-dir", "version": "v0.1.1", "source": { "type": "git", "url": "https://github.com/dnoegel/php-xdg-base-dir.git", "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", "shasum": "" }, "require": { "php": ">=5.3.2" }, "require-dev": { "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" }, "type": "library", "autoload": { "psr-4": { "XdgBaseDir\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "implementation of xdg base directory specification for php", "support": { "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" }, "time": "2019-12-04T15:06:13+00:00" }, { "name": "doctrine/annotations", "version": "1.11.1", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", "reference": "ce77a7ba1770462cd705a91a151b6c3746f9c6ad" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/doctrine/annotations/zipball/ce77a7ba1770462cd705a91a151b6c3746f9c6ad", "reference": "ce77a7ba1770462cd705a91a151b6c3746f9c6ad", "shasum": "" }, "require": { "doctrine/lexer": "1.*", "ext-tokenizer": "*", "php": "^7.1 || ^8.0" }, "require-dev": { "doctrine/cache": "1.*", "doctrine/coding-standard": "^6.0 || ^8.1", "phpstan/phpstan": "^0.12.20", "phpunit/phpunit": "^7.5 || ^9.1.5" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.11.x-dev" } }, "autoload": { "psr-4": { "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com" }, { "name": "Roman Borschel", "email": "roman@code-factory.org" }, { "name": "Benjamin Eberlei", "email": "kontakt@beberlei.de" }, { "name": "Jonathan Wage", "email": "jonwage@gmail.com" }, { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com" } ], "description": "Docblock Annotations Parser", "homepage": "https://www.doctrine-project.org/projects/annotations.html", "keywords": [ "annotations", "docblock", "parser" ], "support": { "issues": "https://github.com/doctrine/annotations/issues", "source": "https://github.com/doctrine/annotations/tree/1.11.1" }, "time": "2020-10-26T10:28:16+00:00" }, { "name": "doctrine/instantiator", "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b", "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "require-dev": { "doctrine/coding-standard": "^8.0", "ext-pdo": "*", "ext-phar": "*", "phpbench/phpbench": "^0.13 || 1.0.0-alpha2", "phpstan/phpstan": "^0.12", "phpstan/phpstan-phpunit": "^0.12", "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" }, "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.4.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": "2020-11-10T18:47:58+00:00" }, { "name": "doctrine/lexer", "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", "reference": "e864bbf5904cb8f5bb334f99209b48018522f042" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/doctrine/lexer/zipball/e864bbf5904cb8f5bb334f99209b48018522f042", "reference": "e864bbf5904cb8f5bb334f99209b48018522f042", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { "doctrine/coding-standard": "^6.0", "phpstan/phpstan": "^0.11.8", "phpunit/phpunit": "^8.2" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.2.x-dev" } }, "autoload": { "psr-4": { "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com" }, { "name": "Roman Borschel", "email": "roman@code-factory.org" }, { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com" } ], "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", "homepage": "https://www.doctrine-project.org/projects/lexer.html", "keywords": [ "annotations", "docblock", "lexer", "parser", "php" ], "support": { "issues": "https://github.com/doctrine/lexer/issues", "source": "https://github.com/doctrine/lexer/tree/1.2.1" }, "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%2Flexer", "type": "tidelift" } ], "time": "2020-05-25T17:44:05+00:00" }, { "name": "felixfbecker/advanced-json-rpc", "version": "v3.1.1", "source": { "type": "git", "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", "reference": "0ed363f8de17d284d479ec813c9ad3f6834b5c40" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/0ed363f8de17d284d479ec813c9ad3f6834b5c40", "reference": "0ed363f8de17d284d479ec813c9ad3f6834b5c40", "shasum": "" }, "require": { "netresearch/jsonmapper": "^1.0 || ^2.0", "php": ">=7.0", "phpdocumentor/reflection-docblock": "^4.0.0 || ^5.0.0" }, "require-dev": { "phpunit/phpunit": "^6.0.0" }, "type": "library", "autoload": { "psr-4": { "AdvancedJsonRpc\\": "lib/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "ISC" ], "authors": [ { "name": "Felix Becker", "email": "felix.b@outlook.com" } ], "description": "A more advanced JSONRPC implementation", "support": { "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/master" }, "time": "2020-03-11T15:21:41+00:00" }, { "name": "felixfbecker/language-server-protocol", "version": "v1.5.0", "source": { "type": "git", "url": "https://github.com/felixfbecker/php-language-server-protocol.git", "reference": "85e83cacd2ed573238678c6875f8f0d7ec699541" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/85e83cacd2ed573238678c6875f8f0d7ec699541", "reference": "85e83cacd2ed573238678c6875f8f0d7ec699541", "shasum": "" }, "require": { "php": ">=7.1" }, "require-dev": { "phpstan/phpstan": "*", "squizlabs/php_codesniffer": "^3.1", "vimeo/psalm": "^4.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.x-dev" } }, "autoload": { "psr-4": { "LanguageServerProtocol\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "ISC" ], "authors": [ { "name": "Felix Becker", "email": "felix.b@outlook.com" } ], "description": "PHP classes for the Language Server Protocol", "keywords": [ "language", "microsoft", "php", "server" ], "support": { "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.0" }, "time": "2020-10-23T13:55:30+00:00" }, { "name": "laminas/laminas-coding-standard", "version": "2.1.4", "source": { "type": "git", "url": "https://github.com/laminas/laminas-coding-standard.git", "reference": "d75f1acf615232e108da2d2cf5a7df3e527b8f38" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/laminas/laminas-coding-standard/zipball/d75f1acf615232e108da2d2cf5a7df3e527b8f38", "reference": "d75f1acf615232e108da2d2cf5a7df3e527b8f38", "shasum": "" }, "require": { "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7", "laminas/laminas-zendframework-bridge": "^1.0", "php": "^7.3 || ~8.0.0", "slevomat/coding-standard": "^6.4.1", "squizlabs/php_codesniffer": "^3.5.8", "webimpress/coding-standard": "^1.1.6" }, "type": "phpcodesniffer-standard", "autoload": { "psr-4": { "LaminasCodingStandard\\": "src/LaminasCodingStandard/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "description": "Laminas Coding Standard", "homepage": "https://laminas.dev", "keywords": [ "Coding Standard", "laminas" ], "support": { "chat": "https://laminas.dev/chat", "docs": "https://docs.laminas.dev/laminas-coding-standard/", "forum": "https://discourse.laminas.dev", "issues": "https://github.com/laminas/laminas-coding-standard/issues", "rss": "https://github.com/laminas/laminas-coding-standard/releases.atom", "source": "https://github.com/laminas/laminas-coding-standard" }, "funding": [ { "url": "https://funding.communitybridge.org/projects/laminas-project", "type": "community_bridge" } ], "time": "2020-10-26T07:33:05+00:00" }, { "name": "laminas/laminas-stdlib", "version": "3.3.1", "source": { "type": "git", "url": "https://github.com/laminas/laminas-stdlib.git", "reference": "d81c7ffe602ed0e6ecb18691019111c0f4bf1efe" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/d81c7ffe602ed0e6ecb18691019111c0f4bf1efe", "reference": "d81c7ffe602ed0e6ecb18691019111c0f4bf1efe", "shasum": "" }, "require": { "laminas/laminas-zendframework-bridge": "^1.0", "php": "^7.3 || ^8.0" }, "replace": { "zendframework/zend-stdlib": "^3.2.1" }, "require-dev": { "laminas/laminas-coding-standard": "~1.0.0", "phpbench/phpbench": "^0.17.1", "phpunit/phpunit": "~9.3.7" }, "type": "library", "autoload": { "psr-4": { "Laminas\\Stdlib\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "description": "SPL extensions, array utilities, error handlers, and more", "homepage": "https://laminas.dev", "keywords": [ "laminas", "stdlib" ], "support": { "chat": "https://laminas.dev/chat", "docs": "https://docs.laminas.dev/laminas-stdlib/", "forum": "https://discourse.laminas.dev", "issues": "https://github.com/laminas/laminas-stdlib/issues", "rss": "https://github.com/laminas/laminas-stdlib/releases.atom", "source": "https://github.com/laminas/laminas-stdlib" }, "funding": [ { "url": "https://funding.communitybridge.org/projects/laminas-project", "type": "community_bridge" } ], "time": "2020-11-19T20:18:59+00:00" }, { "name": "laminas/laminas-zendframework-bridge", "version": "1.1.1", "source": { "type": "git", "url": "https://github.com/laminas/laminas-zendframework-bridge.git", "reference": "6ede70583e101030bcace4dcddd648f760ddf642" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/6ede70583e101030bcace4dcddd648f760ddf642", "reference": "6ede70583e101030bcace4dcddd648f760ddf642", "shasum": "" }, "require": { "php": "^5.6 || ^7.0 || ^8.0" }, "require-dev": { "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.1 || ^9.3", "squizlabs/php_codesniffer": "^3.5" }, "type": "library", "extra": { "laminas": { "module": "Laminas\\ZendFrameworkBridge" } }, "autoload": { "files": [ "src/autoload.php" ], "psr-4": { "Laminas\\ZendFrameworkBridge\\": "src//" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "description": "Alias legacy ZF class names to Laminas Project equivalents.", "keywords": [ "ZendFramework", "autoloading", "laminas", "zf" ], "support": { "forum": "https://discourse.laminas.dev/", "issues": "https://github.com/laminas/laminas-zendframework-bridge/issues", "rss": "https://github.com/laminas/laminas-zendframework-bridge/releases.atom", "source": "https://github.com/laminas/laminas-zendframework-bridge" }, "funding": [ { "url": "https://funding.communitybridge.org/projects/laminas-project", "type": "community_bridge" } ], "time": "2020-09-14T14:23:00+00:00" }, { "name": "myclabs/deep-copy", "version": "1.10.2", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220", "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "replace": { "myclabs/deep-copy": "self.version" }, "require-dev": { "doctrine/collections": "^1.0", "doctrine/common": "^2.6", "phpunit/phpunit": "^7.1" }, "type": "library", "autoload": { "psr-4": { "DeepCopy\\": "src/DeepCopy/" }, "files": [ "src/DeepCopy/deep_copy.php" ] }, "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.10.2" }, "funding": [ { "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", "type": "tidelift" } ], "time": "2020-11-13T09:40:50+00:00" }, { "name": "netresearch/jsonmapper", "version": "v2.1.0", "source": { "type": "git", "url": "https://github.com/cweiske/jsonmapper.git", "reference": "e0f1e33a71587aca81be5cffbb9746510e1fe04e" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/e0f1e33a71587aca81be5cffbb9746510e1fe04e", "reference": "e0f1e33a71587aca81be5cffbb9746510e1fe04e", "shasum": "" }, "require": { "ext-json": "*", "ext-pcre": "*", "ext-reflection": "*", "ext-spl": "*", "php": ">=5.6" }, "require-dev": { "phpunit/phpunit": "~4.8.35 || ~5.7 || ~6.4 || ~7.0", "squizlabs/php_codesniffer": "~3.5" }, "type": "library", "autoload": { "psr-0": { "JsonMapper": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "OSL-3.0" ], "authors": [ { "name": "Christian Weiske", "email": "cweiske@cweiske.de", "homepage": "http://github.com/cweiske/jsonmapper/", "role": "Developer" } ], "description": "Map nested JSON structures onto PHP classes", "support": { "email": "cweiske@cweiske.de", "issues": "https://github.com/cweiske/jsonmapper/issues", "source": "https://github.com/cweiske/jsonmapper/tree/master" }, "time": "2020-04-16T18:48:43+00:00" }, { "name": "nikic/php-parser", "version": "v4.10.3", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", "reference": "dbe56d23de8fcb157bbc0cfb3ad7c7de0cfb0984" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dbe56d23de8fcb157bbc0cfb3ad7c7de0cfb0984", "reference": "dbe56d23de8fcb157bbc0cfb3ad7c7de0cfb0984", "shasum": "" }, "require": { "ext-tokenizer": "*", "php": ">=7.0" }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" }, "bin": [ "bin/php-parse" ], "type": "library", "extra": { "branch-alias": { "dev-master": "4.9-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/v4.10.3" }, "time": "2020-12-03T17:45:45+00:00" }, { "name": "openlss/lib-array2xml", "version": "1.0.0", "source": { "type": "git", "url": "https://github.com/nullivex/lib-array2xml.git", "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/nullivex/lib-array2xml/zipball/a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", "reference": "a91f18a8dfc69ffabe5f9b068bc39bb202c81d90", "shasum": "" }, "require": { "php": ">=5.3.2" }, "type": "library", "autoload": { "psr-0": { "LSS": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "Apache-2.0" ], "authors": [ { "name": "Bryan Tong", "email": "bryan@nullivex.com", "homepage": "https://www.nullivex.com" }, { "name": "Tony Butler", "email": "spudz76@gmail.com", "homepage": "https://www.nullivex.com" } ], "description": "Array2XML conversion library credit to lalit.org", "homepage": "https://www.nullivex.com", "keywords": [ "array", "array conversion", "xml", "xml conversion" ], "support": { "issues": "https://github.com/nullivex/lib-array2xml/issues", "source": "https://github.com/nullivex/lib-array2xml/tree/master" }, "time": "2019-03-29T20:06:56+00:00" }, { "name": "phar-io/manifest", "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phar-io/manifest/zipball/85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", "shasum": "" }, "require": { "ext-dom": "*", "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/master" }, "time": "2020-06-27T14:33:11+00:00" }, { "name": "phar-io/version", "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", "reference": "726c026815142e4f8677b7cb7f2249c9ffb7ecae" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phar-io/version/zipball/726c026815142e4f8677b7cb7f2249c9ffb7ecae", "reference": "726c026815142e4f8677b7cb7f2249c9ffb7ecae", "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.0.3" }, "time": "2020-11-30T09:21:21+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.2.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556", "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556", "shasum": "" }, "require": { "ext-filter": "*", "php": "^7.2 || ^8.0", "phpdocumentor/reflection-common": "^2.2", "phpdocumentor/type-resolver": "^1.3", "webmozart/assert": "^1.9.1" }, "require-dev": { "mockery/mockery": "~1.3.2" }, "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": "account@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/master" }, "time": "2020-09-03T19:13:55+00:00" }, { "name": "phpdocumentor/type-resolver", "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0", "shasum": "" }, "require": { "php": "^7.2 || ^8.0", "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { "ext-tokenizer": "*" }, "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.4.0" }, "time": "2020-09-17T18:55:26+00:00" }, { "name": "phpspec/prophecy", "version": "1.12.1", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", "reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpspec/prophecy/zipball/8ce87516be71aae9b956f81906aaf0338e0d8a2d", "reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d", "shasum": "" }, "require": { "doctrine/instantiator": "^1.2", "php": "^7.2 || ~8.0, <8.1", "phpdocumentor/reflection-docblock": "^5.2", "sebastian/comparator": "^3.0 || ^4.0", "sebastian/recursion-context": "^3.0 || ^4.0" }, "require-dev": { "phpspec/phpspec": "^6.0", "phpunit/phpunit": "^8.0 || ^9.0 <9.3" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.11.x-dev" } }, "autoload": { "psr-4": { "Prophecy\\": "src/Prophecy" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Konstantin Kudryashov", "email": "ever.zet@gmail.com", "homepage": "http://everzet.com" }, { "name": "Marcello Duarte", "email": "marcello.duarte@gmail.com" } ], "description": "Highly opinionated mocking framework for PHP 5.3+", "homepage": "https://github.com/phpspec/prophecy", "keywords": [ "Double", "Dummy", "fake", "mock", "spy", "stub" ], "support": { "issues": "https://github.com/phpspec/prophecy/issues", "source": "https://github.com/phpspec/prophecy/tree/1.12.1" }, "time": "2020-09-29T09:10:42+00:00" }, { "name": "phpstan/phpdoc-parser", "version": "0.4.9", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", "reference": "98a088b17966bdf6ee25c8a4b634df313d8aa531" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/98a088b17966bdf6ee25c8a4b634df313d8aa531", "reference": "98a088b17966bdf6ee25c8a4b634df313d8aa531", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "require-dev": { "consistence/coding-standard": "^3.5", "ergebnis/composer-normalize": "^2.0.2", "jakub-onderka/php-parallel-lint": "^0.9.2", "phing/phing": "^2.16.0", "phpstan/extension-installer": "^1.0", "phpstan/phpstan": "^0.12.26", "phpstan/phpstan-strict-rules": "^0.12", "phpunit/phpunit": "^6.3", "slevomat/coding-standard": "^4.7.2", "symfony/process": "^4.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "0.4-dev" } }, "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/master" }, "time": "2020-08-03T20:32:43+00:00" }, { "name": "phpunit/php-code-coverage", "version": "9.2.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", "reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f3e026641cc91909d421802dd3ac7827ebfd97e1", "reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", "nikic/php-parser": "^4.10.2", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", "sebastian/code-unit-reverse-lookup": "^2.0.2", "sebastian/complexity": "^2.0", "sebastian/environment": "^5.1.2", "sebastian/lines-of-code": "^1.0.3", "sebastian/version": "^3.0.1", "theseer/tokenizer": "^1.2.0" }, "require-dev": { "phpunit/phpunit": "^9.3" }, "suggest": { "ext-pcov": "*", "ext-xdebug": "*" }, "type": "library", "extra": { "branch-alias": { "dev-master": "9.2-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/9.2.5" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-11-28T06:44:49+00:00" }, { "name": "phpunit/php-file-iterator", "version": "3.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/aa4be8575f26070b100fccb67faabb28f21f66f8", "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8", "shasum": "" }, "require": { "php": ">=7.3" }, "require-dev": { "phpunit/phpunit": "^9.3" }, "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", "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/3.0.5" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-09-28T05:57:25+00:00" }, { "name": "phpunit/php-invoker", "version": "3.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", "shasum": "" }, "require": { "php": ">=7.3" }, "require-dev": { "ext-pcntl": "*", "phpunit/phpunit": "^9.3" }, "suggest": { "ext-pcntl": "*" }, "type": "library", "extra": { "branch-alias": { "dev-master": "3.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": "Invoke callables with a timeout", "homepage": "https://github.com/sebastianbergmann/php-invoker/", "keywords": [ "process" ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-09-28T05:58:55+00:00" }, { "name": "phpunit/php-text-template", "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", "shasum": "" }, "require": { "php": ">=7.3" }, "require-dev": { "phpunit/phpunit": "^9.3" }, "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", "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/2.0.4" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-10-26T05:33:50+00:00" }, { "name": "phpunit/php-timer", "version": "5.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", "shasum": "" }, "require": { "php": ">=7.3" }, "require-dev": { "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { "dev-master": "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": "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/5.0.3" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-10-26T13:16:10+00:00" }, { "name": "phpunit/phpunit", "version": "9.5.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", "reference": "8e16c225d57c3d6808014df6b1dd7598d0a5bbbe" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8e16c225d57c3d6808014df6b1dd7598d0a5bbbe", "reference": "8e16c225d57c3d6808014df6b1dd7598d0a5bbbe", "shasum": "" }, "require": { "doctrine/instantiator": "^1.3.1", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", "myclabs/deep-copy": "^1.10.1", "phar-io/manifest": "^2.0.1", "phar-io/version": "^3.0.2", "php": ">=7.3", "phpspec/prophecy": "^1.12.1", "phpunit/php-code-coverage": "^9.2.3", "phpunit/php-file-iterator": "^3.0.5", "phpunit/php-invoker": "^3.1.1", "phpunit/php-text-template": "^2.0.3", "phpunit/php-timer": "^5.0.2", "sebastian/cli-parser": "^1.0.1", "sebastian/code-unit": "^1.0.6", "sebastian/comparator": "^4.0.5", "sebastian/diff": "^4.0.3", "sebastian/environment": "^5.1.3", "sebastian/exporter": "^4.0.3", "sebastian/global-state": "^5.0.1", "sebastian/object-enumerator": "^4.0.3", "sebastian/resource-operations": "^3.0.3", "sebastian/type": "^2.3", "sebastian/version": "^3.0.2" }, "require-dev": { "ext-pdo": "*", "phpspec/prophecy-phpunit": "^2.0.1" }, "suggest": { "ext-soap": "*", "ext-xdebug": "*" }, "bin": [ "phpunit" ], "type": "library", "extra": { "branch-alias": { "dev-master": "9.5-dev" } }, "autoload": { "classmap": [ "src/" ], "files": [ "src/Framework/Assert/Functions.php" ] }, "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", "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.0" }, "funding": [ { "url": "https://phpunit.de/donate.html", "type": "custom" }, { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-12-04T05:05:53+00:00" }, { "name": "psalm/plugin-phpunit", "version": "0.14.0", "source": { "type": "git", "url": "https://github.com/psalm/psalm-plugin-phpunit.git", "reference": "f5147be764449ff5a11bded483b622e1e868f8ab" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/psalm/psalm-plugin-phpunit/zipball/f5147be764449ff5a11bded483b622e1e868f8ab", "reference": "f5147be764449ff5a11bded483b622e1e868f8ab", "shasum": "" }, "require": { "composer/package-versions-deprecated": "^1.10", "composer/semver": "^1.4 || ^2.0 || ^3.0", "ext-simplexml": "*", "php": "^7.1 || ^8.0", "vimeo/psalm": "dev-master || dev-4.x || ^4.0" }, "conflict": { "phpunit/phpunit": "<7.5" }, "require-dev": { "codeception/codeception": "^4.0.3", "php": "^7.3 || ^8.0", "phpunit/phpunit": "^7.5 || ^8.0 || ^9.0", "squizlabs/php_codesniffer": "^3.3.1", "weirdan/codeception-psalm-module": "^0.11.0", "weirdan/prophecy-shim": "^1.0 || ^2.0" }, "type": "psalm-plugin", "extra": { "psalm": { "pluginClass": "Psalm\\PhpUnitPlugin\\Plugin" } }, "autoload": { "psr-4": { "Psalm\\PhpUnitPlugin\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Matt Brown", "email": "github@muglug.com" } ], "description": "Psalm plugin for PHPUnit", "support": { "issues": "https://github.com/psalm/psalm-plugin-phpunit/issues", "source": "https://github.com/psalm/psalm-plugin-phpunit/tree/0.14.0" }, "time": "2020-12-08T22:25:25+00:00" }, { "name": "psr/container", "version": "1.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", "shasum": "" }, "require": { "php": ">=5.3.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "autoload": { "psr-4": { "Psr\\Container\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "PHP-FIG", "homepage": "http://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/master" }, "time": "2017-02-14T16:28:37+00:00" }, { "name": "psr/log", "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc", "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc", "shasum": "" }, "require": { "php": ">=5.3.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.1.x-dev" } }, "autoload": { "psr-4": { "Psr\\Log\\": "Psr/Log/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "PHP-FIG", "homepage": "http://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/1.1.3" }, "time": "2020-03-23T09:12:05+00:00" }, { "name": "sebastian/cli-parser", "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2", "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2", "shasum": "" }, "require": { "php": ">=7.3" }, "require-dev": { "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.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", "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-09-28T06:08:49+00:00" }, { "name": "sebastian/code-unit", "version": "1.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", "shasum": "" }, "require": { "php": ">=7.3" }, "require-dev": { "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.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", "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-10-26T13:08:54+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", "shasum": "" }, "require": { "php": ">=7.3" }, "require-dev": { "phpunit/phpunit": "^9.3" }, "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": "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/2.0.3" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-09-28T05:30:19+00:00" }, { "name": "sebastian/comparator", "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", "reference": "55f4261989e546dc112258c7a75935a81a7ce382" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382", "reference": "55f4261989e546dc112258c7a75935a81a7ce382", "shasum": "" }, "require": { "php": ">=7.3", "sebastian/diff": "^4.0", "sebastian/exporter": "^4.0" }, "require-dev": { "phpunit/phpunit": "^9.3" }, "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" }, { "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/4.0.6" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-10-26T15:49:45+00:00" }, { "name": "sebastian/complexity", "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", "reference": "739b35e53379900cc9ac327b2147867b8b6efd88" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88", "reference": "739b35e53379900cc9ac327b2147867b8b6efd88", "shasum": "" }, "require": { "nikic/php-parser": "^4.7", "php": ">=7.3" }, "require-dev": { "phpunit/phpunit": "^9.3" }, "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", "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", "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-10-26T15:52:27+00:00" }, { "name": "sebastian/diff", "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", "shasum": "" }, "require": { "php": ">=7.3" }, "require-dev": { "phpunit/phpunit": "^9.3", "symfony/process": "^4.2 || ^5" }, "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" }, { "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/4.0.4" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-10-26T13:10:38+00:00" }, { "name": "sebastian/environment", "version": "5.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", "reference": "388b6ced16caa751030f6a69e588299fa09200ac" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac", "reference": "388b6ced16caa751030f6a69e588299fa09200ac", "shasum": "" }, "require": { "php": ">=7.3" }, "require-dev": { "phpunit/phpunit": "^9.3" }, "suggest": { "ext-posix": "*" }, "type": "library", "extra": { "branch-alias": { "dev-master": "5.1-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/5.1.3" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-09-28T05:52:38+00:00" }, { "name": "sebastian/exporter", "version": "4.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/d89cc98761b8cb5a1a235a6b703ae50d34080e65", "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65", "shasum": "" }, "require": { "php": ">=7.3", "sebastian/recursion-context": "^4.0" }, "require-dev": { "ext-mbstring": "*", "phpunit/phpunit": "^9.3" }, "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" }, { "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/4.0.3" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-09-28T05:24:23+00:00" }, { "name": "sebastian/global-state", "version": "5.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", "reference": "a90ccbddffa067b51f574dea6eb25d5680839455" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/a90ccbddffa067b51f574dea6eb25d5680839455", "reference": "a90ccbddffa067b51f574dea6eb25d5680839455", "shasum": "" }, "require": { "php": ">=7.3", "sebastian/object-reflector": "^2.0", "sebastian/recursion-context": "^4.0" }, "require-dev": { "ext-dom": "*", "phpunit/phpunit": "^9.3" }, "suggest": { "ext-uopz": "*" }, "type": "library", "extra": { "branch-alias": { "dev-master": "5.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/5.0.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-10-26T15:55:19+00:00" }, { "name": "sebastian/lines-of-code", "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", "shasum": "" }, "require": { "nikic/php-parser": "^4.6", "php": ">=7.3" }, "require-dev": { "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.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", "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-11-28T06:42:11+00:00" }, { "name": "sebastian/object-enumerator", "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", "shasum": "" }, "require": { "php": ">=7.3", "sebastian/object-reflector": "^2.0", "sebastian/recursion-context": "^4.0" }, "require-dev": { "phpunit/phpunit": "^9.3" }, "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": "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/4.0.4" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-10-26T13:12:34+00:00" }, { "name": "sebastian/object-reflector", "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", "shasum": "" }, "require": { "php": ">=7.3" }, "require-dev": { "phpunit/phpunit": "^9.3" }, "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": "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/2.0.4" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-10-26T13:14:26+00:00" }, { "name": "sebastian/recursion-context", "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", "shasum": "" }, "require": { "php": ">=7.3" }, "require-dev": { "phpunit/phpunit": "^9.3" }, "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" }, { "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/4.0.4" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-10-26T13:17:30+00:00" }, { "name": "sebastian/resource-operations", "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8", "shasum": "" }, "require": { "php": ">=7.3" }, "require-dev": { "phpunit/phpunit": "^9.0" }, "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": "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/3.0.3" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-09-28T06:45:17+00:00" }, { "name": "sebastian/type", "version": "2.3.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", "reference": "81cd61ab7bbf2de744aba0ea61fae32f721df3d2" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/81cd61ab7bbf2de744aba0ea61fae32f721df3d2", "reference": "81cd61ab7bbf2de744aba0ea61fae32f721df3d2", "shasum": "" }, "require": { "php": ">=7.3" }, "require-dev": { "phpunit/phpunit": "^9.3" }, "type": "library", "extra": { "branch-alias": { "dev-master": "2.3-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/2.3.1" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-10-26T13:18:59+00:00" }, { "name": "sebastian/version", "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", "reference": "c6c1022351a901512170118436c764e473f6de8c" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", "reference": "c6c1022351a901512170118436c764e473f6de8c", "shasum": "" }, "require": { "php": ">=7.3" }, "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", "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/3.0.2" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], "time": "2020-09-28T06:39:44+00:00" }, { "name": "slevomat/coding-standard", "version": "6.4.1", "source": { "type": "git", "url": "https://github.com/slevomat/coding-standard.git", "reference": "696dcca217d0c9da2c40d02731526c1e25b65346" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/696dcca217d0c9da2c40d02731526c1e25b65346", "reference": "696dcca217d0c9da2c40d02731526c1e25b65346", "shasum": "" }, "require": { "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7", "php": "^7.1 || ^8.0", "phpstan/phpdoc-parser": "0.4.5 - 0.4.9", "squizlabs/php_codesniffer": "^3.5.6" }, "require-dev": { "phing/phing": "2.16.3", "php-parallel-lint/php-parallel-lint": "1.2.0", "phpstan/phpstan": "0.12.48", "phpstan/phpstan-deprecation-rules": "0.12.5", "phpstan/phpstan-phpunit": "0.12.16", "phpstan/phpstan-strict-rules": "0.12.5", "phpunit/phpunit": "7.5.20|8.5.5|9.4.0" }, "type": "phpcodesniffer-standard", "extra": { "branch-alias": { "dev-master": "6.x-dev" } }, "autoload": { "psr-4": { "SlevomatCodingStandard\\": "SlevomatCodingStandard" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", "support": { "issues": "https://github.com/slevomat/coding-standard/issues", "source": "https://github.com/slevomat/coding-standard/tree/6.4.1" }, "funding": [ { "url": "https://github.com/kukulich", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", "type": "tidelift" } ], "time": "2020-10-05T12:39:37+00:00" }, { "name": "squizlabs/php_codesniffer", "version": "3.5.8", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", "reference": "9d583721a7157ee997f235f327de038e7ea6dac4" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/9d583721a7157ee997f235f327de038e7ea6dac4", "reference": "9d583721a7157ee997f235f327de038e7ea6dac4", "shasum": "" }, "require": { "ext-simplexml": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", "php": ">=5.4.0" }, "require-dev": { "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" }, "bin": [ "bin/phpcs", "bin/phpcbf" ], "type": "library", "extra": { "branch-alias": { "dev-master": "3.x-dev" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Greg Sherwood", "role": "lead" } ], "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", "keywords": [ "phpcs", "standards" ], "support": { "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", "source": "https://github.com/squizlabs/PHP_CodeSniffer", "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" }, "time": "2020-10-23T02:01:07+00:00" }, { "name": "symfony/console", "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", "reference": "3e0564fb08d44a98bd5f1960204c958e57bd586b" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/console/zipball/3e0564fb08d44a98bd5f1960204c958e57bd586b", "reference": "3e0564fb08d44a98bd5f1960204c958e57bd586b", "shasum": "" }, "require": { "php": ">=7.2.5", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php73": "^1.8", "symfony/polyfill-php80": "^1.15", "symfony/service-contracts": "^1.1|^2", "symfony/string": "^5.1" }, "conflict": { "symfony/dependency-injection": "<4.4", "symfony/dotenv": "<5.1", "symfony/event-dispatcher": "<4.4", "symfony/lock": "<4.4", "symfony/process": "<4.4" }, "provide": { "psr/log-implementation": "1.0" }, "require-dev": { "psr/log": "~1.0", "symfony/config": "^4.4|^5.0", "symfony/dependency-injection": "^4.4|^5.0", "symfony/event-dispatcher": "^4.4|^5.0", "symfony/lock": "^4.4|^5.0", "symfony/process": "^4.4|^5.0", "symfony/var-dumper": "^4.4|^5.0" }, "suggest": { "psr/log": "For using the console logger", "symfony/event-dispatcher": "", "symfony/lock": "", "symfony/process": "" }, "type": "library", "autoload": { "psr-4": { "Symfony\\Component\\Console\\": "" }, "exclude-from-classmap": [ "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Console Component", "homepage": "https://symfony.com", "keywords": [ "cli", "command line", "console", "terminal" ], "support": { "source": "https://github.com/symfony/console/tree/v5.2.0" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2020-11-28T11:24:18+00:00" }, { "name": "symfony/polyfill-ctype", "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", "reference": "f4ba089a5b6366e453971d3aad5fe8e897b37f41" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f4ba089a5b6366e453971d3aad5fe8e897b37f41", "reference": "f4ba089a5b6366e453971d3aad5fe8e897b37f41", "shasum": "" }, "require": { "php": ">=7.1" }, "suggest": { "ext-ctype": "For best performance" }, "type": "library", "extra": { "branch-alias": { "dev-main": "1.20-dev" }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" } }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Ctype\\": "" }, "files": [ "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Gert de Pagter", "email": "BackEndTea@gmail.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill for ctype functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", "ctype", "polyfill", "portable" ], "support": { "source": "https://github.com/symfony/polyfill-ctype/tree/v1.20.0" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2020-10-23T14:02:19+00:00" }, { "name": "symfony/polyfill-intl-grapheme", "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", "reference": "c7cf3f858ec7d70b89559d6e6eb1f7c2517d479c" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/c7cf3f858ec7d70b89559d6e6eb1f7c2517d479c", "reference": "c7cf3f858ec7d70b89559d6e6eb1f7c2517d479c", "shasum": "" }, "require": { "php": ">=7.1" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { "branch-alias": { "dev-main": "1.20-dev" }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" } }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Intl\\Grapheme\\": "" }, "files": [ "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill for intl's grapheme_* functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", "grapheme", "intl", "polyfill", "portable", "shim" ], "support": { "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.20.0" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2020-10-23T14:02:19+00:00" }, { "name": "symfony/polyfill-intl-normalizer", "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", "reference": "727d1096295d807c309fb01a851577302394c897" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/727d1096295d807c309fb01a851577302394c897", "reference": "727d1096295d807c309fb01a851577302394c897", "shasum": "" }, "require": { "php": ">=7.1" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { "branch-alias": { "dev-main": "1.20-dev" }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" } }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Intl\\Normalizer\\": "" }, "files": [ "bootstrap.php" ], "classmap": [ "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill for intl's Normalizer class and related functions", "homepage": "https://symfony.com", "keywords": [ "compatibility", "intl", "normalizer", "polyfill", "portable", "shim" ], "support": { "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.20.0" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2020-10-23T14:02:19+00:00" }, { "name": "symfony/polyfill-mbstring", "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", "reference": "39d483bdf39be819deabf04ec872eb0b2410b531" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/39d483bdf39be819deabf04ec872eb0b2410b531", "reference": "39d483bdf39be819deabf04ec872eb0b2410b531", "shasum": "" }, "require": { "php": ">=7.1" }, "suggest": { "ext-mbstring": "For best performance" }, "type": "library", "extra": { "branch-alias": { "dev-main": "1.20-dev" }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" } }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" }, "files": [ "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill for the Mbstring extension", "homepage": "https://symfony.com", "keywords": [ "compatibility", "mbstring", "polyfill", "portable", "shim" ], "support": { "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.20.0" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2020-10-23T14:02:19+00:00" }, { "name": "symfony/polyfill-php73", "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", "reference": "8ff431c517be11c78c48a39a66d37431e26a6bed" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/8ff431c517be11c78c48a39a66d37431e26a6bed", "reference": "8ff431c517be11c78c48a39a66d37431e26a6bed", "shasum": "" }, "require": { "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { "dev-main": "1.20-dev" }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" } }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Php73\\": "" }, "files": [ "bootstrap.php" ], "classmap": [ "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", "polyfill", "portable", "shim" ], "support": { "source": "https://github.com/symfony/polyfill-php73/tree/v1.20.0" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2020-10-23T14:02:19+00:00" }, { "name": "symfony/polyfill-php80", "version": "v1.20.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", "reference": "e70aa8b064c5b72d3df2abd5ab1e90464ad009de" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/e70aa8b064c5b72d3df2abd5ab1e90464ad009de", "reference": "e70aa8b064c5b72d3df2abd5ab1e90464ad009de", "shasum": "" }, "require": { "php": ">=7.1" }, "type": "library", "extra": { "branch-alias": { "dev-main": "1.20-dev" }, "thanks": { "name": "symfony/polyfill", "url": "https://github.com/symfony/polyfill" } }, "autoload": { "psr-4": { "Symfony\\Polyfill\\Php80\\": "" }, "files": [ "bootstrap.php" ], "classmap": [ "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Ion Bazan", "email": "ion.bazan@gmail.com" }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", "polyfill", "portable", "shim" ], "support": { "source": "https://github.com/symfony/polyfill-php80/tree/v1.20.0" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2020-10-23T14:02:19+00:00" }, { "name": "symfony/service-contracts", "version": "v2.2.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d15da7ba4957ffb8f1747218be9e1a121fd298a1", "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1", "shasum": "" }, "require": { "php": ">=7.2.5", "psr/container": "^1.0" }, "suggest": { "symfony/service-implementation": "" }, "type": "library", "extra": { "branch-alias": { "dev-master": "2.2-dev" }, "thanks": { "name": "symfony/contracts", "url": "https://github.com/symfony/contracts" } }, "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Generic abstractions related to writing services", "homepage": "https://symfony.com", "keywords": [ "abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards" ], "support": { "source": "https://github.com/symfony/service-contracts/tree/master" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2020-09-07T11:33:47+00:00" }, { "name": "symfony/string", "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", "reference": "40e975edadd4e32cd16f3753b3bad65d9ac48242" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/string/zipball/40e975edadd4e32cd16f3753b3bad65d9ac48242", "reference": "40e975edadd4e32cd16f3753b3bad65d9ac48242", "shasum": "" }, "require": { "php": ">=7.2.5", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php80": "~1.15" }, "require-dev": { "symfony/error-handler": "^4.4|^5.0", "symfony/http-client": "^4.4|^5.0", "symfony/translation-contracts": "^1.1|^2", "symfony/var-exporter": "^4.4|^5.0" }, "type": "library", "autoload": { "psr-4": { "Symfony\\Component\\String\\": "" }, "files": [ "Resources/functions.php" ], "exclude-from-classmap": [ "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Nicolas Grekas", "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony String component", "homepage": "https://symfony.com", "keywords": [ "grapheme", "i18n", "string", "unicode", "utf-8", "utf8" ], "support": { "source": "https://github.com/symfony/string/tree/v5.2.0" }, "funding": [ { "url": "https://symfony.com/sponsor", "type": "custom" }, { "url": "https://github.com/fabpot", "type": "github" }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], "time": "2020-10-24T12:08:07+00:00" }, { "name": "theseer/tokenizer", "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", "reference": "75a63c33a8577608444246075ea0af0d052e452a" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/theseer/tokenizer/zipball/75a63c33a8577608444246075ea0af0d052e452a", "reference": "75a63c33a8577608444246075ea0af0d052e452a", "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/master" }, "funding": [ { "url": "https://github.com/theseer", "type": "github" } ], "time": "2020-07-12T23:59:07+00:00" }, { "name": "vimeo/psalm", "version": "4.3.1", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", "reference": "2feba22a005a18bf31d4c7b9bdb9252c73897476" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/vimeo/psalm/zipball/2feba22a005a18bf31d4c7b9bdb9252c73897476", "reference": "2feba22a005a18bf31d4c7b9bdb9252c73897476", "shasum": "" }, "require": { "amphp/amp": "^2.1", "amphp/byte-stream": "^1.5", "composer/package-versions-deprecated": "^1.8.0", "composer/semver": "^1.4 || ^2.0 || ^3.0", "composer/xdebug-handler": "^1.1", "dnoegel/php-xdg-base-dir": "^0.1.1", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-simplexml": "*", "ext-tokenizer": "*", "felixfbecker/advanced-json-rpc": "^3.0.3", "felixfbecker/language-server-protocol": "^1.4", "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0", "nikic/php-parser": "^4.10.1", "openlss/lib-array2xml": "^1.0", "php": "^7.1|^8", "sebastian/diff": "^3.0 || ^4.0", "symfony/console": "^3.4.17 || ^4.1.6 || ^5.0", "webmozart/path-util": "^2.3" }, "provide": { "psalm/psalm": "self.version" }, "require-dev": { "amphp/amp": "^2.4.2", "bamarni/composer-bin-plugin": "^1.2", "brianium/paratest": "^4.0.0", "ext-curl": "*", "php": "^7.3|^8", "phpdocumentor/reflection-docblock": "^5", "phpmyadmin/sql-parser": "5.1.0", "phpspec/prophecy": ">=1.9.0", "phpunit/phpunit": "^9.0", "psalm/plugin-phpunit": "^0.13", "slevomat/coding-standard": "^5.0", "squizlabs/php_codesniffer": "^3.5", "symfony/process": "^4.3", "weirdan/prophecy-shim": "^1.0 || ^2.0" }, "suggest": { "ext-igbinary": "^2.0.5" }, "bin": [ "psalm", "psalm-language-server", "psalm-plugin", "psalm-refactor", "psalter" ], "type": "library", "extra": { "branch-alias": { "dev-master": "4.x-dev", "dev-3.x": "3.x-dev", "dev-2.x": "2.x-dev", "dev-1.x": "1.x-dev" } }, "autoload": { "psr-4": { "Psalm\\": "src/Psalm/" }, "files": [ "src/functions.php", "src/spl_object_id.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Matthew Brown" } ], "description": "A static analysis tool for finding errors in PHP applications", "keywords": [ "code", "inspection", "php" ], "support": { "issues": "https://github.com/vimeo/psalm/issues", "source": "https://github.com/vimeo/psalm/tree/4.3.1" }, "time": "2020-12-03T16:44:10+00:00" }, { "name": "webimpress/coding-standard", "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/webimpress/coding-standard.git", "reference": "579818b431e2a2c8f24b60776598499782727897" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/webimpress/coding-standard/zipball/579818b431e2a2c8f24b60776598499782727897", "reference": "579818b431e2a2c8f24b60776598499782727897", "shasum": "" }, "require": { "php": "^7.3 || ^8.0", "squizlabs/php_codesniffer": "^3.5.8" }, "require-dev": { "phpunit/phpunit": "^9.4.3" }, "type": "phpcodesniffer-standard", "extra": { "dev-master": "1.2.x-dev", "dev-develop": "1.3.x-dev" }, "autoload": { "psr-4": { "WebimpressCodingStandard\\": "src/WebimpressCodingStandard/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-2-Clause" ], "description": "Webimpress Coding Standard", "keywords": [ "Coding Standard", "PSR-2", "phpcs", "psr-12", "webimpress" ], "support": { "issues": "https://github.com/webimpress/coding-standard/issues", "source": "https://github.com/webimpress/coding-standard/tree/1.2.0" }, "funding": [ { "url": "https://github.com/michalbundyra", "type": "github" } ], "time": "2020-11-27T20:16:01+00:00" }, { "name": "webmozart/assert", "version": "1.9.1", "source": { "type": "git", "url": "https://github.com/webmozarts/assert.git", "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", "shasum": "" }, "require": { "php": "^5.3.3 || ^7.0 || ^8.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { "phpstan/phpstan": "<0.12.20", "vimeo/psalm": "<3.9.1" }, "require-dev": { "phpunit/phpunit": "^4.8.36 || ^7.5.13" }, "type": "library", "autoload": { "psr-4": { "Webmozart\\Assert\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Bernhard Schussek", "email": "bschussek@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/1.9.1" }, "time": "2020-07-08T17:02:28+00:00" }, { "name": "webmozart/path-util", "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/webmozart/path-util.git", "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725", "reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725", "shasum": "" }, "require": { "php": ">=5.3.3", "webmozart/assert": "~1.0" }, "require-dev": { "phpunit/phpunit": "^4.6", "sebastian/version": "^1.0.1" }, "type": "library", "extra": { "branch-alias": { "dev-master": "2.3-dev" } }, "autoload": { "psr-4": { "Webmozart\\PathUtil\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Bernhard Schussek", "email": "bschussek@gmail.com" } ], "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.", "support": { "issues": "https://github.com/webmozart/path-util/issues", "source": "https://github.com/webmozart/path-util/tree/2.3.0" }, "time": "2015-12-17T08:42:14+00:00" } ], "aliases": [], "minimum-stability": "stable", "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { "php": "^7.4 || ~8.0.0" }, "platform-dev": { "ext-phar": "*" }, "plugin-api-version": "2.1.0" } src/DeclareStatement.php000064400000004737144760112670011313 0ustar00 'integer', self::STRICT_TYPES => 'integer', self::ENCODING => 'string', ]; protected string $directive; /** @var int|string */ protected $value; /** @param int|string $value */ private function __construct(string $directive, $value) { $this->directive = $directive; $this->value = $value; } public function getDirective(): string { return $this->directive; } /** * @return int|string */ public function getValue() { return $this->value; } public static function ticks(int $value): self { return new self(self::TICKS, $value); } public static function strictTypes(int $value): self { return new self(self::STRICT_TYPES, $value); } public static function encoding(string $value): self { return new self(self::ENCODING, $value); } public static function fromArray(array $config): self { $directive = key($config); $value = $config[$directive]; if (! isset(self::ALLOWED[$directive])) { throw new InvalidArgumentException( sprintf( 'Declare directive must be one of: %s.', implode(', ', array_keys(self::ALLOWED)) ) ); } if (gettype($value) !== self::ALLOWED[$directive]) { throw new InvalidArgumentException( sprintf( 'Declare value invalid. Expected %s, got %s.', self::ALLOWED[$directive], gettype($value) ) ); } $method = str_replace('_', '', lcfirst(ucwords($directive, '_'))); return self::{$method}($value); } public function getStatement(): string { $value = is_string($this->value) ? '\'' . $this->value . '\'' : $this->value; return sprintf('declare(%s=%s);', $this->directive, $value); } } src/Exception/BadMethodCallException.php000064400000000215144760112670014312 0ustar00setOptions($options); } } /** * @param bool $isSourceDirty * @return AbstractGenerator */ public function setSourceDirty($isSourceDirty = true) { $this->isSourceDirty = (bool) $isSourceDirty; return $this; } /** * @return bool */ public function isSourceDirty() { return $this->isSourceDirty; } /** * @param string $indentation * @return AbstractGenerator */ public function setIndentation($indentation) { $this->indentation = (string) $indentation; return $this; } /** * @return string */ public function getIndentation() { return $this->indentation; } /** * @param ?string $sourceContent * @return AbstractGenerator */ public function setSourceContent($sourceContent) { $this->sourceContent = (string) $sourceContent; return $this; } /** * @return ?string */ public function getSourceContent() { return $this->sourceContent; } /** * @param array|Traversable $options * @throws Exception\InvalidArgumentException * @return AbstractGenerator */ public function setOptions($options) { if (! is_array($options) && ! $options instanceof Traversable) { throw new Exception\InvalidArgumentException(sprintf( '%s expects an array or Traversable object; received "%s"', __METHOD__, is_object($options) ? get_class($options) : gettype($options) )); } foreach ($options as $optionName => $optionValue) { $methodName = 'set' . $optionName; if (method_exists($this, $methodName)) { $this->{$methodName}($optionValue); } } return $this; } } src/Generator/AbstractMemberGenerator.php000064400000013003144760112670014541 0ustar00flags = $flags; return $this; } /** * @param int $flag * @return AbstractMemberGenerator */ public function addFlag($flag) { $this->setFlags($this->flags | $flag); return $this; } /** * @param int $flag * @return AbstractMemberGenerator */ public function removeFlag($flag) { $this->setFlags($this->flags & ~$flag); return $this; } /** * @param bool $isAbstract * @return AbstractMemberGenerator */ public function setAbstract($isAbstract) { return $isAbstract ? $this->addFlag(self::FLAG_ABSTRACT) : $this->removeFlag(self::FLAG_ABSTRACT); } /** * @return bool */ public function isAbstract() { return (bool) ($this->flags & self::FLAG_ABSTRACT); } /** * @param bool $isInterface * @return AbstractMemberGenerator */ public function setInterface($isInterface) { return $isInterface ? $this->addFlag(self::FLAG_INTERFACE) : $this->removeFlag(self::FLAG_INTERFACE); } /** * @return bool */ public function isInterface() { return (bool) ($this->flags & self::FLAG_INTERFACE); } /** * @param bool $isFinal * @return AbstractMemberGenerator */ public function setFinal($isFinal) { return $isFinal ? $this->addFlag(self::FLAG_FINAL) : $this->removeFlag(self::FLAG_FINAL); } /** * @return bool */ public function isFinal() { return (bool) ($this->flags & self::FLAG_FINAL); } /** * @param bool $isStatic * @return AbstractMemberGenerator */ public function setStatic($isStatic) { return $isStatic ? $this->addFlag(self::FLAG_STATIC) : $this->removeFlag(self::FLAG_STATIC); } /** * @return bool */ public function isStatic() { return (bool) ($this->flags & self::FLAG_STATIC); // is FLAG_STATIC in flags } /** * @param string $visibility * @return AbstractMemberGenerator */ public function setVisibility($visibility) { switch ($visibility) { case self::VISIBILITY_PUBLIC: $this->removeFlag(self::FLAG_PRIVATE | self::FLAG_PROTECTED); // remove both $this->addFlag(self::FLAG_PUBLIC); break; case self::VISIBILITY_PROTECTED: $this->removeFlag(self::FLAG_PUBLIC | self::FLAG_PRIVATE); // remove both $this->addFlag(self::FLAG_PROTECTED); break; case self::VISIBILITY_PRIVATE: $this->removeFlag(self::FLAG_PUBLIC | self::FLAG_PROTECTED); // remove both $this->addFlag(self::FLAG_PRIVATE); break; } return $this; } /** * @return string */ public function getVisibility() { switch (true) { case $this->flags & self::FLAG_PROTECTED: return self::VISIBILITY_PROTECTED; case $this->flags & self::FLAG_PRIVATE: return self::VISIBILITY_PRIVATE; default: return self::VISIBILITY_PUBLIC; } } /** * @param string $name * @return AbstractMemberGenerator */ public function setName($name) { $this->name = (string) $name; return $this; } /** * @return string */ public function getName() { return $this->name; } /** * @param DocBlockGenerator|string $docBlock * @throws Exception\InvalidArgumentException * @return AbstractMemberGenerator */ public function setDocBlock($docBlock) { if (is_string($docBlock)) { $docBlock = new DocBlockGenerator($docBlock); } elseif (! $docBlock instanceof DocBlockGenerator) { throw new Exception\InvalidArgumentException(sprintf( '%s is expecting either a string, array or an instance of %s\DocBlockGenerator', __METHOD__, __NAMESPACE__ )); } $this->docBlock = $docBlock; return $this; } public function removeDocBlock(): void { $this->docBlock = null; } /** * @return DocBlockGenerator|null */ public function getDocBlock() { return $this->docBlock; } } src/Generator/BodyGenerator.php000064400000001055144760112670012547 0ustar00content = (string) $content; return $this; } /** * @return string */ public function getContent() { return $this->content; } /** * @return string */ public function generate() { return $this->getContent(); } } src/Generator/ClassGenerator.php000064400000073103144760112670012722 0ustar00 */ protected array $implementedInterfaces = []; /** @var PropertyGenerator[] */ protected array $properties = []; /** @var PropertyGenerator[] */ protected array $constants = []; /** @var MethodGenerator[] */ protected array $methods = []; /** @var TraitUsageGenerator Object to encapsulate trait usage logic */ protected TraitUsageGenerator $traitUsageGenerator; /** * Build a Code Generation Php Object from a Class Reflection * * @return static */ public static function fromReflection(ClassReflection $classReflection) { $cg = new static($classReflection->getName()); $cg->setSourceContent($cg->getSourceContent()); $cg->setSourceDirty(false); if ($classReflection->getDocComment() != '') { $cg->setDocBlock(DocBlockGenerator::fromReflection($classReflection->getDocBlock())); } $cg->setAbstract($classReflection->isAbstract()); // set the namespace if ($classReflection->inNamespace()) { $cg->setNamespaceName($classReflection->getNamespaceName()); } $parentClass = $classReflection->getParentClass(); $interfaces = $classReflection->getInterfaces(); if ($parentClass) { $cg->setExtendedClass($parentClass->getName()); $interfaces = array_diff($interfaces, $parentClass->getInterfaces()); } $interfaceNames = []; foreach ($interfaces as $interface) { $interfaceNames[] = $interface->getName(); } $cg->setImplementedInterfaces($interfaceNames); $properties = []; foreach ($classReflection->getProperties() as $reflectionProperty) { if ($reflectionProperty->getDeclaringClass()->getName() == $classReflection->getName()) { $properties[] = PropertyGenerator::fromReflection($reflectionProperty); } } $cg->addProperties($properties); $constants = []; foreach ($classReflection->getConstants() as $name => $value) { $constants[] = [ 'name' => $name, 'value' => $value, ]; } $cg->addConstants($constants); $methods = []; foreach ($classReflection->getMethods() as $reflectionMethod) { $className = $cg->getName(); $namespaceName = $cg->getNamespaceName(); if ($namespaceName !== null) { $className = $namespaceName . '\\' . $className; } if ($reflectionMethod->getDeclaringClass()->getName() == $className) { $methods[] = MethodGenerator::fromReflection($reflectionMethod); } } $cg->addMethods($methods); return $cg; } /** * Generate from array * * @configkey name string [required] Class Name * @configkey filegenerator FileGenerator File generator that holds this class * @configkey namespacename string The namespace for this class * @configkey docblock string The docblock information * @configkey flags int Flags, one of ClassGenerator::FLAG_ABSTRACT ClassGenerator::FLAG_FINAL * @configkey extendedclass string Class which this class is extending * @configkey implementedinterfaces * @configkey properties * @configkey methods * @throws Exception\InvalidArgumentException * @param array $array * @return self */ public static function fromArray(array $array) { if (! isset($array['name'])) { throw new Exception\InvalidArgumentException( 'Class generator requires that a name is provided for this object' ); } $cg = new static($array['name']); foreach ($array as $name => $value) { // normalize key switch (strtolower(str_replace(['.', '-', '_'], '', $name))) { case 'containingfile': $cg->setContainingFileGenerator($value); break; case 'namespacename': $cg->setNamespaceName($value); break; case 'docblock': $docBlock = $value instanceof DocBlockGenerator ? $value : DocBlockGenerator::fromArray($value); $cg->setDocBlock($docBlock); break; case 'flags': $cg->setFlags($value); break; case 'extendedclass': $cg->setExtendedClass($value); break; case 'implementedinterfaces': $cg->setImplementedInterfaces($value); break; case 'properties': $cg->addProperties($value); break; case 'methods': $cg->addMethods($value); break; } } return $cg; } /** * @param string $name * @param string $namespaceName * @param int|int[]|null $flags * @param class-string|null $extends * @param string[] $interfaces * @psalm-param array $interfaces * @param PropertyGenerator[]|string[]|array[] $properties * @param MethodGenerator[]|string[]|array[] $methods * @param DocBlockGenerator $docBlock */ public function __construct( $name = null, $namespaceName = null, $flags = null, $extends = null, array $interfaces = [], array $properties = [], array $methods = [], $docBlock = null ) { $this->traitUsageGenerator = new TraitUsageGenerator($this); if ($name !== null) { $this->setName($name); } if ($namespaceName !== null) { $this->setNamespaceName($namespaceName); } if ($flags !== null) { $this->setFlags($flags); } if ($properties !== []) { $this->addProperties($properties); } if ($extends !== null) { $this->setExtendedClass($extends); } if ($interfaces !== []) { $this->setImplementedInterfaces($interfaces); } if ($methods !== []) { $this->addMethods($methods); } if ($docBlock !== null) { $this->setDocBlock($docBlock); } } /** * @param string $name * @return self */ public function setName($name) { if (false !== strpos($name, '\\')) { $namespace = substr($name, 0, strrpos($name, '\\')); $name = substr($name, strrpos($name, '\\') + 1); $this->setNamespaceName($namespace); } $this->name = $name; return $this; } /** * @return string */ public function getName() { return $this->name; } /** * @param ?string $namespaceName * @return self */ public function setNamespaceName($namespaceName) { $this->namespaceName = $namespaceName; return $this; } /** * @return ?string */ public function getNamespaceName() { return $this->namespaceName; } /** * @return self */ public function setContainingFileGenerator(FileGenerator $fileGenerator) { $this->containingFileGenerator = $fileGenerator; return $this; } /** * @return ?FileGenerator */ public function getContainingFileGenerator() { return $this->containingFileGenerator; } /** * @return self */ public function setDocBlock(DocBlockGenerator $docBlock) { $this->docBlock = $docBlock; return $this; } /** * @return ?DocBlockGenerator */ public function getDocBlock() { return $this->docBlock; } /** * @param int[]|int $flags * @return self */ public function setFlags($flags) { if (is_array($flags)) { $flagsArray = $flags; $flags = 0x00; foreach ($flagsArray as $flag) { $flags |= $flag; } } // check that visibility is one of three $this->flags = $flags; return $this; } /** * @param int $flag * @return self */ public function addFlag($flag) { $this->setFlags($this->flags | $flag); return $this; } /** * @param int $flag * @return self */ public function removeFlag($flag) { $this->setFlags($this->flags & ~$flag); return $this; } /** * @param bool $isAbstract * @return self */ public function setAbstract($isAbstract) { return $isAbstract ? $this->addFlag(self::FLAG_ABSTRACT) : $this->removeFlag(self::FLAG_ABSTRACT); } /** * @return bool */ public function isAbstract() { return (bool) ($this->flags & self::FLAG_ABSTRACT); } /** * @param bool $isFinal * @return self */ public function setFinal($isFinal) { return $isFinal ? $this->addFlag(self::FLAG_FINAL) : $this->removeFlag(self::FLAG_FINAL); } /** * @return bool */ public function isFinal() { return (bool) ($this->flags & self::FLAG_FINAL); } /** * @param ?string $extendedClass * @psalm-param ?class-string $extendedClass * @return self */ public function setExtendedClass($extendedClass) { $this->extendedClass = $extendedClass; return $this; } /** * @return ?string * @psalm-return ?class-string */ public function getExtendedClass() { return $this->extendedClass; } /** * @return bool */ public function hasExtentedClass() { return ! empty($this->extendedClass); } /** * @return self */ public function removeExtentedClass() { $this->setExtendedClass(null); return $this; } /** * @param string[] $implementedInterfaces * @psalm-param array $implementedInterfaces * @return self */ public function setImplementedInterfaces(array $implementedInterfaces) { array_map(function ($implementedInterface) { // This loop is just validating that the given `$implementedInterfaces` contains valid syntax/symbols return TypeGenerator::fromTypeString($implementedInterface); }, $implementedInterfaces); $this->implementedInterfaces = $implementedInterfaces; return $this; } /** * @return string[] * @psalm-return array */ public function getImplementedInterfaces() { return $this->implementedInterfaces; } /** * @param string $implementedInterface * @psalm-param class-string $implementedInterface * @return bool */ public function hasImplementedInterface($implementedInterface) { $interfaceType = TypeGenerator::fromTypeString($implementedInterface); return (bool) array_filter( array_map([TypeGenerator::class, 'fromTypeString'], $this->implementedInterfaces), static fn (TypeGenerator $interface): bool => $interfaceType->equals($interface) ); } /** * @param string $implementedInterface * @psalm-param class-string $implementedInterface * @return self */ public function removeImplementedInterface($implementedInterface) { $interfaceType = TypeGenerator::fromTypeString($implementedInterface); $this->implementedInterfaces = array_filter( $this->implementedInterfaces, static fn (string $interface): bool => ! TypeGenerator::fromTypeString($interface)->equals($interfaceType) ); return $this; } /** * @param string $constantName * @return PropertyGenerator|false */ public function getConstant($constantName) { if (isset($this->constants[$constantName])) { return $this->constants[$constantName]; } return false; } /** * @return PropertyGenerator[] indexed by constant name */ public function getConstants() { return $this->constants; } /** * @param string $constantName * @return self */ public function removeConstant($constantName) { unset($this->constants[$constantName]); return $this; } /** * @param string $constantName * @return bool */ public function hasConstant($constantName) { return isset($this->constants[$constantName]); } /** * Add constant from PropertyGenerator * * @throws Exception\InvalidArgumentException * @return self */ public function addConstantFromGenerator(PropertyGenerator $constant) { $constantName = $constant->getName(); if (isset($this->constants[$constantName])) { throw new Exception\InvalidArgumentException(sprintf( 'A constant by name %s already exists in this class.', $constantName )); } if (! $constant->isConst()) { throw new Exception\InvalidArgumentException(sprintf( 'The value %s is not defined as a constant.', $constantName )); } $this->constants[$constantName] = $constant; return $this; } /** * Add Constant * * @param string $name Non-empty string * @param string|int|null|float|array $value Scalar * @throws Exception\InvalidArgumentException * @return self */ public function addConstant($name, $value) { if (empty($name) || ! is_string($name)) { throw new Exception\InvalidArgumentException(sprintf( '%s expects string for name', __METHOD__ )); } $this->validateConstantValue($value); return $this->addConstantFromGenerator( new PropertyGenerator($name, new PropertyValueGenerator($value), PropertyGenerator::FLAG_CONSTANT) ); } /** * @param PropertyGenerator[]|array[] $constants * @return self */ public function addConstants(array $constants) { foreach ($constants as $constant) { if ($constant instanceof PropertyGenerator) { $this->addPropertyFromGenerator($constant); } else { if (is_array($constant)) { $this->addConstant(...array_values($constant)); } } } return $this; } /** * @param PropertyGenerator[]|string[]|array[] $properties * @return self */ public function addProperties(array $properties) { foreach ($properties as $property) { if ($property instanceof PropertyGenerator) { $this->addPropertyFromGenerator($property); } elseif (is_string($property)) { $this->addProperty($property); } else { $this->addProperty(...array_values($property)); } } return $this; } /** * Add Property from scalars * * @param string $name * @param string|array $defaultValue * @param int $flags * @throws Exception\InvalidArgumentException * @return self */ public function addProperty($name, $defaultValue = null, $flags = PropertyGenerator::FLAG_PUBLIC) { if (! is_string($name)) { throw new Exception\InvalidArgumentException(sprintf( '%s::%s expects string for name', static::class, __FUNCTION__ )); } // backwards compatibility // @todo remove this on next major version if ($flags === PropertyGenerator::FLAG_CONSTANT) { return $this->addConstant($name, $defaultValue); } return $this->addPropertyFromGenerator(new PropertyGenerator($name, $defaultValue, $flags)); } /** * Add property from PropertyGenerator * * @throws Exception\InvalidArgumentException * @return self */ public function addPropertyFromGenerator(PropertyGenerator $property) { $propertyName = $property->getName(); if (isset($this->properties[$propertyName])) { throw new Exception\InvalidArgumentException(sprintf( 'A property by name %s already exists in this class.', $propertyName )); } // backwards compatibility // @todo remove this on next major version if ($property->isConst()) { return $this->addConstantFromGenerator($property); } $this->properties[$propertyName] = $property; return $this; } /** * @return PropertyGenerator[] */ public function getProperties() { return $this->properties; } /** * @param string $propertyName * @return PropertyGenerator|false */ public function getProperty($propertyName) { foreach ($this->getProperties() as $property) { if ($property->getName() == $propertyName) { return $property; } } return false; } /** * Add a class to "use" classes * * @param string $use * @param string|null $useAlias * @return self */ public function addUse($use, $useAlias = null) { $this->traitUsageGenerator->addUse($use, $useAlias); return $this; } /** * @param string $use * @return bool */ public function hasUse($use) { return $this->traitUsageGenerator->hasUse($use); } /** * @param string $use * @return self */ public function removeUse($use) { $this->traitUsageGenerator->removeUse($use); return $this; } /** * @param string $use * @return bool */ public function hasUseAlias($use) { return $this->traitUsageGenerator->hasUseAlias($use); } /** * @param string $use * @return self */ public function removeUseAlias($use) { $this->traitUsageGenerator->removeUseAlias($use); return $this; } /** * Returns the "use" classes * * @return array */ public function getUses() { return $this->traitUsageGenerator->getUses(); } /** * @param string $propertyName * @return self */ public function removeProperty($propertyName) { unset($this->properties[$propertyName]); return $this; } /** * @param string $propertyName * @return bool */ public function hasProperty($propertyName) { return isset($this->properties[$propertyName]); } /** * @param MethodGenerator[]|string[]|array[] $methods * @return self */ public function addMethods(array $methods) { foreach ($methods as $method) { if ($method instanceof MethodGenerator) { $this->addMethodFromGenerator($method); } elseif (is_string($method)) { $this->addMethod($method); } else { $this->addMethod(...array_values($method)); } } return $this; } /** * Add Method from scalars * * @param string $name * @param ParameterGenerator[]|array[]|string[] $parameters * @param int $flags * @param string $body * @param string $docBlock * @throws Exception\InvalidArgumentException * @return self */ public function addMethod( $name, array $parameters = [], $flags = MethodGenerator::FLAG_PUBLIC, $body = null, $docBlock = null ) { if (! is_string($name)) { throw new Exception\InvalidArgumentException(sprintf( '%s::%s expects string for name', static::class, __FUNCTION__ )); } return $this->addMethodFromGenerator(new MethodGenerator($name, $parameters, $flags, $body, $docBlock)); } /** * Add Method from MethodGenerator * * @throws Exception\InvalidArgumentException * @return self */ public function addMethodFromGenerator(MethodGenerator $method) { $methodName = $method->getName(); if ($this->hasMethod($methodName)) { throw new Exception\InvalidArgumentException(sprintf( 'A method by name %s already exists in this class.', $methodName )); } $this->methods[strtolower($methodName)] = $method; return $this; } /** * @return MethodGenerator[] */ public function getMethods() { return $this->methods; } /** * @param string $methodName * @return MethodGenerator|false */ public function getMethod($methodName) { return $this->hasMethod($methodName) ? $this->methods[strtolower($methodName)] : false; } /** * @param string $methodName * @return self */ public function removeMethod($methodName) { unset($this->methods[strtolower($methodName)]); return $this; } /** * @param string $methodName * @return bool */ public function hasMethod($methodName) { return isset($this->methods[strtolower($methodName)]); } /** * @inheritDoc */ public function addTrait($trait) { $this->traitUsageGenerator->addTrait($trait); return $this; } /** * @inheritDoc */ public function addTraits(array $traits) { $this->traitUsageGenerator->addTraits($traits); return $this; } /** * @inheritDoc */ public function hasTrait($traitName) { return $this->traitUsageGenerator->hasTrait($traitName); } /** * @inheritDoc */ public function getTraits() { return $this->traitUsageGenerator->getTraits(); } /** * @inheritDoc */ public function removeTrait($traitName) { return $this->traitUsageGenerator->removeTrait($traitName); } /** * @inheritDoc */ public function addTraitAlias($method, $alias, $visibility = null) { $this->traitUsageGenerator->addTraitAlias($method, $alias, $visibility); return $this; } /** * @inheritDoc */ public function getTraitAliases() { return $this->traitUsageGenerator->getTraitAliases(); } /** * @inheritDoc */ public function addTraitOverride($method, $traitsToReplace) { $this->traitUsageGenerator->addTraitOverride($method, $traitsToReplace); return $this; } /** * @inheritDoc */ public function removeTraitOverride($method, $overridesToRemove = null) { $this->traitUsageGenerator->removeTraitOverride($method, $overridesToRemove); return $this; } /** * @inheritDoc */ public function getTraitOverrides() { return $this->traitUsageGenerator->getTraitOverrides(); } /** * @return bool */ public function isSourceDirty() { if (($docBlock = $this->getDocBlock()) && $docBlock->isSourceDirty()) { return true; } foreach ($this->getProperties() as $property) { if ($property->isSourceDirty()) { return true; } } foreach ($this->getMethods() as $method) { if ($method->isSourceDirty()) { return true; } } return parent::isSourceDirty(); } /** * @inheritDoc */ public function generate() { if (! $this->isSourceDirty()) { $output = $this->getSourceContent(); if (! empty($output)) { return $output; } } $indent = $this->getIndentation(); $output = ''; if (null !== ($namespace = $this->getNamespaceName())) { $output .= 'namespace ' . $namespace . ';' . self::LINE_FEED . self::LINE_FEED; } $uses = $this->getUses(); if (! empty($uses)) { foreach ($uses as $use) { $output .= 'use ' . $use . ';' . self::LINE_FEED; } $output .= self::LINE_FEED; } if (null !== ($docBlock = $this->getDocBlock())) { $docBlock->setIndentation(''); $output .= $docBlock->generate(); } if ($this->isAbstract()) { $output .= 'abstract '; } elseif ($this->isFinal()) { $output .= 'final '; } $output .= static::OBJECT_TYPE . ' ' . $this->getName(); if (! empty($this->extendedClass)) { $output .= ' extends ' . $this->generateShortOrCompleteClassname($this->extendedClass); } $implemented = $this->getImplementedInterfaces(); if (! empty($implemented)) { $implemented = array_map([$this, 'generateShortOrCompleteClassname'], $implemented); $output .= ' ' . static::IMPLEMENTS_KEYWORD . ' ' . implode(', ', $implemented); } $output .= self::LINE_FEED . '{' . self::LINE_FEED; $traitUseOutput = rtrim($this->traitUsageGenerator->generate(), self::LINE_FEED); $constants = []; $properties = []; $methods = []; foreach ($this->getConstants() as $constant) { $constants[] = $constant->generate(); } foreach ($this->getProperties() as $property) { $properties[] = $property->generate(); } foreach ($this->getMethods() as $method) { $methods[] = $method->generate(); } $contents = rtrim( implode( self::LINE_FEED . self::LINE_FEED, array_filter([ $traitUseOutput, implode(self::LINE_FEED . self::LINE_FEED, $constants), implode(self::LINE_FEED . self::LINE_FEED, $properties), implode(self::LINE_FEED, $methods), ]) ), self::LINE_FEED ); return $output . $contents . ($contents === '' ? '' : self::LINE_FEED) . '}' . self::LINE_FEED; } /** * @param mixed $value * @return void * @throws Exception\InvalidArgumentException */ private function validateConstantValue($value) { if (null === $value || is_scalar($value)) { return; } if (is_array($value)) { array_walk($value, [$this, 'validateConstantValue']); return; } throw new Exception\InvalidArgumentException(sprintf( 'Expected value for constant, value must be a "scalar" or "null", "%s" found', gettype($value) )); } /** * @param string $fqnClassName * @return string */ private function generateShortOrCompleteClassname($fqnClassName) { $fqnClassName = ltrim($fqnClassName, '\\'); $parts = explode('\\', $fqnClassName); $className = array_pop($parts); $classNamespace = implode('\\', $parts); $currentNamespace = (string) $this->getNamespaceName(); if ($this->hasUseAlias($fqnClassName)) { return $this->traitUsageGenerator->getUseAlias($fqnClassName); } if ($this->hasUseAlias($classNamespace)) { $namespaceAlias = $this->traitUsageGenerator->getUseAlias($classNamespace); return $namespaceAlias . '\\' . $className; } if ($this->traitUsageGenerator->isUseAlias($fqnClassName)) { return $fqnClassName; } if ($this->traitUsageGenerator->isUseAlias($classNamespace)) { return $fqnClassName; } if ($classNamespace === $currentNamespace || in_array($fqnClassName, $this->getUses())) { return $className; } return '\\' . $fqnClassName; } } src/Generator/DocBlock/Tag.php000064400000002151144760112670012174 0ustar00initializeDefaultTags(); return $tagManager->createTagFromReflection($reflectionTag); } /** * @deprecated Deprecated in 2.3. Use GenericTag::setContent() instead * * @param string $description * @return Tag */ public function setDescription($description) { return $this->setContent($description); } /** * @deprecated Deprecated in 2.3. Use GenericTag::getContent() instead * * @return string */ public function getDescription() { return $this->getContent(); } } src/Generator/DocBlock/Tag/AbstractTypeableTag.php000064400000003546144760112670016072 0ustar00setTypes($types); } if (! empty($description)) { $this->setDescription($description); } } /** * @param string $description * @return AbstractTypeableTag */ public function setDescription($description) { $this->description = $description; return $this; } /** * @return string */ public function getDescription() { return $this->description; } /** * Array of types or string with types delimited by pipe (|) * e.g. array('int', 'null') or "int|null" * * @param array|string $types * @return AbstractTypeableTag */ public function setTypes($types) { if (is_string($types)) { $types = explode('|', $types); } $this->types = $types; return $this; } /** * @return array */ public function getTypes() { return $this->types; } /** * @param string $delimiter * @return string */ public function getTypesAsString($delimiter = '|') { return implode($delimiter, $this->types); } } src/Generator/DocBlock/Tag/AuthorTag.php000064400000004161144760112670014075 0ustar00setAuthorName($authorName); } if (! empty($authorEmail)) { $this->setAuthorEmail($authorEmail); } } /** * @deprecated Deprecated in 2.3. Use TagManager::createTagFromReflection() instead * * @return AuthorTag */ public static function fromReflection(ReflectionTagInterface $reflectionTag) { $tagManager = new TagManager(); $tagManager->initializeDefaultTags(); return $tagManager->createTagFromReflection($reflectionTag); } /** * @return string */ public function getName() { return 'author'; } /** * @param string $authorEmail * @return AuthorTag */ public function setAuthorEmail($authorEmail) { $this->authorEmail = $authorEmail; return $this; } /** * @return string */ public function getAuthorEmail() { return $this->authorEmail; } /** * @param string $authorName * @return AuthorTag */ public function setAuthorName($authorName) { $this->authorName = $authorName; return $this; } /** * @return string */ public function getAuthorName() { return $this->authorName; } /** * @return string */ public function generate() { return '@author' . (! empty($this->authorName) ? ' ' . $this->authorName : '') . (! empty($this->authorEmail) ? ' <' . $this->authorEmail . '>' : ''); } } src/Generator/DocBlock/Tag/GenericTag.php000064400000002660144760112670014211 0ustar00setName($name); } if (! empty($content)) { $this->setContent($content); } } /** * @param string $name * @return GenericTag */ public function setName($name) { $this->name = ltrim($name, '@'); return $this; } /** * @return string */ public function getName() { return $this->name; } /** * @param string $content * @return GenericTag */ public function setContent($content) { $this->content = $content; return $this; } /** * @return string */ public function getContent() { return $this->content; } /** * @return string */ public function generate() { return '@' . $this->name . (! empty($this->content) ? ' ' . $this->content : ''); } } src/Generator/DocBlock/Tag/LicenseTag.php000064400000003762144760112670014223 0ustar00setUrl($url); } if (! empty($licenseName)) { $this->setLicenseName($licenseName); } } /** * @deprecated Deprecated in 2.3. Use TagManager::createTagFromReflection() instead * * @return ReturnTag */ public static function fromReflection(ReflectionTagInterface $reflectionTag) { $tagManager = new TagManager(); $tagManager->initializeDefaultTags(); return $tagManager->createTagFromReflection($reflectionTag); } /** * @return string */ public function getName() { return 'license'; } /** * @param string $url * @return LicenseTag */ public function setUrl($url) { $this->url = $url; return $this; } /** * @return string */ public function getUrl() { return $this->url; } /** * @param string $name * @return LicenseTag */ public function setLicenseName($name) { $this->licenseName = $name; return $this; } /** * @return string */ public function getLicenseName() { return $this->licenseName; } /** * @return string */ public function generate() { return '@license' . (! empty($this->url) ? ' ' . $this->url : '') . (! empty($this->licenseName) ? ' ' . $this->licenseName : ''); } } src/Generator/DocBlock/Tag/MethodTag.php000064400000003443144760112670014055 0ustar00setMethodName($methodName); } $this->setIsStatic((bool) $isStatic); parent::__construct($types, $description); } /** * @return string */ public function getName() { return 'method'; } /** * @param bool $isStatic * @return MethodTag */ public function setIsStatic($isStatic) { $this->isStatic = $isStatic; return $this; } /** * @return bool */ public function isStatic() { return $this->isStatic; } /** * @param string $methodName * @return MethodTag */ public function setMethodName($methodName) { $this->methodName = rtrim($methodName, ')('); return $this; } /** * @return string */ public function getMethodName() { return $this->methodName; } /** * @return string */ public function generate() { return '@method' . ($this->isStatic ? ' static' : '') . (! empty($this->types) ? ' ' . $this->getTypesAsString() : '') . (! empty($this->methodName) ? ' ' . $this->methodName . '()' : '') . (! empty($this->description) ? ' ' . $this->description : ''); } } src/Generator/DocBlock/Tag/ParamTag.php000064400000005332144760112670013674 0ustar00setVariableName($variableName); } parent::__construct($types, $description); } /** * @deprecated Deprecated in 2.3. Use TagManager::createTagFromReflection() instead * * @return ParamTag */ public static function fromReflection(ReflectionTagInterface $reflectionTag) { $tagManager = new TagManager(); $tagManager->initializeDefaultTags(); return $tagManager->createTagFromReflection($reflectionTag); } /** * @return string */ public function getName() { return 'param'; } /** * @param string $variableName * @return ParamTag */ public function setVariableName($variableName) { $this->variableName = ltrim($variableName, '$'); return $this; } /** * @return string */ public function getVariableName() { return $this->variableName; } /** * @deprecated Deprecated in 2.3. Use setTypes() instead * * @param string $datatype * @return ParamTag */ public function setDatatype($datatype) { return $this->setTypes($datatype); } /** * @deprecated Deprecated in 2.3. Use getTypes() or getTypesAsString() instead * * @return string */ public function getDatatype() { return $this->getTypesAsString(); } /** * @deprecated Deprecated in 2.3. Use setVariableName() instead * * @param string $paramName * @return ParamTag */ public function setParamName($paramName) { return $this->setVariableName($paramName); } /** * @deprecated Deprecated in 2.3. Use getVariableName() instead * * @return string */ public function getParamName() { return $this->getVariableName(); } /** * @return string */ public function generate() { return '@param' . (! empty($this->types) ? ' ' . $this->getTypesAsString() : '') . (! empty($this->variableName) ? ' $' . $this->variableName : '') . (! empty($this->description) ? ' ' . $this->description : ''); } } src/Generator/DocBlock/Tag/PropertyTag.php000064400000002513144760112670014456 0ustar00setPropertyName($propertyName); } parent::__construct($types, $description); } /** * @return string */ public function getName() { return 'property'; } /** * @param string $propertyName * @return self */ public function setPropertyName($propertyName) { $this->propertyName = ltrim($propertyName, '$'); return $this; } /** * @return string */ public function getPropertyName() { return $this->propertyName; } /** * @return string */ public function generate() { return '@property' . (! empty($this->types) ? ' ' . $this->getTypesAsString() : '') . (! empty($this->propertyName) ? ' $' . $this->propertyName : '') . (! empty($this->description) ? ' ' . $this->description : ''); } } src/Generator/DocBlock/Tag/ReturnTag.php000064400000002614144760112670014113 0ustar00initializeDefaultTags(); return $tagManager->createTagFromReflection($reflectionTag); } /** * @return string */ public function getName() { return 'return'; } /** * @deprecated Deprecated in 2.3. Use setTypes() instead * * @param string $datatype * @return ReturnTag */ public function setDatatype($datatype) { return $this->setTypes($datatype); } /** * @deprecated Deprecated in 2.3. Use getTypes() or getTypesAsString() instead * * @return string */ public function getDatatype() { return $this->getTypesAsString(); } /** * @return string */ public function generate() { return '@return ' . $this->getTypesAsString() . (! empty($this->description) ? ' ' . $this->description : ''); } } src/Generator/DocBlock/Tag/TagInterface.php000064400000000245144760112670014532 0ustar00types) ? ' ' . $this->getTypesAsString() : '') . (! empty($this->description) ? ' ' . $this->description : ''); } } src/Generator/DocBlock/Tag/VarTag.php000064400000002655144760112670013371 0ustar00variableName = ltrim($variableName, '$'); } parent::__construct($types, $description); } /** * {@inheritDoc} */ public function getName(): string { return 'var'; } /** * @internal this code is only public for compatibility with the * * @see \Laminas\Code\Generator\DocBlock\TagManager, which * uses setters */ public function setVariableName(?string $variableName): void { if (null !== $variableName) { $this->variableName = ltrim($variableName, '$'); } } public function getVariableName(): ?string { return $this->variableName; } /** * {@inheritDoc} */ public function generate(): string { return '@var' . (! empty($this->types) ? ' ' . $this->getTypesAsString() : '') . (null !== $this->variableName ? ' $' . $this->variableName : '') . (! empty($this->description) ? ' ' . $this->description : ''); } } src/Generator/DocBlock/TagManager.php000064400000004624144760112670013476 0ustar00addPrototype(new Tag\ParamTag()); $this->addPrototype(new Tag\ReturnTag()); $this->addPrototype(new Tag\MethodTag()); $this->addPrototype(new Tag\PropertyTag()); $this->addPrototype(new Tag\AuthorTag()); $this->addPrototype(new Tag\LicenseTag()); $this->addPrototype(new Tag\ThrowsTag()); $this->addPrototype(new Tag\VarTag()); $this->setGenericPrototype(new Tag\GenericTag()); } /** * @return TagInterface */ public function createTagFromReflection(ReflectionTagInterface $reflectionTag) { $tagName = $reflectionTag->getName(); /** @var TagInterface $newTag */ $newTag = $this->getClonedPrototype($tagName); // transport any properties via accessors and mutators from reflection to codegen object $reflectionClass = new ReflectionClass($reflectionTag); foreach ($reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { if (0 === strpos($method->getName(), 'get')) { $propertyName = substr($method->getName(), 3); if (method_exists($newTag, 'set' . $propertyName)) { $newTag->{'set' . $propertyName}($reflectionTag->{'get' . $propertyName}()); } } elseif (0 === strpos($method->getName(), 'is')) { $propertyName = ucfirst($method->getName()); if (method_exists($newTag, 'set' . $propertyName)) { $newTag->{'set' . $propertyName}($reflectionTag->{$method->getName()}()); } } } return $newTag; } } src/Generator/DocBlockGenerator.php000064400000015262144760112670013337 0ustar00setSourceContent($reflectionDocBlock->getContents()); $docBlock->setSourceDirty(false); $docBlock->setShortDescription($reflectionDocBlock->getShortDescription()); $docBlock->setLongDescription($reflectionDocBlock->getLongDescription()); foreach ($reflectionDocBlock->getTags() as $tag) { $docBlock->setTag(self::getTagManager()->createTagFromReflection($tag)); } return $docBlock; } /** * Generate from array * * @configkey shortdescription string The short description for this doc block * @configkey longdescription string The long description for this doc block * @configkey tags array * @throws Exception\InvalidArgumentException * @param array $array * @return DocBlockGenerator */ public static function fromArray(array $array) { $docBlock = new static(); foreach ($array as $name => $value) { // normalize key switch (strtolower(str_replace(['.', '-', '_'], '', $name))) { case 'shortdescription': $docBlock->setShortDescription($value); break; case 'longdescription': $docBlock->setLongDescription($value); break; case 'tags': $docBlock->setTags($value); break; } } return $docBlock; } /** * @return TagManager */ protected static function getTagManager() { if (! isset(static::$tagManager)) { static::$tagManager = new TagManager(); static::$tagManager->initializeDefaultTags(); } return static::$tagManager; } /** * @param ?string $shortDescription * @param ?string $longDescription * @param array[]|TagInterface[] $tags */ public function __construct($shortDescription = null, $longDescription = null, array $tags = []) { if ($shortDescription) { $this->setShortDescription($shortDescription); } if ($longDescription) { $this->setLongDescription($longDescription); } if ($tags) { $this->setTags($tags); } } /** * @param string $shortDescription * @return DocBlockGenerator */ public function setShortDescription($shortDescription) { $this->shortDescription = $shortDescription; return $this; } /** * @return string */ public function getShortDescription() { return $this->shortDescription; } /** * @param string $longDescription * @return DocBlockGenerator */ public function setLongDescription($longDescription) { $this->longDescription = $longDescription; return $this; } /** * @return string */ public function getLongDescription() { return $this->longDescription; } /** * @param array[]|TagInterface[] $tags * @return DocBlockGenerator */ public function setTags(array $tags) { foreach ($tags as $tag) { $this->setTag($tag); } return $this; } /** * @param array|TagInterface $tag * @throws Exception\InvalidArgumentException * @return DocBlockGenerator */ public function setTag($tag) { if (is_array($tag)) { // use deprecated Tag class for backward compatibility to old array-keys $genericTag = new Tag(); $genericTag->setOptions($tag); $tag = $genericTag; } elseif (! $tag instanceof TagInterface) { throw new Exception\InvalidArgumentException(sprintf( '%s expects either an array of method options or an instance of %s\DocBlock\Tag\TagInterface', __METHOD__, __NAMESPACE__ )); } $this->tags[] = $tag; return $this; } /** * @return TagInterface[] */ public function getTags() { return $this->tags; } /** * @param bool $value * @return DocBlockGenerator */ public function setWordWrap($value) { $this->wordwrap = (bool) $value; return $this; } /** * @return bool */ public function getWordWrap() { return $this->wordwrap; } /** * @return string */ public function generate() { if (! $this->isSourceDirty()) { return $this->docCommentize(trim($this->getSourceContent() ?? '')); } $output = ''; if ($sd = $this->getShortDescription()) { $output .= $sd . self::LINE_FEED . self::LINE_FEED; } if ($ld = $this->getLongDescription()) { $output .= $ld . self::LINE_FEED . self::LINE_FEED; } /** @var GeneratorInterface $tag */ foreach ($this->getTags() as $tag) { $output .= $tag->generate() . self::LINE_FEED; } return $this->docCommentize(trim($output)); } /** * @param string $content * @return string */ protected function docCommentize($content) { $indent = $this->getIndentation(); $output = $indent . '/**' . self::LINE_FEED; $content = $this->getWordWrap() == true ? wordwrap($content, 80, self::LINE_FEED) : $content; $lines = explode(self::LINE_FEED, $content); foreach ($lines as $line) { $output .= $indent . ' *'; if ($line) { $output .= ' ' . $line; } $output .= self::LINE_FEED; } $output .= $indent . ' */' . self::LINE_FEED; return $output; } } src/Generator/Exception/ClassNotFoundException.php000064400000000220144760112670016333 0ustar00 */ protected array $uses = []; /** * @var ClassGenerator[] * @psalm-var array */ protected array $classes = []; protected string $body = ''; /** * @var DeclareStatement[] * @psalm-var array */ protected array $declares = []; /** * Passes $options to {@link setOptions()}. * * @param array|Traversable|null $options */ public function __construct($options = null) { if (null !== $options) { $this->setOptions($options); } } /** * @param array $values * @return FileGenerator */ public static function fromArray(array $values) { $fileGenerator = new static(); foreach ($values as $name => $value) { switch (strtolower(str_replace(['.', '-', '_'], '', $name))) { case 'filename': $fileGenerator->setFilename($value); break; case 'class': $fileGenerator->setClass( $value instanceof ClassGenerator ? $value : ClassGenerator::fromArray($value) ); break; case 'requiredfiles': $fileGenerator->setRequiredFiles($value); break; case 'declares': $fileGenerator->setDeclares(array_map(static function ($directive, $value) { return DeclareStatement::fromArray([$directive => $value]); }, array_keys($value), $value)); break; default: if (property_exists($fileGenerator, $name)) { $fileGenerator->{$name} = $value; } elseif (method_exists($fileGenerator, 'set' . $name)) { $fileGenerator->{'set' . $name}($value); } } } return $fileGenerator; } /** * @param DocBlockGenerator|array|string $docBlock * @throws Exception\InvalidArgumentException * @return FileGenerator */ public function setDocBlock($docBlock) { if (is_string($docBlock)) { $docBlock = ['shortDescription' => $docBlock]; } if (is_array($docBlock)) { $docBlock = new DocBlockGenerator($docBlock); } elseif (! $docBlock instanceof DocBlockGenerator) { throw new Exception\InvalidArgumentException(sprintf( '%s is expecting either a string, array or an instance of %s\DocBlockGenerator', __METHOD__, __NAMESPACE__ )); } $this->docBlock = $docBlock; return $this; } /** * @return ?DocBlockGenerator */ public function getDocBlock() { return $this->docBlock; } /** * @param string[] $requiredFiles * @return FileGenerator */ public function setRequiredFiles(array $requiredFiles) { $this->requiredFiles = $requiredFiles; return $this; } /** * @return string[] */ public function getRequiredFiles() { return $this->requiredFiles; } /** * @return string */ public function getNamespace() { return $this->namespace; } /** * @param string $namespace * @return FileGenerator */ public function setNamespace($namespace) { $this->namespace = (string) $namespace; return $this; } /** * Returns an array with the first element the use statement, second is the as part. * If $withResolvedAs is set to true, there will be a third element that is the * "resolved" as statement, as the second part is not required in use statements * * @param bool $withResolvedAs * @return array * @psalm-return array */ public function getUses($withResolvedAs = false) { $uses = $this->uses; if ($withResolvedAs) { for ($useIndex = 0, $count = count($uses); $useIndex < $count; $useIndex++) { if ($uses[$useIndex][1] == '') { if (($lastSeparator = strrpos($uses[$useIndex][0], '\\')) !== false) { $uses[$useIndex][2] = substr($uses[$useIndex][0], $lastSeparator + 1); } else { $uses[$useIndex][2] = $uses[$useIndex][0]; } } else { $uses[$useIndex][2] = $uses[$useIndex][1]; } } } return $uses; } /** * @param array $uses * @return FileGenerator */ public function setUses(array $uses) { foreach ($uses as $use) { $use = (array) $use; if (array_key_exists('use', $use) && array_key_exists('as', $use)) { $import = $use['use']; $alias = $use['as']; } elseif (count($use) == 2) { [$import, $alias] = $use; } else { $import = current($use); $alias = null; } $this->setUse($import, $alias); } return $this; } /** * @param string $use * @param null|string $as * @return FileGenerator */ public function setUse($use, $as = null) { if (! in_array([$use, $as], $this->uses)) { $this->uses[] = [$use, $as]; } return $this; } /** * @param array[]|string[]|ClassGenerator[] $classes * @return FileGenerator */ public function setClasses(array $classes) { foreach ($classes as $class) { $this->setClass($class); } return $this; } /** * @param string|null $name * @return ClassGenerator * @throws ClassNotFoundException */ public function getClass($name = null) { if ($name === null) { reset($this->classes); $class = current($this->classes); if (false === $class) { throw new ClassNotFoundException('No class is set'); } return $class; } if (false === array_key_exists($name, $this->classes)) { throw new ClassNotFoundException(sprintf('Class %s is not set', $name)); } return $this->classes[$name]; } /** * @param array|string|ClassGenerator $class * @throws Exception\InvalidArgumentException * @return FileGenerator */ public function setClass($class) { if (is_array($class)) { $class = ClassGenerator::fromArray($class); } elseif (is_string($class)) { $class = new ClassGenerator($class); } elseif (! $class instanceof ClassGenerator) { throw new Exception\InvalidArgumentException(sprintf( '%s is expecting either a string, array or an instance of %s\ClassGenerator', __METHOD__, __NAMESPACE__ )); } // @todo check for dup here $className = $class->getName(); $this->classes[$className] = $class; return $this; } /** * @param string $filename * @return FileGenerator */ public function setFilename($filename) { $this->filename = (string) $filename; return $this; } /** * @return string */ public function getFilename() { return $this->filename; } /** * @return ClassGenerator[] */ public function getClasses() { return $this->classes; } /** * @param string $body * @return FileGenerator */ public function setBody($body) { $this->body = (string) $body; return $this; } /** * @return string */ public function getBody() { return $this->body; } /** * @param DeclareStatement[] $declares * @return static */ public function setDeclares(array $declares) { foreach ($declares as $declare) { /** @psalm-suppress DocblockTypeContradiction $declare should be always DeclareStatement */ if (! $declare instanceof DeclareStatement) { throw new InvalidArgumentException(sprintf( '%s is expecting an array of %s objects', __METHOD__, DeclareStatement::class )); } if (! array_key_exists($declare->getDirective(), $this->declares)) { $this->declares[$declare->getDirective()] = $declare; } } return $this; } /** * @return bool */ public function isSourceDirty() { $docBlock = $this->getDocBlock(); if ($docBlock && $docBlock->isSourceDirty()) { return true; } foreach ($this->classes as $class) { if ($class->isSourceDirty()) { return true; } } return parent::isSourceDirty(); } /** * @return string */ public function generate() { if ($this->isSourceDirty() === false) { return $this->sourceContent ?? ''; } $output = ''; // @note body gets populated when FileGenerator created // from a file. @see fromReflection and may also be set // via FileGenerator::setBody $body = $this->getBody(); // start with the body (if there), or open tag if (preg_match('#(?:\s*)<\?php#', $body) == false) { $output = 'getDocBlock())) { $docBlock->setIndentation(''); if (preg_match('#/\* Laminas_Code_Generator_FileGenerator-DocBlockMarker \*/#m', $output)) { // @codingStandardsIgnoreStart $output = preg_replace('#/\* Laminas_Code_Generator_FileGenerator-DocBlockMarker \*/#m', $docBlock->generate(), $output, 1); // @codingStandardsIgnoreEnd } else { $output .= $docBlock->generate() . self::LINE_FEED; } } // newline $output .= self::LINE_FEED; // declares, if any if ($this->declares) { $declareStatements = ''; foreach ($this->declares as $declare) { $declareStatements .= $declare->getStatement() . self::LINE_FEED; } if (preg_match('#/\* Laminas_Code_Generator_FileGenerator-DeclaresMarker \*/#m', $output)) { $output = preg_replace( '#/\* Laminas_Code_Generator_FileGenerator-DeclaresMarker \*/#m', $declareStatements, $output, 1 ); } else { $output .= $declareStatements; } $output .= self::LINE_FEED; } // namespace, if any $namespace = $this->getNamespace(); if ($namespace) { $namespace = sprintf('namespace %s;%s', $namespace, str_repeat(self::LINE_FEED, 2)); if (preg_match('#/\* Laminas_Code_Generator_FileGenerator-NamespaceMarker \*/#m', $output)) { $output = preg_replace( '#/\* Laminas_Code_Generator_FileGenerator-NamespaceMarker \*/#m', $namespace, $output, 1 ); } else { $output .= $namespace; } } // process required files // @todo marker replacement for required files $requiredFiles = $this->getRequiredFiles(); if (! empty($requiredFiles)) { foreach ($requiredFiles as $requiredFile) { $output .= 'require_once \'' . $requiredFile . '\';' . self::LINE_FEED; } $output .= self::LINE_FEED; } $classes = $this->getClasses(); $classUses = []; //build uses array foreach ($classes as $class) { //check for duplicate use statements $uses = $class->getUses(); if (! empty($uses) && is_array($uses)) { $classUses = array_merge($classUses, $uses); } } // process import statements $uses = $this->getUses(); if (! empty($uses)) { $useOutput = ''; foreach ($uses as $use) { [$import, $alias] = $use; if (null === $alias) { $tempOutput = sprintf('%s', $import); } else { $tempOutput = sprintf('%s as %s', $import, $alias); } //don't duplicate use statements if (! in_array($tempOutput, $classUses)) { $useOutput .= 'use ' . $tempOutput . ';'; $useOutput .= self::LINE_FEED; } } $useOutput .= self::LINE_FEED; if (preg_match('#/\* Laminas_Code_Generator_FileGenerator-UseMarker \*/#m', $output)) { $output = preg_replace( '#/\* Laminas_Code_Generator_FileGenerator-UseMarker \*/#m', $useOutput, $output, 1 ); } else { $output .= $useOutput; } } // process classes if (! empty($classes)) { foreach ($classes as $class) { // @codingStandardsIgnoreStart $regex = str_replace('&', $class->getName(), '/\* Laminas_Code_Generator_Php_File-ClassMarker: \{[A-Za-z0-9\\\]+?&\} \*/'); // @codingStandardsIgnoreEnd if (preg_match('#' . $regex . '#m', $output)) { $output = preg_replace('#' . $regex . '#', $class->generate(), $output, 1); } else { if ($namespace) { $class->setNamespaceName(null); } $output .= $class->generate() . self::LINE_FEED; } } } if (! empty($body)) { // add an extra space between classes and if (! empty($classes)) { $output .= self::LINE_FEED; } $output .= $body; } return $output; } /** * @return FileGenerator * @throws Exception\RuntimeException */ public function write() { if ($this->filename == '' || ! is_writable(dirname($this->filename))) { throw new Exception\RuntimeException('This code generator object is not writable.'); } file_put_contents($this->filename, $this->generate()); return $this; } } src/Generator/GeneratorInterface.php000064400000000205144760112670013546 0ustar00isInterface()) { throw new Exception\InvalidArgumentException(sprintf( 'Class %s is not a interface', $classReflection->getName() )); } // class generator $cg = new static($classReflection->getName()); $methods = []; $cg->setSourceContent($cg->getSourceContent()); $cg->setSourceDirty(false); if ($classReflection->getDocComment() != '') { $cg->setDocBlock(DocBlockGenerator::fromReflection($classReflection->getDocBlock())); } // set the namespace if ($classReflection->inNamespace()) { $cg->setNamespaceName($classReflection->getNamespaceName()); } foreach ($classReflection->getMethods() as $reflectionMethod) { $className = $cg->getName(); $namespaceName = $cg->getNamespaceName(); if ($namespaceName !== null) { $className = $namespaceName . '\\' . $className; } if ($reflectionMethod->getDeclaringClass()->getName() == $className) { $methods[] = MethodGenerator::fromReflection($reflectionMethod); } } foreach ($classReflection->getConstants() as $name => $value) { $cg->addConstant($name, $value); } $cg->addMethods($methods); return $cg; } /** * Generate from array * * @configkey name string [required] Class Name * @configkey filegenerator FileGenerator File generator that holds this class * @configkey namespacename string The namespace for this class * @configkey docblock string The docblock information * @configkey constants * @configkey methods * @throws Exception\InvalidArgumentException * @param array $array * @return InterfaceGenerator */ public static function fromArray(array $array) { if (! isset($array['name'])) { throw new Exception\InvalidArgumentException( 'Class generator requires that a name is provided for this object' ); } $cg = new static($array['name']); foreach ($array as $name => $value) { // normalize key switch (strtolower(str_replace(['.', '-', '_'], '', $name))) { case 'containingfile': $cg->setContainingFileGenerator($value); break; case 'namespacename': $cg->setNamespaceName($value); break; case 'docblock': $docBlock = $value instanceof DocBlockGenerator ? $value : DocBlockGenerator::fromArray($value); $cg->setDocBlock($docBlock); break; case 'methods': $cg->addMethods($value); break; case 'constants': $cg->addConstants($value); break; } } return $cg; } /** * {@inheritDoc} */ public function addPropertyFromGenerator(PropertyGenerator $property) { return $this; } /** * {@inheritDoc} */ public function addMethodFromGenerator(MethodGenerator $method) { $method->setInterface(true); return parent::addMethodFromGenerator($method); } /** * {@inheritDoc} */ public function setExtendedClass($extendedClass) { return $this; } /** * {@inheritDoc} */ public function setAbstract($isAbstract) { return $this; } } src/Generator/MethodGenerator.php000064400000025512144760112670013076 0ustar00setSourceContent($reflectionMethod->getContents(false)); $method->setSourceDirty(false); if ($reflectionMethod->getDocComment() != '') { $method->setDocBlock(DocBlockGenerator::fromReflection($reflectionMethod->getDocBlock())); } $method->setBody(static::clearBodyIndention($reflectionMethod->getBody())); return $method; } /** * Returns a MethodGenerator based on a MethodReflection with only the signature copied. * * This is similar to fromReflection() but without the method body and phpdoc as this is quite heavy to copy. * It's for example useful when creating proxies where you normally change the method body anyway. */ public static function copyMethodSignature(MethodReflection $reflectionMethod): MethodGenerator { $method = new static(); $declaringClass = $reflectionMethod->getDeclaringClass(); $method->returnType = TypeGenerator::fromReflectionType($reflectionMethod->getReturnType(), $declaringClass); $method->setFinal($reflectionMethod->isFinal()); if ($reflectionMethod->isPrivate()) { $method->setVisibility(self::VISIBILITY_PRIVATE); } elseif ($reflectionMethod->isProtected()) { $method->setVisibility(self::VISIBILITY_PROTECTED); } else { $method->setVisibility(self::VISIBILITY_PUBLIC); } $method->setInterface($declaringClass->isInterface()); $method->setStatic($reflectionMethod->isStatic()); $method->setReturnsReference($reflectionMethod->returnsReference()); $method->setName($reflectionMethod->getName()); foreach ($reflectionMethod->getParameters() as $reflectionParameter) { $method->setParameter(ParameterGenerator::fromReflection($reflectionParameter)); } return $method; } /** * Identify the space indention from the first line and remove this indention * from all lines * * @param string $body * @return string */ protected static function clearBodyIndention($body) { if (empty($body)) { return $body; } $lines = explode("\n", $body); $indention = str_replace(trim($lines[1]), '', $lines[1]); foreach ($lines as $key => $line) { if (substr($line, 0, strlen($indention)) == $indention) { $lines[$key] = substr($line, strlen($indention)); } } $body = implode("\n", $lines); return $body; } /** * Generate from array * * @configkey name string [required] Class Name * @configkey docblock string The docblock information * @configkey flags int Flags, one of MethodGenerator::FLAG_ABSTRACT MethodGenerator::FLAG_FINAL * @configkey parameters string Class which this class is extending * @configkey body string * @configkey abstract bool * @configkey final bool * @configkey static bool * @configkey visibility string * @throws Exception\InvalidArgumentException * @param array $array * @return MethodGenerator */ public static function fromArray(array $array) { if (! isset($array['name'])) { throw new Exception\InvalidArgumentException( 'Method generator requires that a name is provided for this object' ); } $method = new static($array['name']); foreach ($array as $name => $value) { // normalize key switch (strtolower(str_replace(['.', '-', '_'], '', $name))) { case 'docblock': $docBlock = $value instanceof DocBlockGenerator ? $value : DocBlockGenerator::fromArray($value); $method->setDocBlock($docBlock); break; case 'flags': $method->setFlags($value); break; case 'parameters': $method->setParameters($value); break; case 'body': $method->setBody($value); break; case 'abstract': $method->setAbstract($value); break; case 'final': $method->setFinal($value); break; case 'interface': $method->setInterface($value); break; case 'static': $method->setStatic($value); break; case 'visibility': $method->setVisibility($value); break; case 'returntype': $method->setReturnType($value); break; } } return $method; } /** * @param ?string $name * @param ParameterGenerator[]|array[]|string[] $parameters * @param int|int[] $flags * @param ?string $body * @param DocBlockGenerator|string|null $docBlock */ public function __construct( $name = null, array $parameters = [], $flags = self::FLAG_PUBLIC, $body = null, $docBlock = null ) { if ($name) { $this->setName($name); } if ($parameters) { $this->setParameters($parameters); } if ($flags !== self::FLAG_PUBLIC) { $this->setFlags($flags); } if ($body) { $this->setBody($body); } if ($docBlock) { $this->setDocBlock($docBlock); } } /** * @param ParameterGenerator[]|array[]|string[] $parameters * @return MethodGenerator */ public function setParameters(array $parameters) { foreach ($parameters as $parameter) { $this->setParameter($parameter); } $this->sortParameters(); return $this; } /** * @param ParameterGenerator|array|string $parameter * @throws Exception\InvalidArgumentException * @return MethodGenerator */ public function setParameter($parameter) { if (is_string($parameter)) { $parameter = new ParameterGenerator($parameter); } if (is_array($parameter)) { $parameter = ParameterGenerator::fromArray($parameter); } if (! $parameter instanceof ParameterGenerator) { throw new Exception\InvalidArgumentException(sprintf( '%s is expecting either a string, array or an instance of %s\ParameterGenerator', __METHOD__, __NAMESPACE__ )); } $this->parameters[$parameter->getName()] = $parameter; $this->sortParameters(); return $this; } /** * @return ParameterGenerator[] */ public function getParameters() { return $this->parameters; } /** * @param string $body * @return MethodGenerator */ public function setBody($body) { $this->body = $body; return $this; } /** * @return string */ public function getBody() { return $this->body; } /** * @param string|null $returnType * @return MethodGenerator */ public function setReturnType($returnType = null) { $this->returnType = null === $returnType ? null : TypeGenerator::fromTypeString($returnType); return $this; } /** * @return TypeGenerator|null */ public function getReturnType() { return $this->returnType; } /** * @param bool $returnsReference * @return MethodGenerator */ public function setReturnsReference($returnsReference) { $this->returnsReference = (bool) $returnsReference; return $this; } /** * Sort parameters by their position */ private function sortParameters(): void { usort($this->parameters, static function (ParameterGenerator $item1, ParameterGenerator $item2) { return $item1->getPosition() <=> $item2->getPosition(); }); } /** * @return string */ public function generate() { $output = ''; $indent = $this->getIndentation(); if (($docBlock = $this->getDocBlock()) !== null) { $docBlock->setIndentation($indent); $output .= $docBlock->generate(); } $output .= $indent; if ($this->isAbstract()) { $output .= 'abstract '; } else { $output .= $this->isFinal() ? 'final ' : ''; } $output .= $this->getVisibility() . ($this->isStatic() ? ' static' : '') . ' function ' . ($this->returnsReference ? '& ' : '') . $this->getName() . '('; $parameters = $this->getParameters(); if (! empty($parameters)) { foreach ($parameters as $parameter) { $parameterOutput[] = $parameter->generate(); } $output .= implode(', ', $parameterOutput); } $output .= ')'; if ($this->returnType) { $output .= ' : ' . $this->returnType->generate(); } if ($this->isAbstract()) { return $output . ';'; } if ($this->isInterface()) { return $output . ';'; } $output .= self::LINE_FEED . $indent . '{' . self::LINE_FEED; if ($this->body) { $output .= preg_replace('#^((?![a-zA-Z0-9_-]+;).+?)$#m', $indent . $indent . '$1', trim($this->body)) . self::LINE_FEED; } $output .= $indent . '}' . self::LINE_FEED; return $output; } /** @return string */ public function __toString() { return $this->generate(); } } src/Generator/ParameterGenerator.php000064400000017712144760112670013601 0ustar00setName($reflectionParameter->getName()); $param->type = TypeGenerator::fromReflectionType( $reflectionParameter->getType(), $reflectionParameter->getDeclaringClass() ); $param->setPosition($reflectionParameter->getPosition()); $variadic = $reflectionParameter->isVariadic(); $param->setVariadic($variadic); if (! $variadic && ($reflectionParameter->isOptional() || $reflectionParameter->isDefaultValueAvailable())) { try { $param->setDefaultValue($reflectionParameter->getDefaultValue()); } catch (ReflectionException $e) { $param->setDefaultValue(null); } } $param->setPassedByReference($reflectionParameter->isPassedByReference()); return $param; } /** * Generate from array * * @configkey name string [required] Class Name * @configkey type string * @configkey defaultvalue null|bool|string|int|float|array|ValueGenerator * @configkey passedbyreference bool * @configkey position int * @configkey sourcedirty bool * @configkey indentation string * @configkey sourcecontent string * @configkey omitdefaultvalue bool * @throws Exception\InvalidArgumentException * @param array $array * @return ParameterGenerator */ public static function fromArray(array $array) { if (! isset($array['name'])) { throw new Exception\InvalidArgumentException( 'Parameter generator requires that a name is provided for this object' ); } $param = new static($array['name']); foreach ($array as $name => $value) { // normalize key switch (strtolower(str_replace(['.', '-', '_'], '', $name))) { case 'type': $param->setType($value); break; case 'defaultvalue': $param->setDefaultValue($value); break; case 'passedbyreference': $param->setPassedByReference($value); break; case 'position': $param->setPosition($value); break; case 'sourcedirty': $param->setSourceDirty($value); break; case 'indentation': $param->setIndentation($value); break; case 'sourcecontent': $param->setSourceContent($value); break; case 'omitdefaultvalue': $param->omitDefaultValue($value); break; } } return $param; } /** * @param ?string $name * @param ?string $type * @param ?mixed $defaultValue * @param ?int $position * @param bool $passByReference */ public function __construct( $name = null, $type = null, $defaultValue = null, $position = null, $passByReference = false ) { if (null !== $name) { $this->setName($name); } if (null !== $type) { $this->setType($type); } if (null !== $defaultValue) { $this->setDefaultValue($defaultValue); } if (null !== $position) { $this->setPosition($position); } if (false !== $passByReference) { $this->setPassedByReference(true); } } /** * @param string $type * @return ParameterGenerator */ public function setType($type) { $this->type = TypeGenerator::fromTypeString($type); return $this; } /** * @return string */ public function getType() { return $this->type ? $this->type->__toString() : null; } /** * @param string $name * @return ParameterGenerator */ public function setName($name) { $this->name = (string) $name; return $this; } /** * @return string */ public function getName() { return $this->name; } /** * Set the default value of the parameter. * * Certain variables are difficult to express * * @param null|bool|string|int|float|array|ValueGenerator $defaultValue * @return ParameterGenerator */ public function setDefaultValue($defaultValue) { if ($this->variadic) { throw new Exception\InvalidArgumentException('Variadic parameter cannot have a default value'); } if (! $defaultValue instanceof ValueGenerator) { $defaultValue = new ValueGenerator($defaultValue); } $this->defaultValue = $defaultValue; return $this; } /** * @return ?ValueGenerator */ public function getDefaultValue() { return $this->defaultValue; } /** * @param int $position * @return ParameterGenerator */ public function setPosition($position) { $this->position = (int) $position; return $this; } /** * @return int */ public function getPosition() { return $this->position; } /** * @return bool */ public function getPassedByReference() { return $this->passedByReference; } /** * @param bool $passedByReference * @return ParameterGenerator */ public function setPassedByReference($passedByReference) { $this->passedByReference = (bool) $passedByReference; return $this; } /** * @param bool $variadic * @return ParameterGenerator */ public function setVariadic($variadic) { if (isset($this->defaultValue)) { throw new Exception\InvalidArgumentException('Variadic parameter cannot have a default value'); } $this->variadic = (bool) $variadic; return $this; } /** * @return bool */ public function getVariadic() { return $this->variadic; } /** * @return string */ public function generate() { $output = $this->generateTypeHint(); if (true === $this->passedByReference) { $output .= '&'; } if ($this->variadic) { $output .= '... '; } $output .= '$' . $this->name; if ($this->omitDefaultValue) { return $output; } if ($this->defaultValue instanceof ValueGenerator) { $output .= ' = '; $this->defaultValue->setOutputMode(ValueGenerator::OUTPUT_SINGLE_LINE); $output .= $this->defaultValue; } return $output; } /** * @return string */ private function generateTypeHint() { if (null === $this->type) { return ''; } return $this->type->generate() . ' '; } /** * @return ParameterGenerator */ public function omitDefaultValue(bool $omit = true) { $this->omitDefaultValue = $omit; return $this; } } src/Generator/PropertyGenerator.php000064400000016004144760112670013476 0ustar00setName($reflectionProperty->getName()); $allDefaultProperties = $reflectionProperty->getDeclaringClass()->getDefaultProperties(); $defaultValue = $allDefaultProperties[$reflectionProperty->getName()] ?? null; $property->setDefaultValue($defaultValue); if ($defaultValue === null) { $property->omitDefaultValue = true; } if ($reflectionProperty->getDocComment() != '') { $property->setDocBlock(DocBlockGenerator::fromReflection($reflectionProperty->getDocBlock())); } if ($reflectionProperty->isStatic()) { $property->setStatic(true); } if ($reflectionProperty->isPrivate()) { $property->setVisibility(self::VISIBILITY_PRIVATE); } elseif ($reflectionProperty->isProtected()) { $property->setVisibility(self::VISIBILITY_PROTECTED); } else { $property->setVisibility(self::VISIBILITY_PUBLIC); } $property->setSourceDirty(false); return $property; } /** * Generate from array * * @configkey name string [required] Class Name * @configkey const bool * @configkey defaultvalue null|bool|string|int|float|array|ValueGenerator * @configkey flags int * @configkey abstract bool * @configkey final bool * @configkey static bool * @configkey visibility string * @configkey omitdefaultvalue bool * @throws Exception\InvalidArgumentException * @param array $array * @return static */ public static function fromArray(array $array) { if (! isset($array['name'])) { throw new Exception\InvalidArgumentException( 'Property generator requires that a name is provided for this object' ); } $property = new static($array['name']); foreach ($array as $name => $value) { // normalize key switch (strtolower(str_replace(['.', '-', '_'], '', $name))) { case 'const': $property->setConst($value); break; case 'defaultvalue': $property->setDefaultValue($value); break; case 'docblock': $docBlock = $value instanceof DocBlockGenerator ? $value : DocBlockGenerator::fromArray($value); $property->setDocBlock($docBlock); break; case 'flags': $property->setFlags($value); break; case 'abstract': $property->setAbstract($value); break; case 'final': $property->setFinal($value); break; case 'static': $property->setStatic($value); break; case 'visibility': $property->setVisibility($value); break; case 'omitdefaultvalue': $property->omitDefaultValue($value); break; } } return $property; } /** * @param ?string $name * @param PropertyValueGenerator|string|array|null $defaultValue * @param int $flags */ public function __construct($name = null, $defaultValue = null, $flags = self::FLAG_PUBLIC) { if (null !== $name) { $this->setName($name); } if (null !== $defaultValue) { $this->setDefaultValue($defaultValue); } if ($flags !== self::FLAG_PUBLIC) { $this->setFlags($flags); } } /** * @param bool $const * @return PropertyGenerator */ public function setConst($const) { if ($const) { $this->setFlags(self::FLAG_CONSTANT); } else { $this->removeFlag(self::FLAG_CONSTANT); } return $this; } /** * @return bool */ public function isConst() { return (bool) ($this->flags & self::FLAG_CONSTANT); } /** * @param PropertyValueGenerator|mixed $defaultValue * @param string $defaultValueType * @param string $defaultValueOutputMode * @return $this */ public function setDefaultValue( $defaultValue, $defaultValueType = PropertyValueGenerator::TYPE_AUTO, $defaultValueOutputMode = PropertyValueGenerator::OUTPUT_MULTIPLE_LINE ) { if (! $defaultValue instanceof PropertyValueGenerator) { $defaultValue = new PropertyValueGenerator($defaultValue, $defaultValueType, $defaultValueOutputMode); } $this->defaultValue = $defaultValue; return $this; } /** * @return ?PropertyValueGenerator */ public function getDefaultValue() { return $this->defaultValue; } /** * @throws Exception\RuntimeException * @return string */ public function generate() { $name = $this->getName(); $defaultValue = $this->getDefaultValue(); $output = ''; if (($docBlock = $this->getDocBlock()) !== null) { $docBlock->setIndentation(' '); $output .= $docBlock->generate(); } if ($this->isConst()) { if ($defaultValue !== null && ! $defaultValue->isValidConstantType()) { throw new Exception\RuntimeException(sprintf( 'The property %s is said to be ' . 'constant but does not have a valid constant value.', $this->name )); } return $output . $this->indentation . $this->getVisibility() . ' const ' . $name . ' = ' . ($defaultValue !== null ? $defaultValue->generate() : 'null;'); } $output .= $this->indentation . $this->getVisibility() . ($this->isStatic() ? ' static' : '') . ' $' . $name; if ($this->omitDefaultValue) { return $output . ';'; } return $output . ' = ' . ($defaultValue !== null ? $defaultValue->generate() : 'null;'); } /** * @return PropertyGenerator */ public function omitDefaultValue(bool $omit = true) { $this->omitDefaultValue = $omit; return $this; } } src/Generator/PropertyValueGenerator.php000064400000000400144760112670014464 0ustar00getName()); $cg->setSourceContent($cg->getSourceContent()); $cg->setSourceDirty(false); if ($classReflection->getDocComment() != '') { $cg->setDocBlock(DocBlockGenerator::fromReflection($classReflection->getDocBlock())); } // set the namespace if ($classReflection->inNamespace()) { $cg->setNamespaceName($classReflection->getNamespaceName()); } $properties = []; foreach ($classReflection->getProperties() as $reflectionProperty) { if ($reflectionProperty->getDeclaringClass()->getName() == $classReflection->getName()) { $properties[] = PropertyGenerator::fromReflection($reflectionProperty); } } $cg->addProperties($properties); $methods = []; foreach ($classReflection->getMethods() as $reflectionMethod) { $className = $cg->getName(); $namespaceName = $cg->getNamespaceName(); if ($namespaceName !== null) { $className = $namespaceName . '\\' . $className; } if ($reflectionMethod->getDeclaringClass()->getName() == $className) { $methods[] = MethodGenerator::fromReflection($reflectionMethod); } } $cg->addMethods($methods); return $cg; } /** * Generate from array * * @configkey name string [required] Class Name * @configkey filegenerator FileGenerator File generator that holds this class * @configkey namespacename string The namespace for this class * @configkey docblock string The docblock information * @configkey properties * @configkey methods * @throws Exception\InvalidArgumentException * @param array $array * @return TraitGenerator */ public static function fromArray(array $array) { if (! isset($array['name'])) { throw new Exception\InvalidArgumentException( 'Class generator requires that a name is provided for this object' ); } $cg = new static($array['name']); foreach ($array as $name => $value) { // normalize key switch (strtolower(str_replace(['.', '-', '_'], '', $name))) { case 'containingfile': $cg->setContainingFileGenerator($value); break; case 'namespacename': $cg->setNamespaceName($value); break; case 'docblock': $docBlock = $value instanceof DocBlockGenerator ? $value : DocBlockGenerator::fromArray($value); $cg->setDocBlock($docBlock); break; case 'properties': $cg->addProperties($value); break; case 'methods': $cg->addMethods($value); break; } } return $cg; } /** * @inheritDoc * @param int[]|int $flags */ public function setFlags($flags) { return $this; } /** * @param int $flag * @return self */ public function addFlag($flag) { return $this; } /** * @param int $flag * @return self */ public function removeFlag($flag) { return $this; } /** * @inheritDoc */ public function setFinal($isFinal) { return $this; } /** * @param ?string $extendedClass * @return self */ public function setExtendedClass($extendedClass) { return $this; } /** * @inheritDoc */ public function setImplementedInterfaces(array $implementedInterfaces) { return $this; } /** * @inheritDoc */ public function setAbstract($isAbstract) { return $this; } } src/Generator/TraitUsageGenerator.php000064400000027324144760112670013731 0ustar00 Array of trait names */ protected array $traits = []; /** @var array Array of trait aliases */ protected array $traitAliases = []; /** @var array Array of trait overrides */ protected array $traitOverrides = []; /** @var array Array of string names */ protected array $uses = []; public function __construct(ClassGenerator $classGenerator) { $this->classGenerator = $classGenerator; } /** * @inheritDoc */ public function addUse($use, $useAlias = null) { $this->removeUse($use); if (! empty($useAlias)) { $use .= ' as ' . $useAlias; } $this->uses[$use] = $use; return $this; } /** * @inheritDoc */ public function getUses() { return array_values($this->uses); } /** * @param string $use * @return bool */ public function hasUse($use) { foreach ($this->uses as $key => $value) { $parts = explode(' ', $value); if ($parts[0] === $use) { return true; } } return false; } /** * @param string $use * @return bool */ public function hasUseAlias($use) { foreach ($this->uses as $key => $value) { $parts = explode(' as ', $value); if ($parts[0] === $use && count($parts) == 2) { return true; } } return false; } /** * Returns the alias of the provided FQCN */ public function getUseAlias(string $use): ?string { foreach ($this->uses as $key => $value) { $parts = explode(' as ', $key); if ($parts[0] === $use && count($parts) == 2) { return $parts[1]; } } return null; } /** * Returns true if the alias is defined in the use list */ public function isUseAlias(string $alias): bool { foreach ($this->uses as $key => $value) { $parts = explode(' as ', $key); if (count($parts) === 2 && $parts[1] === $alias) { return true; } } return false; } /** * @param string $use * @return TraitUsageGenerator */ public function removeUse($use) { foreach ($this->uses as $key => $value) { $parts = explode(' ', $value); if ($parts[0] === $use) { unset($this->uses[$value]); } } return $this; } /** * @param string $use * @return TraitUsageGenerator */ public function removeUseAlias($use) { foreach ($this->uses as $key => $value) { $parts = explode(' as ', $value); if ($parts[0] === $use && count($parts) == 2) { unset($this->uses[$value]); } } return $this; } /** * @inheritDoc */ public function addTrait($trait) { if (is_array($trait)) { if (! array_key_exists('traitName', $trait)) { throw new Exception\InvalidArgumentException('Missing required value for traitName'); } $traitName = $trait['traitName']; if (array_key_exists('aliases', $trait)) { foreach ($trait['aliases'] as $alias) { $this->addAlias($alias); } } if (array_key_exists('insteadof', $trait)) { foreach ($trait['insteadof'] as $insteadof) { $this->addTraitOverride($insteadof); } } } else { $traitName = $trait; } if (! $this->hasTrait($traitName)) { $this->traits[] = $traitName; } return $this; } /** * @inheritDoc */ public function addTraits(array $traits) { foreach ($traits as $trait) { $this->addTrait($trait); } return $this; } /** * @inheritDoc */ public function hasTrait($traitName) { return in_array($traitName, $this->traits); } /** * @inheritDoc */ public function getTraits() { return $this->traits; } /** * @inheritDoc */ public function removeTrait($traitName) { $key = array_search($traitName, $this->traits); if (false !== $key) { unset($this->traits[$key]); } return $this; } /** * @inheritDoc */ public function addTraitAlias($method, $alias, $visibility = null) { $traitAndMethod = $method; if (is_array($method)) { if (! array_key_exists('traitName', $method)) { throw new Exception\InvalidArgumentException('Missing required argument "traitName" for $method'); } if (! array_key_exists('method', $method)) { throw new Exception\InvalidArgumentException('Missing required argument "method" for $method'); } $traitAndMethod = $method['traitName'] . '::' . $method['method']; } // Validations if (false === strpos($traitAndMethod, '::')) { throw new Exception\InvalidArgumentException( 'Invalid Format: $method must be in the format of trait::method' ); } if (! is_string($alias)) { throw new Exception\InvalidArgumentException('Invalid Alias: $alias must be a string or array.'); } if ($this->classGenerator->hasMethod($alias)) { throw new Exception\InvalidArgumentException('Invalid Alias: Method name already exists on this class.'); } if ( null !== $visibility && $visibility !== ReflectionMethod::IS_PUBLIC && $visibility !== ReflectionMethod::IS_PRIVATE && $visibility !== ReflectionMethod::IS_PROTECTED ) { throw new Exception\InvalidArgumentException( 'Invalid Type: $visibility must of ReflectionMethod::IS_PUBLIC,' . ' ReflectionMethod::IS_PRIVATE or ReflectionMethod::IS_PROTECTED' ); } [$trait, $method] = explode('::', $traitAndMethod); if (! $this->hasTrait($trait)) { throw new Exception\InvalidArgumentException('Invalid trait: Trait does not exists on this class'); } $this->traitAliases[$traitAndMethod] = [ 'alias' => $alias, 'visibility' => $visibility, ]; return $this; } /** * @inheritDoc */ public function getTraitAliases() { return $this->traitAliases; } /** * @inheritDoc */ public function addTraitOverride($method, $traitsToReplace) { if (false === is_array($traitsToReplace)) { $traitsToReplace = [$traitsToReplace]; } $traitAndMethod = $method; if (is_array($method)) { if (! array_key_exists('traitName', $method)) { throw new Exception\InvalidArgumentException('Missing required argument "traitName" for $method'); } if (! array_key_exists('method', $method)) { throw new Exception\InvalidArgumentException('Missing required argument "method" for $method'); } $traitAndMethod = (string) $method['traitName'] . '::' . (string) $method['method']; } // Validations if (false === strpos($traitAndMethod, '::')) { throw new Exception\InvalidArgumentException( 'Invalid Format: $method must be in the format of trait::method' ); } [$trait, $method] = explode('::', $traitAndMethod); if (! $this->hasTrait($trait)) { throw new Exception\InvalidArgumentException('Invalid trait: Trait does not exists on this class'); } if (! array_key_exists($traitAndMethod, $this->traitOverrides)) { $this->traitOverrides[$traitAndMethod] = []; } foreach ($traitsToReplace as $traitToReplace) { if (! is_string($traitToReplace)) { throw new Exception\InvalidArgumentException( 'Invalid Argument: $traitToReplace must be a string or array of strings' ); } if (! in_array($traitToReplace, $this->traitOverrides[$traitAndMethod])) { $this->traitOverrides[$traitAndMethod][] = $traitToReplace; } } return $this; } /** * @inheritDoc */ public function removeTraitOverride($method, $overridesToRemove = null) { if (! array_key_exists($method, $this->traitOverrides)) { return $this; } if (null === $overridesToRemove) { unset($this->traitOverrides[$method]); return $this; } $overridesToRemove = ! is_array($overridesToRemove) ? [$overridesToRemove] : $overridesToRemove; foreach ($overridesToRemove as $traitToRemove) { $key = array_search($traitToRemove, $this->traitOverrides[$method]); if (false !== $key) { unset($this->traitOverrides[$method][$key]); } } return $this; } /** * @inheritDoc */ public function getTraitOverrides() { return $this->traitOverrides; } /** * @inheritDoc */ public function generate() { $output = ''; $indent = $this->getIndentation(); $traits = $this->getTraits(); if (empty($traits)) { return $output; } $output .= $indent . 'use ' . implode(', ', $traits); $aliases = $this->getTraitAliases(); $overrides = $this->getTraitOverrides(); if (empty($aliases) && empty($overrides)) { return $output . ';' . self::LINE_FEED . self::LINE_FEED; } $output .= ' {' . self::LINE_FEED; foreach ($aliases as $method => $alias) { $visibility = null !== $alias['visibility'] ? current(Reflection::getModifierNames($alias['visibility'])) . ' ' : ''; // validation check if ($this->classGenerator->hasMethod($alias['alias'])) { throw new Exception\RuntimeException(sprintf( 'Generation Error: Aliased method %s already exists on this class', $alias['alias'] )); } $output .= $indent . $indent . $method . ' as ' . $visibility . $alias['alias'] . ';' . self::LINE_FEED; } foreach ($overrides as $method => $insteadofTraits) { foreach ($insteadofTraits as $insteadofTrait) { $output .= $indent . $indent . $method . ' insteadof ' . $insteadofTrait . ';' . self::LINE_FEED; } } return $output . self::LINE_FEED . $indent . '}' . self::LINE_FEED . self::LINE_FEED; } } src/Generator/TraitUsageInterface.php000064400000010374144760112670013700 0ustar00 $traits * @return self */ public function addTraits(array $traits); /** * Check to see if the class has a trait defined * * @param string $traitName * @return bool */ public function hasTrait($traitName); /** * Get a list of trait names * * @return array */ public function getTraits(); /** * Remove a trait by its name * * @param string $traitName */ public function removeTrait($traitName); /** * Add a trait alias. This will be used to generate the AS portion of the use statement. * * $method: * This method provides 2 ways for defining the trait method. * Option 1: String * Option 2: Array * key: traitName value: name of trait * key: method value: trait method * * $alias: * Alias is a string representing the new method name. * * $visibilty: * ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PRIVATE | ReflectionMethod::IS_PROTECTED * * @param mixed $method String or Array * @param string $alias * @param null|int $visibility */ public function addTraitAlias($method, $alias, $visibility = null); /** * @return array */ public function getTraitAliases(); /** * Add a trait method override. This will be used to generate the INSTEADOF portion of the use * statement. * * $method: * This method provides 2 ways for defining the trait method. * Option 1: String Format: :: * Option 2: Array * key: traitName value: trait name * key: method value: method name * * $traitToReplace: * The name of the trait that you wish to supersede. * * This method provides 2 ways for defining the trait method. * Option 1: String of trait to replace * Option 2: Array of strings of traits to replace * @param mixed $method * @param mixed $traitsToReplace */ public function addTraitOverride($method, $traitsToReplace); /** * Remove an override for a given trait::method * * $method: * This method provides 2 ways for defining the trait method. * Option 1: String Format: :: * Option 2: Array * key: traitName value: trait name * key: method value: method name * * $overridesToRemove: * The name of the trait that you wish to remove. * * This method provides 2 ways for defining the trait method. * Option 1: String of trait to replace * Option 2: Array of strings of traits to replace * * @param mixed $method * @param mixed $overridesToRemove * @return self */ public function removeTraitOverride($method, $overridesToRemove = null); /** * Return trait overrides * * @return array */ public function getTraitOverrides(); } src/Generator/TypeGenerator.php000064400000013130144760112670012570 0ustar00 */ private array $types; private bool $nullable; /** * @internal * * @psalm-pure */ public static function fromReflectionType( ?ReflectionType $type, ?ReflectionClass $currentClass ): ?self { if (null === $type) { return null; } assert($type instanceof ReflectionNamedType || $type instanceof ReflectionUnionType); return self::fromTypeString(implode( '|', array_map( static fn(ReflectionNamedType $type): string => self::reflectionNamedTypeToString($type, $currentClass), $type instanceof ReflectionNamedType ? [$type] : $type->getTypes() ) )); } /** @psalm-pure */ private static function reflectionNamedTypeToString( ReflectionNamedType $type, ?ReflectionClass $currentClass ): string { $lowerCaseName = strtolower($type->getName()); if ('mixed' === $lowerCaseName || 'null' === $lowerCaseName) { // `mixed` and `null` are implicitly nullable, therefore we need to skip adding nullability markers to it return $lowerCaseName; } $nullabilityMarker = $type->allowsNull() ? '?' : ''; if ('self' === $lowerCaseName && $currentClass) { return $nullabilityMarker . $currentClass->getName(); } if ('parent' === $lowerCaseName && $currentClass && $parentClass = $currentClass->getParentClass()) { return $nullabilityMarker . $parentClass->getName(); } return $nullabilityMarker . $type->getName(); } /** * @throws InvalidArgumentException * @psalm-pure */ public static function fromTypeString(string $type): self { [$nullable, $trimmedNullable] = self::trimNullable($type); $types = array_map([AtomicType::class, 'fromString'], explode('|', $trimmedNullable)); usort( $types, static fn(AtomicType $left, AtomicType $right): int => [$left->sortIndex, $left->type] <=> [$right->sortIndex, $right->type] ); assert([] !== $types); if (1 === count($types)) { $types[0]->assertCanBeAStandaloneType(); if ($nullable) { $types[0]->assertCanBeStandaloneNullable(); } return new self($types, $nullable); } if ($nullable) { throw new InvalidArgumentException(sprintf( 'Type "%s" is a union type, and therefore cannot be also marked nullable with the "?" prefix', $type )); } foreach ($types as $index => $atomicType) { $otherTypes = array_diff_key($types, array_flip([$index])); assert([] !== $otherTypes, 'There are always 2 or more types in a union type'); $atomicType->assertCanUnionWith($otherTypes); } return new self($types, $nullable); } /** * @param AtomicType[] $types * @psalm-param non-empty-list $types */ private function __construct(array $types, bool $nullable) { $this->types = $types; $this->nullable = $nullable; } /** * {@inheritDoc} * * Generates the type string, including FQCN "\\" prefix, so that * it can directly be used within any code snippet, regardless of * imports. * * @psalm-return non-empty-string */ public function generate() { $typesAsStrings = array_map( fn(AtomicType $type): string => $type->fullyQualifiedName(), $this->types ); if ($this->nullable) { return '?' . implode('|', $typesAsStrings); } return implode('|', $typesAsStrings); } public function equals(TypeGenerator $otherType): bool { return $this->generate() === $otherType->generate(); } /** * @return string the cleaned type string. Please note that this value is not suitable for code generation, * since the returned value does not include any root namespace prefixes, when applicable, * and therefore the values cannot be used as FQCN in generated code. */ public function __toString() { return implode('|', array_map( fn(AtomicType $type): string => $type->type, $this->types )); } /** * @param string $type * @return bool[]|string[] ordered tuple, first key represents whether the type is nullable, second is the * trimmed string * @psalm-return array{bool, string} * @psalm-pure */ private static function trimNullable($type) { if (0 === strpos($type, '?')) { return [true, substr($type, 1)]; } return [false, $type]; } } src/Generator/TypeGenerator/AtomicType.php000064400000013201144760112670014645 0ustar00 */ private const BUILT_IN_TYPES_PRECEDENCE = [ 'bool' => 1, 'int' => 2, 'float' => 3, 'string' => 4, 'array' => 5, 'callable' => 6, 'iterable' => 7, 'object' => 8, 'static' => 9, 'mixed' => 10, 'void' => 11, 'false' => 12, 'null' => 13, ]; /** @psalm-var array */ private const NOT_NULLABLE_TYPES = [ 'null' => null, 'false' => null, 'void' => null, 'mixed' => null, ]; /** A regex pattern to match valid class/interface/trait names */ private const VALID_IDENTIFIER_MATCHER = '/^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*' . '(\\\\[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)*$/'; /** @psalm-var value-of|0 */ public int $sortIndex; /** @psalm-var non-empty-string */ public string $type; /** * @psalm-param non-empty-string $type * @psalm-param value-of|0 $sortIndex */ private function __construct(string $type, int $sortIndex) { $this->type = $type; $this->sortIndex = $sortIndex; } /** * @psalm-pure * @throws InvalidArgumentException */ public static function fromString(string $type): self { $trimmedType = '\\' === ($type[0] ?? '') ? substr($type, 1) : $type; $lowerCaseType = strtolower($trimmedType); if (array_key_exists($lowerCaseType, self::BUILT_IN_TYPES_PRECEDENCE)) { if ($lowerCaseType !== strtolower($type)) { throw new InvalidArgumentException(sprintf( 'Provided type "%s" is a built-in type, and should not be prefixed with "\\"', $type )); } return new self($lowerCaseType, self::BUILT_IN_TYPES_PRECEDENCE[$lowerCaseType]); } if (1 !== preg_match(self::VALID_IDENTIFIER_MATCHER, $trimmedType)) { throw new InvalidArgumentException(sprintf( 'Provided type "%s" is not recognized as a valid expression: ' . 'it must match "%s" or be one of the built-in types (%s)', $type, self::VALID_IDENTIFIER_MATCHER, implode(', ', self::BUILT_IN_TYPES_PRECEDENCE) )); } assert('' !== $trimmedType); return new self($trimmedType, 0); } /** @psalm-pure */ public static function null(): self { return new self('null', self::BUILT_IN_TYPES_PRECEDENCE['null']); } /** @psalm-return non-empty-string */ public function fullyQualifiedName(): string { return array_key_exists($this->type, self::BUILT_IN_TYPES_PRECEDENCE) ? $this->type : '\\' . $this->type; } /** * @psalm-param non-empty-array $others * @throws InvalidArgumentException */ public function assertCanUnionWith(array $others): void { if ( 'mixed' === $this->type || 'void' === $this->type ) { throw new InvalidArgumentException(sprintf( 'Type "%s" cannot be composed in a union with any other types', $this->type )); } foreach ($others as $other) { if ($other->type === $this->type) { throw new InvalidArgumentException(sprintf( 'Type "%s" cannot be composed in a union with the same type "%s"', $this->type, $other->type )); } } if ( $this->requiresUnionWithStandaloneType() && [] === array_filter($others, static fn (self $type): bool => ! $type->requiresUnionWithStandaloneType()) ) { throw new InvalidArgumentException(sprintf( 'Type "%s" requires to be composed with non-standalone types', $this->type )); } } /** @throws InvalidArgumentException */ public function assertCanBeAStandaloneType(): void { if ($this->requiresUnionWithStandaloneType()) { throw new InvalidArgumentException(sprintf( 'Type "%s" cannot be used standalone, and must be part of a union type', $this->type )); } } /** @throws InvalidArgumentException */ public function assertCanBeStandaloneNullable(): void { if (array_key_exists($this->type, self::NOT_NULLABLE_TYPES)) { throw new InvalidArgumentException(sprintf( 'Type "%s" cannot be nullable', $this->type )); } } private function requiresUnionWithStandaloneType(): bool { return 'null' === $this->type || 'false' === $this->type; } } src/Generator/ValueGenerator.php000064400000031142144760112670012726 0ustar00setValue($value); } if ($type !== self::TYPE_AUTO) { $this->setType($type); } if ($outputMode !== self::OUTPUT_MULTIPLE_LINE) { $this->setOutputMode($outputMode); } if ($constants === null) { $constants = new SplArrayObject(); } elseif (! ($constants instanceof SplArrayObject || $constants instanceof StdlibArrayObject)) { throw new InvalidArgumentException( '$constants must be an instance of ArrayObject or Laminas\Stdlib\ArrayObject' ); } $this->constants = $constants; } /** * Init constant list by defined and magic constants */ public function initEnvironmentConstants() { $constants = [ '__DIR__', '__FILE__', '__LINE__', '__CLASS__', '__TRAIT__', '__METHOD__', '__FUNCTION__', '__NAMESPACE__', '::', ]; $constants = array_merge($constants, array_keys(get_defined_constants()), $this->constants->getArrayCopy()); $this->constants->exchangeArray($constants); } /** * Add constant to list * * @param string $constant * @return $this */ public function addConstant($constant) { $this->constants->append($constant); return $this; } /** * Delete constant from constant list * * @param string $constant * @return bool */ public function deleteConstant($constant) { if (($index = array_search($constant, $this->constants->getArrayCopy())) !== false) { $this->constants->offsetUnset($index); } return $index !== false; } /** * Return constant list * * @return SplArrayObject|StdlibArrayObject */ public function getConstants() { return $this->constants; } /** * @return bool */ public function isValidConstantType() { if ($this->type === self::TYPE_AUTO) { $type = $this->getAutoDeterminedType($this->value); } else { $type = $this->type; } $validConstantTypes = [ self::TYPE_ARRAY, self::TYPE_ARRAY_LONG, self::TYPE_ARRAY_SHORT, self::TYPE_BOOLEAN, self::TYPE_BOOL, self::TYPE_NUMBER, self::TYPE_INTEGER, self::TYPE_INT, self::TYPE_FLOAT, self::TYPE_DOUBLE, self::TYPE_STRING, self::TYPE_CONSTANT, self::TYPE_NULL, ]; return in_array($type, $validConstantTypes); } /** * @param mixed $value * @return ValueGenerator */ public function setValue($value) { $this->value = $value; return $this; } /** * @return mixed */ public function getValue() { return $this->value; } /** * @param string $type * @return ValueGenerator */ public function setType($type) { $this->type = (string) $type; return $this; } /** * @return string */ public function getType() { return $this->type; } /** * @param int $arrayDepth * @return ValueGenerator */ public function setArrayDepth($arrayDepth) { $this->arrayDepth = (int) $arrayDepth; return $this; } /** * @return int */ public function getArrayDepth() { return $this->arrayDepth; } /** * @param string $type * @return string */ protected function getValidatedType($type) { $types = [ self::TYPE_AUTO, self::TYPE_BOOLEAN, self::TYPE_BOOL, self::TYPE_NUMBER, self::TYPE_INTEGER, self::TYPE_INT, self::TYPE_FLOAT, self::TYPE_DOUBLE, self::TYPE_STRING, self::TYPE_ARRAY, self::TYPE_ARRAY_SHORT, self::TYPE_ARRAY_LONG, self::TYPE_CONSTANT, self::TYPE_NULL, self::TYPE_OBJECT, self::TYPE_OTHER, ]; if (in_array($type, $types)) { return $type; } return self::TYPE_AUTO; } /** * @param mixed $value * @return string */ public function getAutoDeterminedType($value) { switch (gettype($value)) { case 'boolean': return self::TYPE_BOOLEAN; case 'string': foreach ($this->constants as $constant) { if ($value === $constant) { return self::TYPE_CONSTANT; } if (strpos($value, $constant) !== false) { return self::TYPE_CONSTANT; } } return self::TYPE_STRING; case 'double': case 'float': case 'integer': return self::TYPE_NUMBER; case 'array': return self::TYPE_ARRAY; case 'NULL': return self::TYPE_NULL; case 'object': case 'resource': case 'unknown type': default: return self::TYPE_OTHER; } } /** * @throws Exception\RuntimeException * @return string */ public function generate() { $type = $this->type; if ($type !== self::TYPE_AUTO) { $type = $this->getValidatedType($type); } $value = $this->value; if ($type === self::TYPE_AUTO) { $type = $this->getAutoDeterminedType($value); } $isArrayType = in_array($type, [self::TYPE_ARRAY, self::TYPE_ARRAY_LONG, self::TYPE_ARRAY_SHORT]); if ($isArrayType) { foreach ($value as &$curValue) { if ($curValue instanceof self) { continue; } if (is_array($curValue)) { $newType = $type; } else { $newType = self::TYPE_AUTO; } $curValue = new self($curValue, $newType, self::OUTPUT_MULTIPLE_LINE, $this->getConstants()); $curValue->setIndentation($this->indentation); } } $output = ''; switch ($type) { case self::TYPE_BOOLEAN: case self::TYPE_BOOL: $output .= $value ? 'true' : 'false'; break; case self::TYPE_STRING: $output .= self::escape($value); break; case self::TYPE_NULL: $output .= 'null'; break; case self::TYPE_NUMBER: case self::TYPE_INTEGER: case self::TYPE_INT: case self::TYPE_FLOAT: case self::TYPE_DOUBLE: case self::TYPE_CONSTANT: $output .= $value; break; case self::TYPE_ARRAY: case self::TYPE_ARRAY_LONG: case self::TYPE_ARRAY_SHORT: if ($type === self::TYPE_ARRAY_LONG) { $startArray = 'array('; $endArray = ')'; } else { $startArray = '['; $endArray = ']'; } $output .= $startArray; if ($this->outputMode == self::OUTPUT_MULTIPLE_LINE) { $output .= self::LINE_FEED . str_repeat($this->indentation, $this->arrayDepth + 1); } $outputParts = []; $noKeyIndex = 0; foreach ($value as $n => $v) { /** @var ValueGenerator $v */ $v->setArrayDepth($this->arrayDepth + 1); $partV = $v->generate(); $short = false; if (is_int($n)) { if ($n === $noKeyIndex) { $short = true; $noKeyIndex++; } else { $noKeyIndex = max($n + 1, $noKeyIndex); } } if ($short) { $outputParts[] = $partV; } else { $outputParts[] = (is_int($n) ? $n : self::escape($n)) . ' => ' . $partV; } } $padding = $this->outputMode == self::OUTPUT_MULTIPLE_LINE ? self::LINE_FEED . str_repeat($this->indentation, $this->arrayDepth + 1) : ' '; $output .= implode(',' . $padding, $outputParts); if ($this->outputMode == self::OUTPUT_MULTIPLE_LINE) { if (count($outputParts) > 0) { $output .= ','; } $output .= self::LINE_FEED . str_repeat($this->indentation, $this->arrayDepth); } $output .= $endArray; break; case self::TYPE_OTHER: default: throw new Exception\RuntimeException(sprintf( 'Type "%s" is unknown or cannot be used as property default value.', is_object($value) ? get_class($value) : gettype($value) )); } return $output; } /** * Quotes value for PHP code. * * @param string $input Raw string. * @param bool $quote Whether add surrounding quotes or not. * @return string PHP-ready code. */ public static function escape($input, $quote = true) { $output = addcslashes($input, "\\'"); // adds quoting strings if ($quote) { $output = "'" . $output . "'"; } return $output; } /** * @param string $outputMode * @return ValueGenerator */ public function setOutputMode($outputMode) { $this->outputMode = (string) $outputMode; return $this; } /** * @return string */ public function getOutputMode() { return $this->outputMode; } /** @return string */ public function __toString() { return $this->generate(); } } src/Generic/Prototype/PrototypeClassFactory.php000064400000006061144760112670015763 0ustar00addPrototype($prototype); } if ($genericPrototype) { $this->setGenericPrototype($genericPrototype); } } /** * @throws Exception\InvalidArgumentException */ public function addPrototype(PrototypeInterface $prototype) { $prototypeName = $this->normalizeName($prototype->getName()); if (isset($this->prototypes[$prototypeName])) { throw new Exception\InvalidArgumentException('A prototype with this name already exists in this manager'); } $this->prototypes[$prototypeName] = $prototype; } /** * @throws Exception\InvalidArgumentException */ public function setGenericPrototype(PrototypeGenericInterface $prototype) { if (isset($this->genericPrototype)) { throw new Exception\InvalidArgumentException('A default prototype is already set'); } $this->genericPrototype = $prototype; } /** * @param string $name * @return string */ protected function normalizeName($name) { return str_replace(['-', '_'], '', $name); } /** * @param string $name * @return bool */ public function hasPrototype($name) { $name = $this->normalizeName($name); return isset($this->prototypes[$name]); } /** * @param string $prototypeName * @return PrototypeInterface * @throws Exception\RuntimeException */ public function getClonedPrototype($prototypeName) { $prototypeName = $this->normalizeName($prototypeName); if (! $this->hasPrototype($prototypeName) && ! isset($this->genericPrototype)) { throw new Exception\RuntimeException('This tag name is not supported by this tag manager'); } if (! $this->hasPrototype($prototypeName)) { $newPrototype = clone $this->genericPrototype; $newPrototype->setName($prototypeName); } else { $newPrototype = clone $this->prototypes[$prototypeName]; } return $newPrototype; } } src/Generic/Prototype/PrototypeGenericInterface.php000064400000000416144760112670016561 0ustar00docBlock)) { return $this->docBlock; } if ('' == $this->getDocComment()) { return false; } $this->docBlock = new DocBlockReflection($this); return $this->docBlock; } /** * Return the start line of the class * * @param bool $includeDocComment * @return int */ public function getStartLine($includeDocComment = false) { if ($includeDocComment && $this->getDocComment() != '') { return $this->getDocBlock()->getStartLine(); } return parent::getStartLine(); } /** * Return the contents of the class * * @param bool $includeDocBlock * @return string */ public function getContents($includeDocBlock = true) { $fileName = $this->getFileName(); if (false === $fileName || ! file_exists($fileName)) { return ''; } $filelines = file($fileName); $startnum = $this->getStartLine($includeDocBlock); $endnum = $this->getEndLine() - $this->getStartLine(); // Ensure we get between the open and close braces $lines = array_slice($filelines, $startnum, $endnum); array_unshift($lines, $filelines[$startnum - 1]); return strstr(implode('', $lines), '{'); } /** * Get all reflection objects of implemented interfaces * * @return ClassReflection[] */ public function getInterfaces() { $phpReflections = parent::getInterfaces(); $laminasReflections = []; while ($phpReflections && ($phpReflection = array_shift($phpReflections))) { $instance = new ClassReflection($phpReflection->getName()); $laminasReflections[] = $instance; unset($phpReflection); } unset($phpReflections); return $laminasReflections; } /** * Return method reflection by name * * @param string $name * @return MethodReflection */ public function getMethod($name) { return new MethodReflection($this->getName(), parent::getMethod($name)->getName()); } /** * Get reflection objects of all methods * * @param int $filter * @return MethodReflection[] */ public function getMethods($filter = -1) { $methods = []; foreach (parent::getMethods($filter) as $method) { $instance = new MethodReflection($this->getName(), $method->getName()); $methods[] = $instance; } return $methods; } /** * Returns an array of reflection classes of traits used by this class. * * @return null|array */ public function getTraits() { $vals = []; $traits = parent::getTraits(); if ($traits === null) { return; } foreach ($traits as $trait) { $vals[] = new ClassReflection($trait->getName()); } return $vals; } /** * Get parent reflection class of reflected class * * @return ClassReflection|bool */ public function getParentClass() { $phpReflection = parent::getParentClass(); if ($phpReflection) { $laminasReflection = new ClassReflection($phpReflection->getName()); unset($phpReflection); return $laminasReflection; } return false; } /** * Return reflection property of this class by name * * @param string $name * @return PropertyReflection */ public function getProperty($name) { $phpReflection = parent::getProperty($name); $laminasReflection = new PropertyReflection($this->getName(), $phpReflection->getName()); unset($phpReflection); return $laminasReflection; } /** * Return reflection properties of this class * * @param int $filter * @return PropertyReflection[] */ public function getProperties($filter = -1) { $phpReflections = parent::getProperties($filter); $laminasReflections = []; while ($phpReflections && ($phpReflection = array_shift($phpReflections))) { $instance = new PropertyReflection($this->getName(), $phpReflection->getName()); $laminasReflections[] = $instance; unset($phpReflection); } unset($phpReflections); return $laminasReflections; } /** * @return string */ public function toString() { return parent::__toString(); } /** * @return string */ public function __toString() { return parent::__toString(); } } src/Reflection/DocBlock/Tag/AuthorTag.php000064400000002405144760112670014240 0ustar00]*)\>)?(.*)$/u', $tagDocblockLine, $match)) { return; } if ($match[1] !== '') { $this->authorName = rtrim($match[1]); } if (isset($match[3]) && $match[3] !== '') { $this->authorEmail = $match[3]; } } /** * @return null|string */ public function getAuthorName() { return $this->authorName; } /** * @return null|string */ public function getAuthorEmail() { return $this->authorEmail; } /** * @return string * @psalm-return non-empty-string */ public function __toString() { return 'DocBlock Tag [ * @' . $this->getName() . ' ]' . "\n"; } } src/Reflection/DocBlock/Tag/GenericTag.php000064400000003545144760112670014360 0ustar00contentSplitCharacter = $contentSplitCharacter; } /** * @param string $tagDocBlockLine * @return void */ public function initialize($tagDocBlockLine) { $this->parse($tagDocBlockLine); } /** * Get annotation tag name * * @return string */ public function getName() { return $this->name; } /** * @param string $name */ public function setName($name) { $this->name = $name; } /** * @return string */ public function getContent() { return $this->content; } /** * @param int $position * @return string */ public function returnValue($position) { return $this->values[$position]; } /** * Serialize to string * * Required by Reflector * * @todo What should this do? * @return string * @psalm-return non-empty-string */ public function __toString() { return 'DocBlock Tag [ * @' . $this->name . ' ]' . "\n"; } /** * @param string $docBlockLine */ protected function parse($docBlockLine) { $this->content = trim($docBlockLine); $this->values = explode($this->contentSplitCharacter, $docBlockLine); } } src/Reflection/DocBlock/Tag/LicenseTag.php000064400000002341144760112670014357 0ustar00url = trim($match[1]); } if (isset($match[2]) && $match[2] !== '') { $this->licenseName = $match[2]; } } /** * @return null|string */ public function getUrl() { return $this->url; } /** * @return null|string */ public function getLicenseName() { return $this->licenseName; } /** * @return string * @psalm-return non-empty-string */ public function __toString() { return 'DocBlock Tag [ * @' . $this->getName() . ' ]' . "\n"; } } src/Reflection/DocBlock/Tag/MethodTag.php000064400000004164144760112670014222 0ustar00 */ protected $types = []; /** @var string */ protected $methodName; /** @var string */ protected $description; /** * Is static method * * @var bool */ protected $isStatic = false; /** * @return string */ public function getName() { return 'method'; } /** * Initializer * * @param string $tagDocblockLine */ public function initialize($tagDocblockLine) { $match = []; if (! preg_match('#^(static[\s]+)?(.+[\s]+)?(.+\(\))[\s]*(.*)$#m', $tagDocblockLine, $match)) { return; } if ($match[1] !== '') { $this->isStatic = true; } if ($match[2] !== '') { $this->types = explode('|', rtrim($match[2])); } $this->methodName = $match[3]; if ($match[4] !== '') { $this->description = $match[4]; } } /** * Get return value type * * @deprecated 2.0.4 use getTypes instead * * @return null|string */ public function getReturnType() { if (empty($this->types)) { return; } return $this->types[0]; } /** {@inheritDoc} */ public function getTypes() { return $this->types; } /** * @return string */ public function getMethodName() { return $this->methodName; } /** * @return null|string */ public function getDescription() { return $this->description; } /** * @return bool */ public function isStatic() { return $this->isStatic; } /** * @return string * @psalm-return non-empty-string */ public function __toString() { return 'DocBlock Tag [ * @' . $this->getName() . ' ]' . "\n"; } } src/Reflection/DocBlock/Tag/ParamTag.php000064400000003345144760112670014042 0ustar00 */ protected $types = []; /** @var string */ protected $variableName; /** @var string */ protected $description; /** * @return string */ public function getName() { return 'param'; } /** * Initializer * * @param string $tagDocBlockLine */ public function initialize($tagDocBlockLine) { $matches = []; if (! preg_match('#((?:[\w|\\\]+(?:\[\])*\|?)+)(?:\s+(\$\S+))?(?:\s+(.*))?#s', $tagDocBlockLine, $matches)) { return; } $this->types = explode('|', $matches[1]); if (isset($matches[2])) { $this->variableName = $matches[2]; } if (isset($matches[3])) { $this->description = trim(preg_replace('#\s+#', ' ', $matches[3])); } } /** * Get parameter variable type * * @deprecated 2.0.4 use getTypes instead * * @return string */ public function getType() { if (empty($this->types)) { return ''; } return $this->types[0]; } /** {@inheritDoc} */ public function getTypes() { return $this->types; } /** * Get parameter name * * @return string */ public function getVariableName() { return $this->variableName; } /** * @return string */ public function getDescription() { return $this->description; } } src/Reflection/DocBlock/Tag/PhpDocTypedTagInterface.php000064400000000407144760112670017002 0ustar00 */ public function getTypes(); } src/Reflection/DocBlock/Tag/PropertyTag.php000064400000003465144760112670014631 0ustar00 */ protected $types = []; /** @var string */ protected $propertyName; /** @var string */ protected $description; /** * @return string */ public function getName() { return 'property'; } /** * Initializer * * @param string $tagDocblockLine */ public function initialize($tagDocblockLine) { $match = []; if (! preg_match('#^(.+)?(\$[\S]+)[\s]*(.*)$#m', $tagDocblockLine, $match)) { return; } if ($match[1] !== '') { $this->types = explode('|', rtrim($match[1])); } if ($match[2] !== '') { $this->propertyName = $match[2]; } if ($match[3] !== '') { $this->description = $match[3]; } } /** * @deprecated 2.0.4 use getTypes instead * * @return null|string */ public function getType() { if (empty($this->types)) { return; } return $this->types[0]; } /** {@inheritDoc} */ public function getTypes() { return $this->types; } /** * @return null|string */ public function getPropertyName() { return $this->propertyName; } /** * @return null|string */ public function getDescription() { return $this->description; } /** * @return string * @psalm-return non-empty-string */ public function __toString() { return 'DocBlock Tag [ * @' . $this->getName() . ' ]' . "\n"; } } src/Reflection/DocBlock/Tag/ReturnTag.php000064400000002507144760112670014260 0ustar00types = explode('|', $matches[1]); if (isset($matches[2])) { $this->description = trim(preg_replace('#\s+#', ' ', $matches[2])); } } /** * @deprecated 2.0.4 use getTypes instead * * @return string */ public function getType() { if (empty($this->types)) { return ''; } return $this->types[0]; } /** {@inheritDoc} */ public function getTypes() { return $this->types; } /** * @return string */ public function getDescription() { return $this->description; } } src/Reflection/DocBlock/Tag/TagInterface.php000064400000000423144760112670014674 0ustar00 */ protected $types = []; /** @var string */ protected $description; /** * @return string */ public function getName() { return 'throws'; } /** * @param string $tagDocBlockLine * @return void */ public function initialize($tagDocBlockLine) { $matches = []; preg_match('#([\w|\\\]+)(?:\s+(.*))?#', $tagDocBlockLine, $matches); $this->types = explode('|', $matches[1]); if (isset($matches[2])) { $this->description = $matches[2]; } } /** * Get return variable type * * @deprecated 2.0.4 use getTypes instead * * @return string */ public function getType() { return implode('|', $this->getTypes()); } /** {@inheritDoc} */ public function getTypes() { return $this->types; } /** * @return string */ public function getDescription() { return $this->description; } } src/Reflection/DocBlock/Tag/VarTag.php000064400000003114144760112670013524 0ustar00 */ private $types = []; /** @var string|null */ private $variableName; /** @var string|null */ private $description; /** * {@inheritDoc} */ public function getName(): string { return 'var'; } /** * {@inheritDoc} */ public function initialize($tagDocblockLine): void { $match = []; if ( ! preg_match( '#^([^\$]\S+)?\s*(\$[\S]+)?\s*(.*)$#m', $tagDocblockLine, $match ) ) { return; } if ($match[1] !== '') { $this->types = explode('|', rtrim($match[1])); } if ($match[2] !== '') { $this->variableName = $match[2]; } if ($match[3] !== '') { $this->description = $match[3]; } } /** {@inheritDoc} */ public function getTypes(): array { return $this->types; } public function getVariableName(): ?string { return $this->variableName; } public function getDescription(): ?string { return $this->description; } /** * @psalm-return non-empty-string */ public function __toString(): string { return 'DocBlock Tag [ * @' . $this->getName() . ' ]' . PHP_EOL; } } src/Reflection/DocBlock/TagManager.php000064400000002163144760112670013636 0ustar00addPrototype(new Tag\ParamTag()); $this->addPrototype(new Tag\ReturnTag()); $this->addPrototype(new Tag\MethodTag()); $this->addPrototype(new Tag\PropertyTag()); $this->addPrototype(new Tag\AuthorTag()); $this->addPrototype(new Tag\LicenseTag()); $this->addPrototype(new Tag\ThrowsTag()); $this->addPrototype(new Tag\VarTag()); $this->setGenericPrototype(new Tag\GenericTag()); } /** * @param string $tagName * @param string $content * @return TagInterface */ public function createTag($tagName, $content = null) { /** @var TagInterface $newTag */ $newTag = $this->getClonedPrototype($tagName); if ($content) { $newTag->initialize($content); } return $newTag; } } src/Reflection/DocBlockReflection.php000064400000014600144760112670013642 0ustar00initializeDefaultTags(); } $this->tagManager = $tagManager; if ($commentOrReflector instanceof Reflector) { $this->reflector = $commentOrReflector; if (! method_exists($commentOrReflector, 'getDocComment')) { throw new Exception\InvalidArgumentException('Reflector must contain method "getDocComment"'); } $this->docComment = $commentOrReflector->getDocComment(); // determine line numbers $lineCount = substr_count($this->docComment, "\n"); $this->startLine = $this->reflector->getStartLine() - $lineCount - 1; $this->endLine = $this->reflector->getStartLine() - 1; } elseif (is_string($commentOrReflector)) { $this->docComment = $commentOrReflector; } else { throw new Exception\InvalidArgumentException(sprintf( '%s must have a (string) DocComment or a Reflector in the constructor', static::class )); } if ($this->docComment == '') { throw new Exception\InvalidArgumentException('DocComment cannot be empty'); } $this->reflect(); } /** * Retrieve contents of DocBlock * * @return string */ public function getContents() { $this->reflect(); return $this->cleanDocComment; } /** * Get start line (position) of DocBlock * * @return int */ public function getStartLine() { $this->reflect(); return $this->startLine; } /** * Get last line (position) of DocBlock * * @return int */ public function getEndLine() { $this->reflect(); return $this->endLine; } /** * Get DocBlock short description * * @return string */ public function getShortDescription() { $this->reflect(); return $this->shortDescription; } /** * Get DocBlock long description * * @return string */ public function getLongDescription() { $this->reflect(); return $this->longDescription; } /** * Does the DocBlock contain the given annotation tag? * * @param string $name * @return bool */ public function hasTag($name) { $this->reflect(); foreach ($this->tags as $tag) { if ($tag->getName() == $name) { return true; } } return false; } /** * Retrieve the given DocBlock tag * * @param string $name * @return DocBlockTagInterface|false */ public function getTag($name) { $this->reflect(); foreach ($this->tags as $tag) { if ($tag->getName() == $name) { return $tag; } } return false; } /** * Get all DocBlock annotation tags * * @param string $filter * @return DocBlockTagInterface[] */ public function getTags($filter = null) { $this->reflect(); if ($filter === null || ! is_string($filter)) { return $this->tags; } $returnTags = []; foreach ($this->tags as $tag) { if ($tag->getName() == $filter) { $returnTags[] = $tag; } } return $returnTags; } /** * Parse the DocBlock * * @return void */ protected function reflect() { if ($this->isReflected) { return; } $docComment = preg_replace('#[ ]{0,1}\*/$#', '', $this->docComment); // create a clean docComment $this->cleanDocComment = preg_replace("#[ \t]*(?:/\*\*|\*/|\*)[ ]{0,1}(.*)?#", '$1', $docComment); // @todo should be changed to remove first and last empty line $this->cleanDocComment = ltrim($this->cleanDocComment, "\r\n"); $scanner = new DocBlockScanner($docComment); $this->shortDescription = ltrim($scanner->getShortDescription()); $this->longDescription = ltrim($scanner->getLongDescription()); foreach ($scanner->getTags() as $tag) { $this->tags[] = $this->tagManager->createTag(ltrim($tag['name'], '@'), ltrim($tag['value'])); } $this->isReflected = true; } /** * @return string */ public function toString() { $str = 'DocBlock [ /* DocBlock */ ] {' . "\n\n"; $str .= ' - Tags [' . count($this->tags) . '] {' . "\n"; foreach ($this->tags as $tag) { $str .= ' ' . $tag; } $str .= ' }' . "\n"; $str .= '}' . "\n"; return $str; } /** * Serialize to string * * Required by the Reflector interface * * @return string */ public function __toString() { return $this->toString(); } } src/Reflection/Exception/BadMethodCallException.php000064400000000276144760112670016413 0ustar00getDocComment())) { throw new Exception\InvalidArgumentException(sprintf( '%s does not have a DocBlock', $this->getName() )); } return new DocBlockReflection($comment); } /** * Get start line (position) of function * * @param bool $includeDocComment * @return int */ public function getStartLine($includeDocComment = false) { if ($includeDocComment) { if ($this->getDocComment() != '') { return $this->getDocBlock()->getStartLine(); } } return parent::getStartLine(); } /** * Get contents of function * * @param bool $includeDocBlock * @return string */ public function getContents($includeDocBlock = true) { $fileName = $this->getFileName(); if (false === $fileName) { return ''; } $startLine = $this->getStartLine(); $endLine = $this->getEndLine(); // eval'd protect if (preg_match('#\((\d+)\) : eval\(\)\'d code$#', $fileName, $matches)) { $fileName = preg_replace('#\(\d+\) : eval\(\)\'d code$#', '', $fileName); $startLine = $endLine = $matches[1]; } $lines = array_slice( file($fileName, FILE_IGNORE_NEW_LINES), $startLine - 1, $endLine - ($startLine - 1), true ); $functionLine = implode("\n", $lines); $content = ''; if ($this->isClosure()) { preg_match('#function\s*\([^\)]*\)\s*(use\s*\([^\)]+\))?\s*\{(.*\;)?\s*\}#s', $functionLine, $matches); if (isset($matches[0])) { $content = $matches[0]; } } else { $name = substr($this->getName(), strrpos($this->getName(), '\\') + 1); preg_match( '#function\s+' . preg_quote($name) . '\s*\([^\)]*\)\s*{([^{}]+({[^}]+})*[^}]+)?}#', $functionLine, $matches ); if (isset($matches[0])) { $content = $matches[0]; } } $docComment = $this->getDocComment(); return $includeDocBlock && $docComment ? $docComment . "\n" . $content : $content; } /** * Get method prototype * * @param string $format * @return array|string */ public function getPrototype($format = self::PROTOTYPE_AS_ARRAY) { $returnType = 'mixed'; $docBlock = $this->getDocBlock(); if ($docBlock) { $return = $docBlock->getTag('return'); $returnTypes = $return->getTypes(); $returnType = count($returnTypes) > 1 ? implode('|', $returnTypes) : $returnTypes[0]; } $prototype = [ 'namespace' => $this->getNamespaceName(), 'name' => substr($this->getName(), strlen($this->getNamespaceName()) + 1), 'return' => $returnType, 'arguments' => [], ]; $parameters = $this->getParameters(); foreach ($parameters as $parameter) { $prototype['arguments'][$parameter->getName()] = [ 'type' => $parameter->detectType(), 'required' => ! $parameter->isOptional(), 'by_ref' => $parameter->isPassedByReference(), 'default' => $parameter->isDefaultValueAvailable() ? $parameter->getDefaultValue() : null, ]; } if ($format == self::PROTOTYPE_AS_STRING) { $line = $prototype['return'] . ' ' . $prototype['name'] . '('; $args = []; foreach ($prototype['arguments'] as $name => $argument) { $argsLine = ($argument['type'] ? $argument['type'] . ' ' : '') . ($argument['by_ref'] ? '&' : '') . '$' . $name; if (! $argument['required']) { $argsLine .= ' = ' . var_export($argument['default'], true); } $args[] = $argsLine; } $line .= implode(', ', $args); $line .= ')'; return $line; } return $prototype; } /** * Get function parameters * * @return ParameterReflection[] */ public function getParameters() { $phpReflections = parent::getParameters(); $laminasReflections = []; while ($phpReflections && ($phpReflection = array_shift($phpReflections))) { $instance = new ParameterReflection($this->getName(), $phpReflection->getName()); $laminasReflections[] = $instance; unset($phpReflection); } unset($phpReflections); return $laminasReflections; } /** * Get return type tag * * @throws Exception\InvalidArgumentException * @return DocBlockReflection */ public function getReturn() { $docBlock = $this->getDocBlock(); if (! $docBlock->hasTag('return')) { throw new Exception\InvalidArgumentException( 'Function does not specify an @return annotation tag; cannot determine return type' ); } $tag = $docBlock->getTag('return'); return new DocBlockReflection('@return ' . $tag->getDescription()); } /** * Get method body * * @return string|false */ public function getBody() { $fileName = $this->getFileName(); if (false === $fileName) { throw new Exception\InvalidArgumentException( 'Cannot determine internals functions body' ); } $startLine = $this->getStartLine(); $endLine = $this->getEndLine(); // eval'd protect if (preg_match('#\((\d+)\) : eval\(\)\'d code$#', $fileName, $matches)) { $fileName = preg_replace('#\(\d+\) : eval\(\)\'d code$#', '', $fileName); $startLine = $endLine = $matches[1]; } $lines = array_slice( file($fileName, FILE_IGNORE_NEW_LINES), $startLine - 1, $endLine - ($startLine - 1), true ); $functionLine = implode("\n", $lines); $body = false; if ($this->isClosure()) { preg_match('#function\s*\([^\)]*\)\s*(use\s*\([^\)]+\))?\s*\{(.*\;)\s*\}#s', $functionLine, $matches); if (isset($matches[2])) { $body = $matches[2]; } } else { $name = substr($this->getName(), strrpos($this->getName(), '\\') + 1); preg_match('#function\s+' . $name . '\s*\([^\)]*\)\s*{([^{}]+({[^}]+})*[^}]+)}#', $functionLine, $matches); if (isset($matches[1])) { $body = $matches[1]; } } return $body; } /** * @return string */ public function toString() { return $this->__toString(); } /** * Required due to bug in php * * @return string */ public function __toString() { return parent::__toString(); } } src/Reflection/MethodReflection.php000064400000032416144760112670013407 0ustar00getDocComment()) { return false; } return new DocBlockReflection($this); } /** * Get start line (position) of method * * @param bool $includeDocComment * @return int */ public function getStartLine($includeDocComment = false) { if ($includeDocComment) { if ($this->getDocComment() != '') { return $this->getDocBlock()->getStartLine(); } } return parent::getStartLine(); } /** * Get reflection of declaring class * * @return ClassReflection */ public function getDeclaringClass() { $phpReflection = parent::getDeclaringClass(); $laminasReflection = new ClassReflection($phpReflection->getName()); unset($phpReflection); return $laminasReflection; } /** * Get method prototype * * @param string $format * @return array|string */ public function getPrototype($format = self::PROTOTYPE_AS_ARRAY) { $returnType = 'mixed'; $docBlock = $this->getDocBlock(); if ($docBlock) { $return = $docBlock->getTag('return'); $returnTypes = $return->getTypes(); $returnType = count($returnTypes) > 1 ? implode('|', $returnTypes) : $returnTypes[0]; } $declaringClass = $this->getDeclaringClass(); $prototype = [ 'namespace' => $declaringClass->getNamespaceName(), 'class' => substr($declaringClass->getName(), strlen($declaringClass->getNamespaceName()) + 1), 'name' => $this->getName(), 'visibility' => $this->isPublic() ? 'public' : ($this->isPrivate() ? 'private' : 'protected'), 'return' => $returnType, 'arguments' => [], ]; $parameters = $this->getParameters(); foreach ($parameters as $parameter) { $prototype['arguments'][$parameter->getName()] = [ 'type' => $parameter->detectType(), 'required' => ! $parameter->isOptional(), 'by_ref' => $parameter->isPassedByReference(), 'default' => $parameter->isDefaultValueAvailable() ? $parameter->getDefaultValue() : null, ]; } if ($format == self::PROTOTYPE_AS_STRING) { $line = $prototype['visibility'] . ' ' . $prototype['return'] . ' ' . $prototype['name'] . '('; $args = []; foreach ($prototype['arguments'] as $name => $argument) { $argsLine = ($argument['type'] ? $argument['type'] . ' ' : '') . ($argument['by_ref'] ? '&' : '') . '$' . $name; if (! $argument['required']) { $argsLine .= ' = ' . var_export($argument['default'], true); } $args[] = $argsLine; } $line .= implode(', ', $args); $line .= ')'; return $line; } return $prototype; } /** * Get all method parameter reflection objects * * @return ParameterReflection[] */ public function getParameters() { $phpReflections = parent::getParameters(); $laminasReflections = []; while ($phpReflections && ($phpReflection = array_shift($phpReflections))) { $instance = new ParameterReflection( [$this->getDeclaringClass()->getName(), $this->getName()], $phpReflection->getName() ); $laminasReflections[] = $instance; unset($phpReflection); } unset($phpReflections); return $laminasReflections; } /** * Get method contents * * @param bool $includeDocBlock * @return string */ public function getContents($includeDocBlock = true) { $docComment = $this->getDocComment(); $content = $includeDocBlock && ! empty($docComment) ? $docComment . "\n" : ''; $content .= $this->extractMethodContents(); return $content; } /** * Get method body * * @return string */ public function getBody() { return $this->extractMethodContents(true); } /** * Tokenize method string and return concatenated body * * @param bool $bodyOnly * @return string */ protected function extractMethodContents($bodyOnly = false) { $fileName = $this->getFileName(); if ((class_exists($this->class) && false === $fileName) || ! file_exists($fileName)) { return ''; } $lines = array_slice( file($fileName, FILE_IGNORE_NEW_LINES), $this->getStartLine() - 1, $this->getEndLine() - ($this->getStartLine() - 1), true ); $functionLine = implode("\n", $lines); $tokens = token_get_all(' $token) { $tokenType = is_array($token) ? token_name($token[0]) : $token; $tokenValue = is_array($token) ? $token[1] : $token; switch ($tokenType) { case 'T_FINAL': case 'T_ABSTRACT': case 'T_PUBLIC': case 'T_PROTECTED': case 'T_PRIVATE': case 'T_STATIC': case 'T_FUNCTION': // check to see if we have a valid function // then check if we are inside function and have a closure if ($this->isValidFunction($tokens, $key, $this->getName())) { if ($bodyOnly === false) { //if first instance of tokenType grab prefixed whitespace //and append to body if ($capture === false) { $body .= $this->extractPrefixedWhitespace($tokens, $key); } $body .= $tokenValue; } $capture = true; } else { //closure test if ($firstBrace && $tokenType == 'T_FUNCTION') { $body .= $tokenValue; break; } $capture = false; break; } break; case '{': if ($capture === false) { break; } if ($firstBrace === false) { $firstBrace = true; if ($bodyOnly === true) { break; } } $body .= $tokenValue; break; case '}': if ($capture === false) { break; } //check to see if this is the last brace if ($this->isEndingBrace($tokens, $key)) { //capture the end brace if not bodyOnly if ($bodyOnly === false) { $body .= $tokenValue; } break 2; } $body .= $tokenValue; break; default: if ($capture === false) { break; } // if returning body only wait for first brace before capturing if ($bodyOnly === true && $firstBrace !== true) { break; } $body .= $tokenValue; break; } } //remove ending whitespace and return return rtrim($body); } /** * Take current position and find any whitespace * * @param array $haystack * @param int $position * @return string */ protected function extractPrefixedWhitespace($haystack, $position) { $content = ''; $count = count($haystack); if ($position + 1 == $count) { return $content; } for ($i = $position - 1; $i >= 0; $i--) { $tokenType = is_array($haystack[$i]) ? token_name($haystack[$i][0]) : $haystack[$i]; $tokenValue = is_array($haystack[$i]) ? $haystack[$i][1] : $haystack[$i]; //search only for whitespace if ($tokenType == 'T_WHITESPACE') { $content .= $tokenValue; } else { break; } } return $content; } /** * Test for ending brace * * @param array $haystack * @param int $position * @return bool */ protected function isEndingBrace($haystack, $position) { $count = count($haystack); //advance one position $position += 1; if ($position == $count) { return true; } for ($i = $position; $i < $count; $i++) { $tokenType = is_array($haystack[$i]) ? token_name($haystack[$i][0]) : $haystack[$i]; switch ($tokenType) { case 'T_FINAL': case 'T_ABSTRACT': case 'T_PUBLIC': case 'T_PROTECTED': case 'T_PRIVATE': case 'T_STATIC': return true; case 'T_FUNCTION': // If a function is encountered and that function is not a closure // then return true. otherwise the function is a closure, return false if ($this->isValidFunction($haystack, $i)) { return true; } return false; case '}': case ';': case 'T_BREAK': case 'T_CATCH': case 'T_DO': case 'T_ECHO': case 'T_ELSE': case 'T_ELSEIF': case 'T_EVAL': case 'T_EXIT': case 'T_FINALLY': case 'T_FOR': case 'T_FOREACH': case 'T_GOTO': case 'T_IF': case 'T_INCLUDE': case 'T_INCLUDE_ONCE': case 'T_PRINT': case 'T_STRING': case 'T_STRING_VARNAME': case 'T_THROW': case 'T_USE': case 'T_VARIABLE': case 'T_WHILE': case 'T_YIELD': return false; } } } /** * Test to see if current position is valid function or * closure. Returns true if it's a function and NOT a closure * * @param array $haystack * @param int $position * @param string $functionName * @return bool */ protected function isValidFunction($haystack, $position, $functionName = null) { $isValid = false; $count = count($haystack); for ($i = $position + 1; $i < $count; $i++) { $tokenType = is_array($haystack[$i]) ? token_name($haystack[$i][0]) : $haystack[$i]; $tokenValue = is_array($haystack[$i]) ? $haystack[$i][1] : $haystack[$i]; //check for occurrence of ( or if ($tokenType == 'T_STRING') { //check to see if function name is passed, if so validate against that if ($functionName !== null && $tokenValue != $functionName) { $isValid = false; break; } $isValid = true; break; } elseif ($tokenValue == '(') { break; } } return $isValid; } /** * @return string */ public function toString() { return parent::__toString(); } /** * @return string */ public function __toString() { return parent::__toString(); } } src/Reflection/ParameterReflection.php000064400000005402144760112670014102 0ustar00getName()); unset($phpReflection); return $laminasReflection; } /** * Get class reflection object * * @return null|ClassReflection */ public function getClass() { $phpReflectionType = parent::getType(); if ($phpReflectionType === null) { return null; } $laminasReflection = new ClassReflection($phpReflectionType->getName()); unset($phpReflectionType); return $laminasReflection; } /** * Get declaring function reflection object * * @return FunctionReflection|MethodReflection */ public function getDeclaringFunction() { $phpReflection = parent::getDeclaringFunction(); if ($phpReflection instanceof ReflectionMethod) { $laminasReflection = new MethodReflection($this->getDeclaringClass()->getName(), $phpReflection->getName()); } else { $laminasReflection = new FunctionReflection($phpReflection->getName()); } unset($phpReflection); return $laminasReflection; } /** * Get parameter type * * @return string|null */ public function detectType() { if ( method_exists($this, 'getType') && null !== ($type = $this->getType()) && $type->isBuiltin() ) { return $type->getName(); } if (null !== $type && $type->getName() === 'self') { return $this->getDeclaringClass()->getName(); } if (($class = $this->getClass()) instanceof ReflectionClass) { return $class->getName(); } $docBlock = $this->getDeclaringFunction()->getDocBlock(); if (! $docBlock instanceof DocBlockReflection) { return null; } $params = $docBlock->getTags('param'); if (isset($params[$this->getPosition()])) { return $params[$this->getPosition()]->getType(); } return null; } /** * @return string */ public function toString() { return parent::__toString(); } /** * @return string */ public function __toString() { return parent::__toString(); } } src/Reflection/PropertyReflection.php000064400000002171144760112670014006 0ustar00getName()); unset($phpReflection); return $laminasReflection; } /** * Get DocBlock comment * * @return string|false False if no DocBlock defined */ public function getDocComment() { return parent::getDocComment(); } /** * @return false|DocBlockReflection */ public function getDocBlock() { if (! ($docComment = $this->getDocComment())) { return false; } return new DocBlockReflection($docComment); } /** * @return string */ public function toString() { return $this->__toString(); } } src/Reflection/ReflectionInterface.php000064400000000377144760112670014070 0ustar00docComment = $docComment; } /** * @return string */ public function getShortDescription() { $this->scan(); return $this->shortDescription; } /** * @return string */ public function getLongDescription() { $this->scan(); return $this->longDescription; } /** * @return array */ public function getTags() { $this->scan(); return $this->tags; } /** * @return void */ protected function scan() { if ($this->isScanned) { return; } $mode = 1; $tokens = $this->tokenize(); $tagIndex = null; reset($tokens); SCANNER_TOP: $token = current($tokens); switch ($token[0]) { case 'DOCBLOCK_NEWLINE': if ($this->shortDescription != '' && $tagIndex === null) { $mode = 2; } else { $this->longDescription .= $token[1]; } goto SCANNER_CONTINUE; //goto no break needed case 'DOCBLOCK_WHITESPACE': case 'DOCBLOCK_TEXT': if ($tagIndex !== null) { $this->tags[$tagIndex]['value'] .= $this->tags[$tagIndex]['value'] == '' ? $token[1] : ' ' . $token[1]; goto SCANNER_CONTINUE; } elseif ($mode <= 2) { if ($mode == 1) { $this->shortDescription .= $token[1]; } else { $this->longDescription .= $token[1]; } goto SCANNER_CONTINUE; } //gotos no break needed case 'DOCBLOCK_TAG': array_push($this->tags, [ 'name' => $token[1], 'value' => '', ]); end($this->tags); $tagIndex = key($this->tags); $mode = 3; goto SCANNER_CONTINUE; //goto no break needed case 'DOCBLOCK_COMMENTEND': goto SCANNER_END; } SCANNER_CONTINUE: if (next($tokens) === false) { goto SCANNER_END; } goto SCANNER_TOP; SCANNER_END: $this->shortDescription = trim($this->shortDescription); $this->longDescription = trim($this->longDescription); $this->isScanned = true; } /** * @return array */ protected function tokenize() { static $CONTEXT_INSIDE_DOCBLOCK = 0x01; static $CONTEXT_INSIDE_ASTERISK = 0x02; $context = 0x00; $stream = $this->docComment; $streamIndex = null; $tokens = []; $tokenIndex = null; $currentChar = null; $currentWord = null; $currentLine = null; $MACRO_STREAM_ADVANCE_CHAR = function ($positionsForward = 1) use ( &$stream, &$streamIndex, &$currentChar, &$currentWord, &$currentLine ) { $positionsForward = $positionsForward > 0 ? $positionsForward : 1; $streamIndex = $streamIndex === null ? 0 : $streamIndex + $positionsForward; if (! isset($stream[$streamIndex])) { $currentChar = false; return false; } $currentChar = $stream[$streamIndex]; $matches = []; $currentLine = preg_match('#(.*?)\r?\n#', $stream, $matches, 0, $streamIndex) === 1 ? $matches[1] : substr($stream, $streamIndex); if ($currentChar === ' ') { $currentWord = preg_match('#( +)#', $currentLine, $matches) === 1 ? $matches[1] : $currentLine; } else { $currentWord = ($matches = strpos($currentLine, ' ')) !== false ? substr($currentLine, 0, $matches) : $currentLine; } return $currentChar; }; $MACRO_STREAM_ADVANCE_WORD = function () use (&$currentWord, &$MACRO_STREAM_ADVANCE_CHAR) { return $MACRO_STREAM_ADVANCE_CHAR(strlen($currentWord)); }; $MACRO_STREAM_ADVANCE_LINE = function () use (&$currentLine, &$MACRO_STREAM_ADVANCE_CHAR) { return $MACRO_STREAM_ADVANCE_CHAR(strlen($currentLine)); }; $MACRO_TOKEN_ADVANCE = function () use (&$tokenIndex, &$tokens) { $tokenIndex = $tokenIndex === null ? 0 : $tokenIndex + 1; $tokens[$tokenIndex] = ['DOCBLOCK_UNKNOWN', '']; }; $MACRO_TOKEN_SET_TYPE = function ($type) use (&$tokenIndex, &$tokens) { $tokens[$tokenIndex][0] = $type; }; $MACRO_TOKEN_APPEND_CHAR = function () use (&$currentChar, &$tokens, &$tokenIndex) { $tokens[$tokenIndex][1] .= $currentChar; }; $MACRO_TOKEN_APPEND_WORD = function () use (&$currentWord, &$tokens, &$tokenIndex) { $tokens[$tokenIndex][1] .= $currentWord; }; $MACRO_TOKEN_APPEND_WORD_PARTIAL = function ($length) use (&$currentWord, &$tokens, &$tokenIndex) { $tokens[$tokenIndex][1] .= substr($currentWord, 0, $length); }; $MACRO_TOKEN_APPEND_LINE = function () use (&$currentLine, &$tokens, &$tokenIndex) { $tokens[$tokenIndex][1] .= $currentLine; }; $MACRO_STREAM_ADVANCE_CHAR(); $MACRO_TOKEN_ADVANCE(); TOKENIZER_TOP: if ($context === 0x00 && $currentChar === '/' && $currentWord === '/**') { $MACRO_TOKEN_SET_TYPE('DOCBLOCK_COMMENTSTART'); $MACRO_TOKEN_APPEND_WORD(); $MACRO_TOKEN_ADVANCE(); $context |= $CONTEXT_INSIDE_DOCBLOCK; $context |= $CONTEXT_INSIDE_ASTERISK; if ($MACRO_STREAM_ADVANCE_WORD() === false) { goto TOKENIZER_END; } goto TOKENIZER_TOP; } if ($context & $CONTEXT_INSIDE_DOCBLOCK && $currentWord === '*/') { $MACRO_TOKEN_SET_TYPE('DOCBLOCK_COMMENTEND'); $MACRO_TOKEN_APPEND_WORD(); $MACRO_TOKEN_ADVANCE(); $context &= ~$CONTEXT_INSIDE_DOCBLOCK; if ($MACRO_STREAM_ADVANCE_WORD() === false) { goto TOKENIZER_END; } goto TOKENIZER_TOP; } if ($currentChar === ' ' || $currentChar === "\t") { $MACRO_TOKEN_SET_TYPE( $context & $CONTEXT_INSIDE_ASTERISK ? 'DOCBLOCK_WHITESPACE' : 'DOCBLOCK_WHITESPACE_INDENT' ); $MACRO_TOKEN_APPEND_WORD(); $MACRO_TOKEN_ADVANCE(); if ($MACRO_STREAM_ADVANCE_WORD() === false) { goto TOKENIZER_END; } goto TOKENIZER_TOP; } if ($currentChar === '*') { if (($context & $CONTEXT_INSIDE_DOCBLOCK) && ($context & $CONTEXT_INSIDE_ASTERISK)) { $MACRO_TOKEN_SET_TYPE('DOCBLOCK_TEXT'); } else { $MACRO_TOKEN_SET_TYPE('DOCBLOCK_ASTERISK'); $context |= $CONTEXT_INSIDE_ASTERISK; } $MACRO_TOKEN_APPEND_CHAR(); $MACRO_TOKEN_ADVANCE(); if ($MACRO_STREAM_ADVANCE_CHAR() === false) { goto TOKENIZER_END; } goto TOKENIZER_TOP; } if ($currentChar === '@') { $MACRO_TOKEN_SET_TYPE('DOCBLOCK_TAG'); $MACRO_TOKEN_APPEND_WORD(); $MACRO_TOKEN_ADVANCE(); if ($MACRO_STREAM_ADVANCE_WORD() === false) { goto TOKENIZER_END; } goto TOKENIZER_TOP; } if ($currentChar === "\n") { $MACRO_TOKEN_SET_TYPE('DOCBLOCK_NEWLINE'); $MACRO_TOKEN_APPEND_CHAR(); $MACRO_TOKEN_ADVANCE(); $context &= ~$CONTEXT_INSIDE_ASTERISK; if ($MACRO_STREAM_ADVANCE_CHAR() === false) { goto TOKENIZER_END; } goto TOKENIZER_TOP; } $MACRO_TOKEN_SET_TYPE('DOCBLOCK_TEXT'); $MACRO_TOKEN_APPEND_LINE(); $MACRO_TOKEN_ADVANCE(); if ($MACRO_STREAM_ADVANCE_LINE() === false) { goto TOKENIZER_END; } goto TOKENIZER_TOP; TOKENIZER_END: array_pop($tokens); return $tokens; } }