1
0
mirror of synced 2024-12-15 07:36:03 +03:00
doctrine2/lib/Doctrine/ORM/Mapping/Driver/addendum/annotations.php

336 lines
11 KiB
PHP
Raw Normal View History

<?php
/**
* Addendum PHP Reflection Annotations
* http://code.google.com/p/addendum/
*
* Copyright (C) 2006 Jan "johno Suchal <johno@jsmf.net>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
**/
require_once(dirname(__FILE__).'/annotations/annotation_parser.php');
class Annotation {
public $value;
public final function __construct($data, $target) {
$reflection = new ReflectionClass($this);
foreach($data as $key => $value) {
if($reflection->hasProperty($key)) {
$this->$key = $value;
} else {
$class = $reflection->getName();
trigger_error("Property '$key' not defined for annotation '$class'");
}
}
$this->checkTargetConstraints($target);
$this->checkConstraints($target);
}
private function checkTargetConstraints($target) {
$reflection = new ReflectionAnnotatedClass($this);
if($reflection->hasAnnotation('Target')) {
$value = $reflection->getAnnotation('Target')->value;
$values = is_array($value) ? $value : array($value);
foreach($values as $value) {
if($value == 'class' && $target instanceof ReflectionClass) return;
if($value == 'method' && $target instanceof ReflectionMethod) return;
if($value == 'property' && $target instanceof ReflectionProperty) return;
}
trigger_error("Annotation '".get_class($this)."' not allowed on ".$this->createName($target), E_USER_ERROR);
}
}
private function createName($target) {
if($target instanceof ReflectionMethod) {
return $target->getDeclaringClass()->getName().'::'.$target->getName();
} elseif($target instanceof ReflectionProperty) {
return $target->getDeclaringClass()->getName().'::$'.$target->getName();
} else {
return $target->getName();
}
}
protected function checkConstraints($target) {}
}
class Target extends Annotation {}
class AnnotationsBuilder {
private static $cache = array();
public function build($targetReflection) {
$data = $this->parse($targetReflection);
$annotations = array();
foreach($data as $class => $parameters) {
if(is_subclass_of($class, 'Annotation')) {
foreach($parameters as $params) {
$annotationReflection = new ReflectionClass($class);
$annotations[$class][] = $annotationReflection->newInstance($params, $targetReflection);
}
}
}
return $annotations;
}
private function parse($reflection) {
$key = $this->createName($reflection);
if(!isset(self::$cache[$key])) {
$parser = new AnnotationsMatcher;
$parser->matches($this->getDocComment($reflection), $data);
self::$cache[$key] = $data;
}
return self::$cache[$key];
}
private function createName($target) {
if($target instanceof ReflectionMethod) {
return $target->getDeclaringClass()->getName().'::'.$target->getName();
} elseif($target instanceof ReflectionProperty) {
return $target->getDeclaringClass()->getName().'::$'.$target->getName();
} else {
return $target->getName();
}
}
protected function getDocComment($reflection) {
return Addendum::getDocComment($reflection);
}
public static function clearCache() {
self::$cache = array();
}
}
class ReflectionAnnotatedClass extends ReflectionClass {
private $annotations;
public function __construct($class) {
parent::__construct($class);
$this->annotations = $this->createAnnotationBuilder()->build($this);
}
public function hasAnnotation($annotation) {
return isset($this->annotations[$annotation]);
}
public function getAnnotation($annotation) {
return $this->hasAnnotation($annotation) ? end($this->annotations[$annotation]) : false;
}
public function getAnnotations() {
$result = array();
foreach($this->annotations as $instances) {
$result[] = end($instances);
}
return $result;
}
public function getAllAnnotations($restriction = false) {
$result = array();
foreach($this->annotations as $class => $instances) {
if(!$restriction || $restriction == $class) {
$result = array_merge($result, $instances);
}
}
return $result;
}
public function getConstructor() {
return $this->createReflectionAnnotatedMethod(parent::getConstructor());
}
public function getMethod($name) {
return $this->createReflectionAnnotatedMethod(parent::getMethod($name));
}
public function getMethods($filter = -1) {
$result = array();
foreach(parent::getMethods($filter) as $method) {
$result[] = $this->createReflectionAnnotatedMethod($method);
}
return $result;
}
public function getProperty($name) {
return $this->createReflectionAnnotatedProperty(parent::getProperty($name));
}
public function getProperties($filter = -1) {
$result = array();
foreach(parent::getProperties($filter) as $property) {
$result[] = $this->createReflectionAnnotatedProperty($property);
}
return $result;
}
public function getInterfaces() {
$result = array();
foreach(parent::getInterfaces() as $interface) {
$result[] = $this->createReflectionAnnotatedClass($interface);
}
return $result;
}
public function getParentClass() {
$class = parent::getParentClass();
return $this->createReflectionAnnotatedClass($class);
}
protected function createAnnotationBuilder() {
return new AnnotationsBuilder();
}
private function createReflectionAnnotatedClass($class) {
return ($class !== false) ? new ReflectionAnnotatedClass($class->getName()) : false;
}
private function createReflectionAnnotatedMethod($method) {
return ($method !== null) ? new ReflectionAnnotatedMethod($this->getName(), $method->getName()) : null;
}
private function createReflectionAnnotatedProperty($property) {
return ($property !== null) ? new ReflectionAnnotatedProperty($this->getName(), $property->getName()) : null;
}
}
class ReflectionAnnotatedMethod extends ReflectionMethod {
private $annotations;
public function __construct($class, $name) {
parent::__construct($class, $name);
$this->annotations = $this->createAnnotationBuilder()->build($this);
}
public function hasAnnotation($annotation) {
return isset($this->annotations[$annotation]);
}
public function getAnnotation($annotation) {
return ($this->hasAnnotation($annotation)) ? end($this->annotations[$annotation]) : false;
}
public function getAnnotations() {
$result = array();
foreach($this->annotations as $instances) {
$result[] = end($instances);
}
return $result;
}
public function getAllAnnotations($restriction = false) {
$result = array();
foreach($this->annotations as $class => $instances) {
if(!$restriction || $restriction == $class) {
$result = array_merge($result, $instances);
}
}
return $result;
}
public function getDeclaringClass() {
$class = parent::getDeclaringClass();
return new ReflectionAnnotatedClass($class->getName());
}
protected function createAnnotationBuilder() {
return new AnnotationsBuilder();
}
}
class ReflectionAnnotatedProperty extends ReflectionProperty {
private $annotations;
public function __construct($class, $name) {
parent::__construct($class, $name);
$this->annotations = $this->createAnnotationBuilder()->build($this);
}
public function hasAnnotation($annotation) {
return isset($this->annotations[$annotation]);
}
public function getAnnotation($annotation) {
return ($this->hasAnnotation($annotation)) ? end($this->annotations[$annotation]) : false;
}
public function getAnnotations() {
$result = array();
foreach($this->annotations as $instances) {
$result[] = end($instances);
}
return $result;
}
public function getAllAnnotations($restriction = false) {
$result = array();
foreach($this->annotations as $class => $instances) {
if(!$restriction || $restriction == $class) {
$result = array_merge($result, $instances);
}
}
return $result;
}
public function getDeclaringClass() {
$class = parent::getDeclaringClass();
return new ReflectionAnnotatedClass($class->getName());
}
protected function createAnnotationBuilder() {
return new AnnotationsBuilder();
}
}
class Addendum {
private static $rawMode;
private static $ignored;
public static function getDocComment($reflection) {
if(self::checkRawDocCommentParsingNeeded()) {
$docComment = new DocComment();
return $docComment->get($reflection);
} else {
return $reflection->getDocComment();
}
}
/** Raw mode test */
private static function checkRawDocCommentParsingNeeded() {
if(self::$rawMode === null) {
$reflection = new ReflectionClass('Addendum');
$method = $reflection->getMethod('checkRawDocCommentParsingNeeded');
self::setRawMode($method->getDocComment() === false);
}
return self::$rawMode;
}
public static function setRawMode($enabled = true) {
if($enabled) {
require_once(dirname(__FILE__).'/annotations/doc_comment.php');
}
self::$rawMode = $enabled;
}
public static function ignore(array $annotations) {
self::$ignored = array_combine($annotations, array_fill(0, count($annotations), true));
}
public static function ignores($annotation) {
return isset(self::$ignored[$annotation]);
}
}