pax_global_header00006660000000000000000000000064130034055240014506gustar00rootroot0000000000000052 comment=2899c17f83a7207f2d7f53ec2f421204d3beea27 zend-code-release-3.1.0/000077500000000000000000000000001300340552400147755ustar00rootroot00000000000000zend-code-release-3.1.0/CHANGELOG.md000066400000000000000000000220151300340552400166060ustar00rootroot00000000000000# Changelog All notable changes to this project will be documented in this file, in reverse chronological order by release. ## 3.2.0 - TBD ### Added - Nothing. ### Deprecated - Nothing. ### Removed - Nothing. ### Fixed - Nothing. ## 3.1.1 - TBD ### Added - Nothing. ### Deprecated - Nothing. ### Removed - Nothing. ### Fixed - Nothing. ## 3.1.0 - 2016-10-24 ### Added - [#87](https://github.com/zendframework/zend-code/pull/95) support for PHP 7.1's `void` return type declaration. - [#87](https://github.com/zendframework/zend-code/pull/95) support for PHP 7.1's nullable type declarations. - [#87](https://github.com/zendframework/zend-code/pull/95) support for PHP 7.1's `iterable` type declaration. - [#62](https://github.com/zendframework/zend-code/pull/62) added `Zend\Code\Generator\MethodGenerator#getReturnType()` accessor. - [#68](https://github.com/zendframework/zend-code/pull/68) [#26](https://github.com/zendframework/zend-code/pull/26) added mutators to allow removing/checking for existence of methods, properties, constants, parameters and type declarations across all the code generator API. - [#65](https://github.com/zendframework/zend-code/pull/65) continuous integration testing now checks locked, newest and oldest dependency sets. ### Deprecated - Nothing. ### Removed - Nothing. ### Fixed - Nothing. ## 3.0.5 - 2016-10-24 ### Added - Nothing. ### Deprecated - Nothing. ### Removed - Nothing. ### Fixed - [#92](https://github.com/zendframework/zend-code/pull/92) corrected `Zend\Code\Scanner\ClassScanner` to detect multiple interface inheritance. - [#95](https://github.com/zendframework/zend-code/pull/95) corrected `Zend\Code\Generator\ParameterGenerator` to allow copying parameter signatures for non-optional parameters that are still nullable via a default `= null` value. - [#94](https://github.com/zendframework/zend-code/pull/94) corrected `Zend\Code\Generator\ValueGenerator` so that class constants can now be generated with arrays as default value (supported since PHP 5.6). ## 3.0.4 - 2016-06-30 ### Added - Nothing. ### Deprecated - Nothing. ### Removed - Nothing. ### Fixed - [#59](https://github.com/zendframework/zend-code/pull/59) fixes an issue with detection of multiple trait `use` statements. - [#75](https://github.com/zendframework/zend-code/pull/75) provides a patch to ensure that `extends` statements qualify the parent class based on the current namespace and/or import statements. ## 3.0.3 - 2016-06-27 ### Added - [#66](https://github.com/zendframework/zend-code/pull/66) publishes the documentation to https://docs.zendframework.com/zend-code/. ### Deprecated - Nothing. ### Removed - Nothing. ### Fixed - [#61](https://github.com/zendframework/zend-code/pull/61) fixes an issue with how parameter typehints were generated; previously, fully-qualified class names were not being generated with the leading backslash, causing them to attempt to resolve as if they were relative to the current namespace. - [#69](https://github.com/zendframework/zend-code/pull/69) fixes an issue with how class names under the same namespace are generated when generating typehints, extends, and implements values; they now strip the common namespace from the class name. - [#72](https://github.com/zendframework/zend-code/pull/72) fixes an issue within the `TokenArrayScanner` when scanning closures. ## 3.0.2 - 2016-04-20 ### Added - Nothing. ### Deprecated - Nothing. ### Removed - Nothing. ### Fixed - [#52](https://github.com/zendframework/zend-code/pull/52) updates several dependency constraints: - zend-stdlib now allows either the 2.7 or 3.0 series, as the APIs consumed by zend-code are compatible across versions. - PHP now excludes the 7.0.5 release, as it has known issues in its tokenizer implementation that make the zend-code token scanner unusable. - [#46](https://github.com/zendframework/zend-code/pull/46) updates all generators to use `\n` for line endings in generated code, vs `PHP_EOL`, ensuring cross-platform consistency. ## 3.0.1 - 2016-01-26 ### Added - Nothing. ### Deprecated - Nothing. ### Removed - Nothing. ### Fixed - [#34](https://github.com/zendframework/zend-code/pull/34) method name cannot be optional when adding a method to a class generator. - [#38](https://github.com/zendframework/zend-code/pull/38) PHP_CodeSniffer was moved to dev dependencies ## 3.0.0 - 2016-01-13 ### Changed This section refers to breaking changes: please refer to [doc/book/migration.md](doc/book/migration.md) for migration instructions. - Types `string`, `int`, `float`, `bool` passed to `Zend\Code\Generator\ParameterGenerator#setType()` are no longer ignored in generated code [#30](https://github.com/zendframework/zend-code/pull/30) - Types declared in DocBlocks are now ignored when creating a `Zend\Code\Generator\ParameterGenerator` via `Zend\Code\Generator\ParameterGenerator::fromReflection()`. [#30](https://github.com/zendframework/zend-code/pull/30) - Type strings are now validated: passing an invalid type to any method in the generator API may lead to a `Zend\Code\Generator\InvalidArgumentException` being thrown. [#30](https://github.com/zendframework/zend-code/pull/30) - `Zend\Code\Generator\ParameterGenerator::$simple` was removed. [#30](https://github.com/zendframework/zend-code/pull/30) - `Zend\Code\Generator\ParameterGenerator#$type` is now a `null|Zend\Code\Generator\TypeGenerator`: was a `string` before. [#30](https://github.com/zendframework/zend-code/pull/30) - `Zend\Code\Generator` type-hints are now always prefixed with the namespace separator `\`. [#30](https://github.com/zendframework/zend-code/pull/30) - `Zend\Code\Reflection\ParameterReflection#getType()` was renamed to `Zend\Code\Reflection\ParameterReflection#detectType()` in order to not override the inherited `ReflectionParameter#getType()`, introduced in PHP 7. [#30](https://github.com/zendframework/zend-code/pull/30) ### Added - PHP 7 return type hints generation support via `Zend\Code\Generator\MethodGenerator#setReturnType()`. [#30](https://github.com/zendframework/zend-code/pull/30) - PHP 7 scalar type hints generation support via `Zend\Code\Generator\ParameterGenerator#setType()` and `Zend\Code\Generator\ParameterGenerator#getType()`. [#30](https://github.com/zendframework/zend-code/pull/30) - PHP 5.6 variadic arguments support via `Zend\Code\Generator\ParameterGenerator#setVariadic()` and `Zend\Code\Generator\ParameterGenerator#getVariadic()`. [#30](https://github.com/zendframework/zend-code/pull/30) - Generation of methods returning by reference is supported via `Zend\Code\Generator\ParameterGenerator#setReturnsReference()`. [#30](https://github.com/zendframework/zend-code/pull/30) ### Deprecated - Nothing. ### Removed - `Zend\Code\ParameterGenerator::$simple` was removed. [#30](https://github.com/zendframework/zend-code/pull/30) ### Fixed - Nothing. ## 2.6.2 - 2015-01-05 ### Added - Nothing. ### Deprecated - Nothing. ### Removed - Nothing. ### Fixed - [#31](https://github.com/zendframework/zend-code/pull/31) updated license year. ## 2.6.2 - 2015-01-05 ### Added - Nothing. ### Deprecated - Nothing. ### Removed - Nothing. ### Fixed - [#31](https://github.com/zendframework/zend-code/pull/31) updated license year. ## 2.6.1 - 2015-11-24 ### Added - Nothing. ### Deprecated - Nothing. ### Removed - Nothing. ### Fixed - [#25](https://github.com/zendframework/zend-code/pull/25) changes the `doctrine/common` suggestion/dev-dependency to the more specific `doctrine/annotations` package (which is what is actually consumed). ## 2.6.0 - 2015-11-18 ### Added - [#12](https://github.com/zendframework/zend-code/pull/12) adds the ability to generate arrays using either long/standard syntax (`array(...)`) or short syntax (`[...]`). This can be accomplished by setting the value type to `ValueGenerator::TYPE_ARRAY_SHORT` instead of using `TYPE_ARRAY`. Additionally, you can use `TYPE_ARRAY_LONG` instead of `TYPE_ARRAY`; the two constants are synonyms. - [#11](https://github.com/zendframework/zend-code/pull/11) adds the ability to generate interfaces via the new class `Zend\Code\Generator\InterfaceGenerator`. ### Deprecated - Nothing. ### Removed - Nothing. ### Fixed - [#20](https://github.com/zendframework/zend-code/pull/20) updates the zend-eventmanager dependency to `^2.6|^3.0`, and changes its internal usage to use the `triggerEventUntil()` signature. ## 2.5.3 - 2015-11-18 ### Added - Nothing. ### Deprecated - Nothing. ### Removed - [#10](https://github.com/zendframework/zend-code/pull/10) removes a development dependency on zendframework/zend-version. - [#23](https://github.com/zendframework/zend-code/pull/23) removes a requirement on zendframework/zend-stdlib. This results in a slight change in `Zend\Code\Generator\ValueGenerator`: `setConstants()` and `getConstants()` can now receive/emit *either* an SPL `ArrayObject` or `Zend\Stdlib\ArrayObject`. Since these are functionally equivalent, however, you will experience no change in behavior. ### Fixed - Nothing. zend-code-release-3.1.0/CONDUCT.md000066400000000000000000000045121300340552400164200ustar00rootroot00000000000000# Contributor Code of Conduct The Zend Framework project adheres to [The Code Manifesto](http://codemanifesto.com) as its guidelines for contributor interactions. ## The Code Manifesto We want to work in an ecosystem that empowers developers to reach their potential — one that encourages growth and effective collaboration. A space that is safe for all. A space such as this benefits everyone that participates in it. It encourages new developers to enter our field. It is through discussion and collaboration that we grow, and through growth that we improve. In the effort to create such a place, we hold to these values: 1. **Discrimination limits us.** This includes discrimination on the basis of race, gender, sexual orientation, gender identity, age, nationality, technology and any other arbitrary exclusion of a group of people. 2. **Boundaries honor us.** Your comfort levels are not everyone’s comfort levels. Remember that, and if brought to your attention, heed it. 3. **We are our biggest assets.** None of us were born masters of our trade. Each of us has been helped along the way. Return that favor, when and where you can. 4. **We are resources for the future.** As an extension of #3, share what you know. Make yourself a resource to help those that come after you. 5. **Respect defines us.** Treat others as you wish to be treated. Make your discussions, criticisms and debates from a position of respectfulness. Ask yourself, is it true? Is it necessary? Is it constructive? Anything less is unacceptable. 6. **Reactions require grace.** Angry responses are valid, but abusive language and vindictive actions are toxic. When something happens that offends you, handle it assertively, but be respectful. Escalate reasonably, and try to allow the offender an opportunity to explain themselves, and possibly correct the issue. 7. **Opinions are just that: opinions.** Each and every one of us, due to our background and upbringing, have varying opinions. The fact of the matter, is that is perfectly acceptable. Remember this: if you respect your own opinions, you should respect the opinions of others. 8. **To err is human.** You might not intend it, but mistakes do happen and contribute to build experience. Tolerate honest mistakes, and don't hesitate to apologize if you make one yourself. zend-code-release-3.1.0/CONTRIBUTING.md000066400000000000000000000167571300340552400172460ustar00rootroot00000000000000# CONTRIBUTING ## RESOURCES If you wish to contribute to Zend Framework, please be sure to read/subscribe to the following resources: - [Coding Standards](https://github.com/zendframework/zf2/wiki/Coding-Standards) - [Contributor's Guide](http://framework.zend.com/participate/contributor-guide) - ZF Contributor's mailing list: Archives: http://zend-framework-community.634137.n4.nabble.com/ZF-Contributor-f680267.html Subscribe: zf-contributors-subscribe@lists.zend.com - ZF Contributor's IRC channel: #zftalk.dev on Freenode.net If you are working on new features or refactoring [create a proposal](https://github.com/zendframework/zend-code/issues/new). ## Reporting Potential Security Issues If you have encountered a potential security vulnerability, please **DO NOT** report it on the public issue tracker: send it to us at [zf-security@zend.com](mailto:zf-security@zend.com) instead. We will work with you to verify the vulnerability and patch it as soon as possible. When reporting issues, please provide the following information: - Component(s) affected - A description indicating how to reproduce the issue - A summary of the security vulnerability and impact We request that you contact us via the email address above and give the project contributors a chance to resolve the vulnerability and issue a new release prior to any public exposure; this helps protect users and provides them with a chance to upgrade and/or update in order to protect their applications. For sensitive email communications, please use [our PGP key](http://framework.zend.com/zf-security-pgp-key.asc). ## RUNNING TESTS > ### Note: testing versions prior to 2.4 > > This component originates with Zend Framework 2. During the lifetime of ZF2, > testing infrastructure migrated from PHPUnit 3 to PHPUnit 4. In most cases, no > changes were necessary. However, due to the migration, tests may not run on > versions < 2.4. As such, you may need to change the PHPUnit dependency if > attempting a fix on such a version. To run tests: - Clone the repository: ```console $ git clone git@github.com:zendframework/zend-code.git $ cd ``` - Install dependencies via composer: ```console $ curl -sS https://getcomposer.org/installer | php -- $ ./composer.phar install ``` If you don't have `curl` installed, you can also download `composer.phar` from https://getcomposer.org/ - Run the tests via `phpunit` and the provided PHPUnit config, like in this example: ```console $ ./vendor/bin/phpunit ``` You can turn on conditional tests with the phpunit.xml file. To do so: - Copy `phpunit.xml.dist` file to `phpunit.xml` - Edit `phpunit.xml` to enable any specific functionality you want to test, as well as to provide test values to utilize. ## Running Coding Standards Checks This component uses [php-cs-fixer](http://cs.sensiolabs.org/) for coding standards checks, and provides configuration for our selected checks. `php-cs-fixer` is installed by default via Composer. To run checks only: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --dry-run --config-file=.php_cs ``` To have `php-cs-fixer` attempt to fix problems for you, omit the `--dry-run` flag: ```console $ ./vendor/bin/php-cs-fixer fix . -v --diff --config-file=.php_cs ``` If you allow php-cs-fixer to fix CS issues, please re-run the tests to ensure they pass, and make sure you add and commit the changes after verification. ## Recommended Workflow for Contributions Your first step is to establish a public repository from which we can pull your work into the master repository. We recommend using [GitHub](https://github.com), as that is where the component is already hosted. 1. Setup a [GitHub account](http://github.com/), if you haven't yet 2. Fork the repository (http://github.com/zendframework/zend-code) 3. Clone the canonical repository locally and enter it. ```console $ git clone git://github.com:zendframework/zend-code.git $ cd zend-code ``` 4. Add a remote to your fork; substitute your GitHub username in the command below. ```console $ git remote add {username} git@github.com:{username}/zend-code.git $ git fetch {username} ``` ### Keeping Up-to-Date Periodically, you should update your fork or personal repository to match the canonical ZF repository. Assuming you have setup your local repository per the instructions above, you can do the following: ```console $ git checkout master $ git fetch origin $ git rebase origin/master # OPTIONALLY, to keep your remote up-to-date - $ git push {username} master:master ``` If you're tracking other branches -- for example, the "develop" branch, where new feature development occurs -- you'll want to do the same operations for that branch; simply substitute "develop" for "master". ### Working on a patch We recommend you do each new feature or bugfix in a new branch. This simplifies the task of code review as well as the task of merging your changes into the canonical repository. A typical workflow will then consist of the following: 1. Create a new local branch based off either your master or develop branch. 2. Switch to your new local branch. (This step can be combined with the previous step with the use of `git checkout -b`.) 3. Do some work, commit, repeat as necessary. 4. Push the local branch to your remote repository. 5. Send a pull request. The mechanics of this process are actually quite trivial. Below, we will create a branch for fixing an issue in the tracker. ```console $ git checkout -b hotfix/9295 Switched to a new branch 'hotfix/9295' ``` ... do some work ... ```console $ git commit ``` ... write your log message ... ```console $ git push {username} hotfix/9295:hotfix/9295 Counting objects: 38, done. Delta compression using up to 2 threads. Compression objects: 100% (18/18), done. Writing objects: 100% (20/20), 8.19KiB, done. Total 20 (delta 12), reused 0 (delta 0) To ssh://git@github.com/{username}/zend-code.git b5583aa..4f51698 HEAD -> master ``` To send a pull request, you have two options. If using GitHub, you can do the pull request from there. Navigate to your repository, select the branch you just created, and then select the "Pull Request" button in the upper right. Select the user/organization "zendframework" as the recipient. If using your own repository - or even if using GitHub - you can use `git format-patch` to create a patchset for us to apply; in fact, this is **recommended** for security-related patches. If you use `format-patch`, please send the patches as attachments to: - zf-devteam@zend.com for patches without security implications - zf-security@zend.com for security patches #### What branch to issue the pull request against? Which branch should you issue a pull request against? - For fixes against the stable release, issue the pull request against the "master" branch. - For new features, or fixes that introduce new elements to the public API (such as new public methods or properties), issue the pull request against the "develop" branch. ### Branch Cleanup As you might imagine, if you are a frequent contributor, you'll start to get a ton of branches both locally and on your remote. Once you know that your changes have been accepted to the master repository, we suggest doing some cleanup of these branches. - Local branch cleanup ```console $ git branch -d ``` - Remote branch removal ```console $ git push {username} : ``` ## Conduct Please see our [CONDUCT.md](CONDUCT.md) to understand expected behavior when interacting with others in the project. zend-code-release-3.1.0/LICENSE.md000066400000000000000000000027551300340552400164120ustar00rootroot00000000000000Copyright (c) 2005-2016, Zend Technologies USA, Inc. All rights reserved. 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 Zend Technologies USA, Inc. 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. zend-code-release-3.1.0/Makefile000066400000000000000000000014051300340552400164350ustar00rootroot00000000000000# zend-expressive Makefile # # Primary purpose is for generating the mkdocs.yml from the bookdown.json # sources. # # Configurable variables: # - BOOKDOWN2MKDOCS - specify the path to the executable; defaults to # ./vendor/bin/bookdown2mkdocs # # Available targets: # - mkdocs - regenerate mkdocs.yml # - all - synonym for mkdocs target BOOKDOWN2MKDOCS?=$(CURDIR)/vendor/bin/bookdown2mkdocs.php .PHONY : all mkdocs bookdown2mkdocs all : mkdocs mkdocs : @echo "Generating mkdocs.yml from bookdown.json..." -$(BOOKDOWN2MKDOCS) convert --site-name=zend-code --repo-url=https://github.com/zendframework/zend-code --copyright-url=http://www.zend.com/ --copyright-author="Zend Technologies USA Inc." @echo "[DONE] Generating mkdocs.yml from bookdown.json" zend-code-release-3.1.0/README.md000066400000000000000000000016061300340552400162570ustar00rootroot00000000000000# zend-code [![Build Status](https://secure.travis-ci.org/zendframework/zend-code.svg?branch=master)](https://secure.travis-ci.org/zendframework/zend-code) [![Coverage Status](https://coveralls.io/repos/zendframework/zend-code/badge.svg?branch=master)](https://coveralls.io/r/zendframework/zend-code?branch=master) `Zend\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/zendframework/zend-code/issues - Documentation is at http://zend-code.rtfd.org - Migration documentation from v2 to v3 is at http://zend-code.rtfd.org/en/latest/migration/ zend-code-release-3.1.0/composer.json000066400000000000000000000027771300340552400175340ustar00rootroot00000000000000{ "name": "zendframework/zend-code", "description": "provides facilities to generate arbitrary code using an object oriented interface", "license": "BSD-3-Clause", "keywords": [ "zf2", "code" ], "homepage": "https://github.com/zendframework/zend-code", "autoload": { "psr-4": { "Zend\\Code\\": "src/" } }, "require": { "php": "^5.6 || 7.0.0 - 7.0.4 || ^7.0.6", "zendframework/zend-eventmanager": "^2.6 || ^3.0" }, "require-dev": { "ext-phar": "*", "doctrine/annotations": "~1.0", "zendframework/zend-stdlib": "^2.7 || ^3.0", "squizlabs/php_codesniffer": "^2.5", "phpunit/PHPUnit": "^4.8.21" }, "suggest": { "doctrine/annotations": "Doctrine\\Common\\Annotations >=1.0 for annotation features", "zendframework/zend-stdlib": "Zend\\Stdlib component" }, "minimum-stability": "dev", "prefer-stable": true, "extra": { "branch-alias": { "dev-master": "3.1-dev", "dev-develop": "3.2-dev" } }, "autoload-dev": { "psr-4": { "ZendTest\\Code\\": "test/" } }, "scripts": { "check": [ "@cs-check", "@test" ], "upload-coverage": "coveralls -v", "cs-check": "phpcs", "cs-fix": "phpcbf", "test": "phpunit --colors=always", "test-coverage": "phpunit --colors=always --coverage-clover clover.xml" } } zend-code-release-3.1.0/composer.lock000066400000000000000000001276111300340552400175060ustar00rootroot00000000000000{ "_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#composer-lock-the-lock-file", "This file is @generated automatically" ], "hash": "88ffb754c378b6610da240d3adcc3770", "content-hash": "af1206ea85a3ce06d326cab55fe68657", "packages": [ { "name": "zendframework/zend-eventmanager", "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/zendframework/zend-eventmanager.git", "reference": "5c80bdee0e952be112dcec0968bad770082c3a6e" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-eventmanager/zipball/5c80bdee0e952be112dcec0968bad770082c3a6e", "reference": "5c80bdee0e952be112dcec0968bad770082c3a6e", "shasum": "" }, "require": { "php": "^5.5 || ^7.0" }, "require-dev": { "athletic/athletic": "^0.1", "container-interop/container-interop": "^1.1.0", "phpunit/phpunit": "~4.0", "squizlabs/php_codesniffer": "^2.0", "zendframework/zend-stdlib": "^2.7.3 || ^3.0" }, "suggest": { "container-interop/container-interop": "^1.1.0, to use the lazy listeners feature", "zendframework/zend-stdlib": "^2.7.3 || ^3.0, to use the FilterChain feature" }, "type": "library", "extra": { "branch-alias": { "dev-master": "3.0-dev", "dev-develop": "3.1-dev" } }, "autoload": { "psr-4": { "Zend\\EventManager\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "description": "Trigger and listen to events within a PHP application", "homepage": "https://github.com/zendframework/zend-eventmanager", "keywords": [ "event", "eventmanager", "events", "zf2" ], "time": "2016-02-18 20:53:00" } ], "packages-dev": [ { "name": "doctrine/annotations", "version": "v1.2.7", "source": { "type": "git", "url": "https://github.com/doctrine/annotations.git", "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/doctrine/annotations/zipball/f25c8aab83e0c3e976fd7d19875f198ccf2f7535", "reference": "f25c8aab83e0c3e976fd7d19875f198ccf2f7535", "shasum": "" }, "require": { "doctrine/lexer": "1.*", "php": ">=5.3.2" }, "require-dev": { "doctrine/cache": "1.*", "phpunit/phpunit": "4.*" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.3.x-dev" } }, "autoload": { "psr-0": { "Doctrine\\Common\\Annotations\\": "lib/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Roman Borschel", "email": "roman@code-factory.org" }, { "name": "Benjamin Eberlei", "email": "kontakt@beberlei.de" }, { "name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com" }, { "name": "Jonathan Wage", "email": "jonwage@gmail.com" }, { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com" } ], "description": "Docblock Annotations Parser", "homepage": "http://www.doctrine-project.org", "keywords": [ "annotations", "docblock", "parser" ], "time": "2015-08-31 12:32:49" }, { "name": "doctrine/instantiator", "version": "1.0.5", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", "shasum": "" }, "require": { "php": ">=5.3,<8.0-DEV" }, "require-dev": { "athletic/athletic": "~0.1.8", "ext-pdo": "*", "ext-phar": "*", "phpunit/phpunit": "~4.0", "squizlabs/php_codesniffer": "~2.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "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": "http://ocramius.github.com/" } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", "homepage": "https://github.com/doctrine/instantiator", "keywords": [ "constructor", "instantiate" ], "time": "2015-06-14 21:17:01" }, { "name": "doctrine/lexer", "version": "v1.0.1", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", "shasum": "" }, "require": { "php": ">=5.3.2" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "autoload": { "psr-0": { "Doctrine\\Common\\Lexer\\": "lib/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Roman Borschel", "email": "roman@code-factory.org" }, { "name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com" }, { "name": "Johannes Schmitt", "email": "schmittjoh@gmail.com" } ], "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", "homepage": "http://www.doctrine-project.org", "keywords": [ "lexer", "parser" ], "time": "2014-09-09 13:34:57" }, { "name": "phpdocumentor/reflection-docblock", "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "phpunit/phpunit": "~4.0" }, "suggest": { "dflydev/markdown": "~1.0", "erusev/parsedown": "~1.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }, "autoload": { "psr-0": { "phpDocumentor": [ "src/" ] } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Mike van Riel", "email": "mike.vanriel@naenius.com" } ], "time": "2015-02-03 12:10:50" }, { "name": "phpspec/prophecy", "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3c91bdf81797d725b14cb62906f9a4ce44235972", "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", "phpdocumentor/reflection-docblock": "~2.0", "sebastian/comparator": "~1.1", "sebastian/recursion-context": "~1.0" }, "require-dev": { "phpspec/phpspec": "~2.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.5.x-dev" } }, "autoload": { "psr-0": { "Prophecy\\": "src/" } }, "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" ], "time": "2016-02-15 07:46:21" }, { "name": "phpunit/php-code-coverage", "version": "2.2.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", "shasum": "" }, "require": { "php": ">=5.3.3", "phpunit/php-file-iterator": "~1.3", "phpunit/php-text-template": "~1.2", "phpunit/php-token-stream": "~1.3", "sebastian/environment": "^1.3.2", "sebastian/version": "~1.0" }, "require-dev": { "ext-xdebug": ">=2.1.4", "phpunit/phpunit": "~4" }, "suggest": { "ext-dom": "*", "ext-xdebug": ">=2.2.1", "ext-xmlwriter": "*" }, "type": "library", "extra": { "branch-alias": { "dev-master": "2.2.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sb@sebastian-bergmann.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" ], "time": "2015-10-06 15:47:00" }, { "name": "phpunit/php-file-iterator", "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", "shasum": "" }, "require": { "php": ">=5.3.3" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.4.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sb@sebastian-bergmann.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" ], "time": "2015-06-21 13:08:43" }, { "name": "phpunit/php-text-template", "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", "shasum": "" }, "require": { "php": ">=5.3.3" }, "type": "library", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Simple template engine.", "homepage": "https://github.com/sebastianbergmann/php-text-template/", "keywords": [ "template" ], "time": "2015-06-21 13:50:34" }, { "name": "phpunit/php-timer", "version": "1.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "phpunit/phpunit": "~4|~5" }, "type": "library", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sb@sebastian-bergmann.de", "role": "lead" } ], "description": "Utility class for timing", "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ "timer" ], "time": "2016-05-12 18:03:57" }, { "name": "phpunit/php-token-stream", "version": "1.4.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", "shasum": "" }, "require": { "ext-tokenizer": "*", "php": ">=5.3.3" }, "require-dev": { "phpunit/phpunit": "~4.2" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.4-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Wrapper around PHP's tokenizer extension.", "homepage": "https://github.com/sebastianbergmann/php-token-stream/", "keywords": [ "tokenizer" ], "time": "2015-09-15 10:49:45" }, { "name": "phpunit/phpunit", "version": "4.8.26", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", "reference": "fc1d8cd5b5de11625979125c5639347896ac2c74" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fc1d8cd5b5de11625979125c5639347896ac2c74", "reference": "fc1d8cd5b5de11625979125c5639347896ac2c74", "shasum": "" }, "require": { "ext-dom": "*", "ext-json": "*", "ext-pcre": "*", "ext-reflection": "*", "ext-spl": "*", "php": ">=5.3.3", "phpspec/prophecy": "^1.3.1", "phpunit/php-code-coverage": "~2.1", "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", "phpunit/php-timer": "^1.0.6", "phpunit/phpunit-mock-objects": "~2.3", "sebastian/comparator": "~1.1", "sebastian/diff": "~1.2", "sebastian/environment": "~1.3", "sebastian/exporter": "~1.2", "sebastian/global-state": "~1.0", "sebastian/version": "~1.0", "symfony/yaml": "~2.1|~3.0" }, "suggest": { "phpunit/php-invoker": "~1.1" }, "bin": [ "phpunit" ], "type": "library", "extra": { "branch-alias": { "dev-master": "4.8.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "The PHP Unit Testing framework.", "homepage": "https://phpunit.de/", "keywords": [ "phpunit", "testing", "xunit" ], "time": "2016-05-17 03:09:28" }, { "name": "phpunit/phpunit-mock-objects", "version": "2.3.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": ">=5.3.3", "phpunit/php-text-template": "~1.2", "sebastian/exporter": "~1.2" }, "require-dev": { "phpunit/phpunit": "~4.4" }, "suggest": { "ext-soap": "*" }, "type": "library", "extra": { "branch-alias": { "dev-master": "2.3.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sb@sebastian-bergmann.de", "role": "lead" } ], "description": "Mock Object library for PHPUnit", "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", "keywords": [ "mock", "xunit" ], "time": "2015-10-02 06:51:40" }, { "name": "sebastian/comparator", "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", "shasum": "" }, "require": { "php": ">=5.3.3", "sebastian/diff": "~1.2", "sebastian/exporter": "~1.2" }, "require-dev": { "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.2.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Volker Dusch", "email": "github@wallbash.com" }, { "name": "Bernhard Schussek", "email": "bschussek@2bepublished.at" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Provides the functionality to compare PHP values for equality", "homepage": "http://www.github.com/sebastianbergmann/comparator", "keywords": [ "comparator", "compare", "equality" ], "time": "2015-07-26 15:48:44" }, { "name": "sebastian/diff", "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "phpunit/phpunit": "~4.8" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.4-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Kore Nordmann", "email": "mail@kore-nordmann.de" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Diff implementation", "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ "diff" ], "time": "2015-12-08 07:14:41" }, { "name": "sebastian/environment", "version": "1.3.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716", "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.3.x-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" ], "time": "2016-05-17 03:18:57" }, { "name": "sebastian/exporter", "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", "reference": "7ae5513327cb536431847bcc0c10edba2701064e" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e", "reference": "7ae5513327cb536431847bcc0c10edba2701064e", "shasum": "" }, "require": { "php": ">=5.3.3", "sebastian/recursion-context": "~1.0" }, "require-dev": { "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.2.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Volker Dusch", "email": "github@wallbash.com" }, { "name": "Bernhard Schussek", "email": "bschussek@2bepublished.at" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Adam Harvey", "email": "aharvey@php.net" } ], "description": "Provides the functionality to export PHP variables for visualization", "homepage": "http://www.github.com/sebastianbergmann/exporter", "keywords": [ "export", "exporter" ], "time": "2015-06-21 07:55:53" }, { "name": "sebastian/global-state", "version": "1.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "phpunit/phpunit": "~4.2" }, "suggest": { "ext-uopz": "*" }, "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" } ], "description": "Snapshotting of global state", "homepage": "http://www.github.com/sebastianbergmann/global-state", "keywords": [ "global state" ], "time": "2015-10-12 03:26:01" }, { "name": "sebastian/recursion-context", "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", "reference": "913401df809e99e4f47b27cdd781f4a258d58791" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", "reference": "913401df809e99e4f47b27cdd781f4a258d58791", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Adam Harvey", "email": "aharvey@php.net" } ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", "time": "2015-11-11 19:50:13" }, { "name": "sebastian/version", "version": "1.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", "shasum": "" }, "type": "library", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", "time": "2015-06-21 13:59:46" }, { "name": "squizlabs/php_codesniffer", "version": "2.6.0", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", "reference": "1bcdf03b068a530ac1962ce671dead356eeba43b" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1bcdf03b068a530ac1962ce671dead356eeba43b", "reference": "1bcdf03b068a530ac1962ce671dead356eeba43b", "shasum": "" }, "require": { "ext-simplexml": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", "php": ">=5.1.2" }, "require-dev": { "phpunit/phpunit": "~4.0" }, "bin": [ "scripts/phpcs", "scripts/phpcbf" ], "type": "library", "extra": { "branch-alias": { "dev-master": "2.x-dev" } }, "autoload": { "classmap": [ "CodeSniffer.php", "CodeSniffer/CLI.php", "CodeSniffer/Exception.php", "CodeSniffer/File.php", "CodeSniffer/Fixer.php", "CodeSniffer/Report.php", "CodeSniffer/Reporting.php", "CodeSniffer/Sniff.php", "CodeSniffer/Tokens.php", "CodeSniffer/Reports/", "CodeSniffer/Tokenizers/", "CodeSniffer/DocGenerators/", "CodeSniffer/Standards/AbstractPatternSniff.php", "CodeSniffer/Standards/AbstractScopeSniff.php", "CodeSniffer/Standards/AbstractVariableSniff.php", "CodeSniffer/Standards/IncorrectPatternException.php", "CodeSniffer/Standards/Generic/Sniffs/", "CodeSniffer/Standards/MySource/Sniffs/", "CodeSniffer/Standards/PEAR/Sniffs/", "CodeSniffer/Standards/PSR1/Sniffs/", "CodeSniffer/Standards/PSR2/Sniffs/", "CodeSniffer/Standards/Squiz/Sniffs/", "CodeSniffer/Standards/Zend/Sniffs/" ] }, "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": "http://www.squizlabs.com/php-codesniffer", "keywords": [ "phpcs", "standards" ], "time": "2016-04-03 22:58:34" }, { "name": "symfony/yaml", "version": "v3.0.6", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", "reference": "0047c8366744a16de7516622c5b7355336afae96" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/symfony/yaml/zipball/0047c8366744a16de7516622c5b7355336afae96", "reference": "0047c8366744a16de7516622c5b7355336afae96", "shasum": "" }, "require": { "php": ">=5.5.9" }, "type": "library", "extra": { "branch-alias": { "dev-master": "3.0-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\Yaml\\": "" }, "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 Yaml Component", "homepage": "https://symfony.com", "time": "2016-03-04 07:55:57" }, { "name": "zendframework/zend-stdlib", "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/zendframework/zend-stdlib.git", "reference": "8bafa58574204bdff03c275d1d618aaa601588ae" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/8bafa58574204bdff03c275d1d618aaa601588ae", "reference": "8bafa58574204bdff03c275d1d618aaa601588ae", "shasum": "" }, "require": { "php": "^5.5 || ^7.0" }, "require-dev": { "athletic/athletic": "~0.1", "fabpot/php-cs-fixer": "1.7.*", "phpunit/phpunit": "~4.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "3.0-dev", "dev-develop": "3.1-dev" } }, "autoload": { "psr-4": { "Zend\\Stdlib\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "homepage": "https://github.com/zendframework/zend-stdlib", "keywords": [ "stdlib", "zf2" ], "time": "2016-04-12 21:19:36" } ], "aliases": [], "minimum-stability": "dev", "stability-flags": [], "prefer-stable": true, "prefer-lowest": false, "platform": { "php": "^5.6 || 7.0.0 - 7.0.4 || ^7.0.6" }, "platform-dev": { "ext-phar": "*" } } zend-code-release-3.1.0/doc/000077500000000000000000000000001300340552400155425ustar00rootroot00000000000000zend-code-release-3.1.0/doc/book/000077500000000000000000000000001300340552400164745ustar00rootroot00000000000000zend-code-release-3.1.0/doc/book/generator/000077500000000000000000000000001300340552400204625ustar00rootroot00000000000000zend-code-release-3.1.0/doc/book/generator/bookdown.json000066400000000000000000000002411300340552400231740ustar00rootroot00000000000000{ "title": "zend-code Generator Component", "content": [ {"Intro": "intro.md"}, {"Examples": "examples.md"}, {"Reference": "reference.md"} ] } zend-code-release-3.1.0/doc/book/generator/examples.md000066400000000000000000000215011300340552400226210ustar00rootroot00000000000000# Zend\\Code\\Generator Examples ## Generating PHP classes The following example generates an empty class with a class-level DocBlock. ```php use Zend\Code\Generator\ClassGenerator; use Zend\Code\Generator\DocBlockGenerator; $foo = new ClassGenerator(); $docblock = DocBlockGenerator::fromArray([ 'shortDescription' => 'Sample generated class', 'longDescription' => 'This is a class generated with Zend\Code\Generator.', 'tags' => [ [ 'name' => 'version', 'description' => '$Rev:$', ], [ 'name' => 'license', 'description' => 'New BSD', ], ], ]); $foo->setName('Foo') ->setDocblock($docblock); echo $foo->generate(); ``` The above code will result in the following: ```php /** * Sample generated class * * This is a class generated with Zend\Code\Generator. * * @version $Rev:$ * @license New BSD * */ class Foo { } ``` ### Generating PHP classes with class properties Building on the previous example, we now add properties to our generated class. ```php use Zend\Code\Generator\ClassGenerator; use Zend\Code\Generator\DocBlockGenerator; use Zend\Code\Generator\PropertyGenerator; $foo = new ClassGenerator(); $docblock = DocBlockGenerator::fromArray([ 'shortDescription' => 'Sample generated class', 'longDescription' => 'This is a class generated with Zend\Code\Generator.', 'tags' => [ [ 'name' => 'version', 'description' => '$Rev:$', ], [ 'name' => 'license', 'description' => 'New BSD', ], ], ]); $foo->setName('Foo') ->setDocblock($docblock) ->addProperties([ ['_bar', 'baz', PropertyGenerator::FLAG_PROTECTED], ['baz', 'bat', PropertyGenerator::FLAG_PUBLIC] ]) ->addConstants([ ['bat', 'foobarbazbat'] ]); echo $foo->generate(); ``` The above results in the following class definition: ```php /** * Sample generated class * * This is a class generated with Zend\Code\Generator. * * @version $Rev:$ * @license New BSD * */ class Foo { protected $_bar = 'baz'; public $baz = 'bat'; const bat = 'foobarbazbat'; } ``` ### Generating PHP classes with class methods `Zend\Code\Generator\ClassGenerator` allows you to attach methods with optional content to your classes. Methods may be attached as either arrays or concrete `Zend\Code\Generator\MethodGenerator` instances. ```php use Zend\Code\Generator\ClassGenerator; use Zend\Code\Generator\DocBlockGenerator; use Zend\Code\Generator\DocBlock\Tag; use Zend\Code\Generator\MethodGenerator; use Zend\Code\Generator\PropertyGenerator; $foo = new ClassGenerator(); $docblock = DocBlockGenerator::fromArray([ 'shortDescription' => 'Sample generated class', 'longDescription' => 'This is a class generated with Zend\Code\Generator.', 'tags' => [ [ 'name' => 'version', 'description' => '$Rev:$', ], [ 'name' => 'license', 'description' => 'New BSD', ], ], ]); $foo->setName('Foo') ->setDocblock($docblock) ->addProperties([ ['_bar', 'baz', PropertyGenerator::FLAG_PROTECTED], ['baz', 'bat', PropertyGenerator::FLAG_PUBLIC] ]) ->addConstants([ ['bat', 'foobarbazbat', PropertyGenerator::FLAG_CONSTANT] ]) ->addMethods([ // Method passed as array MethodGenerator::fromArray([ 'name' => 'setBar', 'parameters' => ['bar'], 'body' => '$this->_bar = $bar;' . "\n" . 'return $this;', 'docblock' => DocBlockGenerator::fromArray([ 'shortDescription' => 'Set the bar property', 'longDescription' => null, 'tags' => [ new Tag\ParamTag([ 'paramName' => 'bar', 'datatype' => 'string' ]), new Tag\ReturnTag([ 'datatype' => 'string', ]), ], ]), ]), // Method passed as concrete instance new MethodGenerator( 'getBar', [], MethodGenerator::FLAG_PUBLIC, 'return $this->_bar;', DocBlockGenerator::fromArray([ 'shortDescription' => 'Retrieve the bar property', 'longDescription' => null, 'tags' => [ new Tag\ReturnTag([ 'datatype' => 'string|null', ]), ], ]) ), ]); echo $foo->generate(); ``` The above generates the following output: ```php /** * Sample generated class * * This is a class generated with Zend\Code\Generator. * * @version $Rev:$ * @license New BSD */ class Foo { protected $_bar = 'baz'; public $baz = 'bat'; const bat = 'foobarbazbat'; /** * Set the bar property * * @param string bar * @return string */ public function setBar($bar) { $this->_bar = $bar; return $this; } /** * Retrieve the bar property * * @return string|null */ public function getBar() { return $this->_bar; } } ``` ## Generating PHP files `Zend\Code\Generator\FileGenerator` can be used to generate the contents of a *PHP* file. You can include classes as well as arbitrary content body. When attaching classes, you should attach either concrete `Zend\Code\Generator\ClassGenerator` instances or an array defining the class. In the example below, we will assume you've defined `$foo` per one of the class definitions in a previous example. ```php use Zend\Code\Generator\DocBlockGenerator; use Zend\Code\Generator\FileGenerator; $file = FileGenerator::fromArray([ 'classes' => [$foo], 'docblock' => DocBlockGenerator::fromArray([ 'shortDescription' => 'Foo class file', 'longDescription' => null, 'tags' => [ [ 'name' => 'license', 'description' => 'New BSD', ], ], ]), 'body' => 'define(\'APPLICATION_ENV\', \'testing\');', ]); ``` Calling `generate()` will generate the code -- but not write it to a file. You will need to capture the contents and write them to a file yourself. As an example: ```php $code = $file->generate(); file_put_contents('Foo.php', $code); ``` The above will generate the following file: ```php _bar = $bar; return $this; } /** * Retrieve the bar property * * @return string|null */ public function getBar() { return $this->_bar; } } define('APPLICATION_ENV', 'testing'); ``` ## Add code to existing PHP files and classes ### Seeding PHP file code generation via reflection You can add *PHP* code to an existing *PHP* file using the code generator. To do so, you need to first do reflection on it. The static method `fromReflectedFileName()` allows you to do this. ```php $generator = Zend\Code\Generator\FileGenerator::fromReflectedFileName($path); $generator->setBody("\$foo->bar();"); file_put_contents($path, $generator->generate()); ``` ### Seeding PHP class generation via reflection You may add code to an existing class. To do so, first use the static `fromReflection()` method to map the class into a generator object. From there, you may add additional properties or methods, and then regenerate the class. ```php use Zend\Code\Generator\ClassGenerator; use Zend\Code\Generator\DocBlockGenerator; use Zend\Code\Generator\DocBlock\Tag; use Zend\Code\Generator\MethodGenerator; use Zend\Code\Reflection\ClassReflection; $generator = ClassGenerator::fromReflection( new ClassReflection($class) ); $generator->addMethod( 'setBaz', ['baz'], MethodGenerator::FLAG_PUBLIC, '$this->_baz = $baz;' . "\n" . 'return $this;', DocBlockGenerator::fromArray([ 'shortDescription' => 'Set the baz property', 'longDescription' => null, 'tags' => [ new Tag\ParamTag([ 'paramName' => 'baz', 'datatype' => 'string' ]), new Tag\ReturnTag([ 'datatype' => 'string', ]), ], ]) ); $code = $generator->generate(); ``` zend-code-release-3.1.0/doc/book/generator/intro.md000066400000000000000000000065221300340552400221440ustar00rootroot00000000000000# Introduction `Zend\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. ## Theory of Operation In the most typical use case, you will simply instantiate a code generator class and either pass it the appropriate configuration or configure it after instantiation. To generate the code, you will simply echo the object or call its `generate()` method. ```php // Passing configuration to the constructor: $file = new Zend\Code\Generator\FileGenerator(array( 'classes' => array( new Zend\Code\Generator\ClassGenerator( 'World', // name null, // namespace null, // flags null, // extends array(), // interfaces array(), // properties array( new Zend\Code\Generator\MethodGenerator( 'hello', // name array(), // parameters 'public', // visibility 'echo \'Hello world!\';' // body ), ) ), ), )); // Render the generated file echo $file->generate(); // or write it to a file: file_put_contents('World.php', $file->generate()); // OR // Configuring after instantiation $method = new Zend\Code\Generator\MethodGenerator(); $method->setName('hello') ->setBody('echo \'Hello world!\';'); $class = new Zend\Code\Generator\ClassGenerator(); $class->setName('World') ->addMethodFromGenerator($method); $file = new Zend\Code\Generator\FileGenerator(); $file->setClass($class); // Render the generated file echo $file->generate(); // or write it to a file: file_put_contents('World.php', $file->generate()); ``` Both of the above samples will render the same result: ```php setName('mrMcFeeley') ->setBody('echo \'Hello, Mr. McFeeley!\';'); $class->addMethodFromGenerator($method); $file = new Zend\Code\Generator\FileGenerator(); $file->setClass($class); // Render the generated file echo $file->generate(); // Or, better yet, write it back to the original file: file_put_contents('World.php', $file->generate()); ``` The resulting class file will now look like this: ```php setDefaultValue( new Zend\Code\Generator\ValueGenerator("null") ); $parameter->setDefaultValue( new Zend\Code\Generator\ValueGenerator("['foo', 'bar']") ); ``` Internally `setDefaultValue()` also converts the values which can't be expressed in *PHP* into the value holder. ### Zend\\Code\\Generator\\PropertyGenerator `Zend\Code\Generator\PropertyGenerator` describes a class property, which may be either a constant or a variable. In each case, the property may have an optional default value associated with it. Additionally, the visibility of variable properties may be set, per the parent class, `Zend\Code\Generator\AbstractMemberGenerator`. The *API* of the class is as follows: ```php class Zend\Code\Generator\PropertyGenerator extends Zend\Code\Generator\AbstractMemberGenerator { public static function fromReflection( Zend\Code\Reflection\PropertyReflection $reflectionProperty ) public function setConst($const) public function isConst() public function setDefaultValue($defaultValue) public function getDefaultValue() public function generate() } ``` zend-code-release-3.1.0/doc/book/index.html000066400000000000000000000004311300340552400204670ustar00rootroot00000000000000

