added missing annotation driver class. small refactorings. added first ClassMetadata serialization tests.
This commit is contained in:
parent
bcf0110249
commit
957a6b2c89
@ -19,7 +19,7 @@
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
|
||||
#namespace Doctrine::ORM::Exceptions;
|
||||
#namespace Doctrine\ORM\Exceptions;
|
||||
|
||||
/**
|
||||
* A MappingException indicates that something is wrong with the mapping setup.
|
||||
@ -39,11 +39,6 @@ class Doctrine_ORM_Exceptions_MappingException extends Doctrine_ORM_Exceptions_O
|
||||
return new self("The inheritance type '$type' does not exist.");
|
||||
}
|
||||
|
||||
public static function invalidInheritanceOption($name)
|
||||
{
|
||||
return new self("The inheritance option '$name' does not exist.");
|
||||
}
|
||||
|
||||
public static function generatorNotAllowedWithCompositeId()
|
||||
{
|
||||
return new self("Id generators can't be used with a composite id.");
|
||||
|
@ -28,7 +28,7 @@
|
||||
* @since 2.0
|
||||
* @todo Rename to AssociationMapping.
|
||||
*/
|
||||
abstract class Doctrine_ORM_Mapping_AssociationMapping implements Serializable
|
||||
abstract class Doctrine_ORM_Mapping_AssociationMapping
|
||||
{
|
||||
const FETCH_MANUAL = 1;
|
||||
const FETCH_LAZY = 2;
|
||||
@ -445,18 +445,5 @@ abstract class Doctrine_ORM_Mapping_AssociationMapping implements Serializable
|
||||
}
|
||||
|
||||
abstract public function lazyLoadFor($entity);
|
||||
|
||||
/* Serializable implementation */
|
||||
|
||||
public function serialize()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -22,7 +22,6 @@
|
||||
#namespace Doctrine\ORM\Mapping;
|
||||
|
||||
#use \Serializable;
|
||||
#use Doctrine\Common\ClassMetadata;
|
||||
|
||||
/**
|
||||
* A <tt>ClassMetadata</tt> instance holds all the information (metadata) of an entity and
|
||||
@ -32,7 +31,7 @@
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
*/
|
||||
class Doctrine_ORM_Mapping_ClassMetadata implements Serializable
|
||||
class Doctrine_ORM_Mapping_ClassMetadata
|
||||
{
|
||||
/* The inheritance mapping types */
|
||||
/**
|
||||
@ -243,33 +242,37 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Serializable
|
||||
protected $_lcColumnToFieldNames = array();
|
||||
|
||||
/**
|
||||
* Inheritance options.
|
||||
* Whether to automatically OUTER JOIN subtypes when a basetype is queried.
|
||||
* This does only apply to the JOINED inheritance mapping strategy.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_inheritanceOptions = array(
|
||||
// JOINED & TABLE_PER_CLASS options
|
||||
'discriminatorColumn' => null,
|
||||
'discriminatorMap' => array(),
|
||||
// JOINED options
|
||||
'joinSubclasses' => true
|
||||
);
|
||||
protected $_joinSubclasses = true;
|
||||
|
||||
/**
|
||||
* Specific options that can be set for the database table the class is mapped to.
|
||||
* Some of them are dbms specific and they are only used if the table is generated
|
||||
* by Doctrine (NOT when using Migrations).
|
||||
* A map that maps discriminator values to class names.
|
||||
* This does only apply to the JOINED and SINGLE_TABLE inheritance mapping strategies
|
||||
* where a discriminator column is used.
|
||||
*
|
||||
* -- type table type (mysql example: INNODB)
|
||||
*
|
||||
* -- charset character set
|
||||
*
|
||||
* -- collate collation attribute
|
||||
* @var array
|
||||
* @see _discriminatorColumn
|
||||
*/
|
||||
protected $_tableOptions = array(
|
||||
'tableName' => null,
|
||||
'type' => null,
|
||||
'charset' => null,
|
||||
'collate' => null
|
||||
);
|
||||
protected $_discriminatorMap = array();
|
||||
|
||||
/**
|
||||
* The definition of the descriminator column used in JOINED and SINGLE_TABLE
|
||||
* inheritance mappings.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_discriminatorColumn;
|
||||
|
||||
/**
|
||||
* The name of the primary table.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_tableName;
|
||||
|
||||
/**
|
||||
* The cached lifecycle listeners. There is only one instance of each
|
||||
@ -314,13 +317,25 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Serializable
|
||||
*/
|
||||
protected $_isIdentifierComposite = false;
|
||||
|
||||
/**
|
||||
* The ReflectionClass instance of the mapped class.
|
||||
*
|
||||
* @var ReflectionClass
|
||||
*/
|
||||
protected $_reflectionClass;
|
||||
|
||||
/**
|
||||
* The ReflectionProperty instances of the mapped class.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_reflectionProperties;
|
||||
|
||||
/**
|
||||
* Constructs a new ClassMetadata instance.
|
||||
* Initializes a new ClassMetadata instance that will hold the ORM metadata
|
||||
* of the class with the given name.
|
||||
*
|
||||
* @param string $entityName Name of the entity class the metadata info is used for.
|
||||
* @param string $entityName Name of the entity class the new instance is used for.
|
||||
*/
|
||||
public function __construct($entityName)
|
||||
{
|
||||
@ -434,7 +449,6 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Serializable
|
||||
public function isUniqueField($fieldName)
|
||||
{
|
||||
$mapping = $this->getFieldMapping($fieldName);
|
||||
|
||||
if ($mapping !== false) {
|
||||
return isset($mapping['unique']) && $mapping['unique'] == true;
|
||||
}
|
||||
@ -511,7 +525,7 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Serializable
|
||||
public function getInverseAssociationMapping($mappedByFieldName)
|
||||
{
|
||||
if ( ! isset($this->_associationMappings[$fieldName])) {
|
||||
throw Doctrine_MappingException::mappingNotFound($fieldName);
|
||||
throw new Doctrine_Exception("Mapping not found: " . $fieldName);
|
||||
}
|
||||
return $this->_inverseMappings[$mappedByFieldName];
|
||||
}
|
||||
@ -576,9 +590,10 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Serializable
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a specified column name (all lowercase) exists in this class.
|
||||
*
|
||||
* @param <type> $lcColumnName
|
||||
* @return <type>
|
||||
* @param string $lcColumnName
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasLowerColumn($lcColumnName)
|
||||
{
|
||||
@ -595,10 +610,10 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Serializable
|
||||
{
|
||||
// Check mandatory fields
|
||||
if ( ! isset($mapping['fieldName'])) {
|
||||
throw Doctrine_MappingException::missingFieldName();
|
||||
throw Doctrine_ORM_Exceptions_MappingException::missingFieldName();
|
||||
}
|
||||
if ( ! isset($mapping['type'])) {
|
||||
throw Doctrine_MappingException::missingType();
|
||||
throw Doctrine_ORM_Exceptions_MappingException::missingType();
|
||||
}
|
||||
|
||||
// Complete fieldName and columnName mapping
|
||||
@ -729,7 +744,7 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Serializable
|
||||
*/
|
||||
public function getFieldMappings()
|
||||
{
|
||||
return $this->_fieldMetadata;
|
||||
return $this->_fieldMappings;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -918,7 +933,7 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Serializable
|
||||
*/
|
||||
public function getTableName()
|
||||
{
|
||||
return $this->_tableOptions['tableName'];
|
||||
return $this->_tableName;
|
||||
}
|
||||
|
||||
public function getInheritedFields()
|
||||
@ -1018,7 +1033,7 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Serializable
|
||||
*
|
||||
* @param integer $type
|
||||
*/
|
||||
public function setInheritanceType($type, array $options = array())
|
||||
public function setInheritanceType($type)
|
||||
{
|
||||
if ($parentClassNames = $this->getParentClasses()) {
|
||||
throw new Doctrine_MappingException("All classes in an inheritance hierarchy"
|
||||
@ -1028,83 +1043,7 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Serializable
|
||||
if ( ! $this->_isInheritanceType($type)) {
|
||||
throw Doctrine_MappingException::invalidInheritanceType($type);
|
||||
}
|
||||
|
||||
if ($type == self::INHERITANCE_TYPE_SINGLE_TABLE ||
|
||||
$type == self::INHERITANCE_TYPE_JOINED) {
|
||||
$this->_checkRequiredDiscriminatorOptions($options);
|
||||
}
|
||||
|
||||
$this->_inheritanceType = $type;
|
||||
foreach ($options as $name => $value) {
|
||||
$this->setInheritanceOption($name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the 2 options 'discriminatorColumn' and 'discriminatorMap' are present.
|
||||
* If either of them is missing an exception is thrown.
|
||||
*
|
||||
* @param array $options The options.
|
||||
* @throws Doctrine_ClassMetadata_Exception If at least one of the required discriminator
|
||||
* options is missing.
|
||||
*/
|
||||
private function _checkRequiredDiscriminatorOptions(array $options)
|
||||
{
|
||||
/*if ( ! isset($options['discriminatorColumn'])) {
|
||||
throw new Doctrine_Exception("Missing option 'discriminatorColumn'."
|
||||
. " Inheritance types JOINED and SINGLE_TABLE require this option.");
|
||||
} else if ( ! isset($options['discriminatorMap'])) {
|
||||
throw new Doctrine_ClassMetadata_Exception("Missing option 'discriminatorMap'."
|
||||
. " Inheritance types JOINED and SINGLE_TABLE require this option.");
|
||||
}*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an inheritance option.
|
||||
*
|
||||
*/
|
||||
public function getInheritanceOption($name)
|
||||
{
|
||||
return $this->_inheritanceOptions[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all inheritance options.
|
||||
*/
|
||||
public function getInheritanceOptions()
|
||||
{
|
||||
return $this->_inheritanceOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an inheritance option.
|
||||
*/
|
||||
public function setInheritanceOption($name, $value)
|
||||
{
|
||||
if ( ! array_key_exists($name, $this->_inheritanceOptions)) {
|
||||
throw new Doctrine_ClassMetadata_Exception("Unknown inheritance option: '$name'.");
|
||||
}
|
||||
|
||||
if ($this->_inheritanceType == 'joined' || $this->_inheritanceType == 'singleTable') {
|
||||
switch ($name) {
|
||||
case 'discriminatorColumn':
|
||||
if ($value !== null && ! is_string($value)) {
|
||||
throw new Doctrine_ClassMetadata_Exception("Invalid value '$value' for option"
|
||||
. " 'discriminatorColumn'.");
|
||||
}
|
||||
break;
|
||||
case 'discriminatorMap':
|
||||
if ( ! is_array($value)) {
|
||||
throw new Doctrine_ClassMetadata_Exception("Value for option 'discriminatorMap'"
|
||||
. " must be an array.");
|
||||
}
|
||||
break;
|
||||
// ... further validation checks as needed
|
||||
default:
|
||||
throw Doctrine_MappingException::invalidInheritanceOption($name);
|
||||
}
|
||||
}
|
||||
$this->_inheritanceOptions[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1129,119 +1068,6 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Serializable
|
||||
*/
|
||||
public function getExportableFormat($parseForeignKeys = true)
|
||||
{
|
||||
/*$columns = array();
|
||||
$primary = array();
|
||||
$allColumns = $this->getColumns();
|
||||
|
||||
// If the class is part of a Single Table Inheritance hierarchy, collect the fields
|
||||
// of all classes in the hierarchy.
|
||||
if ($this->_inheritanceType == self::INHERITANCE_TYPE_SINGLE_TABLE) {
|
||||
$parents = $this->getParentClasses();
|
||||
if ($parents) {
|
||||
$rootClass = $this->_classFactory->getClassMetadata(array_pop($parents));
|
||||
} else {
|
||||
$rootClass = $this;
|
||||
}
|
||||
$subClasses = $rootClass->getSubclasses();
|
||||
foreach ($subClasses as $subClass) {
|
||||
$subClassMetadata = $this->_classFactory->getClassMetadata($subClass);
|
||||
$allColumns = array_merge($allColumns, $subClassMetadata->getColumns());
|
||||
}
|
||||
} else if ($this->_inheritanceType == self::INHERITANCE_TYPE_JOINED) {
|
||||
// Remove inherited, non-pk fields. They're not in the table of this class
|
||||
foreach ($allColumns as $name => $definition) {
|
||||
if (isset($definition['id']) && $definition['id'] === true) {
|
||||
if ($this->getParentClasses() && isset($definition['autoincrement'])) {
|
||||
unset($allColumns[$name]['autoincrement']);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (isset($definition['inherited']) && $definition['inherited'] === true) {
|
||||
unset($allColumns[$name]);
|
||||
}
|
||||
}
|
||||
} else if ($this->_inheritanceType == self::INHERITANCE_TYPE_TABLE_PER_CLASS) {
|
||||
// If this is a subclass, just remove existing autoincrement options on the pk
|
||||
if ($this->getParentClasses()) {
|
||||
foreach ($allColumns as $name => $definition) {
|
||||
if (isset($definition['id']) && $definition['id'] === true) {
|
||||
if (isset($definition['autoincrement'])) {
|
||||
unset($allColumns[$name]['autoincrement']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert enum & boolean default values
|
||||
foreach ($allColumns as $name => $definition) {
|
||||
switch ($definition['type']) {
|
||||
case 'enum':
|
||||
if (isset($definition['default'])) {
|
||||
$definition['default'] = $this->enumIndex($name, $definition['default']);
|
||||
}
|
||||
break;
|
||||
case 'boolean':
|
||||
if (isset($definition['default'])) {
|
||||
$definition['default'] = $this->_em->convertBooleans($definition['default']);
|
||||
}
|
||||
break;
|
||||
}
|
||||
$columns[$name] = $definition;
|
||||
|
||||
if (isset($definition['id']) && $definition['id']) {
|
||||
$primary[] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
// Collect foreign keys from the relations
|
||||
$options['foreignKeys'] = array();
|
||||
if ($parseForeignKeys && $this->getAttribute(Doctrine::ATTR_EXPORT)
|
||||
& Doctrine::EXPORT_CONSTRAINTS) {
|
||||
$constraints = array();
|
||||
$emptyIntegrity = array('onUpdate' => null, 'onDelete' => null);
|
||||
foreach ($this->getRelations() as $name => $relation) {
|
||||
$fk = $relation->toArray();
|
||||
$fk['foreignTable'] = $relation->getTable()->getTableName();
|
||||
|
||||
if ($relation->getTable() === $this && in_array($relation->getLocal(), $primary)) {
|
||||
if ($relation->hasConstraint()) {
|
||||
throw new Doctrine_Table_Exception("Badly constructed integrity constraints.");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
$integrity = array('onUpdate' => $fk['onUpdate'],
|
||||
'onDelete' => $fk['onDelete']);
|
||||
|
||||
if ($relation instanceof Doctrine_Relation_LocalKey) {
|
||||
$def = array('local' => $relation->getLocal(),
|
||||
'foreign' => $relation->getForeign(),
|
||||
'foreignTable' => $relation->getTable()->getTableName());
|
||||
|
||||
if (($key = array_search($def, $options['foreignKeys'])) === false) {
|
||||
$options['foreignKeys'][] = $def;
|
||||
$constraints[] = $integrity;
|
||||
} else {
|
||||
if ($integrity !== $emptyIntegrity) {
|
||||
$constraints[$key] = $integrity;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($constraints as $k => $def) {
|
||||
$options['foreignKeys'][$k] = array_merge($options['foreignKeys'][$k], $def);
|
||||
}
|
||||
}
|
||||
|
||||
$options['primary'] = $primary;
|
||||
|
||||
return array('tableName' => $this->getTableOption('tableName'),
|
||||
'columns' => $columns,
|
||||
'options' => array_merge($options, $this->getTableOptions()));
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1261,7 +1087,7 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Serializable
|
||||
*/
|
||||
public function setTableName($tableName)
|
||||
{
|
||||
$this->_tableOptions['tableName'] = $tableName;
|
||||
$this->_tableName = $tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1271,12 +1097,12 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Serializable
|
||||
*
|
||||
* @return string The serialized metadata.
|
||||
*/
|
||||
public function serialize()
|
||||
/* public function serialize()
|
||||
{
|
||||
//$contents = get_object_vars($this);
|
||||
//return serialize($contents);
|
||||
return "";
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Reconstructs the metadata class from it's serialized representation.
|
||||
@ -1285,10 +1111,10 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Serializable
|
||||
*
|
||||
* @param string $serialized The serialized metadata class.
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
/*public function unserialize($serialized)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Checks whether the given type identifies an entity type.
|
||||
@ -1355,7 +1181,7 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Serializable
|
||||
{
|
||||
$this->_validateAndCompleteFieldMapping($mapping);
|
||||
if (isset($this->_fieldMappings[$mapping['fieldName']])) {
|
||||
throw Doctrine_MappingException::duplicateFieldMapping();
|
||||
throw Doctrine_ORM_Exceptions_MappingException::duplicateFieldMapping();
|
||||
}
|
||||
$this->_fieldMappings[$mapping['fieldName']] = $mapping;
|
||||
}
|
||||
@ -1458,26 +1284,42 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Serializable
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Thoughts & Implementation.
|
||||
* Sets whether sub classes should be automatically OUTER JOINed when a base
|
||||
* class is queried in a class hierarchy that uses the JOINED inheritance mapping
|
||||
* strategy.
|
||||
*
|
||||
* This options does only apply to the JOINED inheritance mapping strategy.
|
||||
*
|
||||
* @param boolean $bool
|
||||
* @see getJoinSubClasses()
|
||||
*/
|
||||
public function setJoinSubClasses($bool)
|
||||
{
|
||||
$this->_joinSubclasses = (bool)$bool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the class mapped by this instance should OUTER JOIN sub classes
|
||||
* when a base class is queried.
|
||||
*
|
||||
* @return <type>
|
||||
* @see setJoinSubClasses()
|
||||
*/
|
||||
public function getJoinSubClasses()
|
||||
{
|
||||
return $this->_joinSubclasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Implementation.
|
||||
*/
|
||||
public function setEntityType($type)
|
||||
{
|
||||
//Entity::TYPE_ENTITY
|
||||
//Entity::TYPE_MAPPED_SUPERCLASS
|
||||
//Entity::TYPE_TRANSIENT
|
||||
throw new Doctrine_Exception("Not yet implemented.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the entity instances of this class to a specific EntityManager.
|
||||
*
|
||||
* @todo Implementation. Replaces the bindComponent() methods on the old Doctrine_Manager.
|
||||
* Binding an Entity to a specific EntityManager in 2.0 is the same as binding
|
||||
* it to a Connection in 1.0.
|
||||
*/
|
||||
/*public function bindToEntityManager($emName)
|
||||
{
|
||||
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Dispatches the lifecycle event of the given Entity to the registered
|
||||
@ -1560,35 +1402,79 @@ class Doctrine_ORM_Mapping_ClassMetadata implements Serializable
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Implementation. Immutable entities can not be updated or deleted once
|
||||
* they are created. This means the entity can only be modified as long as it's
|
||||
* new (STATE_NEW).
|
||||
* Sets the discriminator column definition.
|
||||
*
|
||||
* @param array $columnDef
|
||||
* @see getDiscriminatorColumn()
|
||||
*/
|
||||
public function isImmutable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function setDiscriminatorColumn($columnDef)
|
||||
{
|
||||
$this->_inheritanceOptions['discriminatorColumn'] = $columnDef;
|
||||
$this->_discriminatorColumn = $columnDef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the discriminator column definition.
|
||||
*
|
||||
* The discriminator column definition is an array with the following keys:
|
||||
* name: The name of the column
|
||||
* type: The type of the column (only integer and string supported)
|
||||
* length: The length of the column (applies only if type is string)
|
||||
*
|
||||
* A discriminator column is used for JOINED and SINGLE_TABLE inheritance mappings.
|
||||
*
|
||||
* @return array
|
||||
* @see setDiscriminatorColumn()
|
||||
*/
|
||||
public function getDiscriminatorColumn()
|
||||
{
|
||||
return $this->_discriminatorColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the dsicriminator map used for mapping discriminator values to class names.
|
||||
* Used for JOINED and SINGLE_TABLE inheritance mapping strategies.
|
||||
*
|
||||
* @param array $map
|
||||
*/
|
||||
public function setDiscriminatorMap(array $map)
|
||||
{
|
||||
$this->_inheritanceOptions['discriminatorMap'] = $map;
|
||||
$this->_discriminatorMap = $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the discriminator map that maps discriminator values to class names.
|
||||
* Used for JOINED and SINGLE_TABLE inheritance mapping strategies.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDiscriminatorMap()
|
||||
{
|
||||
return $this->_discriminatorMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given column name is the discriminator column.
|
||||
*
|
||||
* @param string $columnName
|
||||
* @return boolean
|
||||
*/
|
||||
public function isDiscriminatorColumn($columnName)
|
||||
{
|
||||
return $columnName === $this->_inheritanceOptions['discriminatorColumn'];
|
||||
return $columnName === $this->_discriminatorColumn['name'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether the class has a mapped association with the given field name.
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasAssociation($fieldName)
|
||||
{
|
||||
return isset($this->_associationMappings[$fieldName]);
|
||||
}
|
||||
|
||||
/** Creates a string representation of the instance. */
|
||||
public function __toString()
|
||||
{
|
||||
return __CLASS__ . '@' . spl_object_hash($this);
|
||||
|
@ -109,7 +109,9 @@ class Doctrine_ORM_Mapping_ClassMetadataFactory
|
||||
$parent = $class;
|
||||
foreach ($parentClasses as $subclassName) {
|
||||
$subClass = new Doctrine_ORM_Mapping_ClassMetadata($subclassName);
|
||||
$subClass->setInheritanceType($parent->getInheritanceType(), $parent->getInheritanceOptions());
|
||||
$subClass->setInheritanceType($parent->getInheritanceType());
|
||||
$subClass->setDiscriminatorMap($parent->getDiscriminatorMap());
|
||||
$subClass->setDiscriminatorColumn($parent->getDiscriminatorColumn());
|
||||
$this->_addInheritedFields($subClass, $parent);
|
||||
$this->_addInheritedRelations($subClass, $parent);
|
||||
$this->_loadClassMetadata($subClass, $subclassName);
|
||||
|
148
lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
Normal file
148
lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
Normal file
@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
#namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
/* Addendum annotation API */
|
||||
require_once dirname(__FILE__) . '/addendum/annotations.php';
|
||||
Addendum::setRawMode(false);
|
||||
Addendum::setParsedAnnotations(array('DoctrineEntity', 'DoctrineInheritanceType',
|
||||
'DoctrineDiscriminatorColumn', 'DoctrineDiscriminatorMap',
|
||||
'DoctrineSubClasses', 'DoctrineTransient', 'DoctrineId',
|
||||
'DoctrineIdGenerator', 'DoctrineColumn', 'DoctrineOneToOne',
|
||||
'DoctrineOneToMany', 'DoctrineManyToOne', 'DoctrineManyToMany'));
|
||||
|
||||
/**
|
||||
* The AnnotationDriver reads the mapping metadata from docblock annotations.
|
||||
*
|
||||
* @author robo
|
||||
*/
|
||||
class Doctrine_ORM_Mapping_Driver_AnnotationDriver {
|
||||
/**
|
||||
* Loads the metadata for the specified class into the provided container.
|
||||
*/
|
||||
public function loadMetadataForClass($className, Doctrine_ORM_Mapping_ClassMetadata $metadata)
|
||||
{
|
||||
$annotClass = new ReflectionAnnotatedClass($className);
|
||||
|
||||
if (($entityAnnot = $annotClass->getAnnotation('DoctrineEntity')) === false) {
|
||||
throw new Doctrine_ORM_Exceptions_MappingException("$className is no entity.");
|
||||
}
|
||||
|
||||
$metadata->setTableName($entityAnnot->tableName);
|
||||
$metadata->setCustomRepositoryClass($entityAnnot->repositoryClass);
|
||||
|
||||
if ($inheritanceTypeAnnot = $annotClass->getAnnotation('DoctrineInheritanceType')) {
|
||||
$metadata->setInheritanceType($inheritanceTypeAnnot->value);
|
||||
}
|
||||
|
||||
if ($discrColumnAnnot = $annotClass->getAnnotation('DoctrineDiscriminatorColumn')) {
|
||||
$metadata->setDiscriminatorColumn(array(
|
||||
'name' => $discrColumnAnnot->name,
|
||||
'type' => $discrColumnAnnot->type,
|
||||
'length' => $discrColumnAnnot->length
|
||||
));
|
||||
}
|
||||
|
||||
if ($discrValueAnnot = $annotClass->getAnnotation('DoctrineDiscriminatorMap')) {
|
||||
$metadata->setDiscriminatorMap((array)$discrValueAnnot->value);
|
||||
}
|
||||
|
||||
if ($subClassesAnnot = $annotClass->getAnnotation('DoctrineSubClasses')) {
|
||||
$metadata->setSubclasses($subClassesAnnot->value);
|
||||
}
|
||||
|
||||
foreach ($annotClass->getProperties() as $property) {
|
||||
if ($property->hasAnnotation('DoctrineTransient')) {
|
||||
continue;
|
||||
}
|
||||
$mapping = array();
|
||||
$mapping['fieldName'] = $property->getName();
|
||||
if ($columnAnnot = $property->getAnnotation('DoctrineColumn')) {
|
||||
if ($columnAnnot->type == null) {
|
||||
throw new Doctrine_ORM_Exceptions_MappingException("Missing type on property " . $property->getName());
|
||||
}
|
||||
$mapping['type'] = $columnAnnot->type;
|
||||
$mapping['length'] = $columnAnnot->length;
|
||||
if ($idAnnot = $property->getAnnotation('DoctrineId')) {
|
||||
$mapping['id'] = true;
|
||||
}
|
||||
if ($idGeneratorAnnot = $property->getAnnotation('DoctrineIdGenerator')) {
|
||||
$mapping['idGenerator'] = $idGeneratorAnnot->value;
|
||||
}
|
||||
$metadata->mapField($mapping);
|
||||
} else if ($oneToOneAnnot = $property->getAnnotation('DoctrineOneToOne')) {
|
||||
$mapping['targetEntity'] = $oneToOneAnnot->targetEntity;
|
||||
$mapping['joinColumns'] = $oneToOneAnnot->joinColumns;
|
||||
$mapping['mappedBy'] = $oneToOneAnnot->mappedBy;
|
||||
$mapping['cascade'] = $oneToOneAnnot->cascade;
|
||||
$metadata->mapOneToOne($mapping);
|
||||
} else if ($oneToManyAnnot = $property->getAnnotation('DoctrineOneToMany')) {
|
||||
$mapping['mappedBy'] = $oneToManyAnnot->mappedBy;
|
||||
$mapping['targetEntity'] = $oneToManyAnnot->targetEntity;
|
||||
$metadata->mapOneToMany($mapping);
|
||||
} else if ($manyToOneAnnot = $property->getAnnotation('DoctrineManyToOne')) {
|
||||
$mapping['joinColumns'] = $manyToOneAnnot->joinColumns;
|
||||
$mapping['targetEntity'] = $manyToOneAnnot->targetEntity;
|
||||
$metadata->mapManyToOne($mapping);
|
||||
} else if ($manyToManyAnnot = $property->getAnnotation('DoctrineManyToMany')) {
|
||||
$mapping['targetEntity'] = $manyToManyAnnot->targetEntity;
|
||||
$mapping['joinColumns'] = $manyToManyAnnot->joinColumns;
|
||||
$mapping['inverseJoinColumns'] = $manyToManyAnnot->inverseJoinColumns;
|
||||
$mapping['joinTable'] = $manyToManyAnnot->joinTable;
|
||||
$mapping['mappedBy'] = $manyToManyAnnot->mappedBy;
|
||||
$metadata->mapManyToMany($mapping);
|
||||
} else {
|
||||
throw new Doctrine_ORM_Exceptions_MappingException($className);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Annotations */
|
||||
|
||||
final class DoctrineEntity extends Annotation {
|
||||
public $tableName;
|
||||
public $repositoryClass;
|
||||
public $inheritanceType;
|
||||
}
|
||||
final class DoctrineInheritanceType extends Annotation {}
|
||||
final class DoctrineDiscriminatorColumn extends Annotation {
|
||||
public $name;
|
||||
public $type;
|
||||
public $length;
|
||||
}
|
||||
final class DoctrineDiscriminatorMap extends Annotation {}
|
||||
final class DoctrineSubClasses extends Annotation {}
|
||||
final class DoctrineTransient extends Annotation {}
|
||||
final class DoctrineId extends Annotation {}
|
||||
final class DoctrineIdGenerator extends Annotation {}
|
||||
final class DoctrineColumn extends Annotation {
|
||||
public $type;
|
||||
public $length;
|
||||
public $unique;
|
||||
public $notnull;
|
||||
}
|
||||
final class DoctrineOneToOne extends Annotation {
|
||||
public $targetEntity;
|
||||
public $mappedBy;
|
||||
public $joinColumns;
|
||||
public $cascade;
|
||||
}
|
||||
final class DoctrineOneToMany extends Annotation {
|
||||
public $mappedBy;
|
||||
public $targetEntity;
|
||||
public $cascade;
|
||||
}
|
||||
final class DoctrineManyToOne extends Annotation {
|
||||
public $targetEntity;
|
||||
public $joinColumns;
|
||||
public $cascade;
|
||||
}
|
||||
final class DoctrineManyToMany extends Annotation {
|
||||
public $targetEntity;
|
||||
public $joinColumns;
|
||||
public $inverseJoinColumns;
|
||||
public $joinTable;
|
||||
public $mappedBy;
|
||||
public $cascade;
|
||||
}
|
@ -11,6 +11,6 @@ class Doctrine_ORM_Mapping_Driver_YamlDriver
|
||||
*/
|
||||
public function loadMetadataForClass($className, Doctrine_ORM_Mapping_ClassMetadata $metadata)
|
||||
{
|
||||
throw new Doctrine_ClassMetadata_Exception("YAML driver not yet implemented.");
|
||||
throw new Doctrine_Exception("YAML driver not yet implemented.");
|
||||
}
|
||||
}
|
@ -1,335 +1,335 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Addendum PHP Reflection Annotations
|
||||
* http://code.google.com/p/addendum/
|
||||
*
|
||||
* Copyright (C) 2006 Jan "johno Suchal <johno@jsmf.net>
|
||||
|
||||
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(Addendum::parses($class)) {
|
||||
foreach($parameters as $params) {
|
||||
$annotationReflection = new ReflectionClass($class);
|
||||
$annotations[$class][] = $annotationReflection->newInstance($params, $targetReflection);
|
||||
}
|
||||
* 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(Addendum::parses($class)) {
|
||||
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 $parsedAnnotations;
|
||||
|
||||
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 setParsedAnnotations(array $annotations) {
|
||||
self::$parsedAnnotations = array_combine($annotations, array_fill(0, count($annotations), true));
|
||||
}
|
||||
}
|
||||
return $annotations;
|
||||
}
|
||||
|
||||
public static function parses($annotation) {
|
||||
return isset(self::$parsedAnnotations[$annotation]);
|
||||
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 $parsedAnnotations;
|
||||
|
||||
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 setParsedAnnotations(array $annotations) {
|
||||
self::$parsedAnnotations = array_combine($annotations, array_fill(0, count($annotations), true));
|
||||
}
|
||||
|
||||
public static function parses($annotation) {
|
||||
return isset(self::$parsedAnnotations[$annotation]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +0,0 @@
|
||||
<?php
|
||||
//@deprecated
|
||||
class Doctrine_ClassMetadata_Exception extends Doctrine_Exception {}
|
@ -84,7 +84,7 @@ class Doctrine_ORM_Mapping_OneToOneMapping extends Doctrine_ORM_Mapping_Associat
|
||||
|
||||
if ($this->isOwningSide()) {
|
||||
if ( ! isset($mapping['joinColumns'])) {
|
||||
throw Doctrine_MappingException::invalidMapping($this->_sourceFieldName);
|
||||
throw Doctrine_ORM_Exceptions_MappingException::invalidMapping($this->_sourceFieldName);
|
||||
}
|
||||
$this->_sourceToTargetKeyColumns = $mapping['joinColumns'];
|
||||
$this->_targetToSourceKeyColumns = array_flip($this->_sourceToTargetKeyColumns);
|
||||
|
@ -282,9 +282,9 @@ abstract class Doctrine_ORM_Persisters_AbstractEntityPersister
|
||||
// Populate the discriminator column on insert in Single & Class Table Inheritance
|
||||
if ($isInsert && ($this->_classMetadata->isInheritanceTypeJoined() ||
|
||||
$this->_classMetadata->isInheritanceTypeSingleTable())) {
|
||||
$discColumn = $this->_classMetadata->getInheritanceOption('discriminatorColumn');
|
||||
$discMap = $this->_classMetadata->getInheritanceOption('discriminatorMap');
|
||||
$result[$discColumn] = array_search($this->_entityName, $discMap);
|
||||
$discColumn = $this->_classMetadata->getDiscriminatorColumn();
|
||||
$discMap = $this->_classMetadata->getDiscriminatorMap();
|
||||
$result[$discColumn['name']] = array_search($this->_entityName, $discMap);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -190,13 +190,13 @@ class Doctrine_ORM_Persisters_JoinedSubclassPersister extends Doctrine_ORM_Persi
|
||||
{
|
||||
$classMetadata = $this->_classMetadata;
|
||||
$conn = $this->_conn;
|
||||
$fields = array($classMetadata->getInheritanceOption('discriminatorColumn'));
|
||||
$discrColumn = $classMetadata->getDiscriminatorColumn();
|
||||
$fields = array($discrColumn['name']);
|
||||
if ($classMetadata->getSubclasses()) {
|
||||
foreach ($classMetadata->getSubclasses() as $subClass) {
|
||||
$fields = array_merge($conn->getClassMetadata($subClass)->getFieldNames(), $fields);
|
||||
}
|
||||
}
|
||||
|
||||
return array_unique($fields);
|
||||
}
|
||||
|
||||
|
@ -1077,15 +1077,15 @@ class Doctrine_ORM_UnitOfWork
|
||||
{
|
||||
$class = $this->_em->getClassMetadata($className);
|
||||
|
||||
$discCol = $class->getInheritanceOption('discriminatorColumn');
|
||||
$discCol = $class->getDiscriminatorColumn();
|
||||
if ( ! $discCol) {
|
||||
return $className;
|
||||
}
|
||||
|
||||
$discMap = $class->getInheritanceOption('discriminatorMap');
|
||||
$discMap = $class->getDiscriminatorMap();
|
||||
|
||||
if (isset($data[$discCol], $discMap[$data[$discCol]])) {
|
||||
return $discMap[$data[$discCol]];
|
||||
if (isset($data[$discCol['name']], $discMap[$data[$discCol['name']]])) {
|
||||
return $discMap[$data[$discCol['name']]];
|
||||
} else {
|
||||
return $className;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ require_once 'Orm/UnitOfWorkTest.php';
|
||||
require_once 'Orm/EntityManagerTest.php';
|
||||
require_once 'Orm/EntityPersisterTest.php';
|
||||
require_once 'Orm/CommitOrderCalculatorTest.php';
|
||||
require_once 'Orm/ClassMetadataTest.php';
|
||||
|
||||
class Orm_AllTests
|
||||
{
|
||||
@ -33,6 +34,7 @@ class Orm_AllTests
|
||||
$suite->addTestSuite('Orm_EntityManagerTest');
|
||||
$suite->addTestSuite('Orm_EntityPersisterTest');
|
||||
$suite->addTestSuite('Orm_CommitOrderCalculatorTest');
|
||||
$suite->addTestSuite('Orm_ClassMetadataTest');
|
||||
|
||||
$suite->addTest(Orm_Query_AllTests::suite());
|
||||
$suite->addTest(Orm_Hydration_AllTests::suite());
|
||||
|
57
tests/Orm/ClassMetadataTest.php
Normal file
57
tests/Orm/ClassMetadataTest.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
require_once 'lib/DoctrineTestInit.php';
|
||||
|
||||
class Orm_ClassMetadataTest extends Doctrine_OrmTestCase
|
||||
{
|
||||
protected function setUp() {
|
||||
;
|
||||
}
|
||||
|
||||
protected function tearDown() {
|
||||
;
|
||||
}
|
||||
|
||||
public function testClassMetadataInstanceSerialization() {
|
||||
$cm = new Doctrine_ORM_Mapping_ClassMetadata('CmsUser');
|
||||
|
||||
// Test initial state
|
||||
$this->assertTrue(count($cm->getReflectionProperties()) > 0);
|
||||
$this->assertTrue($cm->getReflectionClass() instanceof ReflectionClass);
|
||||
$this->assertEquals('CmsUser', $cm->getClassName());
|
||||
$this->assertEquals('CmsUser', $cm->getRootClassName());
|
||||
$this->assertEquals(array(), $cm->getSubclasses());
|
||||
$this->assertEquals(array(), $cm->getParentClasses());
|
||||
|
||||
// Customize state
|
||||
$cm->setSubclasses(array("One", "Two", "Three"));
|
||||
$cm->setParentClasses(array("UserParent"));
|
||||
$cm->setCustomRepositoryClass("UserRepository");
|
||||
$cm->setDiscriminatorColumn(array('name' => 'disc', 'type' => 'integer'));
|
||||
$cm->mapOneToOne(array('fieldName' => 'foo', 'targetEntity' => 'Bar', 'mappedBy' => 'foo'));
|
||||
$this->assertTrue($cm->getAssociationMapping('foo') instanceof Doctrine_ORM_Mapping_OneToOneMapping);
|
||||
$this->assertEquals(1, count($cm->getAssociationMappings()));
|
||||
|
||||
$serialized = serialize($cm);
|
||||
$cm = unserialize($serialized);
|
||||
|
||||
// Check state
|
||||
$this->assertTrue(count($cm->getReflectionProperties()) > 0);
|
||||
$this->assertTrue($cm->getReflectionClass() instanceof ReflectionClass);
|
||||
$this->assertEquals('CmsUser', $cm->getClassName());
|
||||
$this->assertEquals('UserParent', $cm->getRootClassName());
|
||||
$this->assertEquals(array('One', 'Two', 'Three'), $cm->getSubclasses());
|
||||
$this->assertEquals(array('UserParent'), $cm->getParentClasses());
|
||||
$this->assertEquals('UserRepository', $cm->getCustomRepositoryClass());
|
||||
$this->assertEquals(array('name' => 'disc', 'type' => 'integer'), $cm->getDiscriminatorColumn());
|
||||
$this->assertTrue($cm->getAssociationMapping('foo') instanceof Doctrine_ORM_Mapping_OneToOneMapping);
|
||||
$this->assertEquals(1, count($cm->getAssociationMappings()));
|
||||
$oneOneMapping = $cm->getAssociationMapping('foo');
|
||||
$this->assertEquals('foo', $oneOneMapping->getSourceFieldName());
|
||||
$this->assertEquals('Bar', $oneOneMapping->getTargetEntityName());
|
||||
}
|
||||
|
||||
public function testTransientEntityIsManaged()
|
||||
{
|
||||
;
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
<?php
|
||||
require_once 'lib/DoctrineTestInit.php';
|
||||
|
||||
class Orm_ClassMetadataTestCase extends Doctrine_OrmTestCase
|
||||
{
|
||||
protected function setUp() {
|
||||
;
|
||||
}
|
||||
|
||||
protected function tearDown() {
|
||||
;
|
||||
}
|
||||
|
||||
public function testTransientEntityIsManaged()
|
||||
{
|
||||
;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user