Commit e35e083e authored by catch's avatar catch

Issue #1848570 by Xano: Upgrade to Doctrine\Common 2.4.

parent eaacc4e6
This diff is collapsed.
......@@ -4,4 +4,4 @@
require_once __DIR__ . '/composer' . '/autoload_real.php';
return ComposerAutoloaderInit4ae4005bb4ec82f3372265feb7e84f37::getLoader();
return ComposerAutoloaderInitae9396db2008f9b266cde1fb85dfa4f8::getLoader();
......@@ -32,6 +32,11 @@
'Drupal\\Driver' => array($baseDir . '/drivers/lib'),
'Drupal\\Core' => array($baseDir . '/core/lib'),
'Drupal\\Component' => array($baseDir . '/core/lib'),
'Doctrine\\Common' => array($vendorDir . '/doctrine/common/lib'),
'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/lib'),
'Doctrine\\Common\\Inflector\\' => array($vendorDir . '/doctrine/inflector/lib'),
'Doctrine\\Common\\Collections\\' => array($vendorDir . '/doctrine/collections/lib'),
'Doctrine\\Common\\Cache\\' => array($vendorDir . '/doctrine/cache/lib'),
'Doctrine\\Common\\Annotations\\' => array($vendorDir . '/doctrine/annotations/lib'),
'Doctrine\\Common\\' => array($vendorDir . '/doctrine/common/lib'),
'Assetic' => array($vendorDir . '/kriswallsmith/assetic/src'),
);
......@@ -2,7 +2,7 @@
// autoload_real.php generated by Composer
class ComposerAutoloaderInit4ae4005bb4ec82f3372265feb7e84f37
class ComposerAutoloaderInitae9396db2008f9b266cde1fb85dfa4f8
{
private static $loader;
......@@ -19,9 +19,9 @@ public static function getLoader()
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit4ae4005bb4ec82f3372265feb7e84f37', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInitae9396db2008f9b266cde1fb85dfa4f8', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit4ae4005bb4ec82f3372265feb7e84f37', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInitae9396db2008f9b266cde1fb85dfa4f8', 'loadClassLoader'));
$vendorDir = dirname(__DIR__);
$baseDir = dirname(dirname($vendorDir));
......
This diff is collapsed.
language: php
php:
- 5.3
- 5.4
before_script:
- composer --prefer-source --dev install
- phpunit
# Doctrine Annotations
[![Build Status](https://travis-ci.org/doctrine/annotations.png?branch=master)](https://travis-ci.org/doctrine/annotations)
Docblock Annotations Parser library (extracted from Doctrine Common).
## Changelog
### v1.1
* Add Exception when ZendOptimizer+ or Opcache is configured to drop comments
{
"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": ">=5.3.2",
"doctrine/lexer": "1.*"
},
"require-dev": {
"doctrine/cache": "1.*"
},
"autoload": {
"psr-0": { "Doctrine\\Common\\Annotations\\": "lib/" }
},
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
}
}
<?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 construct
*
* @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'];
}
}
\ No newline at end of file
......@@ -124,4 +124,35 @@ public static function requiredError($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)
{
throw 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()
{
throw new self("You have to enable opcache.save_comments=1 or zend_optimizerplus.save_comments=1.");
}
}
......@@ -60,7 +60,7 @@ class AnnotationReader implements Reader
'subpackage'=> true, 'name'=> true, 'global'=> true, 'param'=> true,
'return'=> true, 'staticvar'=> true, 'category'=> true, 'staticVar'=> true,
'static'=> true, 'var'=> true, 'throws'=> true, 'inheritdoc'=> true,
'inheritDoc'=> true, 'license'=> true, 'todo'=> true,
'inheritDoc'=> true, 'license'=> true, 'todo'=> true, 'TODO'=> true,
'deprec'=> true, 'property' => true, 'method' => true,
'abstract'=> true, 'exception'=> true, 'magic' => true, 'api' => true,
'final'=> true, 'filesource'=> true, 'throw' => true, 'uses' => true,
......@@ -69,7 +69,7 @@ class AnnotationReader implements Reader
'Required' => true, 'Attribute' => true, 'Attributes' => true,
'Target' => true, 'SuppressWarnings' => true,
'ingroup' => true, 'code' => true, 'endcode' => true,
'package_version' => true,
'package_version' => true, 'fixme' => true
);
/**
......@@ -124,6 +124,14 @@ static public function addGlobalIgnoredName($name)
*/
public function __construct()
{
if (extension_loaded('Zend Optimizer+') && (ini_get('zend_optimizerplus.save_comments') === "0" || ini_get('opcache.save_comments') === "0")) {
throw AnnotationException::optimizerPlusSaveComments();
}
if (extension_loaded('opcache') && ini_get('opcache.save_comments') == 0) {
throw AnnotationException::optimizerPlusSaveComments();
}
AnnotationRegistry::registerFile(__DIR__ . '/Annotation/IgnoreAnnotation.php');
$this->parser = new DocParser;
......
......@@ -120,7 +120,7 @@ static public function loadAnnotationClass($class)
}
} else {
foreach((array)$dirs AS $dir) {
if (file_exists($dir . DIRECTORY_SEPARATOR . $file)) {
if (is_file($dir . DIRECTORY_SEPARATOR . $file)) {
require $dir . DIRECTORY_SEPARATOR . $file;
return true;
}
......
......@@ -19,7 +19,7 @@
namespace Doctrine\Common\Annotations;
use Doctrine\Common\Lexer;
use Doctrine\Common\Lexer\AbstractLexer;
/**
* Simple lexer for docblock annotations.
......@@ -30,7 +30,7 @@
* @author Roman Borschel <roman@code-factory.org>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
*/
final class DocLexer extends Lexer
final class DocLexer extends AbstractLexer
{
const T_NONE = 1;
const T_INTEGER = 2;
......
......@@ -21,6 +21,7 @@
use Closure;
use ReflectionClass;
use Doctrine\Common\Annotations\Annotation\Enum;
use Doctrine\Common\Annotations\Annotation\Target;
use Doctrine\Common\Annotations\Annotation\Attribute;
use Doctrine\Common\Annotations\Annotation\Attributes;
......@@ -187,6 +188,26 @@ final class DocParser
)
),
),
'Doctrine\Common\Annotations\Annotation\Enum' => array(
'is_annotation' => true,
'has_constructor' => true,
'targets_literal' => 'ANNOTATION_PROPERTY',
'targets' => Target::TARGET_PROPERTY,
'default_property' => 'value',
'properties' => array(
'value' => 'value'
),
'attribute_types' => array(
'value' => array(
'type' => 'array',
'required' => true,
),
'literal' => array(
'type' => 'array',
'required' => false,
),
),
),
);
/**
......@@ -393,13 +414,15 @@ private function collectAnnotationMetadata($name)
{
if (self::$metadataParser == null){
self::$metadataParser = new self();
self::$metadataParser->setTarget(Target::TARGET_CLASS);
self::$metadataParser->setIgnoreNotImportedAnnotations(true);
self::$metadataParser->setIgnoredAnnotationNames($this->ignoredAnnotationNames);
self::$metadataParser->setImports(array(
'enum' => 'Doctrine\Common\Annotations\Annotation\Enum',
'target' => 'Doctrine\Common\Annotations\Annotation\Target',
'attribute' => 'Doctrine\Common\Annotations\Annotation\Attribute',
'attributes' => 'Doctrine\Common\Annotations\Annotation\Attributes'
));
AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Enum.php');
AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Target.php');
AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Attribute.php');
AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Attributes.php');
......@@ -422,6 +445,9 @@ private function collectAnnotationMetadata($name)
// verify that the class is really meant to be an annotation
if ($metadata['is_annotation']) {
self::$metadataParser->setTarget(Target::TARGET_CLASS);
foreach (self::$metadataParser->parse($docComment, 'class @' . $name) as $annotation) {
if ($annotation instanceof Target) {
$metadata['targets'] = $annotation->targets;
......@@ -459,10 +485,13 @@ private function collectAnnotationMetadata($name)
// collect all public properties
foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
$metadata['properties'][$property->name] = $property->name;
if(false === ($propertyComment = $property->getDocComment())) {
continue;
}
// checks if the property has @var annotation
if ((false !== $propertyComment = $property->getDocComment())
&& false !== strpos($propertyComment, '@var')
if (false !== strpos($propertyComment, '@var')
&& preg_match('/@var\s+([^\s]+)/',$propertyComment, $matches)) {
// literal type declaration
$value = $matches[1];
......@@ -489,6 +518,20 @@ private function collectAnnotationMetadata($name)
$metadata['attribute_types'][$property->name]['required'] = false !== strpos($propertyComment, '@Required');
}
}
// checks if the property has @Enum
if (false !== strpos($propertyComment, '@Enum')){
$context = 'property ' . $class->name . "::\$" . $property->name;
self::$metadataParser->setTarget(Target::TARGET_PROPERTY);
foreach (self::$metadataParser->parse($propertyComment, $context) as $annotation) {
if($annotation instanceof Enum) {
$metadata['enum'][$property->name]['value'] = $annotation->value;
$metadata['enum'][$property->name]['literal'] = ! empty($annotation->literal) ? $annotation->literal : $annotation->value;
}
}
}
}
// choose the first property as default property
......@@ -641,6 +684,16 @@ private function Annotation()
$this->match(DocLexer::T_CLOSE_PARENTHESIS);
}
if (isset(self::$annotationMetadata[$name]['enum'])) {
// checks all declared attributes
foreach (self::$annotationMetadata[$name]['enum'] as $property => $enum) {
// checks if the attribute is a valid enumerator
if (isset($values[$property]) && ! in_array($values[$property], $enum['value'])) {
throw AnnotationException::enumeratorError($property, $name, $this->context, $enum['literal'], $values[$property]);
}
}
}
// checks all declared attributes
foreach (self::$annotationMetadata[$name]['attribute_types'] as $property => $type) {
if ($property === self::$annotationMetadata[$name]['default_property']
......@@ -659,7 +712,7 @@ private function Annotation()
if ($type['type'] === 'array') {
// handle the case of a single value
if (!is_array($values[$property])) {
if ( ! is_array($values[$property])) {
$values[$property] = array($values[$property]);
}
......@@ -929,6 +982,14 @@ private function Arrayx()
$array = $values = array();
$this->match(DocLexer::T_OPEN_CURLY_BRACES);
// If the array is empty, stop parsing and return.
if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) {
$this->match(DocLexer::T_CLOSE_CURLY_BRACES);
return $array;
}
$values[] = $this->ArrayEntry();
while ($this->lexer->isNextToken(DocLexer::T_COMMA)) {
......
......@@ -48,6 +48,8 @@ class FileCacheReader implements Reader
*/
private $loadedAnnotations = array();
private $classNameHashes = array();
/**
* Constructor
*
......@@ -79,14 +81,17 @@ public function __construct(Reader $reader, $cacheDir, $debug = false)
*/
public function getClassAnnotations(\ReflectionClass $class)
{
$key = $class->getName();
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 (!file_exists($path)) {
if (!is_file($path)) {
$annot = $this->reader->getClassAnnotations($class);
$this->saveCacheFile($path, $annot);
return $this->loadedAnnotations[$key] = $annot;
......@@ -114,14 +119,17 @@ public function getClassAnnotations(\ReflectionClass $class)
public function getPropertyAnnotations(\ReflectionProperty $property)
{
$class = $property->getDeclaringClass();
$key = $class->getName().'$'.$property->getName();
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 (!file_exists($path)) {
if (!is_file($path)) {
$annot = $this->reader->getPropertyAnnotations($property);
$this->saveCacheFile($path, $annot);
return $this->loadedAnnotations[$key] = $annot;
......@@ -130,7 +138,7 @@ public function getPropertyAnnotations(\ReflectionProperty $property)
if ($this->debug
&& (false !== $filename = $class->getFilename())
&& filemtime($path) < filemtime($filename)) {
unlink($path);
@unlink($path);
$annot = $this->reader->getPropertyAnnotations($property);
$this->saveCacheFile($path, $annot);
......@@ -149,14 +157,17 @@ public function getPropertyAnnotations(\ReflectionProperty $property)
public function getMethodAnnotations(\ReflectionMethod $method)
{
$class = $method->getDeclaringClass();
$key = $class->getName().'#'.$method->getName();
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 (!file_exists($path)) {
if (!is_file($path)) {
$annot = $this->reader->getMethodAnnotations($method);
$this->saveCacheFile($path, $annot);
return $this->loadedAnnotations[$key] = $annot;
......@@ -165,7 +176,7 @@ public function getMethodAnnotations(\ReflectionMethod $method)
if ($this->debug
&& (false !== $filename = $class->getFilename())
&& filemtime($path) < filemtime($filename)) {
unlink($path);
@unlink($path);
$annot = $this->reader->getMethodAnnotations($method);
$this->saveCacheFile($path, $annot);
......
......@@ -46,7 +46,12 @@ public function parseClass(\ReflectionClass $class)
}
$content = $this->getFileContent($filename, $class->getStartLine());
$namespace = str_replace('\\', '\\\\', $class->getNamespaceName());
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);
......@@ -64,6 +69,10 @@ public function parseClass(\ReflectionClass $class)
*/
private function getFileContent($filename, $lineNumber)
{
if ( ! is_file($filename)) {
return null;
}
$content = '';
$lineCnt = 0;
$file = new SplFileObject($filename);
......
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"