Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Added the support of wildcard in ignore annotation (addGlobalIgnoredName) #156

Closed
wants to merge 2 commits into from

5 participants

Enrico Zimuel Marco Pivetta Matthew Weier O'Phinney Johannes Christophe Coevoet
Enrico Zimuel

Using the addGlobalIgnoredName() of the AnnotationReader we can specify annotation tags that should not be considered by Doctrine. The ignored tags must be specified as strings. If we have tags specified by namespace we need to list all the possible sub-namespaces in addGlobalIgnoredName().

This PR add the support of wildcard in addGlobalIgnoredName(), for instance you can specify to ignore all the sub-namespaces of an annotation tag using the "*" syntax:
use Doctrine\Common\Annotations\AnnotationReader;
$reader = new AnnotationReader();
AnnotationReader::addGlobalIgnoredName('Foo\*');
This example will exclude all the Foo annotation tag and all the sub-namespaces.
Here you can find a complete example on how to use it: https://gist.github.com/2972974

I think this PR can be useful to continue to use the annotation of Doctrine with other PHP projects that use different annotation systems. Please note that the PR take care about the parsing performance of Doctrine, the wildcard syntax is activated only if there are annotations specified.

Marco Pivetta
Owner

Apart of the CS issues, which I'll eventually comment later, I would first like to see if the approach of re-introducing the "ignore non imported annotations" has a better feedback. Let's keep this hanging at least till next week :)

Otherwise, the PR's functionality is ok imo :)

Matthew Weier O'Phinney

@ocramius I had @ezimuel go this approach initially as it's the documented approach for whitelisting annotations within Doctrine -- wildcard seemed a good extension of that idea. The problem I see with the "ignore non-imported annotations" is that it can mean typos in annotations leads to the parser silently ignoring something you've written; at least with the whitelist, you'll still get exceptions raised for anything not on the whitelist.

Marco Pivetta
Owner

@weierophinney yeah, as I've already told Enrico on IRC I like this one :)

Johannes
Collaborator

This only works for the top level namespace, no?

Marco Pivetta
Owner

@schmittjoh seems like that

Christophe Coevoet stof commented on the diff
lib/Doctrine/Common/Annotations/AnnotationReader.php
@@ -71,12 +71,22 @@
);
/**
+ * Specify to ignore wildcard namespace (*) in annotation
+ *
+ * @var boolean
+ */
+ private static $ignoreWildcardNamespace = true;
Christophe Coevoet Collaborator
stof added a note

the naming is crappy. According to the implementation, it will be set to false to ignore them, and to true to disable the feature.

Marco Pivetta Owner

@stof skip it for now :)

Christophe Coevoet Collaborator
stof added a note

well, in fact, you should probably keep the name, but change the case where you use true and false

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Christophe Coevoet stof commented on the diff
lib/Doctrine/Common/Annotations/AnnotationReader.php
@@ -145,7 +155,8 @@ public function getClassAnnotations(ReflectionClass $class)
$this->parser->setTarget(Target::TARGET_CLASS);
$this->parser->setImports($this->getImports($class));
$this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class));
-
+ $this->parser->setIgnoreWildcardNamespace(self::$ignoreWildcardNamespace);
+
Christophe Coevoet Collaborator
stof added a note

please don't add trailing whitespaces

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
...trine/Tests/Common/Annotations/AbstractReaderTest.php
@@ -326,6 +326,21 @@ public function testInvalidAnnotationButIgnored()
$this->assertCount(0, $reader->getPropertyAnnotations($class->getProperty('foo')));
}
+ public function testSupportWildcardIgnoredAnnotation()
+ {
+ $reader = $this->getReader();
+ AnnotationReader::addGlobalIgnoredName('Foo\\*');
+
+ $class = new \ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\IgnoreAnnotationWithWildcard');
+ $annots = $reader->getClassAnnotations($class);
+
+ if (!empty($annots)) {
+ $this->assertEquals('foo', $annots[0]->bar);
+ } else {
+ $this->markTestSkipped('Skipped support wildcard ignored annotation');
Christophe Coevoet Collaborator
stof added a note

I don't understand why you have a test skipped conditionally here

Enrico Zimuel
ezimuel added a note

Sorry, I forgot to remove this code, this was a test. I fixed it and moved this test in AnnotationReaderTest.php instead of AbstractReaderTest.php.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Christophe Coevoet
Collaborator

I also vote :+1: for this approach, which is better than disabling the validation of annotation when using external libraries.

Marco Pivetta Ocramius referenced this pull request in zendframework/zf2
Closed

[WIP] - Reuse doctrine common annotations #1581

Johannes
Collaborator

I'd like to add a separate map with ignored namespaces instead of adding this to the names section and a flag.

This would also better allow to validate that not something like Foo\Bar\* is passed which would not work. Also be aware that the check is currently done on the name as it is used in the file, not the actually resolved class name.


use Foo\Bar as Baz;

/** @Baz\Annotation */
class MyClass { }

AnnotationReader::addGlobalIgnoredName('Foo\\*'); // would not ignore above annotation
Christophe Coevoet
Collaborator

@schmittjoh currently, ignored annotations also apply on the unresolved name AFAIK

Johannes
Collaborator

@stof, yes, that is intended, but this feature is a bit different.

Marco Pivetta
Owner

If this is still needed, we should rather move it to https://github.com/doctrine/annotations

Marco Pivetta Ocramius closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
13 lib/Doctrine/Common/Annotations/AnnotationReader.php
View
@@ -71,12 +71,22 @@
);
/**
+ * Specify to ignore wildcard namespace (*) in annotation
+ *
+ * @var boolean
+ */
+ private static $ignoreWildcardNamespace = true;
Christophe Coevoet Collaborator
stof added a note

the naming is crappy. According to the implementation, it will be set to false to ignore them, and to true to disable the feature.

Marco Pivetta Owner

@stof skip it for now :)