zend-code

Extensions to the PHP Reflection API, static code scanning, and code generation.

$ composer require zendframework/zend-code
zend-code-release-3.1.0/doc/book/index.md000077700000000000000000000000001300340552400220252../../README.mdustar00rootroot00000000000000zend-code-release-3.1.0/doc/book/migration.md000066400000000000000000000107411300340552400210120ustar00rootroot00000000000000# Migrating from zend-code v2 to v3 ## `string`, `int`, `float`, `bool` are no longer ignored In 2.x, a `Zend\Code\Generator\ParameterGenerator` with name `foo` and type `string`, `int`, `float` or `bool` simply generated code `"$foo"`: ```php $generator = new \Zend\Code\ParameterGenerator('foo'); $generator->setType('string'); echo $generator->generate(); // "$foo" ``` In 3.x, this code will instead produce `"string $foo"`. If you generate code that should run in PHP 5.x, it is advisable to strip `string`, `int`, `float` and `bool` from type definitions passed to `Zend\Code\ParameterGenerator` instances. The quickest way is to set the type to `null`, if it matches any of these scalar types: ```php if (in_array($type, ['string', 'int', 'float', 'bool'])) { $type = null; } $generator->setType($type); ``` ## `ParameterReflection::getType()` changes PHP 7 introduced [`ReflectionParameter#getType()`](http://php.net/manual/en/reflectionparameter.gettype.php). In order to not override this method, `Zend\Code\Reflection\ParameterReflection#getType()` was renamed to `Zend\Code\Reflection\ParameterReflection#detectType()`. If you relied on `Zend\Code\Reflection\ParameterReflection#getType()`, you can simply replace the method calls in your code. ## DocBlock types ignored by `ParameterGenerator::fromReflection()` As a direct consequence of the previous change, calls to `Zend\Code\Generator\ParameterGenerator::fromReflection()` will not mirror the type hints read from a method's DocBlock. As an example, take following code: ```php class Foo { /** * @param string $baz */ public function bar($baz) { } } $methodGenerator = \Zend\Code\Generator\MethodGenerator::fromReflection( new \Zend\Code\Reflection\MethodReflection('Foo', 'bar') ); var_dump($methodGenerator->getParameters()[0]->getType()); ``` In version 2.x, this code produces `"string"`, in version 3.x it returns `null`. If you need to rely on the types in the annotations, please use `Zend\Code\Reflection\ParameterReflection#detectType()` instead, and build a `MethodGenerator` instance manually. This change is required: since signatures in PHP 7 include scalar type hints. That also means that reflecting scalar type hints from DocBlocks into the signature of a generated method may lead to fatal errors (due to signature mismatch) at runtime. ## Type strings are validated If you attempt to generate type-hints for parameters or return types, those types are now validated before the code is generated. Be sure to check which values you pass to `Zend\Code\Generator\MethodGenerator#setReturnType()` or `Zend\Code\Generator\ParameterGenerator#setType()`, as you may incur in a `Zend\Code\Generator\Exception\InvalidArgumentException` being thrown if any of those types are invalid strings: ```php $parameterGenerator->setType('foo'); // valid $parameterGenerator->setType('array'); // valid $parameterGenerator->setType('bool'); // valid $parameterGenerator->setType('123'); // invalid (throws exception) $parameterGenerator->setType(''); // invalid (throws exception) $parameterGenerator->setType('*'); // invalid (throws exception) $parameterGenerator->setType('\\'); // invalid (throws exception) ``` ## Generated type-hints are now prefixed by `"\"` Generated type-hints are now prefixed with the `NAMESPACE_SEPARATOR`, `"\"`. Take following example code: ```php $parameter = new \Zend\Code\Generator\ParameterGenerator('bar', 'baz'); $method = new \Zend\Code\Generator\MethodGenerator('foo', [$parameter]); $method->setReturnType('tab'); echo $method->generate(); ``` This code produces `public function foo(baz $bar) {}` in 2.x. In version 3.x, it produces `public function foo(\baz $bar) : \tab {}`. In order to avoid migration problems, be sure to always pass fully qualified class names to `Zend\Code\Generator\MethodGenerator` and `Zend\Code\Generator\ParameterGenerator`. ## `ParameterGenerator::$simple` was removed If you extended `Zend\Code\Generator\ParameterGenerator`, be sure to check if you are accessing the protected static variable `$simple`: it was removed, and you should adapt your code by either copying it into your class or avoiding its usage. ## `ParameterGenerator::$type` has changed If you extended `Zend\Code\Generator\ParameterGenerator`, be sure to check if you are accessing the protected variable `$type`: its type has changed. While it can still be used as a string via an explicit `(string)` cast, the type of this protected member is now `null|Zend\Code\Generator\TypeGenerator`. zend-code-release-3.1.0/mkdocs.yml000066400000000000000000000007571300340552400170110ustar00rootroot00000000000000docs_dir: doc/book site_dir: doc/html pages: - index.md - "Code Generation": - Intro: generator/intro.md - Examples: generator/examples.md - Reference: generator/reference.md - Migration: migration.md site_name: zend-code site_description: 'zend-code: Tools for reflecting, scanning, and generating PHP code' repo_url: 'https://github.com/zendframework/zend-code' copyright: 'Copyright (c) 2016 Zend Technologies USA Inc.' zend-code-release-3.1.0/src/000077500000000000000000000000001300340552400155645ustar00rootroot00000000000000zend-code-release-3.1.0/src/Annotation/000077500000000000000000000000001300340552400176765ustar00rootroot00000000000000zend-code-release-3.1.0/src/Annotation/AnnotationCollection.php000066400000000000000000000013771300340552400245450ustar00rootroot00000000000000setIdentifiers([ __CLASS__, get_class($this), ]); $this->events = $events; return $this; } /** * Retrieve event manager * * Lazy loads an instance if none registered. * * @return EventManagerInterface */ public function getEventManager() { if (null === $this->events) { $this->setEventManager(new EventManager()); } return $this->events; } /** * Attach a parser to listen to the createAnnotation event * * @param ParserInterface $parser * @return AnnotationManager */ public function attach(ParserInterface $parser) { $this->getEventManager() ->attach(self::EVENT_CREATE_ANNOTATION, [$parser, 'onCreateAnnotation']); return $this; } /** * Create Annotation * * @param string[] $annotationData * @return false|\stdClass */ public function createAnnotation(array $annotationData) { $event = new Event(); $event->setName(self::EVENT_CREATE_ANNOTATION); $event->setTarget($this); $event->setParams([ 'class' => $annotationData[0], 'content' => $annotationData[1], 'raw' => $annotationData[2], ]); $eventManager = $this->getEventManager(); $results = $eventManager->triggerEventUntil(function ($r) { return (is_object($r)); }, $event); $annotation = $results->last(); return (is_object($annotation) ? $annotation : false); } } zend-code-release-3.1.0/src/Annotation/Parser/000077500000000000000000000000001300340552400211325ustar00rootroot00000000000000zend-code-release-3.1.0/src/Annotation/Parser/DoctrineAnnotationParser.php000066400000000000000000000104521300340552400266240ustar00rootroot00000000000000docParser = $docParser; return $this; } /** * Retrieve the DocParser instance * * If none is registered, lazy-loads a new instance. * * @return DocParser */ public function getDocParser() { if (!$this->docParser instanceof DocParser) { $this->setDocParser(new DocParser()); } return $this->docParser; } /** * Handle annotation creation * * @param EventInterface $e * @return false|\stdClass */ public function onCreateAnnotation(EventInterface $e) { $annotationClass = $e->getParam('class', false); if (!$annotationClass) { return false; } if (!isset($this->allowedAnnotations[$annotationClass])) { return false; } $annotationString = $e->getParam('raw', false); if (!$annotationString) { return false; } // Annotation classes provided by the AnnotationScanner are already // resolved to fully-qualified class names. Adding the global namespace // prefix allows the Doctrine annotation parser to locate the annotation // class correctly. $annotationString = preg_replace('/^(@)/', '$1\\', $annotationString); $parser = $this->getDocParser(); $annotations = $parser->parse($annotationString); if (empty($annotations)) { return false; } $annotation = array_shift($annotations); if (!is_object($annotation)) { return false; } return $annotation; } /** * Specify an allowed annotation class * * @param string $annotation * @return DoctrineAnnotationParser */ public function registerAnnotation($annotation) { $this->allowedAnnotations[$annotation] = true; return $this; } /** * Set many allowed annotations at once * * @param array|Traversable $annotations Array or traversable object of * annotation class names * @throws Exception\InvalidArgumentException * @return DoctrineAnnotationParser */ public function registerAnnotations($annotations) { if (!is_array($annotations) && !$annotations instanceof Traversable) { throw new Exception\InvalidArgumentException(sprintf( '%s: expects an array or Traversable; received "%s"', __METHOD__, (is_object($annotations) ? get_class($annotations) : gettype($annotations)) )); } foreach ($annotations as $annotation) { $this->allowedAnnotations[$annotation] = true; } return $this; } } zend-code-release-3.1.0/src/Annotation/Parser/GenericAnnotationParser.php000066400000000000000000000141541300340552400264340ustar00rootroot00000000000000getParam('class', false); if (!$class || !$this->hasAnnotation($class)) { return false; } $content = $e->getParam('content', ''); $content = trim($content, '()'); if ($this->hasAlias($class)) { $class = $this->resolveAlias($class); } $index = array_search($class, $this->annotationNames); $annotation = $this->annotations[$index]; $newAnnotation = clone $annotation; if ($content) { $newAnnotation->initialize($content); } return $newAnnotation; } /** * Register annotations * * @param string|AnnotationInterface $annotation String class name of an * AnnotationInterface implementation, or actual instance * @return GenericAnnotationParser * @throws Exception\InvalidArgumentException */ public function registerAnnotation($annotation) { $class = false; if (is_string($annotation) && class_exists($annotation)) { $class = $annotation; $annotation = new $annotation(); } if (!$annotation instanceof AnnotationInterface) { throw new Exception\InvalidArgumentException(sprintf( '%s: expects an instance of %s\AnnotationInterface; received "%s"', __METHOD__, __NAMESPACE__, (is_object($annotation) ? get_class($annotation) : gettype($annotation)) )); } $class = $class ?: get_class($annotation); if (in_array($class, $this->annotationNames)) { throw new Exception\InvalidArgumentException(sprintf( 'An annotation for this class %s already exists', $class )); } $this->annotations[] = $annotation; $this->annotationNames[] = $class; } /** * Register many annotations at once * * @param array|Traversable $annotations * @throws Exception\InvalidArgumentException * @return GenericAnnotationParser */ public function registerAnnotations($annotations) { if (!is_array($annotations) && !$annotations instanceof Traversable) { throw new Exception\InvalidArgumentException(sprintf( '%s: expects an array or Traversable; received "%s"', __METHOD__, (is_object($annotations) ? get_class($annotations) : gettype($annotations)) )); } foreach ($annotations as $annotation) { $this->registerAnnotation($annotation); } return $this; } /** * Checks if the manager has annotations for a class * * @param string $class * @return bool */ public function hasAnnotation($class) { if (in_array($class, $this->annotationNames)) { return true; } if ($this->hasAlias($class)) { return true; } return false; } /** * Alias an annotation name * * @param string $alias * @param string $class May be either a registered annotation name or another alias * @throws Exception\InvalidArgumentException * @return GenericAnnotationParser */ public function setAlias($alias, $class) { if (!in_array($class, $this->annotationNames) && !$this->hasAlias($class)) { throw new Exception\InvalidArgumentException(sprintf( '%s: Cannot alias "%s" to "%s", as class "%s" is not currently a registered annotation or alias', __METHOD__, $alias, $class, $class )); } $alias = $this->normalizeAlias($alias); $this->aliases[$alias] = $class; return $this; } /** * Normalize an alias name * * @param string $alias * @return string */ protected function normalizeAlias($alias) { return strtolower(str_replace(['-', '_', ' ', '\\', '/'], '', $alias)); } /** * Do we have an alias by the provided name? * * @param string $alias * @return bool */ protected function hasAlias($alias) { $alias = $this->normalizeAlias($alias); return (isset($this->aliases[$alias])); } /** * Resolve an alias to a class name * * @param string $alias * @return string */ protected function resolveAlias($alias) { do { $normalized = $this->normalizeAlias($alias); $class = $this->aliases[$normalized]; } while ($this->hasAlias($class)); return $class; } } zend-code-release-3.1.0/src/Annotation/Parser/ParserInterface.php000066400000000000000000000017541300340552400247270ustar00rootroot00000000000000setOptions($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; } } zend-code-release-3.1.0/src/Generator/AbstractMemberGenerator.php000066400000000000000000000134171300340552400247730ustar00rootroot00000000000000flags = $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; } /** * @return DocBlockGenerator */ public function getDocBlock() { return $this->docBlock; } } zend-code-release-3.1.0/src/Generator/BodyGenerator.php000066400000000000000000000015671300340552400230000ustar00rootroot00000000000000content = (string) $content; return $this; } /** * @return string */ public function getContent() { return $this->content; } /** * @return string */ public function generate() { return $this->getContent(); } } zend-code-release-3.1.0/src/Generator/ClassGenerator.php000066400000000000000000000704741300340552400231530ustar00rootroot00000000000000getName()); $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()); } /* @var \Zend\Code\Reflection\ClassReflection $parentClass */ $parentClass = $classReflection->getParentClass(); $interfaces = $classReflection->getInterfaces(); if ($parentClass) { $cg->setExtendedClass($parentClass->getName()); $interfaces = array_diff($interfaces, $parentClass->getInterfaces()); } $interfaceNames = []; foreach ($interfaces as $interface) { /* @var \Zend\Code\Reflection\ClassReflection $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->getNamespaceName()) ? $cg->getNamespaceName() . "\\" . $cg->getName() : $cg->getName(); 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 array|string $flags * @param string $extends * @param array $interfaces * @param array $properties * @param array $methods * @param DocBlockGenerator $docBlock */ public function __construct( $name = null, $namespaceName = null, $flags = null, $extends = null, $interfaces = [], $properties = [], $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 (is_array($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 (strstr($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; } /** * @param FileGenerator $fileGenerator * @return self */ public function setContainingFileGenerator(FileGenerator $fileGenerator) { $this->containingFileGenerator = $fileGenerator; return $this; } /** * @return FileGenerator */ public function getContainingFileGenerator() { return $this->containingFileGenerator; } /** * @param DocBlockGenerator $docBlock * @return self */ public function setDocBlock(DocBlockGenerator $docBlock) { $this->docBlock = $docBlock; return $this; } /** * @return DocBlockGenerator */ public function getDocBlock() { return $this->docBlock; } /** * @param array|string $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 string $flag * @return self */ public function addFlag($flag) { $this->setFlags($this->flags | $flag); return $this; } /** * @param string $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 ($this->flags & self::FLAG_FINAL); } /** * @param string $extendedClass * @return self */ public function setExtendedClass($extendedClass) { $this->extendedClass = $extendedClass; return $this; } /** * @return 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 array $implementedInterfaces * @return self */ public function setImplementedInterfaces(array $implementedInterfaces) { array_map(function ($implementedInterface) { return (string) TypeGenerator::fromTypeString($implementedInterface); }, $implementedInterfaces); $this->implementedInterfaces = $implementedInterfaces; return $this; } /** * @return array */ public function getImplementedInterfaces() { return $this->implementedInterfaces; } /** * @param string $implementedInterface * @return bool */ public function hasImplementedInterface($implementedInterface) { $implementedInterface = (string) TypeGenerator::fromTypeString($implementedInterface); return in_array($implementedInterface, $this->implementedInterfaces); } /** * @param $implementedInterface * @return self */ public function removeImplementedInterface($implementedInterface) { $implementedInterface = (string) TypeGenerator::fromTypeString($implementedInterface); unset($this->implementedInterfaces[array_search($implementedInterface, $this->implementedInterfaces)]); 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 * * @param PropertyGenerator $constant * @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)) { call_user_func_array([$this, 'addConstant'], $constant); } } } return $this; } /** * @param array $properties * @return self */ public function addProperties(array $properties) { foreach ($properties as $property) { if ($property instanceof PropertyGenerator) { $this->addPropertyFromGenerator($property); } else { if (is_string($property)) { $this->addProperty($property); } elseif (is_array($property)) { call_user_func_array([$this, 'addProperty'], $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', get_class($this), __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 * * @param PropertyGenerator $property * @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 self */ 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 $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 array $methods * @return self */ public function addMethods(array $methods) { foreach ($methods as $method) { if ($method instanceof MethodGenerator) { $this->addMethodFromGenerator($method); } else { if (is_string($method)) { $this->addMethod($method); } elseif (is_array($method)) { call_user_func_array([$this, 'addMethod'], $method); } } } return $this; } /** * Add Method from scalars * * @param string $name * @param array $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', get_class($this), __FUNCTION__ )); } return $this->addMethodFromGenerator(new MethodGenerator($name, $parameters, $flags, $body, $docBlock)); } /** * Add Method from MethodGenerator * * @param MethodGenerator $method * @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)]); } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ public function addTrait($trait) { $this->traitUsageGenerator->addTrait($trait); return $this; } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ public function addTraits(array $traits) { $this->traitUsageGenerator->addTraits($traits); return $this; } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ public function hasTrait($traitName) { return $this->traitUsageGenerator->hasTrait($traitName); } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ public function getTraits() { return $this->traitUsageGenerator->getTraits(); } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ public function removeTrait($traitName) { return $this->traitUsageGenerator->removeTrait($traitName); } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ public function addTraitAlias($method, $alias, $visibility = null) { $this->traitUsageGenerator->addTraitAlias($method, $alias, $visibility); return $this; } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ public function getTraitAliases() { return $this->traitUsageGenerator->getTraitAliases(); } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ public function addTraitOverride($method, $traitsToReplace) { $this->traitUsageGenerator->addTraitOverride($method, $traitsToReplace); return $this; } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ public function removeTraitOverride($method, $overridesToRemove = null) { $this->traitUsageGenerator->removeTraitOverride($method, $overridesToRemove); return $this; } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ 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(); } /** * @inherit Zend\Code\Generator\GeneratorInterface */ 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 . self::LINE_FEED; $output .= $this->traitUsageGenerator->generate(); $constants = $this->getConstants(); foreach ($constants as $constant) { $output .= $constant->generate() . self::LINE_FEED . self::LINE_FEED; } $properties = $this->getProperties(); foreach ($properties as $property) { $output .= $property->generate() . self::LINE_FEED . self::LINE_FEED; } $methods = $this->getMethods(); foreach ($methods as $method) { $output .= $method->generate() . self::LINE_FEED; } $output .= self::LINE_FEED . '}' . self::LINE_FEED; return $output; } /** * @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 ($classNamespace === $currentNamespace || in_array($fqnClassName, $this->getUses())) { return $className; } return '\\' . $fqnClassName; } } zend-code-release-3.1.0/src/Generator/DocBlock/000077500000000000000000000000001300340552400211725ustar00rootroot00000000000000zend-code-release-3.1.0/src/Generator/DocBlock/Tag.php000066400000000000000000000026571300340552400224300ustar00rootroot00000000000000initializeDefaultTags(); return $tagManager->createTagFromReflection($reflectionTag); } /** * @param string $description * @return Tag * @deprecated Deprecated in 2.3. Use GenericTag::setContent() instead */ public function setDescription($description) { return $this->setContent($description); } /** * @return string * @deprecated Deprecated in 2.3. Use GenericTag::getContent() instead */ public function getDescription() { return $this->getContent(); } } zend-code-release-3.1.0/src/Generator/DocBlock/Tag/000077500000000000000000000000001300340552400217055ustar00rootroot00000000000000zend-code-release-3.1.0/src/Generator/DocBlock/Tag/AbstractTypeableTag.php000066400000000000000000000040751300340552400263110ustar00rootroot00000000000000setTypes($types); } if (!empty($description)) { $this->setDescription($description); } } /** * @param string $description * @return ReturnTag */ 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 ReturnTag */ 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); } } zend-code-release-3.1.0/src/Generator/DocBlock/Tag/AuthorTag.php000066400000000000000000000050031300340552400243120ustar00rootroot00000000000000setAuthorName($authorName); } if (!empty($authorEmail)) { $this->setAuthorEmail($authorEmail); } } /** * @param ReflectionTagInterface $reflectionTag * @return ReturnTag * @deprecated Deprecated in 2.3. Use TagManager::createTagFromReflection() instead */ 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() { $output = '@author' . ((!empty($this->authorName)) ? ' ' . $this->authorName : '') . ((!empty($this->authorEmail)) ? ' <' . $this->authorEmail . '>' : ''); return $output; } } zend-code-release-3.1.0/src/Generator/DocBlock/Tag/GenericTag.php000066400000000000000000000034021300340552400244250ustar00rootroot00000000000000setName($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() { $output = '@' . $this->name . ((!empty($this->content)) ? ' ' . $this->content : ''); return $output; } } zend-code-release-3.1.0/src/Generator/DocBlock/Tag/LicenseTag.php000066400000000000000000000046041300340552400244400ustar00rootroot00000000000000setUrl($url); } if (!empty($licenseName)) { $this->setLicenseName($licenseName); } } /** * @param ReflectionTagInterface $reflectionTag * @return ReturnTag * @deprecated Deprecated in 2.3. Use TagManager::createTagFromReflection() instead */ 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() { $output = '@license' . ((!empty($this->url)) ? ' ' . $this->url : '') . ((!empty($this->licenseName)) ? ' ' . $this->licenseName : ''); return $output; } } zend-code-release-3.1.0/src/Generator/DocBlock/Tag/MethodTag.php000066400000000000000000000041771300340552400243030ustar00rootroot00000000000000setMethodName($methodName); } $this->setIsStatic((bool) $isStatic); parent::__construct($types, $description); } /** * @return string */ public function getName() { return 'method'; } /** * @param boolean $isStatic * @return MethodTag */ public function setIsStatic($isStatic) { $this->isStatic = $isStatic; return $this; } /** * @return boolean */ 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() { $output = '@method' . (($this->isStatic) ? ' static' : '') . ((!empty($this->types)) ? ' ' . $this->getTypesAsString() : '') . ((!empty($this->methodName)) ? ' ' . $this->methodName . '()' : '') . ((!empty($this->description)) ? ' ' . $this->description : ''); return $output; } } zend-code-release-3.1.0/src/Generator/DocBlock/Tag/ParamTag.php000066400000000000000000000060571300340552400241220ustar00rootroot00000000000000setVariableName($variableName); } parent::__construct($types, $description); } /** * @param ReflectionTagInterface $reflectionTag * @return ReturnTag * @deprecated Deprecated in 2.3. Use TagManager::createTagFromReflection() instead */ 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; } /** * @param string $datatype * @return ReturnTag * @deprecated Deprecated in 2.3. Use setTypes() instead */ public function setDatatype($datatype) { return $this->setTypes($datatype); } /** * @return string * @deprecated Deprecated in 2.3. Use getTypes() or getTypesAsString() instead */ public function getDatatype() { return $this->getTypesAsString(); } /** * @param string $paramName * @return ParamTag * @deprecated Deprecated in 2.3. Use setVariableName() instead */ public function setParamName($paramName) { return $this->setVariableName($paramName); } /** * @return string * @deprecated Deprecated in 2.3. Use getVariableName() instead */ public function getParamName() { return $this->getVariableName(); } /** * @return string */ public function generate() { $output = '@param' . ((!empty($this->types)) ? ' ' . $this->getTypesAsString() : '') . ((!empty($this->variableName)) ? ' $' . $this->variableName : '') . ((!empty($this->description)) ? ' ' . $this->description : ''); return $output; } } zend-code-release-3.1.0/src/Generator/DocBlock/Tag/PropertyTag.php000066400000000000000000000032231300340552400246760ustar00rootroot00000000000000setPropertyName($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() { $output = '@property' . ((!empty($this->types)) ? ' ' . $this->getTypesAsString() : '') . ((!empty($this->propertyName)) ? ' $' . $this->propertyName : '') . ((!empty($this->description)) ? ' ' . $this->description : ''); return $output; } } zend-code-release-3.1.0/src/Generator/DocBlock/Tag/ReturnTag.php000066400000000000000000000033561300340552400243400ustar00rootroot00000000000000initializeDefaultTags(); return $tagManager->createTagFromReflection($reflectionTag); } /** * @return string */ public function getName() { return 'return'; } /** * @param string $datatype * @return ReturnTag * @deprecated Deprecated in 2.3. Use setTypes() instead */ public function setDatatype($datatype) { return $this->setTypes($datatype); } /** * @return string * @deprecated Deprecated in 2.3. Use getTypes() or getTypesAsString() instead */ public function getDatatype() { return $this->getTypesAsString(); } /** * @return string */ public function generate() { $output = '@return ' . $this->getTypesAsString() . ((!empty($this->description)) ? ' ' . $this->description : ''); return $output; } } zend-code-release-3.1.0/src/Generator/DocBlock/Tag/TagInterface.php000066400000000000000000000007161300340552400247560ustar00rootroot00000000000000types)) ? ' ' . $this->getTypesAsString() : '') . ((!empty($this->description)) ? ' ' . $this->description : ''); return $output; } } zend-code-release-3.1.0/src/Generator/DocBlock/TagManager.php000066400000000000000000000050711300340552400237140ustar00rootroot00000000000000addPrototype(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->setGenericPrototype(new Tag\GenericTag()); } /** * @param ReflectionTagInterface $reflectionTag * @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 (substr($method->getName(), 0, 3) == 'get') { $propertyName = substr($method->getName(), 3); if (method_exists($newTag, 'set' . $propertyName)) { $newTag->{'set' . $propertyName}($reflectionTag->{'get' . $propertyName}()); } } elseif (substr($method->getName(), 0, 2) == 'is') { $propertyName = ucfirst($method->getName()); if (method_exists($newTag, 'set' . $propertyName)) { $newTag->{'set' . $propertyName}($reflectionTag->{$method->getName()}()); } } } return $newTag; } } zend-code-release-3.1.0/src/Generator/DocBlockGenerator.php000066400000000000000000000156351300340552400235640ustar00rootroot00000000000000setSourceContent($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; } 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 $tags */ public function __construct($shortDescription = null, $longDescription = null, array $tags = []) { if ($shortDescription) { $this->setShortDescription($shortDescription); } if ($longDescription) { $this->setLongDescription($longDescription); } if (is_array($tags) && $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 $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 compatiblity 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 (null !== ($sd = $this->getShortDescription())) { $output .= $sd . self::LINE_FEED . self::LINE_FEED; } if (null !== ($ld = $this->getLongDescription())) { $output .= $ld . self::LINE_FEED . self::LINE_FEED; } /* @var $tag GeneratorInterface */ 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; } } zend-code-release-3.1.0/src/Generator/Exception/000077500000000000000000000000001300340552400214505ustar00rootroot00000000000000zend-code-release-3.1.0/src/Generator/Exception/ExceptionInterface.php000066400000000000000000000007151300340552400257430ustar00rootroot00000000000000setOptions($options); } } /** * Use this if you intend on generating code generation objects based on the same file. * This will keep previous changes to the file in tact during the same PHP process * * @param string $filePath * @param bool $includeIfNotAlreadyIncluded * @throws ReflectionException\InvalidArgumentException If file does not exists * @throws ReflectionException\RuntimeException If file exists but is not included or required * @return FileGenerator */ public static function fromReflectedFileName($filePath, $includeIfNotAlreadyIncluded = true) { $fileReflector = new FileReflection($filePath, $includeIfNotAlreadyIncluded); $codeGenerator = static::fromReflection($fileReflector); return $codeGenerator; } /** * @param FileReflection $fileReflection * @return FileGenerator */ public static function fromReflection(FileReflection $fileReflection) { $file = new static(); $file->setSourceContent($fileReflection->getContents()); $file->setSourceDirty(false); $uses = $fileReflection->getUses(); foreach ($fileReflection->getClasses() as $class) { $phpClass = ClassGenerator::fromReflection($class); $phpClass->setContainingFileGenerator($file); foreach ($uses as $fileUse) { $phpClass->addUse($fileUse['use'], $fileUse['as']); } $file->setClass($phpClass); } $namespace = $fileReflection->getNamespace(); if ($namespace != '') { $file->setNamespace($namespace); } if ($uses) { $file->setUses($uses); } if (($fileReflection->getDocComment() != '')) { $docBlock = $fileReflection->getDocBlock(); $file->setDocBlock(DocBlockGenerator::fromReflection($docBlock)); } return $file; } /** * @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); continue; case 'class': $fileGenerator->setClass( ($value instanceof ClassGenerator) ? $value : ClassGenerator::fromArray($value) ); continue; case 'requiredfiles': $fileGenerator->setRequiredFiles($value); continue; 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 array $requiredFiles * @return FileGenerator */ public function setRequiredFiles(array $requiredFiles) { $this->requiredFiles = $requiredFiles; return $this; } /** * @return array */ 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 */ 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) { list($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 $classes * @return FileGenerator */ public function setClasses(array $classes) { foreach ($classes as $class) { $this->setClass($class); } return $this; } /** * @param string $name * @return ClassGenerator */ public function getClass($name = null) { if ($name === null) { reset($this->classes); return current($this->classes); } return $this->classes[(string) $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; } /** * @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('#/\* Zend_Code_Generator_FileGenerator-DocBlockMarker \*/#m', $output)) { // @codingStandardsIgnoreStart $output = preg_replace('#/\* Zend_Code_Generator_FileGenerator-DocBlockMarker \*/#m', $docBlock->generate(), $output, 1); // @codingStandardsIgnoreEnd } else { $output .= $docBlock->generate() . self::LINE_FEED; } } // newline $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('#/\* Zend_Code_Generator_FileGenerator-NamespaceMarker \*/#m', $output)) { $output = preg_replace( '#/\* Zend_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) { list($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('#/\* Zend_Code_Generator_FileGenerator-UseMarker \*/#m', $output)) { $output = preg_replace( '#/\* Zend_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(), '/\* Zend_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; } } zend-code-release-3.1.0/src/Generator/FileGeneratorRegistry.php000066400000000000000000000025041300340552400245030ustar00rootroot00000000000000getFilename(); } if ($fileName == '') { throw new RuntimeException('FileName does not exist.'); } // cannot use realpath since the file might not exist, but we do need to have the index // in the same DIRECTORY_SEPARATOR that realpath would use: $fileName = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $fileName); static::$fileCodeGenerators[$fileName] = $fileCodeGenerator; } } zend-code-release-3.1.0/src/Generator/GeneratorInterface.php000066400000000000000000000006271300340552400237770ustar00rootroot00000000000000isInterface()) { 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->getNamespaceName()) ? $cg->getNamespaceName() . '\\' . $cg->getName() : $cg->getName(); 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; } } zend-code-release-3.1.0/src/Generator/MethodGenerator.php000066400000000000000000000263441300340552400233230ustar00rootroot00000000000000getDeclaringClass(); $method->setSourceContent($reflectionMethod->getContents(false)); $method->setSourceDirty(false); $method->setReturnType(self::extractReturnTypeFromMethodReflection($reflectionMethod)); if ($reflectionMethod->getDocComment() != '') { $method->setDocBlock(DocBlockGenerator::fromReflection($reflectionMethod->getDocBlock())); } $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)); } $method->setBody(static::clearBodyIndention($reflectionMethod->getBody())); 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 array $parameters * @param int $flags * @param string $body * @param DocBlockGenerator|string $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 array $parameters * @return MethodGenerator */ public function setParameters(array $parameters) { foreach ($parameters as $parameter) { $this->setParameter($parameter); } 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; 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 * * @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; } /** * @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; } public function __toString() { return $this->generate(); } /** * @param MethodReflection $methodReflection * * @return null|string */ private static function extractReturnTypeFromMethodReflection(MethodReflection $methodReflection) { $returnType = method_exists($methodReflection, 'getReturnType') ? $methodReflection->getReturnType() : null; if (! $returnType) { return null; } if (! method_exists($returnType, 'getName')) { return self::expandLiteralType((string) $returnType, $methodReflection); } return ($returnType->allowsNull() ? '?' : '') . self::expandLiteralType($returnType->getName(), $methodReflection); } /** * @param string $literalReturnType * @param ReflectionMethod $methodReflection * * @return string */ private static function expandLiteralType($literalReturnType, ReflectionMethod $methodReflection) { if ('self' === strtolower($literalReturnType)) { return $methodReflection->getDeclaringClass()->getName(); } if ('parent' === strtolower($literalReturnType)) { return $methodReflection->getDeclaringClass()->getParentClass()->getName(); } return $literalReturnType; } } zend-code-release-3.1.0/src/Generator/ParameterGenerator.php000066400000000000000000000237661300340552400240300ustar00rootroot00000000000000setName($reflectionParameter->getName()); if ($type = self::extractFQCNTypeFromReflectionType($reflectionParameter)) { $param->setType($type); } $param->setPosition($reflectionParameter->getPosition()); $variadic = method_exists($reflectionParameter, 'isVariadic') && $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 * * @throws Exception\InvalidArgumentException * @param array $array * @return ParameterGenerator */ public static function fromArray(array $array) { if (!isset($array['name'])) { throw new Exception\InvalidArgumentException( 'Paramerer 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; } } 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 ? (string) $this->type : 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 (!($defaultValue instanceof ValueGenerator)) { $defaultValue = new ValueGenerator($defaultValue); } $this->defaultValue = $defaultValue; return $this; } /** * @return string */ 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) { $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->defaultValue !== null) { $output .= ' = '; if (is_string($this->defaultValue)) { $output .= ValueGenerator::escape($this->defaultValue); } elseif ($this->defaultValue instanceof ValueGenerator) { $this->defaultValue->setOutputMode(ValueGenerator::OUTPUT_SINGLE_LINE); $output .= $this->defaultValue; } else { $output .= $this->defaultValue; } } return $output; } /** * @param ParameterReflection $reflectionParameter * * @return null|string */ private static function extractFQCNTypeFromReflectionType(ParameterReflection $reflectionParameter) { if (! method_exists($reflectionParameter, 'getType')) { return self::prePhp7ExtractFQCNTypeFromReflectionType($reflectionParameter); } $type = method_exists($reflectionParameter, 'getType') ? $reflectionParameter->getType() : null; if (! $type) { return null; } if (! method_exists($type, 'getName')) { return self::expandLiteralParameterType((string) $type, $reflectionParameter); } return ($type->allowsNull() ? '?' : '') . self::expandLiteralParameterType($type->getName(), $reflectionParameter); } /** * For ancient PHP versions (yes, you should upgrade to 7.0): * * @param ParameterReflection $reflectionParameter * * @return string|null */ private static function prePhp7ExtractFQCNTypeFromReflectionType(ParameterReflection $reflectionParameter) { if ($reflectionParameter->isCallable()) { return 'callable'; } if ($reflectionParameter->isArray()) { return 'array'; } if ($class = $reflectionParameter->getClass()) { return $class->getName(); } return null; } /** * @param string $literalParameterType * @param ReflectionParameter $reflectionParameter * * @return string */ private static function expandLiteralParameterType($literalParameterType, ReflectionParameter $reflectionParameter) { if ('self' === strtolower($literalParameterType)) { return $reflectionParameter->getDeclaringClass()->getName(); } if ('parent' === strtolower($literalParameterType)) { return $reflectionParameter->getDeclaringClass()->getParentClass()->getName(); } return $literalParameterType; } /** * @param string|null $type * * @return string */ private function generateTypeHint() { if (null === $this->type) { return ''; } return $this->type->generate() . ' '; } } zend-code-release-3.1.0/src/Generator/PropertyGenerator.php000066400000000000000000000155551300340552400237310ustar00rootroot00000000000000setName($reflectionProperty->getName()); $allDefaultProperties = $reflectionProperty->getDeclaringClass()->getDefaultProperties(); $property->setDefaultValue($allDefaultProperties[$reflectionProperty->getName()]); 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 * * @throws Exception\InvalidArgumentException * @param array $array * @return PropertyGenerator */ 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; } } return $property; } /** * @param string $name * @param PropertyValueGenerator|string|array $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->removeFlag(self::FLAG_PUBLIC | self::FLAG_PRIVATE | self::FLAG_PROTECTED); $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 PropertyGenerator */ 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 )); } $output .= $this->indentation . 'const ' . $name . ' = ' . (($defaultValue !== null) ? $defaultValue->generate() : 'null;'); } else { $output .= $this->indentation . $this->getVisibility() . (($this->isStatic()) ? ' static' : '') . ' $' . $name . ' = ' . (($defaultValue !== null) ? $defaultValue->generate() : 'null;'); } return $output; } } zend-code-release-3.1.0/src/Generator/PropertyValueGenerator.php000066400000000000000000000010501300340552400247070ustar00rootroot00000000000000getName()); $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->getNamespaceName()) ? $cg->getNamespaceName() . '\\' . $cg->getName() : $cg->getName(); 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; } /** * @param array|string $flags * @return self */ public function setFlags($flags) { return $this; } /** * @param string $flag * @return self */ public function addFlag($flag) { return $this; } /** * @param string $flag * @return self */ public function removeFlag($flag) { return $this; } /** * @param bool $isFinal * @return self */ public function setFinal($isFinal) { return $this; } /** * @param string $extendedClass * @return self */ public function setExtendedClass($extendedClass) { return $this; } /** * @param array $implementedInterfaces * @return self */ public function setImplementedInterfaces(array $implementedInterfaces) { return $this; } /** * @param bool $isAbstract * @return self */ public function setAbstract($isAbstract) { return $this; } } zend-code-release-3.1.0/src/Generator/TraitUsageGenerator.php000066400000000000000000000267401300340552400241530ustar00rootroot00000000000000classGenerator = $classGenerator; } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ public function addUse($use, $useAlias = null) { $this->removeUse($use); if (! empty($useAlias)) { $use .= ' as ' . $useAlias; } $this->uses[$use] = $use; return $this; } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ public function getUses() { return array_values($this->uses); } /** * @param $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 $use * @return bool */ public function hasUseAlias($use) { foreach ($this->uses as $key => $value) { $parts = explode(' as ', $value); if ($parts[0] === $use and count($parts) == 2) { return true; } }; return false; } /** * @param $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 $use * @return TraitUsageGenerator */ public function removeUseAlias($use) { foreach ($this->uses as $key => $value) { $parts = explode(' as ', $value); if ($parts[0] === $use and count($parts) == 2) { unset($this->uses[$value]); } }; return $this; } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ public function addTrait($trait) { $traitName = $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); } } } if (! $this->hasTrait($traitName)) { $this->traits[] = $traitName; } return $this; } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ public function addTraits(array $traits) { foreach ($traits as $trait) { $this->addTrait($trait); } return $this; } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ public function hasTrait($traitName) { return in_array($traitName, $this->traits); } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ public function getTraits() { return $this->traits; } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ public function removeTrait($traitName) { $key = array_search($traitName, $this->traits); if (false !== $key) { unset($this->traits[$key]); } return $this; } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ 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' ); } list($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; } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ public function getTraitAliases() { return $this->traitAliases; } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ 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' ); } list($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; } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ 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; } /** * @inherit Zend\Code\Generator\TraitUsageInterface */ public function getTraitOverrides() { return $this->traitOverrides; } /** * @inherit Zend\Code\Generator\GeneratorInterface */ 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)) { $output .= ";" . self::LINE_FEED . self::LINE_FEED; return $output; } $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; } } $output .= self::LINE_FEED . $indent . '}' . self::LINE_FEED . self::LINE_FEED; return $output; } } zend-code-release-3.1.0/src/Generator/TraitUsageInterface.php000066400000000000000000000105401300340552400241140ustar00rootroot00000000000000:: * 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 $traitToReplace */ 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 $traitAndMethod * @param null $overridesToRemove * @return $this */ public function removeTraitOverride($method, $overridesToRemove = null); /** * Return trait overrides * * @return array */ public function getTraitOverrides(); } zend-code-release-3.1.0/src/Generator/TypeGenerator.php000066400000000000000000000077061300340552400230250ustar00rootroot00000000000000type = $trimmedType; $instance->nullable = $nullable; $instance->isInternalPhpType = self::isInternalPhpType($trimmedType); return $instance; } private function __construct() { } /** * {@inheritDoc} */ public function generate() { $nullable = $this->nullable ? '?' : ''; if ($this->isInternalPhpType) { return $nullable . strtolower($this->type); } return $nullable . '\\' . $this->type; } /** * @return string the cleaned type string */ public function __toString() { return ltrim($this->generate(), '?\\'); } /** * @param string $type * * @return bool[]|string[] ordered tuple, first key represents whether the type is nullable, second is the * trimmed string */ private static function trimNullable($type) { if (0 === strpos($type, '?')) { return [true, substr($type, 1)]; } return [false, $type]; } /** * @param string $type * * @return bool[]|string[] ordered tuple, first key represents whether the values was trimmed, second is the * trimmed string */ private static function trimType($type) { if (0 === strpos($type, '\\')) { return [true, substr($type, 1)]; } return [false, $type]; } /** * @param string $type * * @return bool */ private static function isInternalPhpType($type) { return in_array(strtolower($type), self::$internalPhpTypes, true); } } zend-code-release-3.1.0/src/Generator/ValueGenerator.php000066400000000000000000000303301300340552400231450ustar00rootroot00000000000000setValue($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 Zend\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 (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()); } } $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_SHORT) { $startArray = '['; $endArray = ']'; } else { $startArray = 'array('; $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 $v ValueGenerator */ $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.', get_class($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; } public function __toString() { return $this->generate(); } } zend-code-release-3.1.0/src/Generic/000077500000000000000000000000001300340552400171405ustar00rootroot00000000000000zend-code-release-3.1.0/src/Generic/Prototype/000077500000000000000000000000001300340552400211455ustar00rootroot00000000000000zend-code-release-3.1.0/src/Generic/Prototype/PrototypeClassFactory.php000066400000000000000000000066441300340552400262130ustar00rootroot00000000000000addPrototype($prototype); } if ($genericPrototype) { $this->setGenericPrototype($genericPrototype); } } /** * @param PrototypeInterface $prototype * @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; } /** * @param PrototypeGenericInterface $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; } } zend-code-release-3.1.0/src/Generic/Prototype/PrototypeGenericInterface.php000066400000000000000000000007601300340552400270040ustar00rootroot00000000000000setNamespace($namespace); } if ($uses) { $this->setUses($uses); } } /** * @param string $namespace * @return NameInformation */ public function setNamespace($namespace) { $this->namespace = (string) $namespace; return $this; } /** * @return string */ public function getNamespace() { return $this->namespace; } /** * @return bool */ public function hasNamespace() { return ($this->namespace !== null); } /** * @param array $uses * @return NameInformation */ public function setUses(array $uses) { $this->uses = []; $this->addUses($uses); return $this; } /** * @param array $uses * @return NameInformation */ public function addUses(array $uses) { foreach ($uses as $use => $as) { if (is_int($use)) { $this->addUse($as); } elseif (is_string($use)) { $this->addUse($use, $as); } } return $this; } /** * @param array|string $use * @param string $as */ public function addUse($use, $as = null) { if (is_array($use) && array_key_exists('use', $use) && array_key_exists('as', $use)) { $uses = $use; $use = $uses['use']; $as = $uses['as']; } $use = trim($use, '\\'); if ($as === null) { $as = trim($use, '\\'); $nsSeparatorPosition = strrpos($as, '\\'); if ($nsSeparatorPosition !== false && $nsSeparatorPosition !== 0 && $nsSeparatorPosition != strlen($as)) { $as = substr($as, $nsSeparatorPosition + 1); } } $this->uses[$use] = $as; } /** * @return array */ public function getUses() { return $this->uses; } /** * @param string $name * @return string */ public function resolveName($name) { if ($this->namespace && !$this->uses && strlen($name) > 0 && $name{0} != '\\') { return $this->namespace . '\\' . $name; } if (!$this->uses || strlen($name) <= 0 || $name{0} == '\\') { return ltrim($name, '\\'); } if ($this->namespace || $this->uses) { $firstPart = $name; if (($firstPartEnd = strpos($firstPart, '\\')) !== false) { $firstPart = substr($firstPart, 0, $firstPartEnd); } else { $firstPartEnd = strlen($firstPart); } if (($fqns = array_search($firstPart, $this->uses)) !== false) { return substr_replace($name, $fqns, 0, $firstPartEnd); } if ($this->namespace) { return $this->namespace . '\\' . $name; } } return $name; } } zend-code-release-3.1.0/src/Reflection/000077500000000000000000000000001300340552400176565ustar00rootroot00000000000000zend-code-release-3.1.0/src/Reflection/ClassReflection.php000066400000000000000000000160101300340552400234450ustar00rootroot00000000000000getFileName()); return $instance; } /** * Return the classes DocBlock reflection object * * @return DocBlockReflection * @throws Exception\ExceptionInterface for missing DocBock or invalid reflection class */ public function getDocBlock() { if (isset($this->docBlock)) { return $this->docBlock; } if ('' == $this->getDocComment()) { return false; } $this->docBlock = new DocBlockReflection($this); return $this->docBlock; } /** * @param AnnotationManager $annotationManager * @return AnnotationCollection */ public function getAnnotations(AnnotationManager $annotationManager) { $docComment = $this->getDocComment(); if ($docComment == '') { return false; } if ($this->annotations) { return $this->annotations; } $fileScanner = $this->createFileScanner($this->getFileName()); $nameInformation = $fileScanner->getClassNameInformation($this->getName()); if (!$nameInformation) { return false; } $this->annotations = new AnnotationScanner($annotationManager, $docComment, $nameInformation); return $this->annotations; } /** * 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(); $zendReflections = []; while ($phpReflections && ($phpReflection = array_shift($phpReflections))) { $instance = new ClassReflection($phpReflection->getName()); $zendReflections[] = $instance; unset($phpReflection); } unset($phpReflections); return $zendReflections; } /** * Return method reflection by name * * @param string $name * @return MethodReflection */ public function getMethod($name) { $method = new MethodReflection($this->getName(), parent::getMethod($name)->getName()); return $method; } /** * 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 array|null */ 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) { $zendReflection = new ClassReflection($phpReflection->getName()); unset($phpReflection); return $zendReflection; } return false; } /** * Return reflection property of this class by name * * @param string $name * @return PropertyReflection */ public function getProperty($name) { $phpReflection = parent::getProperty($name); $zendReflection = new PropertyReflection($this->getName(), $phpReflection->getName()); unset($phpReflection); return $zendReflection; } /** * Return reflection properties of this class * * @param int $filter * @return PropertyReflection[] */ public function getProperties($filter = -1) { $phpReflections = parent::getProperties($filter); $zendReflections = []; while ($phpReflections && ($phpReflection = array_shift($phpReflections))) { $instance = new PropertyReflection($this->getName(), $phpReflection->getName()); $zendReflections[] = $instance; unset($phpReflection); } unset($phpReflections); return $zendReflections; } /** * @return string */ public function toString() { return parent::__toString(); } /** * @return string */ public function __toString() { return parent::__toString(); } /** * Creates a new FileScanner instance. * * By having this as a seperate method it allows the method to be overridden * if a different FileScanner is needed. * * @param string $filename * * @return FileScanner */ protected function createFileScanner($filename) { return new FileScanner($filename); } } zend-code-release-3.1.0/src/Reflection/DocBlock/000077500000000000000000000000001300340552400213365ustar00rootroot00000000000000zend-code-release-3.1.0/src/Reflection/DocBlock/Tag/000077500000000000000000000000001300340552400220515ustar00rootroot00000000000000zend-code-release-3.1.0/src/Reflection/DocBlock/Tag/AuthorTag.php000066400000000000000000000027341300340552400244660ustar00rootroot00000000000000]*)\>)?(.*)$/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; } public function __toString() { return 'DocBlock Tag [ * @' . $this->getName() . ' ]' . "\n"; } } zend-code-release-3.1.0/src/Reflection/DocBlock/Tag/GenericTag.php000066400000000000000000000042021300340552400245700ustar00rootroot00000000000000contentSplitCharacter = $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 */ 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); } } zend-code-release-3.1.0/src/Reflection/DocBlock/Tag/LicenseTag.php000066400000000000000000000026711300340552400246060ustar00rootroot00000000000000url = 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; } public function __toString() { return 'DocBlock Tag [ * @' . $this->getName() . ' ]' . "\n"; } } zend-code-release-3.1.0/src/Reflection/DocBlock/Tag/MethodTag.php000066400000000000000000000043631300340552400244440ustar00rootroot00000000000000isStatic = 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 * * @return null|string * @deprecated 2.0.4 use getTypes instead */ public function getReturnType() { if (empty($this->types)) { return; } return $this->types[0]; } 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; } public function __toString() { return 'DocBlock Tag [ * @' . $this->getName() . ' ]' . "\n"; } } zend-code-release-3.1.0/src/Reflection/DocBlock/Tag/ParamTag.php000066400000000000000000000036231300340552400242620ustar00rootroot00000000000000types = 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 * * @return string * @deprecated 2.0.4 use getTypes instead */ public function getType() { if (empty($this->types)) { return ''; } return $this->types[0]; } 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; } } zend-code-release-3.1.0/src/Reflection/DocBlock/Tag/PhpDocTypedTagInterface.php000066400000000000000000000010211300340552400272140ustar00rootroot00000000000000types = explode('|', rtrim($match[1])); } if ($match[2] !== '') { $this->propertyName = $match[2]; } if ($match[3] !== '') { $this->description = $match[3]; } } /** * @return null|string * @deprecated 2.0.4 use getTypes instead */ public function getType() { if (empty($this->types)) { return; } return $this->types[0]; } public function getTypes() { return $this->types; } /** * @return null|string */ public function getPropertyName() { return $this->propertyName; } /** * @return null|string */ public function getDescription() { return $this->description; } public function __toString() { return 'DocBlock Tag [ * @' . $this->getName() . ' ]' . "\n"; } } zend-code-release-3.1.0/src/Reflection/DocBlock/Tag/ReturnTag.php000066400000000000000000000030231300340552400244730ustar00rootroot00000000000000types = explode('|', $matches[1]); if (isset($matches[2])) { $this->description = trim(preg_replace('#\s+#', ' ', $matches[2])); } } /** * @return string * @deprecated 2.0.4 use getTypes instead */ public function getType() { if (empty($this->types)) { return ''; } return $this->types[0]; } public function getTypes() { return $this->types; } /** * @return string */ public function getDescription() { return $this->description; } } zend-code-release-3.1.0/src/Reflection/DocBlock/Tag/TagInterface.php000066400000000000000000000010741300340552400251200ustar00rootroot00000000000000types = explode('|', $matches[1]); if (isset($matches[2])) { $this->description = $matches[2]; } } /** * Get return variable type * * @return string * @deprecated 2.0.4 use getTypes instead */ public function getType() { return implode('|', $this->getTypes()); } /** * @return array */ public function getTypes() { return $this->types; } /** * @return string */ public function getDescription() { return $this->description; } } zend-code-release-3.1.0/src/Reflection/DocBlock/TagManager.php000066400000000000000000000025511300340552400240600ustar00rootroot00000000000000addPrototype(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->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; } } zend-code-release-3.1.0/src/Reflection/DocBlockReflection.php000066400000000000000000000154541300340552400240730ustar00rootroot00000000000000initializeDefaultTags(); } $this->tagManager = $tagManager; if ($commentOrReflector instanceof Reflector) { $this->reflector = $commentOrReflector; if (!method_exists($commentOrReflector, 'getDocComment')) { throw new Exception\InvalidArgumentException('Reflector must contain method "getDocComment"'); } /* @var MethodReflection $commentOrReflector */ $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', get_class($this) )); } 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(); } } zend-code-release-3.1.0/src/Reflection/Exception/000077500000000000000000000000001300340552400216145ustar00rootroot00000000000000zend-code-release-3.1.0/src/Reflection/Exception/BadMethodCallException.php000066400000000000000000000007471300340552400266370ustar00rootroot00000000000000filePath = $fileRealPath; $this->reflect(); } /** * Required by the Reflector interface. * * @todo What should this do? * @return null */ public static function export() { return; } /** * Return the file name of the reflected file * * @return string */ public function getFileName() { return basename($this->filePath); } /** * Get the start line - Always 1, staying consistent with the Reflection API * * @return int */ public function getStartLine() { return $this->startLine; } /** * Get the end line / number of lines * * @return int */ public function getEndLine() { return $this->endLine; } /** * @return string */ public function getDocComment() { return $this->docComment; } /** * @return DocBlockReflection */ public function getDocBlock() { if (!($docComment = $this->getDocComment())) { return false; } $instance = new DocBlockReflection($docComment); return $instance; } /** * @return string[] */ public function getNamespaces() { return $this->namespaces; } /** * @return string */ public function getNamespace() { if (count($this->namespaces) == 0) { return; } return $this->namespaces[0]; } /** * @return array */ public function getUses() { return $this->uses; } /** * Return the reflection classes of the classes found inside this file * * @return ClassReflection[] */ public function getClasses() { $classes = []; foreach ($this->classes as $class) { $classes[] = new ClassReflection($class); } return $classes; } /** * Return the reflection functions of the functions found inside this file * * @return FunctionReflection[] */ public function getFunctions() { $functions = []; foreach ($this->functions as $function) { $functions[] = new FunctionReflection($function); } return $functions; } /** * Retrieve the reflection class of a given class found in this file * * @param null|string $name * @return ClassReflection * @throws Exception\InvalidArgumentException for invalid class name or invalid reflection class */ public function getClass($name = null) { if (null === $name) { reset($this->classes); $selected = current($this->classes); return new ClassReflection($selected); } if (in_array($name, $this->classes)) { return new ClassReflection($name); } throw new Exception\InvalidArgumentException(sprintf( 'Class by name %s not found.', $name )); } /** * Return the full contents of file * * @return string */ public function getContents() { return file_get_contents($this->filePath); } public function toString() { return ''; // @todo } /** * Serialize to string * * Required by the Reflector interface * * @todo What should this serialization look like? * @return string */ public function __toString() { return ''; } /** * This method does the work of "reflecting" the file * * Uses Zend\Code\Scanner\FileScanner to gather file information * * @return void */ protected function reflect() { $scanner = new CachingFileScanner($this->filePath); $this->docComment = $scanner->getDocComment(); $this->requiredFiles = $scanner->getIncludes(); $this->classes = $scanner->getClassNames(); $this->namespaces = $scanner->getNamespaces(); $this->uses = $scanner->getUses(); } /** * Validate / check a file level DocBlock * * @param array $tokens Array of tokenizer tokens * @return void */ protected function checkFileDocBlock($tokens) { foreach ($tokens as $token) { $type = $token[0]; $value = $token[1]; $lineNum = $token[2]; if (($type == T_OPEN_TAG) || ($type == T_WHITESPACE)) { continue; } elseif ($type == T_DOC_COMMENT) { $this->docComment = $value; $this->startLine = $lineNum + substr_count($value, "\n") + 1; return; } else { // Only whitespace is allowed before file DocBlocks return; } } } } zend-code-release-3.1.0/src/Reflection/FunctionReflection.php000066400000000000000000000177441300340552400242040ustar00rootroot00000000000000getDocComment())) { throw new Exception\InvalidArgumentException(sprintf( '%s does not have a DocBlock', $this->getName() )); } $instance = new DocBlockReflection($comment); return $instance; } /** * 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 * * @return array */ public function getPrototype($format = FunctionReflection::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 == FunctionReflection::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(); $zendReflections = []; while ($phpReflections && ($phpReflection = array_shift($phpReflections))) { $instance = new ParameterReflection($this->getName(), $phpReflection->getName()); $zendReflections[] = $instance; unset($phpReflection); } unset($phpReflections); return $zendReflections; } /** * 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(); } } zend-code-release-3.1.0/src/Reflection/MethodReflection.php000066400000000000000000000350121300340552400236230ustar00rootroot00000000000000getDocComment()) { return false; } $instance = new DocBlockReflection($this); return $instance; } /** * @param AnnotationManager $annotationManager * @return AnnotationScanner */ public function getAnnotations(AnnotationManager $annotationManager) { if (($docComment = $this->getDocComment()) == '') { return false; } if ($this->annotations) { return $this->annotations; } $cachingFileScanner = $this->createFileScanner($this->getFileName()); $nameInformation = $cachingFileScanner->getClassNameInformation($this->getDeclaringClass()->getName()); if (!$nameInformation) { return false; } $this->annotations = new AnnotationScanner($annotationManager, $docComment, $nameInformation); return $this->annotations; } /** * 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(); $zendReflection = new ClassReflection($phpReflection->getName()); unset($phpReflection); return $zendReflection; } /** * Get method prototype * * @return array */ public function getPrototype($format = MethodReflection::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 == MethodReflection::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(); $zendReflections = []; while ($phpReflections && ($phpReflection = array_shift($phpReflections))) { $instance = new ParameterReflection( [$this->getDeclaringClass()->getName(), $this->getName()], $phpReflection->getName() ); $zendReflections[] = $instance; unset($phpReflection); } unset($phpReflections); return $zendReflections; } /** * 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; continue; } $capture = false; continue; } break; case "{": if ($capture === false) { continue; } if ($firstBrace === false) { $firstBrace = true; if ($bodyOnly === true) { continue; } } $body .= $tokenValue; break; case "}": if ($capture === false) { continue; } //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) { continue; } // if returning body only wait for first brace before capturing if ($bodyOnly === true && $firstBrace !== true) { continue; } $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 = $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 occurance 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(); } /** * Creates a new FileScanner instance. * * By having this as a seperate method it allows the method to be overridden * if a different FileScanner is needed. * * @param string $filename * * @return CachingFileScanner */ protected function createFileScanner($filename) { return new CachingFileScanner($filename); } } zend-code-release-3.1.0/src/Reflection/ParameterReflection.php000066400000000000000000000060511300340552400243240ustar00rootroot00000000000000getName()); unset($phpReflection); return $zendReflection; } /** * Get class reflection object * * @return ClassReflection */ public function getClass() { $phpReflection = parent::getClass(); if ($phpReflection === null) { return; } $zendReflection = new ClassReflection($phpReflection->getName()); unset($phpReflection); return $zendReflection; } /** * Get declaring function reflection object * * @return FunctionReflection|MethodReflection */ public function getDeclaringFunction() { $phpReflection = parent::getDeclaringFunction(); if ($phpReflection instanceof \ReflectionMethod) { $zendReflection = new MethodReflection($this->getDeclaringClass()->getName(), $phpReflection->getName()); } else { $zendReflection = new FunctionReflection($phpReflection->getName()); } unset($phpReflection); return $zendReflection; } /** * Get parameter type * * @return string|null */ public function detectType() { if (method_exists($this, 'getType') && ($type = $this->getType()) && $type->isBuiltin() ) { return (string) $type; } // can be dropped when dropping PHP7 support: if ($this->isArray()) { return 'array'; } // can be dropped when dropping PHP7 support: if ($this->isCallable()) { return 'callable'; } 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(); } } zend-code-release-3.1.0/src/Reflection/PropertyReflection.php000066400000000000000000000055201300340552400242300ustar00rootroot00000000000000getName()); unset($phpReflection); return $zendReflection; } /** * 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; } $docBlockReflection = new DocBlockReflection($docComment); return $docBlockReflection; } /** * @param AnnotationManager $annotationManager * @return AnnotationScanner */ public function getAnnotations(AnnotationManager $annotationManager) { if (null !== $this->annotations) { return $this->annotations; } if (($docComment = $this->getDocComment()) == '') { return false; } $class = $this->getDeclaringClass(); $cachingFileScanner = $this->createFileScanner($class->getFileName()); $nameInformation = $cachingFileScanner->getClassNameInformation($class->getName()); if (!$nameInformation) { return false; } $this->annotations = new AnnotationScanner($annotationManager, $docComment, $nameInformation); return $this->annotations; } /** * @return string */ public function toString() { return $this->__toString(); } /** * Creates a new FileScanner instance. * * By having this as a seperate method it allows the method to be overridden * if a different FileScanner is needed. * * @param string $filename * * @return CachingFileScanner */ protected function createFileScanner($filename) { return new CachingFileScanner($filename); } } zend-code-release-3.1.0/src/Reflection/ReflectionInterface.php000066400000000000000000000007411300340552400243040ustar00rootroot00000000000000directories as $scanner) { $classes += $scanner->getClasses(); } if ($returnScannerClass) { foreach ($classes as $index => $class) { $classes[$index] = $this->getClass($class, $returnScannerClass, $returnDerivedScannerClass); } } return $classes; } /** * @param string $class * @return bool */ public function hasClass($class) { foreach ($this->directories as $scanner) { if ($scanner->hasClass($class)) { break; } else { unset($scanner); } } return (isset($scanner)); } /** * @param string $class * @param bool $returnScannerClass * @param bool $returnDerivedScannerClass * @return ClassScanner|DerivedClassScanner * @throws Exception\RuntimeException */ public function getClass($class, $returnScannerClass = true, $returnDerivedScannerClass = false) { foreach ($this->directories as $scanner) { if ($scanner->hasClass($class)) { break; } else { unset($scanner); } } if (!isset($scanner)) { throw new Exception\RuntimeException('Class by that name was not found.'); } $classScanner = $scanner->getClass($class); return new DerivedClassScanner($classScanner, $this); } /** * @param bool $returnScannerClass */ public function getFunctions($returnScannerClass = false) { $this->scan(); if (!$returnScannerClass) { $functions = []; foreach ($this->infos as $info) { if ($info['type'] == 'function') { $functions[] = $info['name']; } } return $functions; } $scannerClass = new FunctionScanner(); // @todo } } zend-code-release-3.1.0/src/Scanner/AnnotationScanner.php000066400000000000000000000276471300340552400233320ustar00rootroot00000000000000annotationManager = $annotationManager; $this->docComment = $docComment; $this->nameInformation = $nameInformation; $this->scan($this->tokenize()); } /** * @param NameInformation $nameInformation */ public function setNameInformation(NameInformation $nameInformation) { $this->nameInformation = $nameInformation; } /** * @param array $tokens */ protected function scan(array $tokens) { $annotations = []; $annotationIndex = -1; $contentEnd = false; reset($tokens); SCANNER_TOP: $token = current($tokens); switch ($token[0]) { case 'ANNOTATION_CLASS': $contentEnd = false; $annotationIndex++; $class = substr($token[1], 1); $class = $this->nameInformation->resolveName($class); $annotations[$annotationIndex] = [$class, null]; goto SCANNER_CONTINUE; // goto no break needed case 'ANNOTATION_CONTENT_START': $annotations[$annotationIndex][1] = ''; // fall-through case 'ANNOTATION_CONTENT_END': case 'ANNOTATION_CONTENT': case 'ANNOTATION_WHITESPACE': case 'ANNOTATION_NEWLINE': if (!$contentEnd && isset($annotations[$annotationIndex]) && is_string($annotations[$annotationIndex][1]) ) { $annotations[$annotationIndex][1] .= $token[1]; } if ($token[0] === 'ANNOTATION_CONTENT_END') { $contentEnd = true; } goto SCANNER_CONTINUE; // goto no break needed } SCANNER_CONTINUE: if (next($tokens) === false) { goto SCANNER_END; } goto SCANNER_TOP; SCANNER_END: foreach ($annotations as $annotation) { $annotation[] = '@' . $annotation[0] . $annotation[1]; $annotationObject = $this->annotationManager->createAnnotation($annotation); if ($annotationObject) { $this->append($annotationObject); } } } /** * @return array */ protected function tokenize() { static $CONTEXT_DOCBLOCK = 0x01; static $CONTEXT_ASTERISK = 0x02; static $CONTEXT_CLASS = 0x04; static $CONTEXT_CONTENT = 0x08; $context = 0x00; $stream = $this->docComment; $streamIndex = null; $tokens = []; $tokenIndex = null; $currentChar = null; $currentWord = null; $currentLine = null; $annotationParentCount = 0; $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('#(.*?)(?:\n|\r\n?)#', $stream, $matches, null, $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] = ['ANNOTATION_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_LINE = function () use (&$currentLine, &$tokens, &$tokenIndex) { $tokens[$tokenIndex][1] .= $currentLine; }; $MACRO_HAS_CONTEXT = function ($which) use (&$context) { return (($context & $which) === $which); }; $MACRO_STREAM_ADVANCE_CHAR(); $MACRO_TOKEN_ADVANCE(); TOKENIZER_TOP: if ($context === 0x00 && $currentChar === '/' && $currentWord === '/**') { $MACRO_TOKEN_SET_TYPE('ANNOTATION_COMMENTSTART'); $MACRO_TOKEN_APPEND_WORD(); $MACRO_TOKEN_ADVANCE(); $context |= $CONTEXT_DOCBLOCK; $context |= $CONTEXT_ASTERISK; if ($MACRO_STREAM_ADVANCE_WORD() === false) { goto TOKENIZER_END; } goto TOKENIZER_TOP; } if ($MACRO_HAS_CONTEXT($CONTEXT_CLASS)) { if (in_array($currentChar, [' ', '(', "\n", "\r"])) { $context &= ~$CONTEXT_CLASS; $MACRO_TOKEN_ADVANCE(); } else { $MACRO_TOKEN_APPEND_CHAR(); if ($MACRO_STREAM_ADVANCE_CHAR() === false) { goto TOKENIZER_END; } goto TOKENIZER_TOP; } } // Since we don't know what line endings are used in the file, we check for all scenarios. If we find a // cariage return (\r), we check the next character for a line feed (\n). If so we consume it and act as // if the cariage return was a line feed. $lineEnded = $currentChar === "\n"; if ($currentChar === "\r") { $lineEnded = true; $nextChar = $MACRO_STREAM_ADVANCE_CHAR(); if ($nextChar !== "\n") { $streamIndex--; } $currentChar = "\n"; } if ($lineEnded) { $MACRO_TOKEN_SET_TYPE('ANNOTATION_NEWLINE'); $MACRO_TOKEN_APPEND_CHAR(); $MACRO_TOKEN_ADVANCE(); $context &= ~$CONTEXT_ASTERISK; $context &= ~$CONTEXT_CLASS; if ($MACRO_STREAM_ADVANCE_CHAR() === false) { goto TOKENIZER_END; } goto TOKENIZER_TOP; } if ($currentChar === ' ') { $MACRO_TOKEN_SET_TYPE( ($MACRO_HAS_CONTEXT($CONTEXT_ASTERISK)) ? 'ANNOTATION_WHITESPACE' : 'ANNOTATION_WHITESPACE_INDENT' ); $MACRO_TOKEN_APPEND_WORD(); $MACRO_TOKEN_ADVANCE(); if ($MACRO_STREAM_ADVANCE_WORD() === false) { goto TOKENIZER_END; } goto TOKENIZER_TOP; } if ($MACRO_HAS_CONTEXT($CONTEXT_CONTENT) && $MACRO_HAS_CONTEXT($CONTEXT_ASTERISK)) { $MACRO_TOKEN_SET_TYPE('ANNOTATION_CONTENT'); $annotationParentCount += substr_count($currentWord, '('); $annotationParentCount -= substr_count($currentWord, ')'); if ($annotationParentCount === 0) { $context &= ~$CONTEXT_CONTENT; $MACRO_TOKEN_SET_TYPE('ANNOTATION_CONTENT_END'); } $MACRO_TOKEN_APPEND_WORD(); $MACRO_TOKEN_ADVANCE(); if ($MACRO_STREAM_ADVANCE_WORD() === false) { goto TOKENIZER_END; } goto TOKENIZER_TOP; } if ($currentChar === '(' && $tokens[$tokenIndex - 1][0] === 'ANNOTATION_CLASS') { $context |= $CONTEXT_CONTENT; $annotationParentCount = 1; $MACRO_TOKEN_SET_TYPE('ANNOTATION_CONTENT_START'); $MACRO_TOKEN_APPEND_CHAR(); $MACRO_TOKEN_ADVANCE(); if ($MACRO_STREAM_ADVANCE_CHAR() === false) { goto TOKENIZER_END; } goto TOKENIZER_TOP; } if ($MACRO_HAS_CONTEXT($CONTEXT_DOCBLOCK) && $currentWord === '*/') { $MACRO_TOKEN_SET_TYPE('ANNOTATION_COMMENTEND'); $MACRO_TOKEN_APPEND_WORD(); $MACRO_TOKEN_ADVANCE(); $context &= ~$CONTEXT_DOCBLOCK; if ($MACRO_STREAM_ADVANCE_WORD() === false) { goto TOKENIZER_END; } goto TOKENIZER_TOP; } if ($currentChar === '*') { if ($MACRO_HAS_CONTEXT($CONTEXT_DOCBLOCK) && ($MACRO_HAS_CONTEXT($CONTEXT_ASTERISK))) { $MACRO_TOKEN_SET_TYPE('ANNOTATION_IGNORE'); } else { $MACRO_TOKEN_SET_TYPE('ANNOTATION_ASTERISK'); $context |= $CONTEXT_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('ANNOTATION_CLASS'); $context |= $CONTEXT_CLASS; $MACRO_TOKEN_APPEND_CHAR(); if ($MACRO_STREAM_ADVANCE_CHAR() === false) { goto TOKENIZER_END; } goto TOKENIZER_TOP; } TOKENIZER_CONTINUE: if ($context && $CONTEXT_CONTENT) { $MACRO_TOKEN_APPEND_CHAR(); if ($MACRO_STREAM_ADVANCE_CHAR() === false) { goto TOKENIZER_END; } } else { $MACRO_TOKEN_SET_TYPE('ANNOTATION_IGNORE'); $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; } } zend-code-release-3.1.0/src/Scanner/CachingFileScanner.php000066400000000000000000000067171300340552400233470ustar00rootroot00000000000000fileScanner = static::$cache[$cacheId]; } else { $this->fileScanner = new FileScanner($file, $annotationManager); static::$cache[$cacheId] = $this->fileScanner; } } /** * @return void */ public static function clearCache() { static::$cache = []; } /** * @return AnnotationManager */ public function getAnnotationManager() { return $this->fileScanner->getAnnotationManager(); } /** * @return array|null|string */ public function getFile() { return $this->fileScanner->getFile(); } /** * @return null|string */ public function getDocComment() { return $this->fileScanner->getDocComment(); } /** * @return array */ public function getNamespaces() { return $this->fileScanner->getNamespaces(); } /** * @param null|string $namespace * @return array|null */ public function getUses($namespace = null) { return $this->fileScanner->getUses($namespace); } /** * @return array */ public function getIncludes() { return $this->fileScanner->getIncludes(); } /** * @return array */ public function getClassNames() { return $this->fileScanner->getClassNames(); } /** * @return array */ public function getClasses() { return $this->fileScanner->getClasses(); } /** * @param int|string $className * @return ClassScanner */ public function getClass($className) { return $this->fileScanner->getClass($className); } /** * @param string $className * @return bool|null|NameInformation */ public function getClassNameInformation($className) { return $this->fileScanner->getClassNameInformation($className); } /** * @return array */ public function getFunctionNames() { return $this->fileScanner->getFunctionNames(); } /** * @return array */ public function getFunctions() { return $this->fileScanner->getFunctions(); } } zend-code-release-3.1.0/src/Scanner/ClassScanner.php000066400000000000000000001173761300340552400222640ustar00rootroot00000000000000tokens = $classTokens; $this->nameInformation = $nameInformation; } /** * Get annotations * * @param Annotation\AnnotationManager $annotationManager * @return Annotation\AnnotationCollection */ public function getAnnotations(Annotation\AnnotationManager $annotationManager) { if (($docComment = $this->getDocComment()) == '') { return false; } return new AnnotationScanner($annotationManager, $docComment, $this->nameInformation); } /** * Return documentation comment * * @return null|string */ public function getDocComment() { $this->scan(); return $this->docComment; } /** * Return documentation block * * @return false|DocBlockScanner */ public function getDocBlock() { if (!$docComment = $this->getDocComment()) { return false; } return new DocBlockScanner($docComment); } /** * Return a name of class * * @return null|string */ public function getName() { $this->scan(); return $this->name; } /** * Return short name of class * * @return null|string */ public function getShortName() { $this->scan(); return $this->shortName; } /** * Return number of first line * * @return int|null */ public function getLineStart() { $this->scan(); return $this->lineStart; } /** * Return number of last line * * @return int|null */ public function getLineEnd() { $this->scan(); return $this->lineEnd; } /** * Verify if class is final * * @return bool */ public function isFinal() { $this->scan(); return $this->isFinal; } /** * Verify if class is a trait * @return bool */ public function isTrait() { $this->scan(); return $this->isTrait; } /** * Verify if class is instantiable * * @return bool */ public function isInstantiable() { $this->scan(); return (!$this->isAbstract && !$this->isInterface && !$this->isTrait); } /** * Verify if class is an abstract class * * @return bool */ public function isAbstract() { $this->scan(); return $this->isAbstract; } /** * Verify if class is an interface * * @return bool */ public function isInterface() { $this->scan(); return $this->isInterface; } /** * Verify if class has parent * * @return bool */ public function hasParentClass() { $this->scan(); return ($this->parentClass !== null); } /** * Return a name of parent class * * @return null|string */ public function getParentClass() { $this->scan(); return $this->parentClass; } /** * Return a list of interface names * * @return array */ public function getInterfaces() { $this->scan(); return $this->interfaces; } /** * Return a list of constant names * * @return array */ public function getConstantNames() { $this->scan(); $return = []; foreach ($this->infos as $info) { if ($info['type'] != 'constant') { continue; } $return[] = $info['name']; } return $return; } /** * Return a list of constants * * @param bool $namesOnly Set false to return instances of ConstantScanner * @return array|ConstantScanner[] */ public function getConstants($namesOnly = true) { if (true === $namesOnly) { trigger_error('Use method getConstantNames() instead', E_USER_DEPRECATED); return $this->getConstantNames(); } $this->scan(); $return = []; foreach ($this->infos as $info) { if ($info['type'] != 'constant') { continue; } $return[] = $this->getConstant($info['name']); } return $return; } /** * Return a single constant by given name or index of info * * @param string|int $constantNameOrInfoIndex * @throws Exception\InvalidArgumentException * @return bool|ConstantScanner */ public function getConstant($constantNameOrInfoIndex) { $this->scan(); if (is_int($constantNameOrInfoIndex)) { $info = $this->infos[$constantNameOrInfoIndex]; if ($info['type'] != 'constant') { throw new Exception\InvalidArgumentException('Index of info offset is not about a constant'); } } elseif (is_string($constantNameOrInfoIndex)) { $constantFound = false; foreach ($this->infos as $info) { if ($info['type'] === 'constant' && $info['name'] === $constantNameOrInfoIndex) { $constantFound = true; break; } } if (!$constantFound) { return false; } } else { throw new Exception\InvalidArgumentException( 'Invalid constant name of info index type. Must be of type int or string' ); } if (!isset($info)) { return false; } $p = new ConstantScanner( array_slice($this->tokens, $info['tokenStart'], $info['tokenEnd'] - $info['tokenStart'] + 1), $this->nameInformation ); $p->setClass($this->name); $p->setScannerClass($this); return $p; } /** * Verify if class has constant * * @param string $name * @return bool */ public function hasConstant($name) { $this->scan(); foreach ($this->infos as $info) { if ($info['type'] === 'constant' && $info['name'] === $name) { return true; } } return false; } /** * Return a list of property names * * @return array */ public function getPropertyNames() { $this->scan(); $return = []; foreach ($this->infos as $info) { if ($info['type'] != 'property') { continue; } $return[] = $info['name']; } return $return; } /** * Return a list of properties * * @return PropertyScanner[] */ public function getProperties() { $this->scan(); $return = []; foreach ($this->infos as $info) { if ($info['type'] != 'property') { continue; } $return[] = $this->getProperty($info['name']); } return $return; } /** * Return a single property by given name or index of info * * @param string|int $propertyNameOrInfoIndex * @throws Exception\InvalidArgumentException * @return bool|PropertyScanner */ public function getProperty($propertyNameOrInfoIndex) { $this->scan(); if (is_int($propertyNameOrInfoIndex)) { $info = $this->infos[$propertyNameOrInfoIndex]; if ($info['type'] != 'property') { throw new Exception\InvalidArgumentException('Index of info offset is not about a property'); } } elseif (is_string($propertyNameOrInfoIndex)) { $propertyFound = false; foreach ($this->infos as $info) { if ($info['type'] === 'property' && $info['name'] === $propertyNameOrInfoIndex) { $propertyFound = true; break; } } if (!$propertyFound) { return false; } } else { throw new Exception\InvalidArgumentException( 'Invalid property name of info index type. Must be of type int or string' ); } if (!isset($info)) { return false; } $p = new PropertyScanner( array_slice($this->tokens, $info['tokenStart'], $info['tokenEnd'] - $info['tokenStart'] + 1), $this->nameInformation ); $p->setClass($this->name); $p->setScannerClass($this); return $p; } /** * Verify if class has property * * @param string $name * @return bool */ public function hasProperty($name) { $this->scan(); foreach ($this->infos as $info) { if ($info['type'] === 'property' && $info['name'] === $name) { return true; } } return false; } /** * Retrieve any traits used by the class. * * @return ClassScanner[] */ public function getTraits() { if (! empty($this->traits)) { return $this->traits; } // get list of trait names $traitNames = $this->getTraitNames(); foreach ($traitNames as $traitName) { $r = new ReflectionClass($traitName); if (! $r->isTrait()) { throw new Exception\RuntimeException(sprintf( 'Non-trait class detected as a trait: %s', $traitName )); } $fileName = $r->getFileName(); $file = new FileScanner($fileName); $this->traits[] = $file->getClass($traitName); } return $this->traits; } /** * Retrieve a list of trait names used by this class. * * @return array */ public function getTraitNames() { $this->scan(); $return = []; foreach ($this->infos as $info) { if ($info['type'] !== 'use') { continue; } if (is_array($info['use_statements'])) { foreach ($info['use_statements'] as $trait) { $traitName = $trait; if ($this->nameInformation instanceof NameInformation) { $traitName = $this->nameInformation->resolveName($traitName); } $return[] = $traitName; } } } return $return; } /** * Retrieve a list of aliased traits used by the class. * * @return array */ public function getTraitAliases() { $this->scan(); $return = []; foreach ($this->infos as $info) { if ($info['type'] !== 'use') { continue; } if (is_array($info['aliases'])) { foreach ($info['aliases'] as $alias) { if (null === $alias || (! empty($alias['type']) && $alias['type'] !== 'as') ) { continue; } // attempt to get fqcn list($trait, $method) = explode('::', $alias['original']); if ($this->nameInformation instanceof NameInformation) { $trait = $this->nameInformation->resolveName($trait); } $return[$alias['alias']] = $trait . '::' . $method; } } } return $return; } /** * Retrieve visibility for a given alias. * * @param mixed $aliasName * @return string */ protected function getVisibilityForAlias($aliasName) { $this->scan(); $return = null; foreach ($this->infos as $info) { if ($info['type'] !== 'use') { continue; } if (is_array($info['aliases'])) { foreach ($info['aliases'] as $alias) { if (null === $alias && (! empty($alias['type']) && $alias['type'] !== 'as') ) { continue; } if ($alias['alias'] === $aliasName) { $return = $alias['visibility']; break 2; } } } } return $return; } /** * Return an array of key = trait to keep, value = trait::method to ignore * * @return array */ protected function getBlockedTraitMethods() { $this->scan(); $return = []; foreach ($this->infos as $info) { if ($info['type'] !== 'use') { continue; } if (is_array($info['aliases'])) { foreach ($info['aliases'] as $alias) { if (null === $alias || (! empty($alias['type']) && $alias['type'] !== 'insteadof') ) { continue; } // attempt to get fqcn list($trait, $method) = explode('::', $alias['original']); if ($this->nameInformation instanceof NameInformation) { $trait = $this->nameInformation->resolveName($alias['alias']); } $return[] = $trait . '::' . $method; } } } return $return; } /** * Return a list of method names * * @return array */ public function getMethodNames() { $this->scan(); $methods = $this->getMethods(); $return = []; foreach ($methods as $method) { $return[] = $method->getName(); } return $return; } /** * Return a list of methods * * @return MethodScanner[] */ public function getMethods() { $this->scan(); if (! empty($this->methods)) { return $this->methods; } foreach ($this->infos as $info) { if ($info['type'] !== 'method' && $info['type'] !== 'use') { continue; } // Merge in trait methods if ($info['type'] === "use") { $traitMethods = []; $traits = $this->getTraits(); $insteadof = $this->getBlockedTraitMethods(); $aliases = $this->getTraitAliases(); foreach ($traits as $trait) { $tempMethods = $trait->getMethods(); foreach ($tempMethods as $tempMethod) { $methodFullName = $trait->getName() . '::' . $tempMethod->getName(); $methodAlias = array_search($methodFullName, $aliases); if (false !== $methodAlias) { // trait::method is aliased // clone the tempMethod as we need to change // the name and possibly the visibility of the // scanned method. // // @todo setName and setVisibility were added to // MethodScanner to accomplish this, may not be the // best option, could use ReflectionClass instead? $newMethod = clone $tempMethod; $newMethod->setName($methodAlias); // if visibility exists, change it on the MethodScanner $visibility = $this->getVisibilityForAlias($methodAlias); if (null !== $visibility) { $newMethod->setVisibility($visibility); } $traitMethods[$methodAlias] = $newMethod; } elseif (in_array($methodFullName, $insteadof)) { // ignore overridden methods continue; } else { if (array_key_exists($tempMethod->getName(), $traitMethods)) { throw new Exception\RuntimeException(sprintf( 'Trait method %s has not been applied because there are' . ' collisions with other trait methods see: (insteadof OR as)', $tempMethod->getName() )); } $traitMethods[$tempMethod->getName()] = $tempMethod; } } } $this->methods = array_merge($this->methods, array_values($traitMethods)); continue; } $m = new MethodScanner( array_slice( $this->tokens, $info['tokenStart'], $info['tokenEnd'] - $info['tokenStart'] + 1 ), $this->nameInformation ); $m->setClass($this->name); $m->setScannerClass($this); $this->methods[] = $m; } return $this->methods; } /** * Return a single method by given name or index of info * * @param string|int $methodNameOrInfoIndex * @throws Exception\InvalidArgumentException * @return MethodScanner */ public function getMethod($methodNameOrInfoIndex) { $this->scan(); if (is_int($methodNameOrInfoIndex)) { $info = $this->infos[$methodNameOrInfoIndex]; if ($info['type'] != 'method') { throw new Exception\InvalidArgumentException('Index of info offset is not about a method'); } $methodNameOrInfoIndex = $info['name']; } $returnMethod = false; $methods = $this->getMethods(); foreach ($methods as $method) { if ($method->getName() === $methodNameOrInfoIndex) { $returnMethod = $method; break; } } return $returnMethod; } /** * Verify if class has method by given name * * @param string $name * @return bool */ public function hasMethod($name) { $this->scan(); return is_object($this->getMethod($name)); } public static function export() { // @todo } public function __toString() { // @todo } /** * Scan tokens * * @return void * @throws Exception\RuntimeException */ protected function scan() { if ($this->isScanned) { return; } if (!$this->tokens) { throw new Exception\RuntimeException('No tokens were provided'); } /** * Variables & Setup */ $tokens = &$this->tokens; // localize $infos = &$this->infos; // localize $tokenIndex = null; $token = null; $tokenType = null; $tokenContent = null; $tokenLine = null; $namespace = null; $infoIndex = 0; $braceCount = 0; /* * MACRO creation */ $MACRO_TOKEN_ADVANCE = function () use ( &$tokens, &$tokenIndex, &$token, &$tokenType, &$tokenContent, &$tokenLine ) { static $lastTokenArray = null; $tokenIndex = ($tokenIndex === null) ? 0 : $tokenIndex + 1; if (!isset($tokens[$tokenIndex])) { $token = false; $tokenContent = false; $tokenType = false; $tokenLine = false; return false; } $token = $tokens[$tokenIndex]; if (is_string($token)) { $tokenType = null; $tokenContent = $token; $tokenLine = $tokenLine + substr_count( $lastTokenArray[1], "\n" ); // adjust token line by last known newline count } else { $lastTokenArray = $token; list($tokenType, $tokenContent, $tokenLine) = $token; } return $tokenIndex; }; $MACRO_INFO_ADVANCE = function () use (&$infoIndex, &$infos, &$tokenIndex, &$tokenLine) { $infos[$infoIndex]['tokenEnd'] = $tokenIndex; $infos[$infoIndex]['lineEnd'] = $tokenLine; $infoIndex++; return $infoIndex; }; /** * START FINITE STATE MACHINE FOR SCANNING TOKENS */ // Initialize token $MACRO_TOKEN_ADVANCE(); SCANNER_TOP: switch ($tokenType) { case T_DOC_COMMENT: $this->docComment = $tokenContent; goto SCANNER_CONTINUE; //goto no break needed case T_FINAL: case T_ABSTRACT: case T_CLASS: case T_INTERFACE: case T_TRAIT: // CLASS INFORMATION $classContext = null; $classInterfaceIndex = 0; SCANNER_CLASS_INFO_TOP: if (is_string($tokens[$tokenIndex + 1]) && $tokens[$tokenIndex + 1] === '{') { goto SCANNER_CLASS_INFO_END; } $this->lineStart = $tokenLine; switch ($tokenType) { case T_FINAL: $this->isFinal = true; goto SCANNER_CLASS_INFO_CONTINUE; // goto no break needed case T_ABSTRACT: $this->isAbstract = true; goto SCANNER_CLASS_INFO_CONTINUE; // goto no break needed case T_TRAIT: $this->isTrait = true; $this->shortName = $tokens[$tokenIndex + 2][1]; if ($this->nameInformation && $this->nameInformation->hasNamespace()) { $this->name = $this->nameInformation->getNamespace() . '\\' . $this->shortName; } else { $this->name = $this->shortName; } goto SCANNER_CLASS_INFO_CONTINUE; // goto no break needed case T_INTERFACE: $this->isInterface = true; // fall-through case T_CLASS: $this->shortName = $tokens[$tokenIndex + 2][1]; if ($this->nameInformation && $this->nameInformation->hasNamespace()) { $this->name = $this->nameInformation->getNamespace() . '\\' . $this->shortName; } else { $this->name = $this->shortName; } goto SCANNER_CLASS_INFO_CONTINUE; // goto no break needed case T_NS_SEPARATOR: case T_STRING: switch ($classContext) { case T_EXTENDS: if ($this->isInterface) { $this->shortInterfaces[$classInterfaceIndex] .= $tokenContent; } else { $this->shortParentClass .= $tokenContent; } break; case T_IMPLEMENTS: $this->shortInterfaces[$classInterfaceIndex] .= $tokenContent; break; } goto SCANNER_CLASS_INFO_CONTINUE; // goto no break needed case T_EXTENDS: case T_IMPLEMENTS: $classContext = $tokenType; if (($this->isInterface && $classContext === T_EXTENDS) || $classContext === T_IMPLEMENTS) { $this->shortInterfaces[$classInterfaceIndex] = ''; } elseif (!$this->isInterface && $classContext === T_EXTENDS) { $this->shortParentClass = ''; } goto SCANNER_CLASS_INFO_CONTINUE; // goto no break needed case null: if (($classContext == T_IMPLEMENTS && $tokenContent == ',') || ($classContext == T_EXTENDS && $tokenContent == ',' && $this->isInterface)) { $classInterfaceIndex++; $this->shortInterfaces[$classInterfaceIndex] = ''; } } SCANNER_CLASS_INFO_CONTINUE: if ($MACRO_TOKEN_ADVANCE() === false) { goto SCANNER_END; } goto SCANNER_CLASS_INFO_TOP; SCANNER_CLASS_INFO_END: goto SCANNER_CONTINUE; } if ($tokenType === null && $tokenContent === '{' && $braceCount === 0) { $braceCount++; if ($MACRO_TOKEN_ADVANCE() === false) { goto SCANNER_END; } SCANNER_CLASS_BODY_TOP: if ($braceCount === 0) { goto SCANNER_CLASS_BODY_END; } switch ($tokenType) { case T_CONST: $infos[$infoIndex] = [ 'type' => 'constant', 'tokenStart' => $tokenIndex, 'tokenEnd' => null, 'lineStart' => $tokenLine, 'lineEnd' => null, 'name' => null, 'value' => null, ]; SCANNER_CLASS_BODY_CONST_TOP: if ($tokenContent === ';') { goto SCANNER_CLASS_BODY_CONST_END; } if ($tokenType === T_STRING && null === $infos[$infoIndex]['name']) { $infos[$infoIndex]['name'] = $tokenContent; } SCANNER_CLASS_BODY_CONST_CONTINUE: if ($MACRO_TOKEN_ADVANCE() === false) { goto SCANNER_END; } goto SCANNER_CLASS_BODY_CONST_TOP; SCANNER_CLASS_BODY_CONST_END: $MACRO_INFO_ADVANCE(); goto SCANNER_CLASS_BODY_CONTINUE; // goto no break needed case T_USE: // ensure php backwards compatibility if (! defined('T_INSTEADOF')) { define('T_INSTEADOF', 24000); } $infos[$infoIndex] = [ 'type' => 'use', 'tokenStart' => $tokenIndex, 'tokenEnd' => null, 'lineStart' => $tokens[$tokenIndex][2], 'lineEnd' => null, 'name' => $namespace, 'use_statements' => [0 => null], 'aliases' => [0 => null], ]; $isOriginalName = [T_STRING, T_DOUBLE_COLON]; $isAlias = [T_STRING]; $isVisibility = [T_PRIVATE, T_PROTECTED, T_PUBLIC, T_STATIC]; $isAliasType = [T_AS, T_INSTEADOF]; $isValidAlias = array_merge($isOriginalName, $isAlias, $isVisibility, $isAliasType); $useStatementIndex = 0; $aliasStatementIndex = 0; $useAliasContext = false; $useAsContext = false; // start processing with next token if ($MACRO_TOKEN_ADVANCE() === false) { goto SCANNER_END; } SCANNER_USE_TOP: if ($tokenType === null) { if ($tokenContent === "{") { $useStatementIndex = 0; $useAliasContext = true; $infos[$infoIndex]['aliases'][$useStatementIndex] = [ 'original' => null, 'alias' => null, 'visibility' => null, 'type' => 'as' ]; } elseif ($tokenContent === "}") { $useAliasContext = false; goto SCANNER_USE_END; } elseif ($tokenContent === ';') { if ($useAliasContext === true) { $useStatementIndex++; $useAsContext = false; } // only end if we aren't inside braces if (false === $useAliasContext) { goto SCANNER_USE_END; } } elseif ($tokenContent === ',') { $useStatementIndex++; $infos[$infoIndex]['use_statements'][$useStatementIndex] = ''; } } // ANALYZE if ($tokenType !== null) { // use context if (false === $useAliasContext) { if ($tokenType == T_NS_SEPARATOR || $tokenType == T_STRING) { $infos[$infoIndex]['use_statements'][$useStatementIndex] .= $tokenContent; } } else { if (in_array($tokenType, $isValidAlias) && empty($infos[$infoIndex]['aliases'][$useStatementIndex]) ) { $infos[$infoIndex]['aliases'][$useStatementIndex] = [ 'original' => null, 'visibility' => null, 'alias' => null, 'type' => null ]; } if ($tokenType == T_AS || $tokenType == T_INSTEADOF) { $useAsContext = true; $infos[$infoIndex]['aliases'][$useStatementIndex]['type'] = ($tokenType == T_INSTEADOF) ? 'insteadof' : 'as'; goto SCANNER_USE_CONTINUE; } // in alias context if ($useAsContext === true && in_array($tokenType, $isAlias)) { $infos[$infoIndex]['aliases'][$useStatementIndex]['alias'] = $tokenContent; } elseif (in_array($tokenType, $isOriginalName)) { $infos[$infoIndex]['aliases'][$useStatementIndex]['original'] .= $tokenContent; } elseif (in_array($tokenType, $isVisibility)) { //add whitespace (will trim later) $infos[$infoIndex]['aliases'][$useStatementIndex]['visibility'] = $tokenType; } } } SCANNER_USE_CONTINUE: if ($MACRO_TOKEN_ADVANCE() === false) { goto SCANNER_END; } goto SCANNER_USE_TOP; SCANNER_USE_END: $MACRO_INFO_ADVANCE(); goto SCANNER_CLASS_BODY_CONTINUE; // goto no break needed case T_DOC_COMMENT: case T_PUBLIC: case T_PROTECTED: case T_PRIVATE: case T_ABSTRACT: case T_FINAL: case T_VAR: case T_FUNCTION: $infos[$infoIndex] = [ 'type' => null, 'tokenStart' => $tokenIndex, 'tokenEnd' => null, 'lineStart' => $tokenLine, 'lineEnd' => null, 'name' => null, ]; $memberContext = null; $methodBodyStarted = false; SCANNER_CLASS_BODY_MEMBER_TOP: if ($memberContext === 'method') { switch ($tokenContent) { case '{': $methodBodyStarted = true; $braceCount++; goto SCANNER_CLASS_BODY_MEMBER_CONTINUE; // goto no break needed case '}': $braceCount--; goto SCANNER_CLASS_BODY_MEMBER_CONTINUE; // goto no break needed case ';': $infos[$infoIndex]['tokenEnd'] = $tokenIndex; goto SCANNER_CLASS_BODY_MEMBER_CONTINUE; // goto no break needed } } if ($memberContext !== null) { if (($memberContext === 'property' && $tokenContent === ';') || ($memberContext === 'method' && $methodBodyStarted && $braceCount === 1) || ($memberContext === 'method' && $this->isInterface && $tokenContent === ';') ) { goto SCANNER_CLASS_BODY_MEMBER_END; } } switch ($tokenType) { case T_CONST: $memberContext = 'constant'; $infos[$infoIndex]['type'] = 'constant'; goto SCANNER_CLASS_BODY_CONST_CONTINUE; //goto no break needed case T_VARIABLE: if ($memberContext === null) { $memberContext = 'property'; $infos[$infoIndex]['type'] = 'property'; $infos[$infoIndex]['name'] = ltrim($tokenContent, '$'); } goto SCANNER_CLASS_BODY_MEMBER_CONTINUE; // goto no break needed case T_FUNCTION: $memberContext = 'method'; $infos[$infoIndex]['type'] = 'method'; goto SCANNER_CLASS_BODY_MEMBER_CONTINUE; // goto no break needed case T_STRING: if ($memberContext === 'method' && null === $infos[$infoIndex]['name']) { $infos[$infoIndex]['name'] = $tokenContent; } goto SCANNER_CLASS_BODY_MEMBER_CONTINUE; // goto no break needed } SCANNER_CLASS_BODY_MEMBER_CONTINUE: if ($MACRO_TOKEN_ADVANCE() === false) { goto SCANNER_END; } goto SCANNER_CLASS_BODY_MEMBER_TOP; SCANNER_CLASS_BODY_MEMBER_END: $memberContext = null; $MACRO_INFO_ADVANCE(); goto SCANNER_CLASS_BODY_CONTINUE; // goto no break needed case null: // no type, is a string switch ($tokenContent) { case '{': $braceCount++; goto SCANNER_CLASS_BODY_CONTINUE; // goto no break needed case '}': $braceCount--; goto SCANNER_CLASS_BODY_CONTINUE; // goto no break needed } } SCANNER_CLASS_BODY_CONTINUE: if ($braceCount === 0 || $MACRO_TOKEN_ADVANCE() === false) { goto SCANNER_CONTINUE; } goto SCANNER_CLASS_BODY_TOP; SCANNER_CLASS_BODY_END: goto SCANNER_CONTINUE; } SCANNER_CONTINUE: if ($tokenContent === '}') { $this->lineEnd = $tokenLine; } if ($MACRO_TOKEN_ADVANCE() === false) { goto SCANNER_END; } goto SCANNER_TOP; SCANNER_END: // process short names if ($this->nameInformation) { if ($this->shortParentClass) { $this->parentClass = $this->nameInformation->resolveName($this->shortParentClass); } if ($this->shortInterfaces) { foreach ($this->shortInterfaces as $siIndex => $si) { $this->interfaces[$siIndex] = $this->nameInformation->resolveName($si); } } } else { $this->parentClass = $this->shortParentClass; $this->interfaces = $this->shortInterfaces; } $this->isScanned = true; return; } } zend-code-release-3.1.0/src/Scanner/ConstantScanner.php000066400000000000000000000125111300340552400227710ustar00rootroot00000000000000tokens = $constantTokens; $this->nameInformation = $nameInformation; } /** * @param string $class */ public function setClass($class) { $this->class = $class; } /** * @param ClassScanner $scannerClass */ public function setScannerClass(ClassScanner $scannerClass) { $this->scannerClass = $scannerClass; } /** * @return ClassScanner */ public function getClassScanner() { return $this->scannerClass; } /** * @return string */ public function getName() { $this->scan(); return $this->name; } /** * @return string */ public function getValue() { $this->scan(); return $this->value; } /** * @return string */ public function getDocComment() { $this->scan(); return $this->docComment; } /** * @param Annotation\AnnotationManager $annotationManager * @return AnnotationScanner */ public function getAnnotations(Annotation\AnnotationManager $annotationManager) { if (($docComment = $this->getDocComment()) == '') { return false; } return new AnnotationScanner($annotationManager, $docComment, $this->nameInformation); } /** * @return string */ public function __toString() { $this->scan(); return var_export($this, true); } /** * Scan tokens * * @throws Exception\RuntimeException */ protected function scan() { if ($this->isScanned) { return; } if (!$this->tokens) { throw new Exception\RuntimeException('No tokens were provided'); } /** * Variables & Setup */ $tokens = &$this->tokens; reset($tokens); SCANNER_TOP: $token = current($tokens); if (!is_string($token)) { list($tokenType, $tokenContent, $tokenLine) = $token; switch ($tokenType) { case T_DOC_COMMENT: if ($this->docComment === null && $this->name === null) { $this->docComment = $tokenContent; } goto SCANNER_CONTINUE; // fall-through case T_STRING: $string = (is_string($token)) ? $token : $tokenContent; if (null === $this->name) { $this->name = $string; } else { if ('self' == strtolower($string)) { list($tokenNextType, $tokenNextContent, $tokenNextLine) = next($tokens); if ('::' == $tokenNextContent) { list($tokenNextType, $tokenNextContent, $tokenNextLine) = next($tokens); if ($this->getClassScanner()->getConstant($tokenNextContent)) { $this->value = $this->getClassScanner()->getConstant($tokenNextContent)->getValue(); } } } } goto SCANNER_CONTINUE; // fall-through case T_CONSTANT_ENCAPSED_STRING: case T_DNUMBER: case T_LNUMBER: $string = (is_string($token)) ? $token : $tokenContent; if (substr($string, 0, 1) === '"' || substr($string, 0, 1) === "'") { $this->value = substr($string, 1, -1); // Remove quotes } else { $this->value = $string; } goto SCANNER_CONTINUE; // fall-trough default: goto SCANNER_CONTINUE; } } SCANNER_CONTINUE: if (next($this->tokens) === false) { goto SCANNER_END; } goto SCANNER_TOP; SCANNER_END: $this->isScanned = true; } } zend-code-release-3.1.0/src/Scanner/DerivedClassScanner.php000066400000000000000000000237231300340552400235570ustar00rootroot00000000000000classScanner = $classScanner; $this->directoryScanner = $directoryScanner; $currentScannerClass = $classScanner; while ($currentScannerClass && $currentScannerClass->hasParentClass()) { $currentParentClassName = $currentScannerClass->getParentClass(); if ($directoryScanner->hasClass($currentParentClassName)) { $currentParentClass = $directoryScanner->getClass($currentParentClassName); $this->parentClassScanners[$currentParentClassName] = $currentParentClass; $currentScannerClass = $currentParentClass; } else { $currentScannerClass = false; } } foreach ($interfaces = $this->classScanner->getInterfaces() as $iName) { if ($directoryScanner->hasClass($iName)) { $this->interfaceClassScanners[$iName] = $directoryScanner->getClass($iName); } } } /** * @return null|string */ public function getName() { return $this->classScanner->getName(); } /** * @return null|string */ public function getShortName() { return $this->classScanner->getShortName(); } /** * @return bool */ public function isInstantiable() { return $this->classScanner->isInstantiable(); } /** * @return bool */ public function isFinal() { return $this->classScanner->isFinal(); } /** * @return bool */ public function isAbstract() { return $this->classScanner->isAbstract(); } /** * @return bool */ public function isInterface() { return $this->classScanner->isInterface(); } /** * @return array */ public function getParentClasses() { return array_keys($this->parentClassScanners); } /** * @return bool */ public function hasParentClass() { return ($this->classScanner->getParentClass() !== null); } /** * @return null|string */ public function getParentClass() { return $this->classScanner->getParentClass(); } /** * @param bool $returnClassScanners * @return array */ public function getInterfaces($returnClassScanners = false) { if ($returnClassScanners) { return $this->interfaceClassScanners; } $interfaces = $this->classScanner->getInterfaces(); foreach ($this->parentClassScanners as $pClassScanner) { $interfaces = array_merge($interfaces, $pClassScanner->getInterfaces()); } return $interfaces; } /** * Return a list of constant names * * @return array */ public function getConstantNames() { $constants = $this->classScanner->getConstantNames(); foreach ($this->parentClassScanners as $pClassScanner) { $constants = array_merge($constants, $pClassScanner->getConstantNames()); } return $constants; } /** * Return a list of constants * * @param bool $namesOnly Set false to return instances of ConstantScanner * @return array|ConstantScanner[] */ public function getConstants($namesOnly = true) { if (true === $namesOnly) { trigger_error('Use method getConstantNames() instead', E_USER_DEPRECATED); return $this->getConstantNames(); } $constants = $this->classScanner->getConstants(); foreach ($this->parentClassScanners as $pClassScanner) { $constants = array_merge($constants, $pClassScanner->getConstants($namesOnly)); } return $constants; } /** * Return a single constant by given name or index of info * * @param string|int $constantNameOrInfoIndex * @throws Exception\InvalidArgumentException * @return bool|ConstantScanner */ public function getConstant($constantNameOrInfoIndex) { if ($this->classScanner->hasConstant($constantNameOrInfoIndex)) { return $this->classScanner->getConstant($constantNameOrInfoIndex); } foreach ($this->parentClassScanners as $pClassScanner) { if ($pClassScanner->hasConstant($constantNameOrInfoIndex)) { return $pClassScanner->getConstant($constantNameOrInfoIndex); } } throw new Exception\InvalidArgumentException(sprintf( 'Constant %s not found in %s', $constantNameOrInfoIndex, $this->classScanner->getName() )); } /** * Verify if class or parent class has constant * * @param string $name * @return bool */ public function hasConstant($name) { if ($this->classScanner->hasConstant($name)) { return true; } foreach ($this->parentClassScanners as $pClassScanner) { if ($pClassScanner->hasConstant($name)) { return true; } } return false; } /** * Return a list of property names * * @return array */ public function getPropertyNames() { $properties = $this->classScanner->getPropertyNames(); foreach ($this->parentClassScanners as $pClassScanner) { $properties = array_merge($properties, $pClassScanner->getPropertyNames()); } return $properties; } /** * @param bool $returnScannerProperty * @return array */ public function getProperties($returnScannerProperty = false) { $properties = $this->classScanner->getProperties($returnScannerProperty); foreach ($this->parentClassScanners as $pClassScanner) { $properties = array_merge($properties, $pClassScanner->getProperties($returnScannerProperty)); } return $properties; } /** * Return a single property by given name or index of info * * @param string|int $propertyNameOrInfoIndex * @throws Exception\InvalidArgumentException * @return bool|PropertyScanner */ public function getProperty($propertyNameOrInfoIndex) { if ($this->classScanner->hasProperty($propertyNameOrInfoIndex)) { return $this->classScanner->getProperty($propertyNameOrInfoIndex); } foreach ($this->parentClassScanners as $pClassScanner) { if ($pClassScanner->hasProperty($propertyNameOrInfoIndex)) { return $pClassScanner->getProperty($propertyNameOrInfoIndex); } } throw new Exception\InvalidArgumentException(sprintf( 'Property %s not found in %s', $propertyNameOrInfoIndex, $this->classScanner->getName() )); } /** * Verify if class or parent class has property * * @param string $name * @return bool */ public function hasProperty($name) { if ($this->classScanner->hasProperty($name)) { return true; } foreach ($this->parentClassScanners as $pClassScanner) { if ($pClassScanner->hasProperty($name)) { return true; } } return false; } /** * @return array */ public function getMethodNames() { $methods = $this->classScanner->getMethodNames(); foreach ($this->parentClassScanners as $pClassScanner) { $methods = array_merge($methods, $pClassScanner->getMethodNames()); } return $methods; } /** * @return MethodScanner[] */ public function getMethods() { $methods = $this->classScanner->getMethods(); foreach ($this->parentClassScanners as $pClassScanner) { $methods = array_merge($methods, $pClassScanner->getMethods()); } return $methods; } /** * @param int|string $methodNameOrInfoIndex * @return MethodScanner * @throws Exception\InvalidArgumentException */ public function getMethod($methodNameOrInfoIndex) { if ($this->classScanner->hasMethod($methodNameOrInfoIndex)) { return $this->classScanner->getMethod($methodNameOrInfoIndex); } foreach ($this->parentClassScanners as $pClassScanner) { if ($pClassScanner->hasMethod($methodNameOrInfoIndex)) { return $pClassScanner->getMethod($methodNameOrInfoIndex); } } throw new Exception\InvalidArgumentException(sprintf( 'Method %s not found in %s', $methodNameOrInfoIndex, $this->classScanner->getName() )); } /** * Verify if class or parent class has method by given name * * @param string $name * @return bool */ public function hasMethod($name) { if ($this->classScanner->hasMethod($name)) { return true; } foreach ($this->parentClassScanners as $pClassScanner) { if ($pClassScanner->hasMethod($name)) { return true; } } return false; } } zend-code-release-3.1.0/src/Scanner/DirectoryScanner.php000066400000000000000000000155221300340552400231510ustar00rootroot00000000000000addDirectory($directory); } elseif (is_array($directory)) { foreach ($directory as $d) { $this->addDirectory($d); } } } } /** * @param DirectoryScanner|string $directory * @return void * @throws Exception\InvalidArgumentException */ public function addDirectory($directory) { if ($directory instanceof DirectoryScanner) { $this->directories[] = $directory; } elseif (is_string($directory)) { $realDir = realpath($directory); if (!$realDir || !is_dir($realDir)) { throw new Exception\InvalidArgumentException(sprintf( 'Directory "%s" does not exist', $realDir )); } $this->directories[] = $realDir; } else { throw new Exception\InvalidArgumentException( 'The argument provided was neither a DirectoryScanner or directory path' ); } } /** * @param DirectoryScanner $directoryScanner * @return void */ public function addDirectoryScanner(DirectoryScanner $directoryScanner) { $this->addDirectory($directoryScanner); } /** * @param FileScanner $fileScanner * @return void */ public function addFileScanner(FileScanner $fileScanner) { $this->fileScanners[] = $fileScanner; } /** * @return void */ protected function scan() { if ($this->isScanned) { return; } // iterate directories creating file scanners foreach ($this->directories as $directory) { if ($directory instanceof DirectoryScanner) { $directory->scan(); if ($directory->fileScanners) { $this->fileScanners = array_merge($this->fileScanners, $directory->fileScanners); } } else { $rdi = new RecursiveDirectoryIterator($directory); foreach (new RecursiveIteratorIterator($rdi) as $item) { if ($item->isFile() && pathinfo($item->getRealPath(), PATHINFO_EXTENSION) == 'php') { $this->fileScanners[] = new FileScanner($item->getRealPath()); } } } } $this->isScanned = true; } /** * @todo implement method */ public function getNamespaces() { // @todo } /** * @param bool $returnFileScanners * @return array */ public function getFiles($returnFileScanners = false) { $this->scan(); $return = []; foreach ($this->fileScanners as $fileScanner) { $return[] = ($returnFileScanners) ? $fileScanner : $fileScanner->getFile(); } return $return; } /** * @return array */ public function getClassNames() { $this->scan(); if ($this->classToFileScanner === null) { $this->createClassToFileScannerCache(); } return array_keys($this->classToFileScanner); } /** * @param bool $returnDerivedScannerClass * @return array */ public function getClasses($returnDerivedScannerClass = false) { $this->scan(); if ($this->classToFileScanner === null) { $this->createClassToFileScannerCache(); } $returnClasses = []; foreach ($this->classToFileScanner as $className => $fsIndex) { $classScanner = $this->fileScanners[$fsIndex]->getClass($className); if ($returnDerivedScannerClass) { $classScanner = new DerivedClassScanner($classScanner, $this); } $returnClasses[] = $classScanner; } return $returnClasses; } /** * @param string $class * @return bool */ public function hasClass($class) { $this->scan(); if ($this->classToFileScanner === null) { $this->createClassToFileScannerCache(); } return (isset($this->classToFileScanner[$class])); } /** * @param string $class * @param bool $returnDerivedScannerClass * @return ClassScanner|DerivedClassScanner * @throws Exception\InvalidArgumentException */ public function getClass($class, $returnDerivedScannerClass = false) { $this->scan(); if ($this->classToFileScanner === null) { $this->createClassToFileScannerCache(); } if (!isset($this->classToFileScanner[$class])) { throw new Exception\InvalidArgumentException('Class not found.'); } /** @var FileScanner $fs */ $fs = $this->fileScanners[$this->classToFileScanner[$class]]; $returnClass = $fs->getClass($class); if (($returnClass instanceof ClassScanner) && $returnDerivedScannerClass) { return new DerivedClassScanner($returnClass, $this); } return $returnClass; } /** * Create class to file scanner cache * * @return void */ protected function createClassToFileScannerCache() { if ($this->classToFileScanner !== null) { return; } $this->classToFileScanner = []; /** @var FileScanner $fileScanner */ foreach ($this->fileScanners as $fsIndex => $fileScanner) { $fsClasses = $fileScanner->getClassNames(); foreach ($fsClasses as $fsClassName) { $this->classToFileScanner[$fsClassName] = $fsIndex; } } } /** * Export * * @todo implement method */ public static function export() { // @todo } /** * __ToString * * @todo implement method */ public function __toString() { // @todo } } zend-code-release-3.1.0/src/Scanner/DocBlockScanner.php000066400000000000000000000236321300340552400226660ustar00rootroot00000000000000docComment = $docComment; $this->nameInformation = $nameInformation; } /** * @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 array */ public function getAnnotations() { $this->scan(); return $this->annotations; } /** * @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, null, $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; } } zend-code-release-3.1.0/src/Scanner/FileScanner.php000066400000000000000000000022751300340552400220650ustar00rootroot00000000000000file = $file; if (!file_exists($file)) { throw new Exception\InvalidArgumentException(sprintf( 'File "%s" not found', $file )); } parent::__construct(token_get_all(file_get_contents($file)), $annotationManager); } /** * @return string */ public function getFile() { return $this->file; } } zend-code-release-3.1.0/src/Scanner/FunctionScanner.php000066400000000000000000000007371300340552400227740ustar00rootroot00000000000000tokens = $methodTokens; $this->nameInformation = $nameInformation; } /** * @param string $class * @return MethodScanner */ public function setClass($class) { $this->class = (string) $class; return $this; } /** * @param ClassScanner $scannerClass * @return MethodScanner */ public function setScannerClass(ClassScanner $scannerClass) { $this->scannerClass = $scannerClass; return $this; } /** * @return MethodScanner */ public function getClassScanner() { return $this->scannerClass; } /** * @return string */ public function getName() { $this->scan(); return $this->name; } /** * @return int */ public function getLineStart() { $this->scan(); return $this->lineStart; } /** * @return int */ public function getLineEnd() { $this->scan(); return $this->lineEnd; } /** * @return string */ public function getDocComment() { $this->scan(); return $this->docComment; } /** * @param AnnotationManager $annotationManager * @return AnnotationScanner */ public function getAnnotations(AnnotationManager $annotationManager) { if (($docComment = $this->getDocComment()) == '') { return false; } return new AnnotationScanner($annotationManager, $docComment, $this->nameInformation); } /** * @return bool */ public function isFinal() { $this->scan(); return $this->isFinal; } /** * @return bool */ public function isAbstract() { $this->scan(); return $this->isAbstract; } /** * @return bool */ public function isPublic() { $this->scan(); return $this->isPublic; } /** * @return bool */ public function isProtected() { $this->scan(); return $this->isProtected; } /** * @return bool */ public function isPrivate() { $this->scan(); return $this->isPrivate; } /** * @return bool */ public function isStatic() { $this->scan(); return $this->isStatic; } /** * Override the given name for a method, this is necessary to * support traits. * * @param $name * @return self */ public function setName($name) { $this->name = $name; return $this; } /** * Visibility must be of T_PUBLIC, T_PRIVATE or T_PROTECTED * Needed to support traits * * @param $visibility T_PUBLIC | T_PRIVATE | T_PROTECTED * @return self * @throws \Zend\Code\Exception */ public function setVisibility($visibility) { switch (strtolower($visibility)) { case T_PUBLIC: $this->isPublic = true; $this->isPrivate = false; $this->isProtected = false; break; case T_PRIVATE: $this->isPublic = false; $this->isPrivate = true; $this->isProtected = false; break; case T_PROTECTED: $this->isPublic = false; $this->isPrivate = false; $this->isProtected = true; break; default: throw new Exception("Invalid visibility argument passed to setVisibility."); } return $this; } /** * @return int */ public function getNumberOfParameters() { return count($this->getParameters()); } /** * @param bool $returnScanner * @return array */ public function getParameters($returnScanner = false) { $this->scan(); $return = []; foreach ($this->infos as $info) { if ($info['type'] != 'parameter') { continue; } if (!$returnScanner) { $return[] = $info['name']; } else { $return[] = $this->getParameter($info['name']); } } return $return; } /** * @param int|string $parameterNameOrInfoIndex * @return ParameterScanner * @throws Exception\InvalidArgumentException */ public function getParameter($parameterNameOrInfoIndex) { $this->scan(); if (is_int($parameterNameOrInfoIndex)) { $info = $this->infos[$parameterNameOrInfoIndex]; if ($info['type'] != 'parameter') { throw new Exception\InvalidArgumentException('Index of info offset is not about a parameter'); } } elseif (is_string($parameterNameOrInfoIndex)) { foreach ($this->infos as $info) { if ($info['type'] === 'parameter' && $info['name'] === $parameterNameOrInfoIndex) { break; } unset($info); } if (!isset($info)) { throw new Exception\InvalidArgumentException('Index of info offset is not about a parameter'); } } $p = new ParameterScanner( array_slice($this->tokens, $info['tokenStart'], $info['tokenEnd'] - $info['tokenStart']), $this->nameInformation ); $p->setDeclaringFunction($this->name); $p->setDeclaringScannerFunction($this); $p->setDeclaringClass($this->class); $p->setDeclaringScannerClass($this->scannerClass); $p->setPosition($info['position']); return $p; } /** * @return string */ public function getBody() { $this->scan(); return $this->body; } public static function export() { // @todo } public function __toString() { $this->scan(); return var_export($this, true); } protected function scan() { if ($this->isScanned) { return; } if (!$this->tokens) { throw new Exception\RuntimeException('No tokens were provided'); } /** * Variables & Setup */ $tokens = &$this->tokens; // localize $infos = &$this->infos; // localize $tokenIndex = null; $token = null; $tokenType = null; $tokenContent = null; $tokenLine = null; $infoIndex = 0; $parentCount = 0; /* * MACRO creation */ $MACRO_TOKEN_ADVANCE = function () use ( &$tokens, &$tokenIndex, &$token, &$tokenType, &$tokenContent, &$tokenLine ) { static $lastTokenArray = null; $tokenIndex = ($tokenIndex === null) ? 0 : $tokenIndex + 1; if (!isset($tokens[$tokenIndex])) { $token = false; $tokenContent = false; $tokenType = false; $tokenLine = false; return false; } $token = $tokens[$tokenIndex]; if (is_string($token)) { $tokenType = null; $tokenContent = $token; $tokenLine = $tokenLine + substr_count( $lastTokenArray[1], "\n" ); // adjust token line by last known newline count } else { list($tokenType, $tokenContent, $tokenLine) = $token; } return $tokenIndex; }; $MACRO_INFO_START = function () use (&$infoIndex, &$infos, &$tokenIndex, &$tokenLine) { $infos[$infoIndex] = [ 'type' => 'parameter', 'tokenStart' => $tokenIndex, 'tokenEnd' => null, 'lineStart' => $tokenLine, 'lineEnd' => $tokenLine, 'name' => null, 'position' => $infoIndex + 1, // position is +1 of infoIndex ]; }; $MACRO_INFO_ADVANCE = function () use (&$infoIndex, &$infos, &$tokenIndex, &$tokenLine) { $infos[$infoIndex]['tokenEnd'] = $tokenIndex; $infos[$infoIndex]['lineEnd'] = $tokenLine; $infoIndex++; return $infoIndex; }; /** * START FINITE STATE MACHINE FOR SCANNING TOKENS */ // Initialize token $MACRO_TOKEN_ADVANCE(); SCANNER_TOP: $this->lineStart = ($this->lineStart) ? : $tokenLine; switch ($tokenType) { case T_DOC_COMMENT: $this->lineStart = null; if ($this->docComment === null && $this->name === null) { $this->docComment = $tokenContent; } goto SCANNER_CONTINUE_SIGNATURE; // goto (no break needed); case T_FINAL: $this->isFinal = true; goto SCANNER_CONTINUE_SIGNATURE; // goto (no break needed); case T_ABSTRACT: $this->isAbstract = true; goto SCANNER_CONTINUE_SIGNATURE; // goto (no break needed); case T_PUBLIC: // use defaults goto SCANNER_CONTINUE_SIGNATURE; // goto (no break needed); case T_PROTECTED: $this->setVisibility(T_PROTECTED); goto SCANNER_CONTINUE_SIGNATURE; // goto (no break needed); case T_PRIVATE: $this->setVisibility(T_PRIVATE); goto SCANNER_CONTINUE_SIGNATURE; // goto (no break needed); case T_STATIC: $this->isStatic = true; goto SCANNER_CONTINUE_SIGNATURE; // goto (no break needed); case T_NS_SEPARATOR: if (!isset($infos[$infoIndex])) { $MACRO_INFO_START(); } goto SCANNER_CONTINUE_SIGNATURE; // goto (no break needed); case T_VARIABLE: case T_STRING: if ($tokenType === T_STRING && $parentCount === 0) { $this->name = $tokenContent; } if ($parentCount === 1) { if (!isset($infos[$infoIndex])) { $MACRO_INFO_START(); } if ($tokenType === T_VARIABLE) { $infos[$infoIndex]['name'] = ltrim($tokenContent, '$'); } } goto SCANNER_CONTINUE_SIGNATURE; // goto (no break needed); case null: switch ($tokenContent) { case '&': if (!isset($infos[$infoIndex])) { $MACRO_INFO_START(); } goto SCANNER_CONTINUE_SIGNATURE; // goto (no break needed); case '(': $parentCount++; goto SCANNER_CONTINUE_SIGNATURE; // goto (no break needed); case ')': $parentCount--; if ($parentCount > 0) { goto SCANNER_CONTINUE_SIGNATURE; } if ($parentCount === 0) { if ($infos) { $MACRO_INFO_ADVANCE(); } $context = 'body'; } goto SCANNER_CONTINUE_BODY; // goto (no break needed); case ',': if ($parentCount === 1) { $MACRO_INFO_ADVANCE(); } goto SCANNER_CONTINUE_SIGNATURE; } } SCANNER_CONTINUE_SIGNATURE: if ($MACRO_TOKEN_ADVANCE() === false) { goto SCANNER_END; } goto SCANNER_TOP; SCANNER_CONTINUE_BODY: $braceCount = 0; while ($MACRO_TOKEN_ADVANCE() !== false) { if ($tokenContent == '}') { $braceCount--; } if ($braceCount > 0) { $this->body .= $tokenContent; } if ($tokenContent == '{') { $braceCount++; } $this->lineEnd = $tokenLine; } SCANNER_END: $this->isScanned = true; return; } } zend-code-release-3.1.0/src/Scanner/ParameterScanner.php000066400000000000000000000150371300340552400231260ustar00rootroot00000000000000tokens = $parameterTokens; $this->nameInformation = $nameInformation; } /** * Set declaring class * * @param string $class * @return void */ public function setDeclaringClass($class) { $this->declaringClass = (string) $class; } /** * Set declaring scanner class * * @param ClassScanner $scannerClass * @return void */ public function setDeclaringScannerClass(ClassScanner $scannerClass) { $this->declaringScannerClass = $scannerClass; } /** * Set declaring function * * @param string $function * @return void */ public function setDeclaringFunction($function) { $this->declaringFunction = $function; } /** * Set declaring scanner function * * @param MethodScanner $scannerFunction * @return void */ public function setDeclaringScannerFunction(MethodScanner $scannerFunction) { $this->declaringScannerFunction = $scannerFunction; } /** * Set position * * @param int $position * @return void */ public function setPosition($position) { $this->position = $position; } /** * Scan * * @return void */ protected function scan() { if ($this->isScanned) { return; } $tokens = &$this->tokens; reset($tokens); SCANNER_TOP: $token = current($tokens); if (is_string($token)) { // check pass by ref if ($token === '&') { $this->isPassedByReference = true; goto SCANNER_CONTINUE; } if ($token === '=') { $this->isOptional = true; $this->isDefaultValueAvailable = true; goto SCANNER_CONTINUE; } } else { if ($this->name === null && ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR)) { $this->class .= $token[1]; goto SCANNER_CONTINUE; } if ($token[0] === T_VARIABLE) { $this->name = ltrim($token[1], '$'); goto SCANNER_CONTINUE; } } if ($this->name !== null) { $this->defaultValue .= trim((is_string($token)) ? $token : $token[1]); } SCANNER_CONTINUE: if (next($this->tokens) === false) { goto SCANNER_END; } goto SCANNER_TOP; SCANNER_END: if ($this->class && $this->nameInformation) { $this->class = $this->nameInformation->resolveName($this->class); } $this->isScanned = true; } /** * Get declaring scanner class * * @return ClassScanner */ public function getDeclaringScannerClass() { return $this->declaringScannerClass; } /** * Get declaring class * * @return string */ public function getDeclaringClass() { return $this->declaringClass; } /** * Get declaring scanner function * * @return MethodScanner */ public function getDeclaringScannerFunction() { return $this->declaringScannerFunction; } /** * Get declaring function * * @return string */ public function getDeclaringFunction() { return $this->declaringFunction; } /** * Get default value * * @return string */ public function getDefaultValue() { $this->scan(); return $this->defaultValue; } /** * Get class * * @return string */ public function getClass() { $this->scan(); return $this->class; } /** * Get name * * @return string */ public function getName() { $this->scan(); return $this->name; } /** * Get position * * @return int */ public function getPosition() { $this->scan(); return $this->position; } /** * Check if is array * * @return bool */ public function isArray() { $this->scan(); return $this->isArray; } /** * Check if default value is available * * @return bool */ public function isDefaultValueAvailable() { $this->scan(); return $this->isDefaultValueAvailable; } /** * Check if is optional * * @return bool */ public function isOptional() { $this->scan(); return $this->isOptional; } /** * Check if is passed by reference * * @return bool */ public function isPassedByReference() { $this->scan(); return $this->isPassedByReference; } } zend-code-release-3.1.0/src/Scanner/PropertyScanner.php000066400000000000000000000152401300340552400230260ustar00rootroot00000000000000tokens = $propertyTokens; $this->nameInformation = $nameInformation; } /** * @param string $class */ public function setClass($class) { $this->class = $class; } /** * @param ClassScanner $scannerClass */ public function setScannerClass(ClassScanner $scannerClass) { $this->scannerClass = $scannerClass; } /** * @return ClassScanner */ public function getClassScanner() { return $this->scannerClass; } /** * @return string */ public function getName() { $this->scan(); return $this->name; } /** * @return string */ public function getValueType() { $this->scan(); return $this->valueType; } /** * @return bool */ public function isPublic() { $this->scan(); return $this->isPublic; } /** * @return bool */ public function isPrivate() { $this->scan(); return $this->isPrivate; } /** * @return bool */ public function isProtected() { $this->scan(); return $this->isProtected; } /** * @return bool */ public function isStatic() { $this->scan(); return $this->isStatic; } /** * @return string */ public function getValue() { $this->scan(); return $this->value; } /** * @return string */ public function getDocComment() { $this->scan(); return $this->docComment; } /** * @param Annotation\AnnotationManager $annotationManager * @return AnnotationScanner */ public function getAnnotations(Annotation\AnnotationManager $annotationManager) { if (($docComment = $this->getDocComment()) == '') { return false; } return new AnnotationScanner($annotationManager, $docComment, $this->nameInformation); } /** * @return string */ public function __toString() { $this->scan(); return var_export($this, true); } /** * Scan tokens * * @throws \Zend\Code\Exception\RuntimeException */ protected function scan() { if ($this->isScanned) { return; } if (!$this->tokens) { throw new Exception\RuntimeException('No tokens were provided'); } /** * Variables & Setup */ $value = ''; $concatenateValue = false; $tokens = &$this->tokens; reset($tokens); foreach ($tokens as $token) { $tempValue = $token; if (!is_string($token)) { list($tokenType, $tokenContent, $tokenLine) = $token; switch ($tokenType) { case T_DOC_COMMENT: if ($this->docComment === null && $this->name === null) { $this->docComment = $tokenContent; } break; case T_VARIABLE: $this->name = ltrim($tokenContent, '$'); break; case T_PUBLIC: // use defaults break; case T_PROTECTED: $this->isProtected = true; $this->isPublic = false; break; case T_PRIVATE: $this->isPrivate = true; $this->isPublic = false; break; case T_STATIC: $this->isStatic = true; break; default: $tempValue = trim($tokenContent); break; } } //end value concatenation if (!is_array($token) && trim($token) == ";") { $concatenateValue = false; } if (true === $concatenateValue) { $value .= $tempValue; } //start value concatenation if (!is_array($token) && trim($token) == "=") { $concatenateValue = true; } } $this->valueType = self::T_UNKNOWN; if ($value == "false" || $value == "true") { $this->valueType = self::T_BOOLEAN; } elseif (is_numeric($value)) { $this->valueType = self::T_INTEGER; } elseif (0 === strpos($value, 'array') || 0 === strpos($value, "[")) { $this->valueType = self::T_ARRAY; } elseif (substr($value, 0, 1) === '"' || substr($value, 0, 1) === "'") { $value = substr($value, 1, -1); // Remove quotes $this->valueType = self::T_STRING; } $this->value = empty($value) ? null : $value; $this->isScanned = true; } } zend-code-release-3.1.0/src/Scanner/ScannerInterface.php000066400000000000000000000007131300340552400231010ustar00rootroot00000000000000tokens = $tokens; $this->annotationManager = $annotationManager; } /** * @return AnnotationManager */ public function getAnnotationManager() { return $this->annotationManager; } /** * Get doc comment * * @todo Assignment of $this->docComment should probably be done in scan() * and then $this->getDocComment() just retrieves it. * * @return string */ public function getDocComment() { foreach ($this->tokens as $token) { $type = $token[0]; $value = $token[1]; if (($type == T_OPEN_TAG) || ($type == T_WHITESPACE)) { continue; } elseif ($type == T_DOC_COMMENT) { $this->docComment = $value; return $this->docComment; } else { // Only whitespace is allowed before file docblocks return; } } } /** * @return array */ public function getNamespaces() { $this->scan(); $namespaces = []; foreach ($this->infos as $info) { if ($info['type'] == 'namespace') { $namespaces[] = $info['namespace']; } } return $namespaces; } /** * @param null|string $namespace * @return array|null */ public function getUses($namespace = null) { $this->scan(); return $this->getUsesNoScan($namespace); } /** * @return array */ public function getIncludes() { $this->scan(); // @todo Implement getIncludes() in TokenArrayScanner } /** * @return array */ public function getClassNames() { $this->scan(); $return = []; foreach ($this->infos as $info) { if ($info['type'] != 'class') { continue; } $return[] = $info['name']; } return $return; } /** * @return ClassScanner[] */ public function getClasses() { $this->scan(); $return = []; foreach ($this->infos as $info) { if ($info['type'] != 'class') { continue; } $return[] = $this->getClass($info['name']); } return $return; } /** * Return the class object from this scanner * * @param string|int $name * @throws Exception\InvalidArgumentException * @return ClassScanner */ public function getClass($name) { $this->scan(); if (is_int($name)) { $info = $this->infos[$name]; if ($info['type'] != 'class') { throw new Exception\InvalidArgumentException('Index of info offset is not about a class'); } } elseif (is_string($name)) { $classFound = false; foreach ($this->infos as $info) { if ($info['type'] === 'class' && $info['name'] === $name) { $classFound = true; break; } } if (!$classFound) { return false; } } return new ClassScanner( array_slice( $this->tokens, $info['tokenStart'], ($info['tokenEnd'] - $info['tokenStart'] + 1) ), // zero indexed array new NameInformation($info['namespace'], $info['uses']) ); } /** * @param string $className * @return bool|null|NameInformation */ public function getClassNameInformation($className) { $this->scan(); $classFound = false; foreach ($this->infos as $info) { if ($info['type'] === 'class' && $info['name'] === $className) { $classFound = true; break; } } if (!$classFound) { return false; } if (!isset($info)) { return; } return new NameInformation($info['namespace'], $info['uses']); } /** * @return array */ public function getFunctionNames() { $this->scan(); $functionNames = []; foreach ($this->infos as $info) { if ($info['type'] == 'function') { $functionNames[] = $info['name']; } } return $functionNames; } /** * @return array */ public function getFunctions() { $this->scan(); $functions = []; foreach ($this->infos as $info) { if ($info['type'] == 'function') { // @todo $functions[] = new FunctionScanner($info['name']); } } return $functions; } /** * Export * * @param $tokens */ public static function export($tokens) { // @todo } public function __toString() { // @todo } /** * Scan * * @todo: $this->docComment should be assigned for valid docblock during * the scan instead of $this->getDocComment() (starting with * T_DOC_COMMENT case) * * @throws Exception\RuntimeException */ protected function scan() { if ($this->isScanned) { return; } if (!$this->tokens) { throw new Exception\RuntimeException('No tokens were provided'); } /** * Variables & Setup */ $tokens = &$this->tokens; // localize $infos = &$this->infos; // localize $tokenIndex = null; $token = null; $tokenType = null; $tokenContent = null; $tokenLine = null; $namespace = null; $docCommentIndex = false; $infoIndex = 0; /* * MACRO creation */ $MACRO_TOKEN_ADVANCE = function () use ( &$tokens, &$tokenIndex, &$token, &$tokenType, &$tokenContent, &$tokenLine ) { $tokenIndex = ($tokenIndex === null) ? 0 : $tokenIndex + 1; if (!isset($tokens[$tokenIndex])) { $token = false; $tokenContent = false; $tokenType = false; $tokenLine = false; return false; } if (is_string($tokens[$tokenIndex]) && $tokens[$tokenIndex] === '"') { do { $tokenIndex++; } while (!(is_string($tokens[$tokenIndex]) && $tokens[$tokenIndex] === '"')); } $token = $tokens[$tokenIndex]; if (is_array($token)) { list($tokenType, $tokenContent, $tokenLine) = $token; } else { $tokenType = null; $tokenContent = $token; } return $tokenIndex; }; $MACRO_TOKEN_LOGICAL_START_INDEX = function () use (&$tokenIndex, &$docCommentIndex) { return ($docCommentIndex === false) ? $tokenIndex : $docCommentIndex; }; $MACRO_DOC_COMMENT_START = function () use (&$tokenIndex, &$docCommentIndex) { $docCommentIndex = $tokenIndex; return $docCommentIndex; }; $MACRO_DOC_COMMENT_VALIDATE = function () use (&$tokenType, &$docCommentIndex) { static $validTrailingTokens = null; if ($validTrailingTokens === null) { $validTrailingTokens = [T_WHITESPACE, T_FINAL, T_ABSTRACT, T_INTERFACE, T_CLASS, T_FUNCTION]; } if ($docCommentIndex !== false && !in_array($tokenType, $validTrailingTokens)) { $docCommentIndex = false; } return $docCommentIndex; }; $MACRO_INFO_ADVANCE = function () use (&$infoIndex, &$infos, &$tokenIndex, &$tokenLine) { $infos[$infoIndex]['tokenEnd'] = $tokenIndex; $infos[$infoIndex]['lineEnd'] = $tokenLine; $infoIndex++; return $infoIndex; }; /** * START FINITE STATE MACHINE FOR SCANNING TOKENS */ // Initialize token $MACRO_TOKEN_ADVANCE(); SCANNER_TOP: if ($token === false) { goto SCANNER_END; } // Validate current doc comment index $MACRO_DOC_COMMENT_VALIDATE(); switch ($tokenType) { case T_DOC_COMMENT: $MACRO_DOC_COMMENT_START(); goto SCANNER_CONTINUE; // goto no break needed case T_NAMESPACE: $infos[$infoIndex] = [ 'type' => 'namespace', 'tokenStart' => $MACRO_TOKEN_LOGICAL_START_INDEX(), 'tokenEnd' => null, 'lineStart' => $token[2], 'lineEnd' => null, 'namespace' => null, ]; // start processing with next token if ($MACRO_TOKEN_ADVANCE() === false) { goto SCANNER_END; } SCANNER_NAMESPACE_TOP: if ($tokenType === null && $tokenContent === ';' || $tokenContent === '{') { goto SCANNER_NAMESPACE_END; } if ($tokenType === T_WHITESPACE) { goto SCANNER_NAMESPACE_CONTINUE; } if ($tokenType === T_NS_SEPARATOR || $tokenType === T_STRING) { $infos[$infoIndex]['namespace'] .= $tokenContent; } SCANNER_NAMESPACE_CONTINUE: if ($MACRO_TOKEN_ADVANCE() === false) { goto SCANNER_END; } goto SCANNER_NAMESPACE_TOP; SCANNER_NAMESPACE_END: $namespace = $infos[$infoIndex]['namespace']; $MACRO_INFO_ADVANCE(); goto SCANNER_CONTINUE; // goto no break needed case T_USE: $infos[$infoIndex] = [ 'type' => 'use', 'tokenStart' => $MACRO_TOKEN_LOGICAL_START_INDEX(), 'tokenEnd' => null, 'lineStart' => $tokens[$tokenIndex][2], 'lineEnd' => null, 'namespace' => $namespace, 'statements' => [0 => ['use' => null, 'as' => null]], ]; $useStatementIndex = 0; $useAsContext = false; // start processing with next token if ($MACRO_TOKEN_ADVANCE() === false) { goto SCANNER_END; } SCANNER_USE_TOP: if ($tokenType === null) { if ($tokenContent === ';') { goto SCANNER_USE_END; } elseif ($tokenContent === ',') { $useAsContext = false; $useStatementIndex++; $infos[$infoIndex]['statements'][$useStatementIndex] = ['use' => null, 'as' => null]; } } // ANALYZE if ($tokenType !== null) { if ($tokenType == T_AS) { $useAsContext = true; goto SCANNER_USE_CONTINUE; } if ($tokenType == T_NS_SEPARATOR || $tokenType == T_STRING) { if ($useAsContext == false) { $infos[$infoIndex]['statements'][$useStatementIndex]['use'] .= $tokenContent; } else { $infos[$infoIndex]['statements'][$useStatementIndex]['as'] = $tokenContent; } } } SCANNER_USE_CONTINUE: if ($MACRO_TOKEN_ADVANCE() === false) { goto SCANNER_END; } goto SCANNER_USE_TOP; SCANNER_USE_END: $MACRO_INFO_ADVANCE(); goto SCANNER_CONTINUE; // goto no break needed case T_INCLUDE: case T_INCLUDE_ONCE: case T_REQUIRE: case T_REQUIRE_ONCE: // Static for performance static $includeTypes = [ T_INCLUDE => 'include', T_INCLUDE_ONCE => 'include_once', T_REQUIRE => 'require', T_REQUIRE_ONCE => 'require_once' ]; $infos[$infoIndex] = [ 'type' => 'include', 'tokenStart' => $MACRO_TOKEN_LOGICAL_START_INDEX(), 'tokenEnd' => null, 'lineStart' => $tokens[$tokenIndex][2], 'lineEnd' => null, 'includeType' => $includeTypes[$tokens[$tokenIndex][0]], 'path' => '', ]; // start processing with next token if ($MACRO_TOKEN_ADVANCE() === false) { goto SCANNER_END; } SCANNER_INCLUDE_TOP: if ($tokenType === null && $tokenContent === ';') { goto SCANNER_INCLUDE_END; } $infos[$infoIndex]['path'] .= $tokenContent; SCANNER_INCLUDE_CONTINUE: if ($MACRO_TOKEN_ADVANCE() === false) { goto SCANNER_END; } goto SCANNER_INCLUDE_TOP; SCANNER_INCLUDE_END: $MACRO_INFO_ADVANCE(); goto SCANNER_CONTINUE; // goto no break needed case T_FUNCTION: case T_FINAL: case T_ABSTRACT: case T_CLASS: case T_INTERFACE: case T_TRAIT: $infos[$infoIndex] = [ 'type' => ($tokenType === T_FUNCTION) ? 'function' : 'class', 'tokenStart' => $MACRO_TOKEN_LOGICAL_START_INDEX(), 'tokenEnd' => null, 'lineStart' => $tokens[$tokenIndex][2], 'lineEnd' => null, 'namespace' => $namespace, 'uses' => $this->getUsesNoScan($namespace), 'name' => null, 'shortName' => null, ]; $classBraceCount = 0; // start processing with current token SCANNER_CLASS_TOP: // process the name if ($infos[$infoIndex]['shortName'] == '' && (($tokenType === T_CLASS || $tokenType === T_INTERFACE || $tokenType === T_TRAIT) && $infos[$infoIndex]['type'] === 'class' || ($tokenType === T_FUNCTION && $infos[$infoIndex]['type'] === 'function')) ) { $infos[$infoIndex]['shortName'] = is_array($tokens[$tokenIndex + 2]) ? $tokens[$tokenIndex + 2][1] : $tokens[$tokenIndex + 2]; $infos[$infoIndex]['name'] = (($namespace !== null) ? $namespace . '\\' : '') . $infos[$infoIndex]['shortName']; } if ($tokenType === null) { if ($tokenContent == '{') { $classBraceCount++; } if ($tokenContent == '}') { $classBraceCount--; if ($classBraceCount === 0) { goto SCANNER_CLASS_END; } } } SCANNER_CLASS_CONTINUE: if ($MACRO_TOKEN_ADVANCE() === false) { goto SCANNER_END; } goto SCANNER_CLASS_TOP; SCANNER_CLASS_END: $MACRO_INFO_ADVANCE(); goto SCANNER_CONTINUE; // goto no break needed } SCANNER_CONTINUE: if ($MACRO_TOKEN_ADVANCE() === false) { goto SCANNER_END; } goto SCANNER_TOP; SCANNER_END: /** * END FINITE STATE MACHINE FOR SCANNING TOKENS */ $this->isScanned = true; } /** * Check for namespace * * @param string $namespace * @return bool */ public function hasNamespace($namespace) { $this->scan(); foreach ($this->infos as $info) { if ($info['type'] == 'namespace' && $info['namespace'] == $namespace) { return true; } } return false; } /** * @param string $namespace * @return null|array * @throws Exception\InvalidArgumentException */ protected function getUsesNoScan($namespace) { $namespaces = []; foreach ($this->infos as $info) { if ($info['type'] == 'namespace') { $namespaces[] = $info['namespace']; } } if ($namespace === null) { $namespace = array_shift($namespaces); } elseif (!is_string($namespace)) { throw new Exception\InvalidArgumentException('Invalid namespace provided'); } elseif (!in_array($namespace, $namespaces)) { return; } $uses = []; foreach ($this->infos as $info) { if ($info['type'] !== 'use') { continue; } foreach ($info['statements'] as $statement) { if ($info['namespace'] == $namespace) { $uses[] = $statement; } } } return $uses; } } zend-code-release-3.1.0/src/Scanner/Util.php000066400000000000000000000040531300340552400206050ustar00rootroot00000000000000namespace && !$data->uses && strlen($value) > 0 && $value{0} != '\\') { $value = $data->namespace . '\\' . $value; return; } if (!$data->uses || strlen($value) <= 0 || $value{0} == '\\') { $value = ltrim($value, '\\'); return; } if ($data->namespace || $data->uses) { $firstPart = $value; if (($firstPartEnd = strpos($firstPart, '\\')) !== false) { $firstPart = substr($firstPart, 0, $firstPartEnd); } else { $firstPartEnd = strlen($firstPart); } if (array_key_exists($firstPart, $data->uses)) { $value = substr_replace($value, $data->uses[$firstPart], 0, $firstPartEnd); return; } if ($data->namespace) { $value = $data->namespace . '\\' . $value; return; } } } } zend-code-release-3.1.0/src/Scanner/ValueScanner.php000066400000000000000000000005701300340552400222560ustar00rootroot00000000000000