| @@ -0,0 +1,151 @@ | ||
| <?php | ||
| namespace WhiteBox\Routing\Controllers; | ||
|
|
||
|
|
||
| use Doctrine\Common\Annotations\Annotation; | ||
| use Doctrine\Common\Annotations\AnnotationException; | ||
| use Doctrine\Common\Annotations\AnnotationReader; | ||
| use Doctrine\Common\Annotations\IndexedReader; | ||
| use ReflectionClass; | ||
| use ReflectionMethod; | ||
| use WhiteBox\Helpers\RegexHandler; | ||
| use WhiteBox\Routing\Abstractions\A_CisRouter; | ||
| use WhiteBox\Routing\Abstractions\T_NamedRedirectionManager; | ||
| use WhiteBox\Routing\Controllers\Routing; | ||
| use WhiteBox\Routing\Controllers\SubRouting; | ||
| use WhiteBox\Routing\Route; | ||
|
|
||
| /** | ||
| * Class A_ControllerSubRouter | ||
| * @package WhiteBox\Routing | ||
| */ | ||
| abstract class A_ControllerSubRouter extends A_CisRouter{ | ||
| use T_NamedRedirectionManager; | ||
|
|
||
| protected $annotationsReader; | ||
|
|
||
| /** | ||
| * A_ControllerSubRouter constructor. | ||
| * @param callable|null $defaultAuthMW | ||
| * @throws AnnotationException | ||
| */ | ||
| public function __construct(?callable $defaultAuthMW = null) { | ||
| $this->annotationsReader = new IndexedReader(new AnnotationReader()); | ||
| parent::__construct($this->getPrefix(), $defaultAuthMW); | ||
| } | ||
|
|
||
| /** | ||
| * @return string | ||
| * @throws AnnotationException | ||
| */ | ||
| public function getPrefix(): string { | ||
| $ThisClass = new ReflectionClass(static::class); | ||
| $subRoutingAnnotation = $this->annotationsReader->getClassAnnotation($ThisClass, SubRouting::class); | ||
|
|
||
| if(is_null($subRoutingAnnotation)) | ||
| throw new AnnotationException("There is no SubRouting annotation found for this controller"); | ||
|
|
||
| return $subRoutingAnnotation->prefix; | ||
| } | ||
|
|
||
| /** | ||
| * @return array | ||
| */ | ||
| public function getRoutes(): array { | ||
| $routeRefMethods = $this->getRouteMethods(); | ||
| $routings = array_map(function(ReflectionMethod $method){ | ||
| $annotations = $this->annotationsReader->getMethodAnnotations($method); | ||
| foreach($annotations as $annotation){ | ||
| if($annotation instanceof Routing) | ||
| return ["annotation"=>$annotation, "methodName"=>$method->getName()]; | ||
| } | ||
| return null; | ||
| }, $routeRefMethods); | ||
| $routings = array_filter($routings, function($elem){ | ||
| return !is_null($elem); | ||
| }); | ||
|
|
||
| return array_map(function(array $routing): Route{ | ||
| /** | ||
| * @var Routing | ||
| */ | ||
| $annotation = $routing["annotation"]; | ||
| $methodName = $routing["methodName"]; | ||
|
|
||
| return (new Route($annotation->method, $annotation->uri, [$this, $methodName], $this->getDefaultAuthMiddleware())) | ||
| ->name($annotation->name); | ||
| }, $routings); | ||
| } | ||
|
|
||
| /** | ||
| * @return ReflectionMethod[] | ||
| */ | ||
| protected function getRouteMethods(): array{ | ||
| $ThisClass = new ReflectionClass(static::class); | ||
| $publics = $ThisClass->getMethods(ReflectionMethod::IS_PUBLIC); | ||
| return array_filter($publics, function(ReflectionMethod $method){ | ||
| $annotations = $this->annotationsReader->getMethodAnnotations($method); | ||
| return array_reduce($annotations, function(bool $acc, $annotation){ | ||
| return $acc || ($annotation instanceof Routing); | ||
| }, false); | ||
| }); | ||
| } | ||
|
|
||
| protected function hasRoute(string $method, string $re): bool { | ||
| $paramRoute = new Route($method, $re); | ||
| foreach($this->getRoutes() as $route){ | ||
| if($paramRoute->equals($route)) | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| protected function getRoute(string $method, string $re): ?Route { | ||
| $paramRoute = new Route($method, $re); | ||
| foreach($this->getRoutes() as $route){ | ||
| if($paramRoute->equals($route)) | ||
| return $route; | ||
| } | ||
| return null; | ||
| } | ||
|
|
||
| protected function addRoute(Route $route) { | ||
| $this->routes[] = $route; | ||
| } | ||
|
|
||
| /** | ||
| * @param string $method | ||
| * @return array | ||
| * @throws AnnotationException | ||
| */ | ||
| protected function getRoutesForMethod(string $method): array { | ||
| return array_filter($this->getRoutes(), function(Route $route) use($method){ | ||
| return $route->method() === $method; | ||
| }); | ||
| } | ||
|
|
||
| protected function setupRoute(string $method, string $re, callable $functor, ?callable $authMiddleware = null): Route { | ||
| if ($this->hasRoute($method, $re)) { | ||
| $route = $this->getRoute($method, $re); | ||
| if (!is_null($route)) { | ||
| $route->setHandler($functor); | ||
|
|
||
| if (!is_null($authMiddleware)) | ||
| $route->setAuthMiddleware($authMiddleware); | ||
| } | ||
|
|
||
| return $route; | ||
| //throw new Exception("It is impossible to override/declare twice a single Route"); | ||
| } | ||
| //otherwise | ||
| //push it to the arrays | ||
| $route = new Route($method, $re); | ||
| $this->addRoute($route); | ||
| $route->setHandler($functor); | ||
|
|
||
| if (!is_null($authMiddleware)) | ||
| $route->setAuthMiddleware($authMiddleware); | ||
|
|
||
| return $route; | ||
| } | ||
| } |
| @@ -0,0 +1,39 @@ | ||
| <?php | ||
| namespace WhiteBox\Routing\Controllers; | ||
| use Doctrine\Common\Annotations\Annotation; | ||
| use Doctrine\Common\Annotations\Annotation\Required; | ||
| use Doctrine\Common\Annotations\Annotation\Target; | ||
| use Doctrine\Common\Annotations\AnnotationException; | ||
| use Doctrine\Common\Annotations\AnnotationRegistry; | ||
| use PHPUnit\Runner\Exception; | ||
|
|
||
| /** | ||
| * Class Routing | ||
| * @package WhiteBox\Routing\Controllers | ||
| * @Annotation | ||
| * @Target("METHOD") | ||
| */ | ||
| class Routing{ | ||
| /** | ||
| * @var string | ||
| * @Required | ||
| */ | ||
| public $method; | ||
|
|
||
| /** | ||
| * @var string | ||
| * @Required | ||
| */ | ||
| public $uri; | ||
|
|
||
| /** | ||
| * @var string | ||
| */ | ||
| public $name; | ||
|
|
||
| public function __construct(array $values) { | ||
| $this->method = $values["method"]; | ||
| $this->uri = $values["uri"]; | ||
| $this->name = isset($values["name"]) ? $values["name"] : null; | ||
| } | ||
| } |
| @@ -0,0 +1,21 @@ | ||
| <?php | ||
| namespace WhiteBox\Routing\Controllers; | ||
| use Doctrine\Common\Annotations\Annotation; | ||
| use Doctrine\Common\Annotations\Annotation\Required; | ||
| use Doctrine\Common\Annotations\Annotation\Target; | ||
| use Doctrine\Common\Annotations\AnnotationException; | ||
| use Doctrine\Common\Annotations\AnnotationRegistry; | ||
|
|
||
| /** | ||
| * Class SubRouting | ||
| * @package WhiteBox\Routing\Controllers | ||
| * @Annotation | ||
| * @Target("CLASS") | ||
| */ | ||
| class SubRouting extends Annotation{ | ||
| /** | ||
| * @var string | ||
| * @Required | ||
| */ | ||
| public $prefix; | ||
| } |
| @@ -7,4 +7,5 @@ | ||
|
|
||
| return array( | ||
| 'Prophecy\\' => array($vendorDir . '/phpspec/prophecy/src'), | ||
| 'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/lib'), | ||
| ); | ||
| @@ -0,0 +1,130 @@ | ||
| ## Changelog | ||
|
|
||
| ### 1.5.0 | ||
|
|
||
| This release increments the minimum supported PHP version to 7.1.0. | ||
|
|
||
| Also, HHVM official support has been dropped. | ||
|
|
||
| Some noticeable performance improvements to annotation autoloading | ||
| have been applied, making failed annotation autoloading less heavy | ||
| on the filesystem access. | ||
|
|
||
| - [133: Add @throws annotation in AnnotationReader#__construct()](https://github.com/doctrine/annotations/issues/133) thanks to @SenseException | ||
| - [134: Require PHP 7.1, drop HHVM support](https://github.com/doctrine/annotations/issues/134) thanks to @lcobucci | ||
| - [135: Prevent the same loader from being registered twice](https://github.com/doctrine/annotations/issues/135) thanks to @jrjohnson | ||
| - [137: #135 optimise multiple class load attempts in AnnotationRegistry](https://github.com/doctrine/annotations/issues/137) thanks to @Ocramius | ||
|
|
||
|
|
||
| ### 1.4.0 | ||
|
|
||
| This release fix an issue were some annotations could be not loaded if the namespace in the use statement started with a backslash. | ||
| It also update the tests and drop the support for php 5.X | ||
|
|
||
| - [115: Missing annotations with the latest composer version](https://github.com/doctrine/annotations/issues/115) thanks to @pascalporedda | ||
| - [120: Missing annotations with the latest composer version](https://github.com/doctrine/annotations/pull/120) thanks to @gnat42 | ||
| - [121: Adding a more detailed explanation of the test](https://github.com/doctrine/annotations/pull/121) thanks to @mikeSimonson | ||
| - [101: Test annotation parameters containing space](https://github.com/doctrine/annotations/pull/101) thanks to @mikeSimonson | ||
| - [111: Cleanup: move to correct phpunit assertions](https://github.com/doctrine/annotations/pull/111) thanks to @Ocramius | ||
| - [112: Removes support for PHP 5.x](https://github.com/doctrine/annotations/pull/112) thanks to @railto | ||
| - [113: bumped phpunit version to 5.7](https://github.com/doctrine/annotations/pull/113) thanks to @gabbydgab | ||
| - [114: Enhancement: Use SVG Travis build badge](https://github.com/doctrine/annotations/pull/114) thanks to @localheinz | ||
| - [118: Integrating PHPStan](https://github.com/doctrine/annotations/pull/118) thanks to @ondrejmirtes | ||
|
|
||
| ### 1.3.1 - 2016-12-30 | ||
|
|
||
| This release fixes an issue with ignored annotations that were already | ||
| autoloaded, causing the `SimpleAnnotationReader` to pick them up | ||
| anyway. [#110](https://github.com/doctrine/annotations/pull/110) | ||
|
|
||
| Additionally, an issue was fixed in the `CachedReader`, which was | ||
| not correctly checking the freshness of cached annotations when | ||
| traits were defined on a class. [#105](https://github.com/doctrine/annotations/pull/105) | ||
|
|
||
| Total issues resolved: **2** | ||
|
|
||
| - [105: Return single max timestamp](https://github.com/doctrine/annotations/pull/105) | ||
| - [110: setIgnoreNotImportedAnnotations(true) didn’t work for existing classes](https://github.com/doctrine/annotations/pull/110) | ||
|
|
||
| ### 1.3.0 | ||
|
|
||
| This release introduces a PHP version bump. `doctrine/annotations` now requires PHP | ||
| 5.6 or later to be installed. | ||
|
|
||
| A series of additional improvements have been introduced: | ||
|
|
||
| * support for PHP 7 "grouped use statements" | ||
| * support for ignoring entire namespace names | ||
| via `Doctrine\Common\Annotations\AnnotationReader::addGlobalIgnoredNamespace()` and | ||
| `Doctrine\Common\Annotations\DocParser::setIgnoredAnnotationNamespaces()`. This will | ||
| allow you to ignore annotations from namespaces that you cannot autoload | ||
| * testing all parent classes and interfaces when checking if the annotation cache | ||
| in the `CachedReader` is fresh | ||
| * simplifying the cache keys used by the `CachedReader`: keys are no longer artificially | ||
| namespaced, since `Doctrine\Common\Cache` already supports that | ||
| * corrected parsing of multibyte strings when `mbstring.func_overload` is enabled | ||
| * corrected parsing of annotations when `"\t"` is put before the first annotation | ||
| in a docblock | ||
| * allow skipping non-imported annotations when a custom `DocParser` is passed to | ||
| the `AnnotationReader` constructor | ||
|
|
||
| Total issues resolved: **15** | ||
|
|
||
| - [45: DocParser can now ignore whole namespaces](https://github.com/doctrine/annotations/pull/45) | ||
| - [57: Switch to the docker-based infrastructure on Travis](https://github.com/doctrine/annotations/pull/57) | ||
| - [59: opcache.load_comments has been removed from PHP 7](https://github.com/doctrine/annotations/pull/59) | ||
| - [62: [CachedReader\ Test traits and parent class to see if cache is fresh](https://github.com/doctrine/annotations/pull/62) | ||
| - [65: Remove cache salt making key unnecessarily long](https://github.com/doctrine/annotations/pull/65) | ||
| - [66: Fix of incorrect parsing multibyte strings](https://github.com/doctrine/annotations/pull/66) | ||
| - [68: Annotations that are indented by tab are not processed.](https://github.com/doctrine/annotations/issues/68) | ||
| - [69: Support for Group Use Statements](https://github.com/doctrine/annotations/pull/69) | ||
| - [70: Allow tab character before first annotation in DocBlock](https://github.com/doctrine/annotations/pull/70) | ||
| - [74: Ignore not registered annotations fix](https://github.com/doctrine/annotations/pull/74) | ||
| - [92: Added tests for AnnotationRegistry class.](https://github.com/doctrine/annotations/pull/92) | ||
| - [96: Fix/#62 check trait and parent class ttl in annotations](https://github.com/doctrine/annotations/pull/96) | ||
| - [97: Feature - #45 - allow ignoring entire namespaces](https://github.com/doctrine/annotations/pull/97) | ||
| - [98: Enhancement/#65 remove cache salt from cached reader](https://github.com/doctrine/annotations/pull/98) | ||
| - [99: Fix - #70 - allow tab character before first annotation in docblock](https://github.com/doctrine/annotations/pull/99) | ||
|
|
||
| ### 1.2.4 | ||
|
|
||
| Total issues resolved: **1** | ||
|
|
||
| - [51: FileCacheReader::saveCacheFile::unlink fix](https://github.com/doctrine/annotations/pull/51) | ||
|
|
||
| ### 1.2.3 | ||
|
|
||
| Total issues resolved: [**2**](https://github.com/doctrine/annotations/milestones/v1.2.3) | ||
|
|
||
| - [49: #46 - applying correct `chmod()` to generated cache file](https://github.com/doctrine/annotations/pull/49) | ||
| - [50: Hotfix: match escaped quotes (revert #44)](https://github.com/doctrine/annotations/pull/50) | ||
|
|
||
| ### 1.2.2 | ||
|
|
||
| Total issues resolved: **4** | ||
|
|
||
| - [43: Exclude files from distribution with .gitattributes](https://github.com/doctrine/annotations/pull/43) | ||
| - [44: Update DocLexer.php](https://github.com/doctrine/annotations/pull/44) | ||
| - [46: A plain "file_put_contents" can cause havoc](https://github.com/doctrine/annotations/pull/46) | ||
| - [48: Deprecating the `FileCacheReader` in 1.2.2: will be removed in 2.0.0](https://github.com/doctrine/annotations/pull/48) | ||
|
|
||
| ### 1.2.1 | ||
|
|
||
| Total issues resolved: **4** | ||
|
|
||
| - [38: fixes doctrine/common#326](https://github.com/doctrine/annotations/pull/38) | ||
| - [39: Remove superfluous NS](https://github.com/doctrine/annotations/pull/39) | ||
| - [41: Warn if load_comments is not enabled.](https://github.com/doctrine/annotations/pull/41) | ||
| - [42: Clean up unused uses](https://github.com/doctrine/annotations/pull/42) | ||
|
|
||
| ### 1.2.0 | ||
|
|
||
| * HHVM support | ||
| * Allowing dangling comma in annotations | ||
| * Excluded annotations are no longer autoloaded | ||
| * Importing namespaces also in traits | ||
| * Added support for `::class` 5.5-style constant, works also in 5.3 and 5.4 | ||
|
|
||
| ### 1.1.0 | ||
|
|
||
| * Add Exception when ZendOptimizer+ or Opcache is configured to drop comments |
| @@ -0,0 +1,19 @@ | ||
| Copyright (c) 2006-2013 Doctrine Project | ||
|
|
||
| Permission is hereby granted, free of charge, to any person obtaining a copy of | ||
| this software and associated documentation files (the "Software"), to deal in | ||
| the Software without restriction, including without limitation the rights to | ||
| use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies | ||
| of the Software, and to permit persons to whom the Software is furnished to do | ||
| so, subject to the following conditions: | ||
|
|
||
| The above copyright notice and this permission notice shall be included in all | ||
| copies or substantial portions of the Software. | ||
|
|
||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| SOFTWARE. |
| @@ -0,0 +1,17 @@ | ||
| # Doctrine Annotations | ||
|
|
||
| [](https://travis-ci.org/doctrine/annotations) | ||
| [](https://www.versioneye.com/package/php--doctrine--annotations) | ||
| [](https://www.versioneye.com/php/doctrine:annotations/references) | ||
| [](https://packagist.org/packages/doctrine/annotations) | ||
| [](https://packagist.org/packages/doctrine/annotations) | ||
|
|
||
| Docblock Annotations Parser library (extracted from [Doctrine Common](https://github.com/doctrine/common)). | ||
|
|
||
| ## Documentation | ||
|
|
||
| See the [doctrine-project website](http://docs.doctrine-project.org/projects/doctrine-common/en/latest/reference/annotations.html). | ||
|
|
||
| ## Changelog | ||
|
|
||
| See [CHANGELOG.md](CHANGELOG.md). |
| @@ -0,0 +1,34 @@ | ||
| { | ||
| "name": "doctrine/annotations", | ||
| "type": "library", | ||
| "description": "Docblock Annotations Parser", | ||
| "keywords": ["annotations", "docblock", "parser"], | ||
| "homepage": "http://www.doctrine-project.org", | ||
| "license": "MIT", | ||
| "authors": [ | ||
| {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, | ||
| {"name": "Roman Borschel", "email": "roman@code-factory.org"}, | ||
| {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, | ||
| {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, | ||
| {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"} | ||
| ], | ||
| "require": { | ||
| "php": "^7.1", | ||
| "doctrine/lexer": "1.*" | ||
| }, | ||
| "require-dev": { | ||
| "doctrine/cache": "1.*", | ||
| "phpunit/phpunit": "^6.4" | ||
| }, | ||
| "autoload": { | ||
| "psr-4": { "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" } | ||
| }, | ||
| "autoload-dev": { | ||
| "psr-4": { "Doctrine\\Tests\\Common\\Annotations\\": "tests/Doctrine/Tests/Common/Annotations" } | ||
| }, | ||
| "extra": { | ||
| "branch-alias": { | ||
| "dev-master": "1.6.x-dev" | ||
| } | ||
| } | ||
| } |
| @@ -0,0 +1,79 @@ | ||
| <?php | ||
| /* | ||
| * 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. | ||
| * | ||
| * This software consists of voluntary contributions made by many individuals | ||
| * and is licensed under the MIT license. For more information, see | ||
| * <http://www.doctrine-project.org>. | ||
| */ | ||
|
|
||
| namespace Doctrine\Common\Annotations; | ||
|
|
||
| /** | ||
| * Annotations class. | ||
| * | ||
| * @author Benjamin Eberlei <kontakt@beberlei.de> | ||
| * @author Guilherme Blanco <guilhermeblanco@hotmail.com> | ||
| * @author Jonathan Wage <jonwage@gmail.com> | ||
| * @author Roman Borschel <roman@code-factory.org> | ||
| */ | ||
| class Annotation | ||
| { | ||
| /** | ||
| * Value property. Common among all derived classes. | ||
| * | ||
| * @var string | ||
| */ | ||
| public $value; | ||
|
|
||
| /** | ||
| * Constructor. | ||
| * | ||
| * @param array $data Key-value for properties to be defined in this class. | ||
| */ | ||
| public final function __construct(array $data) | ||
| { | ||
| foreach ($data as $key => $value) { | ||
| $this->$key = $value; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Error handler for unknown property accessor in Annotation class. | ||
| * | ||
| * @param string $name Unknown property name. | ||
| * | ||
| * @throws \BadMethodCallException | ||
| */ | ||
| public function __get($name) | ||
| { | ||
| throw new \BadMethodCallException( | ||
| sprintf("Unknown property '%s' on annotation '%s'.", $name, get_class($this)) | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Error handler for unknown property mutator in Annotation class. | ||
| * | ||
| * @param string $name Unknown property name. | ||
| * @param mixed $value Property value. | ||
| * | ||
| * @throws \BadMethodCallException | ||
| */ | ||
| public function __set($name, $value) | ||
| { | ||
| throw new \BadMethodCallException( | ||
| sprintf("Unknown property '%s' on annotation '%s'.", $name, get_class($this)) | ||
| ); | ||
| } | ||
| } |
| @@ -0,0 +1,47 @@ | ||
| <?php | ||
|
|
||
| /* | ||
| * 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. | ||
| * | ||
| * This software consists of voluntary contributions made by many individuals | ||
| * and is licensed under the MIT license. For more information, see | ||
| * <http://www.doctrine-project.org>. | ||
| */ | ||
|
|
||
| namespace Doctrine\Common\Annotations\Annotation; | ||
|
|
||
| /** | ||
| * Annotation that can be used to signal to the parser | ||
| * to check the attribute type during the parsing process. | ||
| * | ||
| * @author Fabio B. Silva <fabio.bat.silva@gmail.com> | ||
| * | ||
| * @Annotation | ||
| */ | ||
| final class Attribute | ||
| { | ||
| /** | ||
| * @var string | ||
| */ | ||
| public $name; | ||
|
|
||
| /** | ||
| * @var string | ||
| */ | ||
| public $type; | ||
|
|
||
| /** | ||
| * @var boolean | ||
| */ | ||
| public $required = false; | ||
| } |
| @@ -0,0 +1,37 @@ | ||
| <?php | ||
|
|
||
| /* | ||
| * 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. | ||
| * | ||
| * This software consists of voluntary contributions made by many individuals | ||
| * and is licensed under the MIT license. For more information, see | ||
| * <http://www.doctrine-project.org>. | ||
| */ | ||
|
|
||
| namespace Doctrine\Common\Annotations\Annotation; | ||
|
|
||
| /** | ||
| * Annotation that can be used to signal to the parser | ||
| * to check the types of all declared attributes during the parsing process. | ||
| * | ||
| * @author Fabio B. Silva <fabio.bat.silva@gmail.com> | ||
| * | ||
| * @Annotation | ||
| */ | ||
| final class Attributes | ||
| { | ||
| /** | ||
| * @var array<Doctrine\Common\Annotations\Annotation\Attribute> | ||
| */ | ||
| public $value; | ||
| } |
| @@ -0,0 +1,84 @@ | ||
| <?php | ||
|
|
||
| /* | ||
| * 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. | ||
| * | ||
| * This software consists of voluntary contributions made by many individuals | ||
| * and is licensed under the MIT license. For more information, see | ||
| * <http://www.doctrine-project.org>. | ||
| */ | ||
|
|
||
| namespace Doctrine\Common\Annotations\Annotation; | ||
|
|
||
| /** | ||
| * Annotation that can be used to signal to the parser | ||
| * to check the available values during the parsing process. | ||
| * | ||
| * @since 2.4 | ||
| * @author Fabio B. Silva <fabio.bat.silva@gmail.com> | ||
| * | ||
| * @Annotation | ||
| * @Attributes({ | ||
| * @Attribute("value", required = true, type = "array"), | ||
| * @Attribute("literal", required = false, type = "array") | ||
| * }) | ||
| */ | ||
| final class Enum | ||
| { | ||
| /** | ||
| * @var array | ||
| */ | ||
| public $value; | ||
|
|
||
| /** | ||
| * Literal target declaration. | ||
| * | ||
| * @var array | ||
| */ | ||
| public $literal; | ||
|
|
||
| /** | ||
| * Annotation constructor. | ||
| * | ||
| * @param array $values | ||
| * | ||
| * @throws \InvalidArgumentException | ||
| */ | ||
| public function __construct(array $values) | ||
| { | ||
| if ( ! isset($values['literal'])) { | ||
| $values['literal'] = array(); | ||
| } | ||
|
|
||
| foreach ($values['value'] as $var) { | ||
| if( ! is_scalar($var)) { | ||
| throw new \InvalidArgumentException(sprintf( | ||
| '@Enum supports only scalar values "%s" given.', | ||
| is_object($var) ? get_class($var) : gettype($var) | ||
| )); | ||
| } | ||
| } | ||
|
|
||
| foreach ($values['literal'] as $key => $var) { | ||
| if( ! in_array($key, $values['value'])) { | ||
| throw new \InvalidArgumentException(sprintf( | ||
| 'Undefined enumerator value "%s" for literal "%s".', | ||
| $key , $var | ||
| )); | ||
| } | ||
| } | ||
|
|
||
| $this->value = $values['value']; | ||
| $this->literal = $values['literal']; | ||
| } | ||
| } |
| @@ -0,0 +1,54 @@ | ||
| <?php | ||
| /* | ||
| * 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. | ||
| * | ||
| * This software consists of voluntary contributions made by many individuals | ||
| * and is licensed under the MIT license. For more information, see | ||
| * <http://www.doctrine-project.org>. | ||
| */ | ||
|
|
||
| namespace Doctrine\Common\Annotations\Annotation; | ||
|
|
||
| /** | ||
| * Annotation that can be used to signal to the parser to ignore specific | ||
| * annotations during the parsing process. | ||
| * | ||
| * @Annotation | ||
| * @author Johannes M. Schmitt <schmittjoh@gmail.com> | ||
| */ | ||
| final class IgnoreAnnotation | ||
| { | ||
| /** | ||
| * @var array | ||
| */ | ||
| public $names; | ||
|
|
||
| /** | ||
| * Constructor. | ||
| * | ||
| * @param array $values | ||
| * | ||
| * @throws \RuntimeException | ||
| */ | ||
| public function __construct(array $values) | ||
| { | ||
| if (is_string($values['value'])) { | ||
| $values['value'] = array($values['value']); | ||
| } | ||
| if (!is_array($values['value'])) { | ||
| throw new \RuntimeException(sprintf('@IgnoreAnnotation expects either a string name, or an array of strings, but got %s.', json_encode($values['value']))); | ||
| } | ||
|
|
||
| $this->names = $values['value']; | ||
| } | ||
| } |
| @@ -0,0 +1,33 @@ | ||
| <?php | ||
|
|
||
| /* | ||
| * 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. | ||
| * | ||
| * This software consists of voluntary contributions made by many individuals | ||
| * and is licensed under the MIT license. For more information, see | ||
| * <http://www.doctrine-project.org>. | ||
| */ | ||
|
|
||
| namespace Doctrine\Common\Annotations\Annotation; | ||
|
|
||
| /** | ||
| * Annotation that can be used to signal to the parser | ||
| * to check if that attribute is required during the parsing process. | ||
| * | ||
| * @author Fabio B. Silva <fabio.bat.silva@gmail.com> | ||
| * | ||
| * @Annotation | ||
| */ | ||
| final class Required | ||
| { | ||
| } |
| @@ -0,0 +1,107 @@ | ||
| <?php | ||
|
|
||
| /* | ||
| * 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. | ||
| * | ||
| * This software consists of voluntary contributions made by many individuals | ||
| * and is licensed under the MIT license. For more information, see | ||
| * <http://www.doctrine-project.org>. | ||
| */ | ||
|
|
||
| namespace Doctrine\Common\Annotations\Annotation; | ||
|
|
||
| /** | ||
| * Annotation that can be used to signal to the parser | ||
| * to check the annotation target during the parsing process. | ||
| * | ||
| * @author Fabio B. Silva <fabio.bat.silva@gmail.com> | ||
| * | ||
| * @Annotation | ||
| */ | ||
| final class Target | ||
| { | ||
| const TARGET_CLASS = 1; | ||
| const TARGET_METHOD = 2; | ||
| const TARGET_PROPERTY = 4; | ||
| const TARGET_ANNOTATION = 8; | ||
| const TARGET_ALL = 15; | ||
|
|
||
| /** | ||
| * @var array | ||
| */ | ||
| private static $map = array( | ||
| 'ALL' => self::TARGET_ALL, | ||
| 'CLASS' => self::TARGET_CLASS, | ||
| 'METHOD' => self::TARGET_METHOD, | ||
| 'PROPERTY' => self::TARGET_PROPERTY, | ||
| 'ANNOTATION' => self::TARGET_ANNOTATION, | ||
| ); | ||
|
|
||
| /** | ||
| * @var array | ||
| */ | ||
| public $value; | ||
|
|
||
| /** | ||
| * Targets as bitmask. | ||
| * | ||
| * @var integer | ||
| */ | ||
| public $targets; | ||
|
|
||
| /** | ||
| * Literal target declaration. | ||
| * | ||
| * @var integer | ||
| */ | ||
| public $literal; | ||
|
|
||
| /** | ||
| * Annotation constructor. | ||
| * | ||
| * @param array $values | ||
| * | ||
| * @throws \InvalidArgumentException | ||
| */ | ||
| public function __construct(array $values) | ||
| { | ||
| if (!isset($values['value'])){ | ||
| $values['value'] = null; | ||
| } | ||
| if (is_string($values['value'])){ | ||
| $values['value'] = array($values['value']); | ||
| } | ||
| if (!is_array($values['value'])){ | ||
| throw new \InvalidArgumentException( | ||
| sprintf('@Target expects either a string value, or an array of strings, "%s" given.', | ||
| is_object($values['value']) ? get_class($values['value']) : gettype($values['value']) | ||
| ) | ||
| ); | ||
| } | ||
|
|
||
| $bitmask = 0; | ||
| foreach ($values['value'] as $literal) { | ||
| if(!isset(self::$map[$literal])){ | ||
| throw new \InvalidArgumentException( | ||
| sprintf('Invalid Target "%s". Available targets: [%s]', | ||
| $literal, implode(', ', array_keys(self::$map))) | ||
| ); | ||
| } | ||
| $bitmask |= self::$map[$literal]; | ||
| } | ||
|
|
||
| $this->targets = $bitmask; | ||
| $this->value = $values['value']; | ||
| $this->literal = implode(', ', $this->value); | ||
| } | ||
| } |
| @@ -0,0 +1,197 @@ | ||
| <?php | ||
| /* | ||
| * 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. | ||
| * | ||
| * This software consists of voluntary contributions made by many individuals | ||
| * and is licensed under the MIT license. For more information, see | ||
| * <http://www.doctrine-project.org>. | ||
| */ | ||
|
|
||
| namespace Doctrine\Common\Annotations; | ||
|
|
||
| /** | ||
| * Description of AnnotationException | ||
| * | ||
| * @since 2.0 | ||
| * @author Benjamin Eberlei <kontakt@beberlei.de> | ||
| * @author Guilherme Blanco <guilhermeblanco@hotmail.com> | ||
| * @author Jonathan Wage <jonwage@gmail.com> | ||
| * @author Roman Borschel <roman@code-factory.org> | ||
| */ | ||
| class AnnotationException extends \Exception | ||
| { | ||
| /** | ||
| * Creates a new AnnotationException describing a Syntax error. | ||
| * | ||
| * @param string $message Exception message | ||
| * | ||
| * @return AnnotationException | ||
| */ | ||
| public static function syntaxError($message) | ||
| { | ||
| return new self('[Syntax Error] ' . $message); | ||
| } | ||
|
|
||
| /** | ||
| * Creates a new AnnotationException describing a Semantical error. | ||
| * | ||
| * @param string $message Exception message | ||
| * | ||
| * @return AnnotationException | ||
| */ | ||
| public static function semanticalError($message) | ||
| { | ||
| return new self('[Semantical Error] ' . $message); | ||
| } | ||
|
|
||
| /** | ||
| * Creates a new AnnotationException describing an error which occurred during | ||
| * the creation of the annotation. | ||
| * | ||
| * @since 2.2 | ||
| * | ||
| * @param string $message | ||
| * | ||
| * @return AnnotationException | ||
| */ | ||
| public static function creationError($message) | ||
| { | ||
| return new self('[Creation Error] ' . $message); | ||
| } | ||
|
|
||
| /** | ||
| * Creates a new AnnotationException describing a type error. | ||
| * | ||
| * @since 1.1 | ||
| * | ||
| * @param string $message | ||
| * | ||
| * @return AnnotationException | ||
| */ | ||
| public static function typeError($message) | ||
| { | ||
| return new self('[Type Error] ' . $message); | ||
| } | ||
|
|
||
| /** | ||
| * Creates a new AnnotationException describing a constant semantical error. | ||
| * | ||
| * @since 2.3 | ||
| * | ||
| * @param string $identifier | ||
| * @param string $context | ||
| * | ||
| * @return AnnotationException | ||
| */ | ||
| public static function semanticalErrorConstants($identifier, $context = null) | ||
| { | ||
| return self::semanticalError(sprintf( | ||
| "Couldn't find constant %s%s.", | ||
| $identifier, | ||
| $context ? ', ' . $context : '' | ||
| )); | ||
| } | ||
|
|
||
| /** | ||
| * Creates a new AnnotationException describing an type error of an attribute. | ||
| * | ||
| * @since 2.2 | ||
| * | ||
| * @param string $attributeName | ||
| * @param string $annotationName | ||
| * @param string $context | ||
| * @param string $expected | ||
| * @param mixed $actual | ||
| * | ||
| * @return AnnotationException | ||
| */ | ||
| public static function attributeTypeError($attributeName, $annotationName, $context, $expected, $actual) | ||
| { | ||
| return self::typeError(sprintf( | ||
| 'Attribute "%s" of @%s declared on %s expects %s, but got %s.', | ||
| $attributeName, | ||
| $annotationName, | ||
| $context, | ||
| $expected, | ||
| is_object($actual) ? 'an instance of ' . get_class($actual) : gettype($actual) | ||
| )); | ||
| } | ||
|
|
||
| /** | ||
| * Creates a new AnnotationException describing an required error of an attribute. | ||
| * | ||
| * @since 2.2 | ||
| * | ||
| * @param string $attributeName | ||
| * @param string $annotationName | ||
| * @param string $context | ||
| * @param string $expected | ||
| * | ||
| * @return AnnotationException | ||
| */ | ||
| public static function requiredError($attributeName, $annotationName, $context, $expected) | ||
| { | ||
| return self::typeError(sprintf( | ||
| 'Attribute "%s" of @%s declared on %s expects %s. This value should not be null.', | ||
| $attributeName, | ||
| $annotationName, | ||
| $context, | ||
| $expected | ||
| )); | ||
| } | ||
|
|
||
| /** | ||
| * Creates a new AnnotationException describing a invalid enummerator. | ||
| * | ||
| * @since 2.4 | ||
| * | ||
| * @param string $attributeName | ||
| * @param string $annotationName | ||
| * @param string $context | ||
| * @param array $available | ||
| * @param mixed $given | ||
| * | ||
| * @return AnnotationException | ||
| */ | ||
| public static function enumeratorError($attributeName, $annotationName, $context, $available, $given) | ||
| { | ||
| return new self(sprintf( | ||
| '[Enum Error] Attribute "%s" of @%s declared on %s accept only [%s], but got %s.', | ||
| $attributeName, | ||
| $annotationName, | ||
| $context, | ||
| implode(', ', $available), | ||
| is_object($given) ? get_class($given) : $given | ||
| )); | ||
| } | ||
|
|
||
| /** | ||
| * @return AnnotationException | ||
| */ | ||
| public static function optimizerPlusSaveComments() | ||
| { | ||
| return new self( | ||
| "You have to enable opcache.save_comments=1 or zend_optimizerplus.save_comments=1." | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * @return AnnotationException | ||
| */ | ||
| public static function optimizerPlusLoadComments() | ||
| { | ||
| return new self( | ||
| "You have to enable opcache.load_comments=1 or zend_optimizerplus.load_comments=1." | ||
| ); | ||
| } | ||
| } |
| @@ -0,0 +1,174 @@ | ||
| <?php | ||
| /* | ||
| * 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. | ||
| * | ||
| * This software consists of voluntary contributions made by many individuals | ||
| * and is licensed under the MIT license. For more information, see | ||
| * <http://www.doctrine-project.org>. | ||
| */ | ||
|
|
||
| namespace Doctrine\Common\Annotations; | ||
|
|
||
| final class AnnotationRegistry | ||
| { | ||
| /** | ||
| * A map of namespaces to use for autoloading purposes based on a PSR-0 convention. | ||
| * | ||
| * Contains the namespace as key and an array of directories as value. If the value is NULL | ||
| * the include path is used for checking for the corresponding file. | ||
| * | ||
| * This autoloading mechanism does not utilize the PHP autoloading but implements autoloading on its own. | ||
| * | ||
| * @var string[][]|string[]|null[] | ||
| */ | ||
| static private $autoloadNamespaces = []; | ||
|
|
||
| /** | ||
| * A map of autoloader callables. | ||
| * | ||
| * @var callable[] | ||
| */ | ||
| static private $loaders = []; | ||
|
|
||
| /** | ||
| * An array of classes which cannot be found | ||
| * | ||
| * @var null[] indexed by class name | ||
| */ | ||
| static private $failedToAutoload = []; | ||
|
|
||
| public static function reset() : void | ||
| { | ||
| self::$autoloadNamespaces = []; | ||
| self::$loaders = []; | ||
| self::$failedToAutoload = []; | ||
| } | ||
|
|
||
| /** | ||
| * Registers file. | ||
| * | ||
| * @deprecated this method is deprecated and will be removed in doctrine/annotations 2.0 | ||
| * autoloading should be deferred to the globally registered autoloader by then. For now, | ||
| * use @example AnnotationRegistry::registerLoader('class_exists') | ||
| */ | ||
| public static function registerFile(string $file) : void | ||
| { | ||
| require_once $file; | ||
| } | ||
|
|
||
| /** | ||
| * Adds a namespace with one or many directories to look for files or null for the include path. | ||
| * | ||
| * Loading of this namespaces will be done with a PSR-0 namespace loading algorithm. | ||
| * | ||
| * @param string $namespace | ||
| * @param string|array|null $dirs | ||
| * | ||
| * @deprecated this method is deprecated and will be removed in doctrine/annotations 2.0 | ||
| * autoloading should be deferred to the globally registered autoloader by then. For now, | ||
| * use @example AnnotationRegistry::registerLoader('class_exists') | ||
| */ | ||
| public static function registerAutoloadNamespace(string $namespace, $dirs = null) : void | ||
| { | ||
| self::$autoloadNamespaces[$namespace] = $dirs; | ||
| } | ||
|
|
||
| /** | ||
| * Registers multiple namespaces. | ||
| * | ||
| * Loading of this namespaces will be done with a PSR-0 namespace loading algorithm. | ||
| * | ||
| * @param string[][]|string[]|null[] $namespaces indexed by namespace name | ||
| * | ||
| * @deprecated this method is deprecated and will be removed in doctrine/annotations 2.0 | ||
| * autoloading should be deferred to the globally registered autoloader by then. For now, | ||
| * use @example AnnotationRegistry::registerLoader('class_exists') | ||
| */ | ||
| public static function registerAutoloadNamespaces(array $namespaces) : void | ||
| { | ||
| self::$autoloadNamespaces = \array_merge(self::$autoloadNamespaces, $namespaces); | ||
| } | ||
|
|
||
| /** | ||
| * Registers an autoloading callable for annotations, much like spl_autoload_register(). | ||
| * | ||
| * NOTE: These class loaders HAVE to be silent when a class was not found! | ||
| * IMPORTANT: Loaders have to return true if they loaded a class that could contain the searched annotation class. | ||
| * | ||
| * @deprecated this method is deprecated and will be removed in doctrine/annotations 2.0 | ||
| * autoloading should be deferred to the globally registered autoloader by then. For now, | ||
| * use @example AnnotationRegistry::registerLoader('class_exists') | ||
| */ | ||
| public static function registerLoader(callable $callable) : void | ||
| { | ||
| // Reset our static cache now that we have a new loader to work with | ||
| self::$failedToAutoload = []; | ||
| self::$loaders[] = $callable; | ||
| } | ||
|
|
||
| /** | ||
| * Registers an autoloading callable for annotations, if it is not already registered | ||
| * | ||
| * @deprecated this method is deprecated and will be removed in doctrine/annotations 2.0 | ||
| */ | ||
| public static function registerUniqueLoader(callable $callable) : void | ||
| { | ||
| if ( ! in_array($callable, self::$loaders, true) ) { | ||
| self::registerLoader($callable); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Autoloads an annotation class silently. | ||
| */ | ||
| public static function loadAnnotationClass(string $class) : bool | ||
| { | ||
| if (\class_exists($class, false)) { | ||
| return true; | ||
| } | ||
|
|
||
| if (\array_key_exists($class, self::$failedToAutoload)) { | ||
| return false; | ||
| } | ||
|
|
||
| foreach (self::$autoloadNamespaces AS $namespace => $dirs) { | ||
| if (\strpos($class, $namespace) === 0) { | ||
| $file = \str_replace('\\', \DIRECTORY_SEPARATOR, $class) . '.php'; | ||
|
|
||
| if ($dirs === null) { | ||
| if ($path = stream_resolve_include_path($file)) { | ||
| require $path; | ||
| return true; | ||
| } | ||
| } else { | ||
| foreach((array) $dirs AS $dir) { | ||
| if (is_file($dir . \DIRECTORY_SEPARATOR . $file)) { | ||
| require $dir . \DIRECTORY_SEPARATOR . $file; | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| foreach (self::$loaders AS $loader) { | ||
| if ($loader($class) === true) { | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| self::$failedToAutoload[$class] = null; | ||
|
|
||
| return false; | ||
| } | ||
| } |
| @@ -0,0 +1,262 @@ | ||
| <?php | ||
| /* | ||
| * 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. | ||
| * | ||
| * This software consists of voluntary contributions made by many individuals | ||
| * and is licensed under the MIT license. For more information, see | ||
| * <http://www.doctrine-project.org>. | ||
| */ | ||
|
|
||
| namespace Doctrine\Common\Annotations; | ||
|
|
||
| use Doctrine\Common\Cache\Cache; | ||
| use ReflectionClass; | ||
|
|
||
| /** | ||
| * A cache aware annotation reader. | ||
| * | ||
| * @author Johannes M. Schmitt <schmittjoh@gmail.com> | ||
| * @author Benjamin Eberlei <kontakt@beberlei.de> | ||
| */ | ||
| final class CachedReader implements Reader | ||
| { | ||
| /** | ||
| * @var Reader | ||
| */ | ||
| private $delegate; | ||
|
|
||
| /** | ||
| * @var Cache | ||
| */ | ||
| private $cache; | ||
|
|
||
| /** | ||
| * @var boolean | ||
| */ | ||
| private $debug; | ||
|
|
||
| /** | ||
| * @var array | ||
| */ | ||
| private $loadedAnnotations = array(); | ||
|
|
||
| /** | ||
| * Constructor. | ||
| * | ||
| * @param Reader $reader | ||
| * @param Cache $cache | ||
| * @param bool $debug | ||
| */ | ||
| public function __construct(Reader $reader, Cache $cache, $debug = false) | ||
| { | ||
| $this->delegate = $reader; | ||
| $this->cache = $cache; | ||
| $this->debug = (boolean) $debug; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getClassAnnotations(ReflectionClass $class) | ||
| { | ||
| $cacheKey = $class->getName(); | ||
|
|
||
| if (isset($this->loadedAnnotations[$cacheKey])) { | ||
| return $this->loadedAnnotations[$cacheKey]; | ||
| } | ||
|
|
||
| if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) { | ||
| $annots = $this->delegate->getClassAnnotations($class); | ||
| $this->saveToCache($cacheKey, $annots); | ||
| } | ||
|
|
||
| return $this->loadedAnnotations[$cacheKey] = $annots; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getClassAnnotation(ReflectionClass $class, $annotationName) | ||
| { | ||
| foreach ($this->getClassAnnotations($class) as $annot) { | ||
| if ($annot instanceof $annotationName) { | ||
| return $annot; | ||
| } | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getPropertyAnnotations(\ReflectionProperty $property) | ||
| { | ||
| $class = $property->getDeclaringClass(); | ||
| $cacheKey = $class->getName().'$'.$property->getName(); | ||
|
|
||
| if (isset($this->loadedAnnotations[$cacheKey])) { | ||
| return $this->loadedAnnotations[$cacheKey]; | ||
| } | ||
|
|
||
| if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) { | ||
| $annots = $this->delegate->getPropertyAnnotations($property); | ||
| $this->saveToCache($cacheKey, $annots); | ||
| } | ||
|
|
||
| return $this->loadedAnnotations[$cacheKey] = $annots; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName) | ||
| { | ||
| foreach ($this->getPropertyAnnotations($property) as $annot) { | ||
| if ($annot instanceof $annotationName) { | ||
| return $annot; | ||
| } | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getMethodAnnotations(\ReflectionMethod $method) | ||
| { | ||
| $class = $method->getDeclaringClass(); | ||
| $cacheKey = $class->getName().'#'.$method->getName(); | ||
|
|
||
| if (isset($this->loadedAnnotations[$cacheKey])) { | ||
| return $this->loadedAnnotations[$cacheKey]; | ||
| } | ||
|
|
||
| if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) { | ||
| $annots = $this->delegate->getMethodAnnotations($method); | ||
| $this->saveToCache($cacheKey, $annots); | ||
| } | ||
|
|
||
| return $this->loadedAnnotations[$cacheKey] = $annots; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getMethodAnnotation(\ReflectionMethod $method, $annotationName) | ||
| { | ||
| foreach ($this->getMethodAnnotations($method) as $annot) { | ||
| if ($annot instanceof $annotationName) { | ||
| return $annot; | ||
| } | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| /** | ||
| * Clears loaded annotations. | ||
| * | ||
| * @return void | ||
| */ | ||
| public function clearLoadedAnnotations() | ||
| { | ||
| $this->loadedAnnotations = array(); | ||
| } | ||
|
|
||
| /** | ||
| * Fetches a value from the cache. | ||
| * | ||
| * @param string $cacheKey The cache key. | ||
| * @param ReflectionClass $class The related class. | ||
| * | ||
| * @return mixed The cached value or false when the value is not in cache. | ||
| */ | ||
| private function fetchFromCache($cacheKey, ReflectionClass $class) | ||
| { | ||
| if (($data = $this->cache->fetch($cacheKey)) !== false) { | ||
| if (!$this->debug || $this->isCacheFresh($cacheKey, $class)) { | ||
| return $data; | ||
| } | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * Saves a value to the cache. | ||
| * | ||
| * @param string $cacheKey The cache key. | ||
| * @param mixed $value The value. | ||
| * | ||
| * @return void | ||
| */ | ||
| private function saveToCache($cacheKey, $value) | ||
| { | ||
| $this->cache->save($cacheKey, $value); | ||
| if ($this->debug) { | ||
| $this->cache->save('[C]'.$cacheKey, time()); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Checks if the cache is fresh. | ||
| * | ||
| * @param string $cacheKey | ||
| * @param ReflectionClass $class | ||
| * | ||
| * @return boolean | ||
| */ | ||
| private function isCacheFresh($cacheKey, ReflectionClass $class) | ||
| { | ||
| if (null === $lastModification = $this->getLastModification($class)) { | ||
| return true; | ||
| } | ||
|
|
||
| return $this->cache->fetch('[C]'.$cacheKey) >= $lastModification; | ||
| } | ||
|
|
||
| /** | ||
| * Returns the time the class was last modified, testing traits and parents | ||
| * | ||
| * @param ReflectionClass $class | ||
| * @return int | ||
| */ | ||
| private function getLastModification(ReflectionClass $class) | ||
| { | ||
| $filename = $class->getFileName(); | ||
| $parent = $class->getParentClass(); | ||
|
|
||
| return max(array_merge( | ||
| [$filename ? filemtime($filename) : 0], | ||
| array_map([$this, 'getTraitLastModificationTime'], $class->getTraits()), | ||
| array_map([$this, 'getLastModification'], $class->getInterfaces()), | ||
| $parent ? [$this->getLastModification($parent)] : [] | ||
| )); | ||
| } | ||
|
|
||
| /** | ||
| * @param ReflectionClass $reflectionTrait | ||
| * @return int | ||
| */ | ||
| private function getTraitLastModificationTime(ReflectionClass $reflectionTrait) | ||
| { | ||
| $fileName = $reflectionTrait->getFileName(); | ||
|
|
||
| return max(array_merge( | ||
| [$fileName ? filemtime($fileName) : 0], | ||
| array_map([$this, 'getTraitLastModificationTime'], $reflectionTrait->getTraits()) | ||
| )); | ||
| } | ||
| } |
| @@ -0,0 +1,134 @@ | ||
| <?php | ||
| /* | ||
| * 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. | ||
| * | ||
| * This software consists of voluntary contributions made by many individuals | ||
| * and is licensed under the MIT license. For more information, see | ||
| * <http://www.doctrine-project.org>. | ||
| */ | ||
|
|
||
| namespace Doctrine\Common\Annotations; | ||
|
|
||
| use Doctrine\Common\Lexer\AbstractLexer; | ||
|
|
||
| /** | ||
| * Simple lexer for docblock annotations. | ||
| * | ||
| * @author Benjamin Eberlei <kontakt@beberlei.de> | ||
| * @author Guilherme Blanco <guilhermeblanco@hotmail.com> | ||
| * @author Jonathan Wage <jonwage@gmail.com> | ||
| * @author Roman Borschel <roman@code-factory.org> | ||
| * @author Johannes M. Schmitt <schmittjoh@gmail.com> | ||
| */ | ||
| final class DocLexer extends AbstractLexer | ||
| { | ||
| const T_NONE = 1; | ||
| const T_INTEGER = 2; | ||
| const T_STRING = 3; | ||
| const T_FLOAT = 4; | ||
|
|
||
| // All tokens that are also identifiers should be >= 100 | ||
| const T_IDENTIFIER = 100; | ||
| const T_AT = 101; | ||
| const T_CLOSE_CURLY_BRACES = 102; | ||
| const T_CLOSE_PARENTHESIS = 103; | ||
| const T_COMMA = 104; | ||
| const T_EQUALS = 105; | ||
| const T_FALSE = 106; | ||
| const T_NAMESPACE_SEPARATOR = 107; | ||
| const T_OPEN_CURLY_BRACES = 108; | ||
| const T_OPEN_PARENTHESIS = 109; | ||
| const T_TRUE = 110; | ||
| const T_NULL = 111; | ||
| const T_COLON = 112; | ||
|
|
||
| /** | ||
| * @var array | ||
| */ | ||
| protected $noCase = array( | ||
| '@' => self::T_AT, | ||
| ',' => self::T_COMMA, | ||
| '(' => self::T_OPEN_PARENTHESIS, | ||
| ')' => self::T_CLOSE_PARENTHESIS, | ||
| '{' => self::T_OPEN_CURLY_BRACES, | ||
| '}' => self::T_CLOSE_CURLY_BRACES, | ||
| '=' => self::T_EQUALS, | ||
| ':' => self::T_COLON, | ||
| '\\' => self::T_NAMESPACE_SEPARATOR | ||
| ); | ||
|
|
||
| /** | ||
| * @var array | ||
| */ | ||
| protected $withCase = array( | ||
| 'true' => self::T_TRUE, | ||
| 'false' => self::T_FALSE, | ||
| 'null' => self::T_NULL | ||
| ); | ||
|
|
||
| /** | ||
| * {@inheritdoc} | ||
| */ | ||
| protected function getCatchablePatterns() | ||
| { | ||
| return array( | ||
| '[a-z_\\\][a-z0-9_\:\\\]*[a-z_][a-z0-9_]*', | ||
| '(?:[+-]?[0-9]+(?:[\.][0-9]+)*)(?:[eE][+-]?[0-9]+)?', | ||
| '"(?:""|[^"])*+"', | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritdoc} | ||
| */ | ||
| protected function getNonCatchablePatterns() | ||
| { | ||
| return array('\s+', '\*+', '(.)'); | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritdoc} | ||
| */ | ||
| protected function getType(&$value) | ||
| { | ||
| $type = self::T_NONE; | ||
|
|
||
| if ($value[0] === '"') { | ||
| $value = str_replace('""', '"', substr($value, 1, strlen($value) - 2)); | ||
|
|
||
| return self::T_STRING; | ||
| } | ||
|
|
||
| if (isset($this->noCase[$value])) { | ||
| return $this->noCase[$value]; | ||
| } | ||
|
|
||
| if ($value[0] === '_' || $value[0] === '\\' || ctype_alpha($value[0])) { | ||
| return self::T_IDENTIFIER; | ||
| } | ||
|
|
||
| $lowerValue = strtolower($value); | ||
|
|
||
| if (isset($this->withCase[$lowerValue])) { | ||
| return $this->withCase[$lowerValue]; | ||
| } | ||
|
|
||
| // Checking numeric value | ||
| if (is_numeric($value)) { | ||
| return (strpos($value, '.') !== false || stripos($value, 'e') !== false) | ||
| ? self::T_FLOAT : self::T_INTEGER; | ||
| } | ||
|
|
||
| return $type; | ||
| } | ||
| } |
| @@ -0,0 +1,290 @@ | ||
| <?php | ||
| /* | ||
| * 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. | ||
| * | ||
| * This software consists of voluntary contributions made by many individuals | ||
| * and is licensed under the MIT license. For more information, see | ||
| * <http://www.doctrine-project.org>. | ||
| */ | ||
|
|
||
| namespace Doctrine\Common\Annotations; | ||
|
|
||
| /** | ||
| * File cache reader for annotations. | ||
| * | ||
| * @author Johannes M. Schmitt <schmittjoh@gmail.com> | ||
| * @author Benjamin Eberlei <kontakt@beberlei.de> | ||
| * | ||
| * @deprecated the FileCacheReader is deprecated and will be removed | ||
| * in version 2.0.0 of doctrine/annotations. Please use the | ||
| * {@see \Doctrine\Common\Annotations\CachedReader} instead. | ||
| */ | ||
| class FileCacheReader implements Reader | ||
| { | ||
| /** | ||
| * @var Reader | ||
| */ | ||
| private $reader; | ||
|
|
||
| /** | ||
| * @var string | ||
| */ | ||
| private $dir; | ||
|
|
||
| /** | ||
| * @var bool | ||
| */ | ||
| private $debug; | ||
|
|
||
| /** | ||
| * @var array | ||
| */ | ||
| private $loadedAnnotations = array(); | ||
|
|
||
| /** | ||
| * @var array | ||
| */ | ||
| private $classNameHashes = array(); | ||
|
|
||
| /** | ||
| * @var int | ||
| */ | ||
| private $umask; | ||
|
|
||
| /** | ||
| * Constructor. | ||
| * | ||
| * @param Reader $reader | ||
| * @param string $cacheDir | ||
| * @param boolean $debug | ||
| * | ||
| * @throws \InvalidArgumentException | ||
| */ | ||
| public function __construct(Reader $reader, $cacheDir, $debug = false, $umask = 0002) | ||
| { | ||
| if ( ! is_int($umask)) { | ||
| throw new \InvalidArgumentException(sprintf( | ||
| 'The parameter umask must be an integer, was: %s', | ||
| gettype($umask) | ||
| )); | ||
| } | ||
|
|
||
| $this->reader = $reader; | ||
| $this->umask = $umask; | ||
|
|
||
| if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777 & (~$this->umask), true)) { | ||
| throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist and could not be created.', $cacheDir)); | ||
| } | ||
|
|
||
| $this->dir = rtrim($cacheDir, '\\/'); | ||
| $this->debug = $debug; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getClassAnnotations(\ReflectionClass $class) | ||
| { | ||
| if ( ! isset($this->classNameHashes[$class->name])) { | ||
| $this->classNameHashes[$class->name] = sha1($class->name); | ||
| } | ||
| $key = $this->classNameHashes[$class->name]; | ||
|
|
||
| if (isset($this->loadedAnnotations[$key])) { | ||
| return $this->loadedAnnotations[$key]; | ||
| } | ||
|
|
||
| $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php'; | ||
| if (!is_file($path)) { | ||
| $annot = $this->reader->getClassAnnotations($class); | ||
| $this->saveCacheFile($path, $annot); | ||
| return $this->loadedAnnotations[$key] = $annot; | ||
| } | ||
|
|
||
| if ($this->debug | ||
| && (false !== $filename = $class->getFileName()) | ||
| && filemtime($path) < filemtime($filename)) { | ||
| @unlink($path); | ||
|
|
||
| $annot = $this->reader->getClassAnnotations($class); | ||
| $this->saveCacheFile($path, $annot); | ||
| return $this->loadedAnnotations[$key] = $annot; | ||
| } | ||
|
|
||
| return $this->loadedAnnotations[$key] = include $path; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getPropertyAnnotations(\ReflectionProperty $property) | ||
| { | ||
| $class = $property->getDeclaringClass(); | ||
| if ( ! isset($this->classNameHashes[$class->name])) { | ||
| $this->classNameHashes[$class->name] = sha1($class->name); | ||
| } | ||
| $key = $this->classNameHashes[$class->name].'$'.$property->getName(); | ||
|
|
||
| if (isset($this->loadedAnnotations[$key])) { | ||
| return $this->loadedAnnotations[$key]; | ||
| } | ||
|
|
||
| $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php'; | ||
| if (!is_file($path)) { | ||
| $annot = $this->reader->getPropertyAnnotations($property); | ||
| $this->saveCacheFile($path, $annot); | ||
| return $this->loadedAnnotations[$key] = $annot; | ||
| } | ||
|
|
||
| if ($this->debug | ||
| && (false !== $filename = $class->getFilename()) | ||
| && filemtime($path) < filemtime($filename)) { | ||
| @unlink($path); | ||
|
|
||
| $annot = $this->reader->getPropertyAnnotations($property); | ||
| $this->saveCacheFile($path, $annot); | ||
| return $this->loadedAnnotations[$key] = $annot; | ||
| } | ||
|
|
||
| return $this->loadedAnnotations[$key] = include $path; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getMethodAnnotations(\ReflectionMethod $method) | ||
| { | ||
| $class = $method->getDeclaringClass(); | ||
| if ( ! isset($this->classNameHashes[$class->name])) { | ||
| $this->classNameHashes[$class->name] = sha1($class->name); | ||
| } | ||
| $key = $this->classNameHashes[$class->name].'#'.$method->getName(); | ||
|
|
||
| if (isset($this->loadedAnnotations[$key])) { | ||
| return $this->loadedAnnotations[$key]; | ||
| } | ||
|
|
||
| $path = $this->dir.'/'.strtr($key, '\\', '-').'.cache.php'; | ||
| if (!is_file($path)) { | ||
| $annot = $this->reader->getMethodAnnotations($method); | ||
| $this->saveCacheFile($path, $annot); | ||
| return $this->loadedAnnotations[$key] = $annot; | ||
| } | ||
|
|
||
| if ($this->debug | ||
| && (false !== $filename = $class->getFilename()) | ||
| && filemtime($path) < filemtime($filename)) { | ||
| @unlink($path); | ||
|
|
||
| $annot = $this->reader->getMethodAnnotations($method); | ||
| $this->saveCacheFile($path, $annot); | ||
| return $this->loadedAnnotations[$key] = $annot; | ||
| } | ||
|
|
||
| return $this->loadedAnnotations[$key] = include $path; | ||
| } | ||
|
|
||
| /** | ||
| * Saves the cache file. | ||
| * | ||
| * @param string $path | ||
| * @param mixed $data | ||
| * | ||
| * @return void | ||
| */ | ||
| private function saveCacheFile($path, $data) | ||
| { | ||
| if (!is_writable($this->dir)) { | ||
| throw new \InvalidArgumentException(sprintf('The directory "%s" is not writable. Both, the webserver and the console user need access. You can manage access rights for multiple users with "chmod +a". If your system does not support this, check out the acl package.', $this->dir)); | ||
| } | ||
|
|
||
| $tempfile = tempnam($this->dir, uniqid('', true)); | ||
|
|
||
| if (false === $tempfile) { | ||
| throw new \RuntimeException(sprintf('Unable to create tempfile in directory: %s', $this->dir)); | ||
| } | ||
|
|
||
| @chmod($tempfile, 0666 & (~$this->umask)); | ||
|
|
||
| $written = file_put_contents($tempfile, '<?php return unserialize('.var_export(serialize($data), true).');'); | ||
|
|
||
| if (false === $written) { | ||
| throw new \RuntimeException(sprintf('Unable to write cached file to: %s', $tempfile)); | ||
| } | ||
|
|
||
| @chmod($tempfile, 0666 & (~$this->umask)); | ||
|
|
||
| if (false === rename($tempfile, $path)) { | ||
| @unlink($tempfile); | ||
| throw new \RuntimeException(sprintf('Unable to rename %s to %s', $tempfile, $path)); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getClassAnnotation(\ReflectionClass $class, $annotationName) | ||
| { | ||
| $annotations = $this->getClassAnnotations($class); | ||
|
|
||
| foreach ($annotations as $annotation) { | ||
| if ($annotation instanceof $annotationName) { | ||
| return $annotation; | ||
| } | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getMethodAnnotation(\ReflectionMethod $method, $annotationName) | ||
| { | ||
| $annotations = $this->getMethodAnnotations($method); | ||
|
|
||
| foreach ($annotations as $annotation) { | ||
| if ($annotation instanceof $annotationName) { | ||
| return $annotation; | ||
| } | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName) | ||
| { | ||
| $annotations = $this->getPropertyAnnotations($property); | ||
|
|
||
| foreach ($annotations as $annotation) { | ||
| if ($annotation instanceof $annotationName) { | ||
| return $annotation; | ||
| } | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| /** | ||
| * Clears loaded annotations. | ||
| * | ||
| * @return void | ||
| */ | ||
| public function clearLoadedAnnotations() | ||
| { | ||
| $this->loadedAnnotations = array(); | ||
| } | ||
| } |
| @@ -0,0 +1,119 @@ | ||
| <?php | ||
| /* | ||
| * 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. | ||
| * | ||
| * This software consists of voluntary contributions made by many individuals | ||
| * and is licensed under the MIT license. For more information, see | ||
| * <http://www.doctrine-project.org>. | ||
| */ | ||
|
|
||
| namespace Doctrine\Common\Annotations; | ||
|
|
||
| /** | ||
| * Allows the reader to be used in-place of Doctrine's reader. | ||
| * | ||
| * @author Johannes M. Schmitt <schmittjoh@gmail.com> | ||
| */ | ||
| class IndexedReader implements Reader | ||
| { | ||
| /** | ||
| * @var Reader | ||
| */ | ||
| private $delegate; | ||
|
|
||
| /** | ||
| * Constructor. | ||
| * | ||
| * @param Reader $reader | ||
| */ | ||
| public function __construct(Reader $reader) | ||
| { | ||
| $this->delegate = $reader; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getClassAnnotations(\ReflectionClass $class) | ||
| { | ||
| $annotations = array(); | ||
| foreach ($this->delegate->getClassAnnotations($class) as $annot) { | ||
| $annotations[get_class($annot)] = $annot; | ||
| } | ||
|
|
||
| return $annotations; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getClassAnnotation(\ReflectionClass $class, $annotation) | ||
| { | ||
| return $this->delegate->getClassAnnotation($class, $annotation); | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getMethodAnnotations(\ReflectionMethod $method) | ||
| { | ||
| $annotations = array(); | ||
| foreach ($this->delegate->getMethodAnnotations($method) as $annot) { | ||
| $annotations[get_class($annot)] = $annot; | ||
| } | ||
|
|
||
| return $annotations; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getMethodAnnotation(\ReflectionMethod $method, $annotation) | ||
| { | ||
| return $this->delegate->getMethodAnnotation($method, $annotation); | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getPropertyAnnotations(\ReflectionProperty $property) | ||
| { | ||
| $annotations = array(); | ||
| foreach ($this->delegate->getPropertyAnnotations($property) as $annot) { | ||
| $annotations[get_class($annot)] = $annot; | ||
| } | ||
|
|
||
| return $annotations; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getPropertyAnnotation(\ReflectionProperty $property, $annotation) | ||
| { | ||
| return $this->delegate->getPropertyAnnotation($property, $annotation); | ||
| } | ||
|
|
||
| /** | ||
| * Proxies all methods to the delegate. | ||
| * | ||
| * @param string $method | ||
| * @param array $args | ||
| * | ||
| * @return mixed | ||
| */ | ||
| public function __call($method, $args) | ||
| { | ||
| return call_user_func_array(array($this->delegate, $method), $args); | ||
| } | ||
| } |
| @@ -0,0 +1,91 @@ | ||
| <?php | ||
| /* | ||
| * 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. | ||
| * | ||
| * This software consists of voluntary contributions made by many individuals | ||
| * and is licensed under the MIT license. For more information, see | ||
| * <http://www.doctrine-project.org>. | ||
| */ | ||
|
|
||
| namespace Doctrine\Common\Annotations; | ||
|
|
||
| use SplFileObject; | ||
|
|
||
| /** | ||
| * Parses a file for namespaces/use/class declarations. | ||
| * | ||
| * @author Fabien Potencier <fabien@symfony.com> | ||
| * @author Christian Kaps <christian.kaps@mohiva.com> | ||
| */ | ||
| final class PhpParser | ||
| { | ||
| /** | ||
| * Parses a class. | ||
| * | ||
| * @param \ReflectionClass $class A <code>ReflectionClass</code> object. | ||
| * | ||
| * @return array A list with use statements in the form (Alias => FQN). | ||
| */ | ||
| public function parseClass(\ReflectionClass $class) | ||
| { | ||
| if (method_exists($class, 'getUseStatements')) { | ||
| return $class->getUseStatements(); | ||
| } | ||
|
|
||
| if (false === $filename = $class->getFileName()) { | ||
| return array(); | ||
| } | ||
|
|
||
| $content = $this->getFileContent($filename, $class->getStartLine()); | ||
|
|
||
| if (null === $content) { | ||
| return array(); | ||
| } | ||
|
|
||
| $namespace = preg_quote($class->getNamespaceName()); | ||
| $content = preg_replace('/^.*?(\bnamespace\s+' . $namespace . '\s*[;{].*)$/s', '\\1', $content); | ||
| $tokenizer = new TokenParser('<?php ' . $content); | ||
|
|
||
| $statements = $tokenizer->parseUseStatements($class->getNamespaceName()); | ||
|
|
||
| return $statements; | ||
| } | ||
|
|
||
| /** | ||
| * Gets the content of the file right up to the given line number. | ||
| * | ||
| * @param string $filename The name of the file to load. | ||
| * @param integer $lineNumber The number of lines to read from file. | ||
| * | ||
| * @return string|null The content of the file or null if the file does not exist. | ||
| */ | ||
| private function getFileContent($filename, $lineNumber) | ||
| { | ||
| if ( ! is_file($filename)) { | ||
| return null; | ||
| } | ||
|
|
||
| $content = ''; | ||
| $lineCnt = 0; | ||
| $file = new SplFileObject($filename); | ||
| while (!$file->eof()) { | ||
| if ($lineCnt++ == $lineNumber) { | ||
| break; | ||
| } | ||
|
|
||
| $content .= $file->fgets(); | ||
| } | ||
|
|
||
| return $content; | ||
| } | ||
| } |
| @@ -0,0 +1,89 @@ | ||
| <?php | ||
| /* | ||
| * 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. | ||
| * | ||
| * This software consists of voluntary contributions made by many individuals | ||
| * and is licensed under the MIT license. For more information, see | ||
| * <http://www.doctrine-project.org>. | ||
| */ | ||
|
|
||
| namespace Doctrine\Common\Annotations; | ||
|
|
||
| /** | ||
| * Interface for annotation readers. | ||
| * | ||
| * @author Johannes M. Schmitt <schmittjoh@gmail.com> | ||
| */ | ||
| interface Reader | ||
| { | ||
| /** | ||
| * Gets the annotations applied to a class. | ||
| * | ||
| * @param \ReflectionClass $class The ReflectionClass of the class from which | ||
| * the class annotations should be read. | ||
| * | ||
| * @return array An array of Annotations. | ||
| */ | ||
| function getClassAnnotations(\ReflectionClass $class); | ||
|
|
||
| /** | ||
| * Gets a class annotation. | ||
| * | ||
| * @param \ReflectionClass $class The ReflectionClass of the class from which | ||
| * the class annotations should be read. | ||
| * @param string $annotationName The name of the annotation. | ||
| * | ||
| * @return object|null The Annotation or NULL, if the requested annotation does not exist. | ||
| */ | ||
| function getClassAnnotation(\ReflectionClass $class, $annotationName); | ||
|
|
||
| /** | ||
| * Gets the annotations applied to a method. | ||
| * | ||
| * @param \ReflectionMethod $method The ReflectionMethod of the method from which | ||
| * the annotations should be read. | ||
| * | ||
| * @return array An array of Annotations. | ||
| */ | ||
| function getMethodAnnotations(\ReflectionMethod $method); | ||
|
|
||
| /** | ||
| * Gets a method annotation. | ||
| * | ||
| * @param \ReflectionMethod $method The ReflectionMethod to read the annotations from. | ||
| * @param string $annotationName The name of the annotation. | ||
| * | ||
| * @return object|null The Annotation or NULL, if the requested annotation does not exist. | ||
| */ | ||
| function getMethodAnnotation(\ReflectionMethod $method, $annotationName); | ||
|
|
||
| /** | ||
| * Gets the annotations applied to a property. | ||
| * | ||
| * @param \ReflectionProperty $property The ReflectionProperty of the property | ||
| * from which the annotations should be read. | ||
| * | ||
| * @return array An array of Annotations. | ||
| */ | ||
| function getPropertyAnnotations(\ReflectionProperty $property); | ||
|
|
||
| /** | ||
| * Gets a property annotation. | ||
| * | ||
| * @param \ReflectionProperty $property The ReflectionProperty to read the annotations from. | ||
| * @param string $annotationName The name of the annotation. | ||
| * | ||
| * @return object|null The Annotation or NULL, if the requested annotation does not exist. | ||
| */ | ||
| function getPropertyAnnotation(\ReflectionProperty $property, $annotationName); | ||
| } |
| @@ -0,0 +1,127 @@ | ||
| <?php | ||
| /* | ||
| * 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. | ||
| * | ||
| * This software consists of voluntary contributions made by many individuals | ||
| * and is licensed under the MIT license. For more information, see | ||
| * <http://www.doctrine-project.org>. | ||
| */ | ||
|
|
||
| namespace Doctrine\Common\Annotations; | ||
|
|
||
| /** | ||
| * Simple Annotation Reader. | ||
| * | ||
| * This annotation reader is intended to be used in projects where you have | ||
| * full-control over all annotations that are available. | ||
| * | ||
| * @since 2.2 | ||
| * @author Johannes M. Schmitt <schmittjoh@gmail.com> | ||
| * @author Fabio B. Silva <fabio.bat.silva@gmail.com> | ||
| */ | ||
| class SimpleAnnotationReader implements Reader | ||
| { | ||
| /** | ||
| * @var DocParser | ||
| */ | ||
| private $parser; | ||
|
|
||
| /** | ||
| * Constructor. | ||
| * | ||
| * Initializes a new SimpleAnnotationReader. | ||
| */ | ||
| public function __construct() | ||
| { | ||
| $this->parser = new DocParser(); | ||
| $this->parser->setIgnoreNotImportedAnnotations(true); | ||
| } | ||
|
|
||
| /** | ||
| * Adds a namespace in which we will look for annotations. | ||
| * | ||
| * @param string $namespace | ||
| * | ||
| * @return void | ||
| */ | ||
| public function addNamespace($namespace) | ||
| { | ||
| $this->parser->addNamespace($namespace); | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getClassAnnotations(\ReflectionClass $class) | ||
| { | ||
| return $this->parser->parse($class->getDocComment(), 'class '.$class->getName()); | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getMethodAnnotations(\ReflectionMethod $method) | ||
| { | ||
| return $this->parser->parse($method->getDocComment(), 'method '.$method->getDeclaringClass()->name.'::'.$method->getName().'()'); | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getPropertyAnnotations(\ReflectionProperty $property) | ||
| { | ||
| return $this->parser->parse($property->getDocComment(), 'property '.$property->getDeclaringClass()->name.'::$'.$property->getName()); | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getClassAnnotation(\ReflectionClass $class, $annotationName) | ||
| { | ||
| foreach ($this->getClassAnnotations($class) as $annot) { | ||
| if ($annot instanceof $annotationName) { | ||
| return $annot; | ||
| } | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getMethodAnnotation(\ReflectionMethod $method, $annotationName) | ||
| { | ||
| foreach ($this->getMethodAnnotations($method) as $annot) { | ||
| if ($annot instanceof $annotationName) { | ||
| return $annot; | ||
| } | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName) | ||
| { | ||
| foreach ($this->getPropertyAnnotations($property) as $annot) { | ||
| if ($annot instanceof $annotationName) { | ||
| return $annot; | ||
| } | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
| } |