1
0
mirror of synced 2025-02-20 22:23:14 +03:00

added missing annotation driver class. small refactorings. added first ClassMetadata serialization tests.

This commit is contained in:
romanb 2009-01-05 20:18:56 +00:00
parent bcf0110249
commit 957a6b2c89
15 changed files with 692 additions and 636 deletions

View File

@ -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.");

View File

@ -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;
}
}
?>

View File

@ -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);

View File

@ -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);

View 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;
}

View File

@ -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.");
}
}

View File

@ -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]);
}
}

View File

@ -1,3 +0,0 @@
<?php
//@deprecated
class Doctrine_ClassMetadata_Exception extends Doctrine_Exception {}

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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());

View 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()
{
;
}
}

View File

@ -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()
{
;
}
}