forked from doctrine/orm
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DCOM-93 - Removed reflection dependency from ClassMetadata completly,…
… moving all the code into ClassMetadataInfo for BC reasons.
- Loading branch information
Showing
8 changed files
with
308 additions
and
364 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,7 +20,6 @@ | |
namespace Doctrine\ORM\Mapping; | ||
|
||
use ReflectionClass, ReflectionProperty; | ||
use Doctrine\Common\Persistence\Mapping\ClassMetadata AS IClassMetadata; | ||
|
||
/** | ||
* A <tt>ClassMetadata</tt> instance holds all the object-relational mapping metadata | ||
|
@@ -40,318 +39,6 @@ | |
* @author Jonathan H. Wage <[email protected]> | ||
* @since 2.0 | ||
*/ | ||
class ClassMetadata extends ClassMetadataInfo implements IClassMetadata | ||
class ClassMetadata extends ClassMetadataInfo | ||
{ | ||
/** | ||
* The ReflectionProperty instances of the mapped class. | ||
* | ||
* @var array | ||
*/ | ||
public $reflFields = array(); | ||
|
||
/** | ||
* The prototype from which new instances of the mapped class are created. | ||
* | ||
* @var object | ||
*/ | ||
private $_prototype; | ||
|
||
/** | ||
* Initializes a new ClassMetadata instance that will hold the object-relational mapping | ||
* metadata of the class with the given name. | ||
* | ||
* @param string $entityName The name of the entity class the new instance is used for. | ||
*/ | ||
public function initializeReflection($reflService) | ||
{ | ||
$this->reflClass = $reflService->getClass($this->name); | ||
$this->namespace = $reflService->getClassNamespace($this->name); | ||
$this->table['name'] = $reflService->getClassShortName($this->name); | ||
|
||
if ($this->reflClass) { | ||
$this->name = $this->rootEntityName = $this->reflClass->getName(); | ||
} | ||
} | ||
|
||
/** | ||
* Gets the ReflectionPropertys of the mapped class. | ||
* | ||
* @return array An array of ReflectionProperty instances. | ||
*/ | ||
public function getReflectionProperties() | ||
{ | ||
return $this->reflFields; | ||
} | ||
|
||
/** | ||
* Gets a ReflectionProperty for a specific field of the mapped class. | ||
* | ||
* @param string $name | ||
* @return ReflectionProperty | ||
*/ | ||
public function getReflectionProperty($name) | ||
{ | ||
return $this->reflFields[$name]; | ||
} | ||
|
||
/** | ||
* Gets the ReflectionProperty for the single identifier field. | ||
* | ||
* @return ReflectionProperty | ||
* @throws BadMethodCallException If the class has a composite identifier. | ||
*/ | ||
public function getSingleIdReflectionProperty() | ||
{ | ||
if ($this->isIdentifierComposite) { | ||
throw new \BadMethodCallException("Class " . $this->name . " has a composite identifier."); | ||
} | ||
return $this->reflFields[$this->identifier[0]]; | ||
} | ||
|
||
/** | ||
* Validates & completes the given field mapping. | ||
* | ||
* @param array $mapping The field mapping to validated & complete. | ||
* @return array The validated and completed field mapping. | ||
* | ||
* @throws MappingException | ||
*/ | ||
protected function _validateAndCompleteFieldMapping(array &$mapping) | ||
{ | ||
parent::_validateAndCompleteFieldMapping($mapping); | ||
|
||
// Store ReflectionProperty of mapped field | ||
$refProp = $this->reflClass->getProperty($mapping['fieldName']); | ||
$refProp->setAccessible(true); | ||
$this->reflFields[$mapping['fieldName']] = $refProp; | ||
} | ||
|
||
/** | ||
* Validates & completes the basic mapping information that is common to all | ||
* association mappings (one-to-one, many-ot-one, one-to-many, many-to-many). | ||
* | ||
* @param array $mapping The mapping. | ||
* @return array The updated mapping. | ||
* @throws MappingException If something is wrong with the mapping. | ||
*/ | ||
protected function _validateAndCompleteAssociationMapping(array $mapping) | ||
{ | ||
$mapping = parent::_validateAndCompleteAssociationMapping($mapping); | ||
|
||
if ( ! \Doctrine\Common\ClassLoader::classExists($mapping['targetEntity']) ) { | ||
throw MappingException::invalidTargetEntityClass($mapping['targetEntity'], $this->name, $mapping['fieldName']); | ||
} | ||
|
||
return $mapping; | ||
} | ||
|
||
/** | ||
* Extracts the identifier values of an entity of this class. | ||
* | ||
* For composite identifiers, the identifier values are returned as an array | ||
* with the same order as the field order in {@link identifier}. | ||
* | ||
* @param object $entity | ||
* @return array | ||
*/ | ||
public function getIdentifierValues($entity) | ||
{ | ||
if ($this->isIdentifierComposite) { | ||
$id = array(); | ||
|
||
foreach ($this->identifier as $idField) { | ||
$value = $this->reflFields[$idField]->getValue($entity); | ||
|
||
if ($value !== null) { | ||
$id[$idField] = $value; | ||
} | ||
} | ||
|
||
return $id; | ||
} | ||
|
||
$value = $this->reflFields[$this->identifier[0]]->getValue($entity); | ||
|
||
if ($value !== null) { | ||
return array($this->identifier[0] => $value); | ||
} | ||
|
||
return array(); | ||
} | ||
|
||
/** | ||
* Populates the entity identifier of an entity. | ||
* | ||
* @param object $entity | ||
* @param mixed $id | ||
* @todo Rename to assignIdentifier() | ||
*/ | ||
public function setIdentifierValues($entity, array $id) | ||
{ | ||
foreach ($id as $idField => $idValue) { | ||
$this->reflFields[$idField]->setValue($entity, $idValue); | ||
} | ||
} | ||
|
||
/** | ||
* Sets the specified field to the specified value on the given entity. | ||
* | ||
* @param object $entity | ||
* @param string $field | ||
* @param mixed $value | ||
*/ | ||
public function setFieldValue($entity, $field, $value) | ||
{ | ||
$this->reflFields[$field]->setValue($entity, $value); | ||
} | ||
|
||
/** | ||
* Gets the specified field's value off the given entity. | ||
* | ||
* @param object $entity | ||
* @param string $field | ||
*/ | ||
public function getFieldValue($entity, $field) | ||
{ | ||
return $this->reflFields[$field]->getValue($entity); | ||
} | ||
|
||
/** | ||
* Stores the association mapping. | ||
* | ||
* @param AssociationMapping $assocMapping | ||
*/ | ||
protected function _storeAssociationMapping(array $assocMapping) | ||
{ | ||
parent::_storeAssociationMapping($assocMapping); | ||
|
||
// Store ReflectionProperty of mapped field | ||
$sourceFieldName = $assocMapping['fieldName']; | ||
|
||
$refProp = $this->reflClass->getProperty($sourceFieldName); | ||
$refProp->setAccessible(true); | ||
$this->reflFields[$sourceFieldName] = $refProp; | ||
} | ||
|
||
/** | ||
* Creates a string representation of this instance. | ||
* | ||
* @return string The string representation of this instance. | ||
* @todo Construct meaningful string representation. | ||
*/ | ||
public function __toString() | ||
{ | ||
return __CLASS__ . '@' . spl_object_hash($this); | ||
} | ||
|
||
/** | ||
* Determines which fields get serialized. | ||
* | ||
* It is only serialized what is necessary for best unserialization performance. | ||
* That means any metadata properties that are not set or empty or simply have | ||
* their default value are NOT serialized. | ||
* | ||
* Parts that are also NOT serialized because they can not be properly unserialized: | ||
* - reflClass (ReflectionClass) | ||
* - reflFields (ReflectionProperty array) | ||
* | ||
* @return array The names of all the fields that should be serialized. | ||
*/ | ||
public function __sleep() | ||
{ | ||
// This metadata is always serialized/cached. | ||
$serialized = array( | ||
'associationMappings', | ||
'columnNames', //TODO: Not really needed. Can use fieldMappings[$fieldName]['columnName'] | ||
'fieldMappings', | ||
'fieldNames', | ||
'identifier', | ||
'isIdentifierComposite', // TODO: REMOVE | ||
'name', | ||
'namespace', // TODO: REMOVE | ||
'table', | ||
'rootEntityName', | ||
'idGenerator', //TODO: Does not really need to be serialized. Could be moved to runtime. | ||
); | ||
|
||
// The rest of the metadata is only serialized if necessary. | ||
if ($this->changeTrackingPolicy != self::CHANGETRACKING_DEFERRED_IMPLICIT) { | ||
$serialized[] = 'changeTrackingPolicy'; | ||
} | ||
|
||
if ($this->customRepositoryClassName) { | ||
$serialized[] = 'customRepositoryClassName'; | ||
} | ||
|
||
if ($this->inheritanceType != self::INHERITANCE_TYPE_NONE) { | ||
$serialized[] = 'inheritanceType'; | ||
$serialized[] = 'discriminatorColumn'; | ||
$serialized[] = 'discriminatorValue'; | ||
$serialized[] = 'discriminatorMap'; | ||
$serialized[] = 'parentClasses'; | ||
$serialized[] = 'subClasses'; | ||
} | ||
|
||
if ($this->generatorType != self::GENERATOR_TYPE_NONE) { | ||
$serialized[] = 'generatorType'; | ||
if ($this->generatorType == self::GENERATOR_TYPE_SEQUENCE) { | ||
$serialized[] = 'sequenceGeneratorDefinition'; | ||
} | ||
} | ||
|
||
if ($this->isMappedSuperclass) { | ||
$serialized[] = 'isMappedSuperclass'; | ||
} | ||
|
||
if ($this->containsForeignIdentifier) { | ||
$serialized[] = 'containsForeignIdentifier'; | ||
} | ||
|
||
if ($this->isVersioned) { | ||
$serialized[] = 'isVersioned'; | ||
$serialized[] = 'versionField'; | ||
} | ||
|
||
if ($this->lifecycleCallbacks) { | ||
$serialized[] = 'lifecycleCallbacks'; | ||
} | ||
|
||
if ($this->namedQueries) { | ||
$serialized[] = 'namedQueries'; | ||
} | ||
|
||
if ($this->isReadOnly) { | ||
$serialized[] = 'isReadOnly'; | ||
} | ||
|
||
return $serialized; | ||
} | ||
|
||
/** | ||
* Creates a new instance of the mapped class, without invoking the constructor. | ||
* | ||
* @return object | ||
*/ | ||
public function newInstance() | ||
{ | ||
if ($this->_prototype === null) { | ||
$this->_prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name)); | ||
} | ||
|
||
return clone $this->_prototype; | ||
} | ||
|
||
/** | ||
* @param string $callback | ||
* @param string $event | ||
*/ | ||
public function addLifecycleCallback($callback, $event) | ||
{ | ||
if ( !$this->reflClass->hasMethod($callback) || | ||
($this->reflClass->getMethod($callback)->getModifiers() & \ReflectionMethod::IS_PUBLIC) == 0) { | ||
throw MappingException::lifecycleCallbackMethodNotFound($this->name, $callback); | ||
} | ||
|
||
return parent::addLifecycleCallback($callback, $event); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.