Christophe Coevoet Collaborator
stof added a note

well, in fact, you should probably keep the name, but change the case where you use true and false

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+
+ /**
* Add a new annotation to the globally ignored annotation names with regard to exception handling.
*
* @param string $name
*/
static public function addGlobalIgnoredName($name)
{
+ if (self::$ignoreWildcardNamespace && false !== strpos($name, '\\*')) {
+ self::$ignoreWildcardNamespace = false;
+ }
self::$globalIgnoredNames[$name] = true;
}
@@ -145,7 +155,8 @@ public function getClassAnnotations(ReflectionClass $class)
$this->parser->setTarget(Target::TARGET_CLASS);
$this->parser->setImports($this->getImports($class));
$this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class));
-
+ $this->parser->setIgnoreWildcardNamespace(self::$ignoreWildcardNamespace);
+
Christophe Coevoet Collaborator
stof added a note

please don't add trailing whitespaces

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
return $this->parser->parse($class->getDocComment(), 'class ' . $class->getName());
}
24 lib/Doctrine/Common/Annotations/DocParser.php
View
@@ -115,6 +115,13 @@
private $ignoredAnnotationNames = array();
/**
+ * Specify to ignore wildcard namespace (*) in annotation
+ *
+ * @var boolean
+ */
+ private $ignoreWildcardNamespace = true;
+
+ /**
* @var string
*/
private $context = '';
@@ -224,6 +231,16 @@ public function setIgnoredAnnotationNames(array $names)
}
/**
+ * Sets ignore wildcard namespace in annotation
+ *
+ * @param boolean $bool
+ */
+ public function setIgnoreWildcardNamespace ($bool)
+ {
+ $this->ignoreWildcardNamespace = (Boolean) $bool;
+ }
+
+ /**
* Sets ignore on not-imported annotations
*
* @param $bool
@@ -588,7 +605,12 @@ private function Annotation()
if ($this->ignoreNotImportedAnnotations || isset($this->ignoredAnnotationNames[$name])) {
return false;
}
-
+ if (!$this->ignoreWildcardNamespace) {
+ $namespace = explode('\\', $name, 2);
+ if (isset($this->ignoredAnnotationNames[$namespace[0].'\\*'])) {
+ return false;
+ }
+ }
throw AnnotationException::semanticalError(sprintf('The annotation "@%s" in %s was never imported. Did you maybe forget to add a "use" statement for this annotation?', $name, $this->context));
}
}
2  tests/Doctrine/Tests/Common/Annotations/AbstractReaderTest.php
View
@@ -325,7 +325,7 @@ public function testInvalidAnnotationButIgnored()
$this->assertCount(0, $reader->getMethodAnnotations($class->getMethod('bar')));
$this->assertCount(0, $reader->getPropertyAnnotations($class->getProperty('foo')));
}
-
+
abstract protected function getReader();
}
12 tests/Doctrine/Tests/Common/Annotations/AnnotationReaderTest.php
View
@@ -10,4 +10,16 @@ protected function getReader()
{
return new AnnotationReader();
}
+
+ public function testSupportWildcardIgnoredAnnotation()
+ {
+ $reader = $this->getReader();
+ AnnotationReader::addGlobalIgnoredName('Foo\\*');
+
+ $class = new \ReflectionClass('Doctrine\Tests\Common\Annotations\Fixtures\IgnoreAnnotationWithWildcard');
+ $annots = $reader->getClassAnnotations($class);
+
+ $this->assertEquals('foo', $annots[0]->bar);
+ $this->assertEquals('bar', $annots[1]->foo);
+ }
}
34 tests/Doctrine/Tests/Common/Annotations/Fixtures/IgnoreAnnotationWithWildcard.php
View
@@ -0,0 +1,34 @@
+<?php
+
+namespace MyCompany\Annotations {
+ /**
+ * @Annotation
+ */
+ class Foo
+ {
+ public $bar;
+ }
+
+ /**
+ * @Annotation
+ */
+ class Bar
+ {
+ public $foo;
+ }
+}
+
+namespace Doctrine\Tests\Common\Annotations\Fixtures {
+
+
+ /**
+ * @MyCompany\Annotations\Foo(bar="foo")
+ * @MyCompany\Annotations\Bar(foo="bar")
+ * @Foo\Bar
+ * @Foo\Bar\Baz
+ */
+ class IgnoreAnnotationWithWildcard
+ {
+
+ }
+}
Something went wrong with that request. Please try again.