Collects parsing metadata for a given annotation class
string $name The annotation name:
private function collectAnnotationMetadata($name) {
if (self::$metadataParser == null) {
self::$metadataParser = new self();
self::$metadataParser
->setTarget(Target::TARGET_CLASS);
self::$metadataParser
->setIgnoreNotImportedAnnotations(true);
self::$metadataParser
->setImports(array(
'target' => 'Doctrine\\Common\\Annotations\\Annotation\\Target',
'attribute' => 'Doctrine\\Common\\Annotations\\Annotation\\Attribute',
'attributes' => 'Doctrine\\Common\\Annotations\\Annotation\\Attributes',
));
AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Target.php');
AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Attribute.php');
AnnotationRegistry::registerFile(__DIR__ . '/Annotation/Attributes.php');
}
$class = new \ReflectionClass($name);
$docComment = $class
->getDocComment();
// Sets default values for annotation metadata
$metadata = array(
'default_property' => null,
'has_constructor' => null !== ($constructor = $class
->getConstructor()) && $constructor
->getNumberOfParameters() > 0,
'properties' => array(),
'property_types' => array(),
'attribute_types' => array(),
'targets_literal' => null,
'targets' => Target::TARGET_ALL,
'is_annotation' => false !== strpos($docComment, '@Annotation'),
);
// verify that the class is really meant to be an annotation
if ($metadata['is_annotation']) {
foreach (self::$metadataParser
->parse($docComment, 'class @' . $name) as $annotation) {
if ($annotation instanceof Target) {
$metadata['targets'] = $annotation->targets;
$metadata['targets_literal'] = $annotation->literal;
}
elseif ($annotation instanceof Attributes) {
foreach ($annotation->value as $attrib) {
// handle internal type declaration
$type = isset(self::$typeMap[$attrib->type]) ? self::$typeMap[$attrib->type] : $attrib->type;
// handle the case if the property type is mixed
if ('mixed' !== $type) {
// Checks if the property has array<type>
if (false !== ($pos = strpos($type, '<'))) {
$arrayType = substr($type, $pos + 1, -1);
$type = 'array';
if (isset(self::$typeMap[$arrayType])) {
$arrayType = self::$typeMap[$arrayType];
}
$metadata['attribute_types'][$attrib->name]['array_type'] = $arrayType;
}
$metadata['attribute_types'][$attrib->name]['type'] = $type;
$metadata['attribute_types'][$attrib->name]['value'] = $attrib->type;
$metadata['attribute_types'][$attrib->name]['required'] = $attrib->required;
}
}
}
}
// if not has a constructor will inject values into public properties
if (false === $metadata['has_constructor']) {
// collect all public properties
foreach ($class
->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
$metadata['properties'][$property->name] = $property->name;
// checks if the property has @var annotation
if (false !== ($propertyComment = $property
->getDocComment()) && false !== strpos($propertyComment, '@var') && preg_match('/@var\\s+([^\\s]+)/', $propertyComment, $matches)) {
// literal type declaration
$value = $matches[1];
// handle internal type declaration
$type = isset(self::$typeMap[$value]) ? self::$typeMap[$value] : $value;
// handle the case if the property type is mixed
if ('mixed' !== $type) {
// Checks if the property has @var array<type> annotation
if (false !== ($pos = strpos($type, '<'))) {
$arrayType = substr($type, $pos + 1, -1);
$type = 'array';
if (isset(self::$typeMap[$arrayType])) {
$arrayType = self::$typeMap[$arrayType];
}
$metadata['attribute_types'][$property->name]['array_type'] = $arrayType;
}
$metadata['attribute_types'][$property->name]['type'] = $type;
$metadata['attribute_types'][$property->name]['value'] = $value;
$metadata['attribute_types'][$property->name]['required'] = false !== strpos($propertyComment, '@Required');
}
}
}
// choose the first property as default property
$metadata['default_property'] = reset($metadata['properties']);
}
}
self::$annotationMetadata[$name] = $metadata;
}