From 115e4d01f28a5ab2cb4e1d852b7ea87f80856202 Mon Sep 17 00:00:00 2001 From: jwage Date: Fri, 5 Jun 2009 21:40:47 +0000 Subject: [PATCH] [2.0] Refactoring the meta data drivers and refactoring yaml/xml and adding tests for yaml. --- .../ORM/Mapping/Driver/AbstractFileDriver.php | 236 ++++++++++++++ .../ORM/Mapping/Driver/AnnotationDriver.php | 2 +- lib/Doctrine/ORM/Mapping/Driver/Driver.php | 54 +++ lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php | 151 +-------- .../ORM/Mapping/Driver/YamlDriver.php | 307 +++++++++++++----- tests/Doctrine/Tests/ORM/Mapping/AllTests.php | 3 +- .../ORM/Mapping/ClassMetadataFactoryTest.php | 7 + .../Tests/ORM/Mapping/XmlDriverTest.php | 5 +- .../Tests/ORM/Mapping/YamlDriverTest.php | 66 ++++ tests/Doctrine/Tests/ORM/Mapping/xml/User.php | 2 +- .../Mapping/xml/XmlMappingTest.User.dcm.xml | 2 +- .../Doctrine/Tests/ORM/Mapping/yaml/User.php | 13 + .../Mapping/yaml/YamlMappingTest.User.dcm.yml | 34 ++ 13 files changed, 645 insertions(+), 237 deletions(-) create mode 100644 lib/Doctrine/ORM/Mapping/Driver/AbstractFileDriver.php create mode 100644 lib/Doctrine/ORM/Mapping/Driver/Driver.php create mode 100644 tests/Doctrine/Tests/ORM/Mapping/YamlDriverTest.php create mode 100644 tests/Doctrine/Tests/ORM/Mapping/yaml/User.php create mode 100644 tests/Doctrine/Tests/ORM/Mapping/yaml/YamlMappingTest.User.dcm.yml diff --git a/lib/Doctrine/ORM/Mapping/Driver/AbstractFileDriver.php b/lib/Doctrine/ORM/Mapping/Driver/AbstractFileDriver.php new file mode 100644 index 000000000..47013d66d --- /dev/null +++ b/lib/Doctrine/ORM/Mapping/Driver/AbstractFileDriver.php @@ -0,0 +1,236 @@ +. + */ + +namespace Doctrine\ORM\Mapping\Driver; + +use Doctrine\ORM\Mapping\MappingException; + +/** + * SchemaMetadata mapping driver interface + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.0 + * @version $Revision: 1393 $ + * @author Jonathan H. Wage + */ +abstract class AbstractFileDriver implements Driver +{ + /** + * The FILE_PER_CLASS mode is an operating mode of the FileDriver where it loads + * the mapping files of individual classes on demand. This requires the user to + * adhere to the convention of 1 mapping file per class and the file names of + * the mapping files must correspond to the full class name, including namespace, + * with the namespace delimiters '\', replaced by dots '.'. + * + * Example: + * Class: My\Project\Model\User + * Mapping file: My.Project.Model.User.dcm.xml + * + * @var integer + */ + const FILE_PER_CLASS = 1; + + /** + * The PRELOAD mode is an operating mode of the FileDriver where it loads + * all mapping files in advance. This is the default behavior. It does not + * require a naming convention or the convention of 1 class per mapping file. + * + * @var integer + */ + const PRELOAD = 2; + + /** + * The paths where to look for mapping files. + * + * @var array + */ + protected $_paths; + + /** + * The operating mode. Either FILE_PER_CLASS or PRELOAD. + * + * @var integer + */ + protected $_mode; + + /** + * The file extension of mapping documents. + * + * @var string + */ + protected $_fileExtension; + + /** + * Any preloaded elements. + * + * @var array + */ + protected $_elements = array(); + + /** + * Initializes a new FileDriver that looks in the given path(s) for mapping + * documents and operates in the specified operating mode. + * + * @param string|array $paths One or multiple paths where mapping documents can be found. + * @param integer $mode The operating mode. Either PRELOAD (default) or FILE_PER_CLASS. + */ + public function __construct($paths, $mode = self::PRELOAD) + { + $this->_paths = $paths; + $this->_mode = $mode; + } + + /** + * Get the file extension used to look for mapping files under + * + * @return void + */ + public function getfileExtension() + { + return $this->_fileExtension; + } + + /** + * Set the file extension used to look for mapping files under + * + * @param string $fileExtension The file extension to set + * @return void + */ + public function setFileExtension($fileExtension) + { + $this->_fileExtension = $fileExtension; + } + + /** + * Get the element of schema meta data for the class from the mapping file. + * This will lazily load the mapping file if it is not loaded yet + * + * @return array $element The element of schema meta data + */ + public function getElement($className) + { + if (isset($this->_elements[$className])) { + $element = $this->_elements[$className]; + unset($this->_elements[$className]); + return $element; + } else { + $result = $this->_loadMappingFile($this->_findMappingFile($className)); + return $result[$className]; + } + } + + /** + * Gets any preloaded elements. + * + * @return array + */ + public function getPreloadedElements() + { + return $this->_elements; + } + + /** + * Whether the class with the specified name should have its metadata loaded. + * This is only the case if it is either mapped as an Entity or a + * MappedSuperclass. + * + * @param string $className + * @return boolean + */ + public function isTransient($className) + { + $isTransient = true; + if ($this->_mode == self::FILE_PER_CLASS) { + // check whether file exists + foreach ((array)$this->_paths as $path) { + if (file_exists($path . DIRECTORY_SEPARATOR . str_replace('\\', '.', $className) . $this->_fileExtension)) { + $isTransient = false; + break; + } + } + } else { + $isTransient = isset($this->_elements[$className]); + } + + return $isTransient; + } + + /** + * Preloads all mapping information found in any documents within the + * configured paths and returns a list of class names that have been preloaded. + * + * @return array The list of class names that have been preloaded. + */ + public function preload() + { + if ($this->_mode != self::PRELOAD) { + return array(); + } + + foreach ((array)$this->_paths as $path) { + if (is_dir($path)) { + $files = glob($path . '/*' . $this->_fileExtension); + foreach ($files as $file) { + $this->_elements = array_merge($this->_elements, $this->_loadMappingFile($file)); + } + } else if (is_file($path)) { + $this->_elements = array_merge($this->_elements, $this->_loadMappingFile($path)); + } + } + + return array_keys($this->_elements); + } + + /** + * Finds the mapping file for the class with the given name by searching + * through the configured paths. + * + * @param $className + * @return string The (absolute) file name. + * @throws MappingException + */ + protected function _findMappingFile($className) + { + $fileName = null; + foreach ((array)$this->_paths as $path) { + $fileName = $path . DIRECTORY_SEPARATOR . str_replace('\\', '.', $className) . $this->_fileExtension; + if (file_exists($fileName)) { + break; + } + } + + if ($fileName === null) { + throw MappingException::mappingFileNotFound($className); + } + + return $fileName; + } + + /** + * Loads a mapping file with the given name and returns a map + * from class/entity names to their corresponding elements. + * + * @param string $file The mapping file to load. + * @return array + */ + abstract protected function _loadMappingFile($file); +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php index 3ab8d4911..82f2f0609 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php @@ -38,7 +38,7 @@ require __DIR__ . '/DoctrineAnnotations.php'; * @author Roman Borschel * @since 2.0 */ -class AnnotationDriver +class AnnotationDriver implements Driver { /** * Loads the metadata for the specified class into the provided container. diff --git a/lib/Doctrine/ORM/Mapping/Driver/Driver.php b/lib/Doctrine/ORM/Mapping/Driver/Driver.php new file mode 100644 index 000000000..ab9d509ae --- /dev/null +++ b/lib/Doctrine/ORM/Mapping/Driver/Driver.php @@ -0,0 +1,54 @@ +. + */ + +namespace Doctrine\ORM\Mapping\Driver; + +use Doctrine\ORM\Mapping\ClassMetadata; + +/** + * SchemaMetadata mapping driver interface + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 2.0 + * @version $Revision: 1393 $ + * @author Jonathan H. Wage + */ +interface Driver +{ + /** + * Loads the metadata for the specified class into the provided container. + * + * @param string $className + * @param ClassMetadata $metadata + */ + public function loadMetadataForClass($className, ClassMetadata $metadata); + + /** + * Whether the class with the specified name should have its metadata loaded. + * This is only the case if it is either mapped as an Entity or a + * MappedSuperclass. + * + * @param string $className + * @return boolean + */ + public function isTransient($className); +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php index 5d9b25505..8098f1c7f 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php @@ -22,7 +22,6 @@ namespace Doctrine\ORM\Mapping\Driver; use Doctrine\ORM\Mapping\ClassMetadata; -use Doctrine\ORM\Mapping\MappingException; /** * XmlDriver is a metadata driver that enables mapping through XML files. @@ -30,63 +29,9 @@ use Doctrine\ORM\Mapping\MappingException; * @author Roman Borschel * @since 2.0 */ -class XmlDriver +class XmlDriver extends AbstractFileDriver { - /** - * The FILE_PER_CLASS mode is an operating mode of the XmlDriver where it loads - * the mapping files of individual classes on demand. This requires the user to - * adhere to the convention of 1 mapping file per class and the file names of - * the mapping files must correspond to the full class name, including namespace, - * with the namespace delimiters '\', replaced by dots '.'. - * - * Example: - * Class: My\Project\Model\User - * Mapping file: My.Project.Model.User.dcm.xml - * - * @var integer - */ - const FILE_PER_CLASS = 1; - - /** - * The PRELOAD mode is an operating mode of the XmlDriver where it loads - * all mapping files in advance. This is the default behavior. It does not - * require a naming convention or the convention of 1 class per mapping file. - * - * @var integer - */ - const PRELOAD = 2; - - /** The paths where to look for mapping files. */ - private $_paths; - /** The operating mode. Either FILE_PER_CLASS or PRELOAD. */ - private $_mode; - /** The file extension of mapping documents. */ - private $_fileExtension = '.dcm.xml'; - /** Any preloaded XML elements. */ - private $_xmlElements = array(); - - /** - * Initializes a new XmlDriver that looks in the given path(s) for mapping - * documents and operates in the specified operating mode. - * - * @param string|array $paths One or multiple paths where mapping documents can be found. - * @param integer $mode The operating mode. Either PRELOAD (default) or FILE_PER_CLASS. - */ - public function __construct($paths, $mode = self::PRELOAD) - { - $this->_paths = $paths; - $this->_mode = $mode; - } - - /** - * Gets any preloaded XML documents. - * - * @return array - */ - public function getPreloadedXmlElements() - { - return $this->_xmlElements; - } + protected $_fileExtension = '.dcm.xml'; /** * Loads the metadata for the specified class into the provided container. @@ -96,13 +41,7 @@ class XmlDriver */ public function loadMetadataForClass($className, ClassMetadata $metadata) { - if (isset($this->_xmlElements[$className])) { - $xmlRoot = $this->_xmlElements[$className]; - unset($this->_xmlElements[$className]); - } else { - $result = $this->_loadMappingFile($this->_findMappingFile($className)); - $xmlRoot = $result[$className]; - } + $xmlRoot = $this->getElement($className); if ($xmlRoot->getName() == 'entity') { @@ -134,7 +73,6 @@ class XmlDriver } } - // Evaluate mappings foreach ($xmlRoot->id as $idElement) { $mapping = array( @@ -263,59 +201,6 @@ class XmlDriver } else if ($xmlRoot->getName() == 'mapped-superclass') { throw MappingException::notImplemented('Mapped superclasses are not yet supported.'); } - - } - - /** - * Whether the class with the specified name should have its metadata loaded. - * This is only the case if it is either mapped as an Entity or a - * MappedSuperclass. - * - * @param string $className - * @return boolean - */ - public function isTransient($className) - { - $isTransient = true; - if ($this->_mode == self::FILE_PER_CLASS) { - // check whether file exists - foreach ((array)$this->_paths as $path) { - if (file_exists($path . DIRECTORY_SEPARATOR . str_replace('\\', '.', $className) . $this->_fileExtension)) { - $isTransient = false; - break; - } - } - } else { - $isTransient = isset($this->_xmlElements[$className]); - } - - return $isTransient; - } - - /** - * Preloads all mapping information found in any documents within the - * configured paths and returns a list of class names that have been preloaded. - * - * @return array The list of class names that have been preloaded. - */ - public function preload() - { - if ($this->_mode != self::PRELOAD) { - return array(); - } - - foreach ((array)$this->_paths as $path) { - if (is_dir($path)) { - $files = glob($path . '/*' . $this->_fileExtension); - foreach ($files as $file) { - $this->_xmlElements = array_merge($this->_xmlElements, $this->_loadMappingFile($file)); - } - } else if (is_file($path)) { - $this->_xmlElements = array_merge($this->_xmlElements, $this->_loadMappingFile($path)); - } - } - - return array_keys($this->_xmlElements); } /** @@ -325,7 +210,7 @@ class XmlDriver * @param string $file The mapping file to load. * @return array */ - private function _loadMappingFile($file) + protected function _loadMappingFile($file) { $result = array(); $xmlElement = simplexml_load_file($file); @@ -345,31 +230,6 @@ class XmlDriver return $result; } - /** - * Finds the mapping file for the class with the given name by searching - * through the configured paths. - * - * @param $className - * @return string The (absolute) file name. - * @throws MappingException - */ - private function _findMappingFile($className) - { - $fileName = null; - foreach ((array)$this->_paths as $path) { - $fileName = $path . DIRECTORY_SEPARATOR . str_replace('\\', '.', $className) . $this->_fileExtension; - if (file_exists($fileName)) { - break; - } - } - - if ($fileName === null) { - throw MappingException::mappingFileNotFound($className); - } - - return $fileName; - } - /** * Constructs a joinColumn mapping array based on the information * found in the given SimpleXMLElement. @@ -423,5 +283,4 @@ class XmlDriver return $cascades; } -} - +} \ No newline at end of file diff --git a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php index 3c7318782..09c06251b 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php @@ -36,110 +36,249 @@ if ( ! class_exists('sfYaml', false)) { * @author Jonathan H. Wage * @since 2.0 */ -class YamlDriver +class YamlDriver extends AbstractFileDriver { - protected - $_paths = array(), - $_entities = array(); - - public function __construct($paths) - { - $this->_paths = $paths; - $this->_entities = $this->_loadYaml($this->_paths); - } - - public function getEntities() - { - return $this->_entities; - } + protected $_fileExtension = '.dcm.yml'; public function loadMetadataForClass($className, ClassMetadata $metadata) { - $entity = $this->_entities[$className]; + $element = $this->getElement($className); - if (isset($entity['repositoryClass']) && $entity['repositoryClass']) { - $metadata->setCustomRepositoryClass($entity['repositoryClass']); - } + if ($element['type'] == 'entity') { - if (isset($entity['table'])) { - $metadata->setPrimaryTable($entity['table']); - } - - if (isset($entity['inheritanceType']) && $entity['inheritanceType']) { - $metadata->setInheritanceType($entity['inheritanceType']); - } - - if (isset($entity['discriminatorColumn'])) { - $metadata->setDiscriminatorColumn($entity['discriminatorColumn']); - } - - if (isset($entity['discriminatorValue']) && $entity['discriminatorValue']) { - $metadata->setDiscriminatorValue($entity['discriminatorValue']); - } - - if (isset($entity['subClasses']) && $entity['subClasses']) { - $metadata->setSubclasses((array) $entity['subClasses']); - } - - $relationTypes = array('OneToOne', 'OneToMany', 'ManyToOne', 'ManyToMany'); - - foreach ($entity['properties'] as $name => $property) { - $mapping = array(); - $mapping['fieldName'] = $name; - - $joinColumns = array(); - if (isset($property['joinColumn']) && $property['joinColumn']) { - $joinColumns[] = $property['joinColumn']; - } else if (isset($property['joinColumns']) && $property['joinColumns']) { - $joinColumns = $property['joinColumns']; + // Evaluate root level properties + if (isset($element['table'])) { + $metadata->primaryTable['name'] = $element['table']; + } + if (isset($element['schema'])) { + $metadata->primaryTable['schema'] = $element['schema']; + } + if (isset($element['inheritanceType'])) { + $metadata->setInheritanceType($element['inheritanceType']); } - $type = $property['type']; + // Evaluate fields + if (isset($element['fields'])) { + foreach ($element['fields'] as $name => $fieldMapping) { + $mapping = array( + 'fieldName' => $name, + 'type' => $fieldMapping['type'] + ); + if (isset($fieldMapping['column'])) { + $mapping['columnName'] = $fieldMapping['column']; + } + if (isset($fieldMapping['length'])) { + $mapping['length'] = $fieldMapping['length']; + } + $metadata->mapField($mapping); + } + } - $mapping = array_merge($mapping, $property); + // Evaluate identifier settings + foreach ($element['id'] as $name => $idElement) { + $mapping = array( + 'id' => true, + 'fieldName' => $name, + 'type' => $idElement['type'] + ); + if (isset($idElement['column'])) { + $mapping['columnName'] = $idElement['column']; + } + $metadata->mapField($mapping); - if (in_array($type, $relationTypes)) { - unset($property['type']); + if (isset($idElement['generator'])) { + $metadata->setIdGeneratorType($idElement['generator']['strategy']); + } + } - switch ($type) { - case 'ManyToOne': - case 'OneToOne': + // Evaluate oneToOne relationships + if (isset($element['oneToOne'])) { + foreach ($element['oneToOne'] as $name => $oneToOneElement) { + $mapping = array( + 'fieldName' => $name, + 'targetEntity' => $oneToOneElement['targetEntity'] + ); + if (isset($oneToOneElement['mappedBy'])) { + $mapping['mappedBy'] = $oneToOneElement['mappedBy']; + } else { + $joinColumns = array(); + if (isset($oneToOneElement['joinColumn'])) { + $joinColumns[] = $this->_getJoinColumnMapping($oneToOneElement['joinColumn']); + } else if (isset($oneToOneElement['joinColumns'])) { + foreach ($oneToOneElement['joinColumns'] as $name => $joinColumnElement) { + if (!isset($joinColumnElement['name'])) { + $joinColumnElement['name'] = $name; + } + $joinColumns[] = $this->_getJoinColumnMapping($joinColumnElement); + } + } else { + throw MappingException::invalidMapping($mapping['fieldName']); + } $mapping['joinColumns'] = $joinColumns; - break; - case 'ManyToMany': - $joinTable = array(); - if (isset($property['joinTable'])) { - $joinTable = $property['joinTable']; + } + + if (isset($oneToOneElement['cascade'])) { + $mapping['cascade'] = $this->_getCascadeMappings($oneToOneElement['cascade']); + } + + $metadata->mapOneToOne($mapping); + } + } + + // Evaluate oneToMany relationships + if (isset($element['oneToMany'])) { + foreach ($element['oneToMany'] as $name => $oneToManyElement) { + $mapping = array( + 'fieldName' => $name, + 'targetEntity' => $oneToManyElement['targetEntity'], + 'mappedBy' => $oneToManyElement['mappedBy'] + ); + if (isset($oneToManyElement['cascade'])) { + $mapping['cascade'] = $this->_getCascadeMappings($oneToManyElement['cascade']); + } + $metadata->mapOneToMany($mapping); + } + } + + // Evaluate manyToOne relationships + if (isset($element['manyToOne'])) { + foreach ($element['manyToOne'] as $name => $manyToOneElement) { + $mapping = array( + 'fieldName' => $name, + 'targetEntity' => $manyToOneElement['targetEntity'] + ); + $joinColumns = array(); + if (isset($manyToOneElement['joinColumn'])) { + $joinColumns[] = $this->_getJoinColumnMapping($manyToOneElement['joinColumn']); + } else if (isset($manyToOneElement['joinColumns'])) { + foreach ($manyToOneElement['joinColumns'] as $name => $joinColumnElement) { + if (!isset($joinColumnElement['name'])) { + $joinColumnElement['name'] = $name; + } + $joinColumns[] = $this->_getJoinColumnMapping($joinColumnElement); + } + } else { + throw MappingException::invalidMapping($mapping['fieldName']); + } + $mapping['joinColumns'] = $joinColumns; + if (isset($manyToOneElement['cascade'])) { + $mapping['cascade'] = $this->_getCascadeMappings($manyToOneElement['cascade']); + } + $metadata->mapManyToOne($mapping); + } + } + + // Evaluate manyToMany relationships + if (isset($element['manyToMany'])) { + foreach ($element['manyToMany'] as $name => $manyToManyElement) { + $mapping = array( + 'fieldName' => $name, + 'targetEntity' => $manyToManyElement['targetEntity'] + ); + + if (isset($manyToManyElement['mappedBy'])) { + $mapping['mappedBy'] = $manyToManyElement['mappedBy']; + } else if (isset($manyToManyElement['joinTable'])) { + $joinTableElement = $manyToManyElement['joinTable']; + $joinTable = array( + 'name' => $joinTableElement['name'] + ); + if (isset($joinTableElement['schema'])) { + $joinTable['schema'] = $joinTableElement['schema']; + } + foreach ($joinTableElement['joinColumns'] as $name => $joinColumnElement) { + if (!isset($joinColumnElement['name'])) { + $joinColumnElement['name'] = $name; + } + $joinTable['joinColumns'][] = $this->_getJoinColumnMapping($joinColumnElement); + } + foreach ($joinTableElement['inverseJoinColumns'] as $name => $joinColumnElement) { + if (!isset($joinColumnElement['name'])) { + $joinColumnElement['name'] = $name; + } + $joinTable['inverseJoinColumns'][] = $this->_getJoinColumnMapping($joinColumnElement); } $mapping['joinTable'] = $joinTable; - break; - case 'OneToMany': - default: - break; - } + } else { + throw MappingException::invalidMapping($mapping['fieldName']); + } + + if (isset($manyToManyElement['cascade'])) { + $mapping['cascade'] = $this->_getCascadeMappings($manyToManyElement['cascade']); + } - $func = 'map' . $type; - $metadata->$func($mapping); - } else { - $metadata->mapField($mapping); + $metadata->mapManyToMany($mapping); + } } - + + } else if ($element['type'] == 'mapped-superclass') { + throw MappingException::notImplemented('Mapped superclasses are not yet supported.'); } } - protected function _loadYaml($paths) + /** + * Constructs a joinColumn mapping array based on the information + * found in the given SimpleXMLElement. + * + * @param $joinColumnElement The XML element. + * @return array The mapping array. + */ + private function _getJoinColumnMapping($joinColumnElement) { - $array = array(); - foreach ((array) $paths as $path) { - if (is_dir($path)) { - $files = glob($path . '/*.yml'); - foreach ($files as $file) { - $array = array_merge($array, \sfYaml::load($file)); - } - } else if (is_file($path)) { - $array = array_merge($array, \sfYaml::load($path)); - } + $joinColumn = array( + 'name' => $joinColumnElement['name'], + 'referencedColumnName' => $joinColumnElement['referencedColumnName'] + ); + if (isset($joinColumnElement['unique'])) { + $joinColumn['unique'] = (bool) $joinColumnElement['unique']; } - return $array; + if (isset($joinColumnElement['nullable'])) { + $joinColumn['nullable'] = (bool) $joinColumnElement['nullable']; + } + if (isset($joinColumnElement['onDelete'])) { + $joinColumn['onDelete'] = $joinColumnElement['onDelete']; + } + if (isset($joinColumnElement['onUpdate'])) { + $joinColumn['onUpdate'] = $joinColumnElement['onUpdate']; + } + + return $joinColumn; + } + + /** + * Gathers a list of cascade options found in the given cascade element. + * + * @param $cascadeElement The cascade element. + * @return array The list of cascade options. + */ + private function _getCascadeMappings($cascadeElement) + { + $cascades = array(); + if (isset($cascadeElement['cascadeSave'])) { + $cascades[] = 'save'; + } + if (isset($cascadeElement['cascadeDelete'])) { + $cascades[] = 'delete'; + } + if (isset($cascadeElement['cascadeMerge'])) { + $cascades[] = 'merge'; + } + if (isset($cascadeElement['cascadeRefresh'])) { + $cascades[] = 'refresh'; + } + + return $cascades; + } + + /** + * Loads a mapping file with the given name and returns a map + * from class/entity names to their corresponding elements. + * + * @param string $file The mapping file to load. + * @return array + */ + protected function _loadMappingFile($file) + { + return \sfYaml::load($file); } } \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Mapping/AllTests.php b/tests/Doctrine/Tests/ORM/Mapping/AllTests.php index 2a004ac78..29e94c011 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/AllTests.php +++ b/tests/Doctrine/Tests/ORM/Mapping/AllTests.php @@ -21,7 +21,8 @@ class AllTests $suite->addTestSuite('Doctrine\Tests\ORM\Mapping\ClassMetadataTest'); $suite->addTestSuite('Doctrine\Tests\ORM\Mapping\XmlDriverTest'); - //$suite->addTestSuite('Doctrine\Tests\ORM\Mapping\ClassMetadataFactoryTest'); + $suite->addTestSuite('Doctrine\Tests\ORM\Mapping\YamlDriverTest'); + $suite->addTestSuite('Doctrine\Tests\ORM\Mapping\ClassMetadataFactoryTest'); return $suite; } diff --git a/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataFactoryTest.php b/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataFactoryTest.php index 1d234f098..cbebad0a3 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataFactoryTest.php +++ b/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataFactoryTest.php @@ -75,3 +75,10 @@ class ClassMetadataFactoryTestSubject extends \Doctrine\ORM\Mapping\ClassMetadat return $this->_requestedClasses; } } + +class TestEntity1 +{ + private $id; + private $name; + private $other; +} \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Mapping/XmlDriverTest.php b/tests/Doctrine/Tests/ORM/Mapping/XmlDriverTest.php index 1fae46529..bbebce3cb 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/XmlDriverTest.php +++ b/tests/Doctrine/Tests/ORM/Mapping/XmlDriverTest.php @@ -46,7 +46,6 @@ class XmlDriverTest extends \Doctrine\Tests\OrmTestCase $this->assertTrue($class->associationMappings['groups'] instanceof \Doctrine\ORM\Mapping\ManyToManyMapping); $this->assertTrue(isset($class->associationMappings['groups'])); $this->assertTrue($class->associationMappings['groups']->isOwningSide); - } public function testPreloadMode() @@ -58,10 +57,10 @@ class XmlDriverTest extends \Doctrine\Tests\OrmTestCase $classNames = $xmlDriver->preload(); $this->assertEquals($className, $classNames[0]); - $this->assertEquals(1, count($xmlDriver->getPreloadedXmlElements())); + $this->assertEquals(1, count($xmlDriver->getPreloadedElements())); $xmlDriver->loadMetadataForClass($className, $class); - $this->assertEquals(0, count($xmlDriver->getPreloadedXmlElements())); + $this->assertEquals(0, count($xmlDriver->getPreloadedElements())); } } \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Mapping/YamlDriverTest.php b/tests/Doctrine/Tests/ORM/Mapping/YamlDriverTest.php new file mode 100644 index 000000000..061fd5db8 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Mapping/YamlDriverTest.php @@ -0,0 +1,66 @@ +assertFalse($yamlDriver->isTransient($className)); + + $yamlDriver->loadMetadataForClass($className, $class); + + $this->assertEquals('cms_users', $class->getTableName()); + $this->assertEquals(ClassMetadata::INHERITANCE_TYPE_NONE, $class->getInheritanceType()); + $this->assertEquals(2, count($class->fieldMappings)); + $this->assertTrue(isset($class->fieldMappings['id'])); + $this->assertTrue(isset($class->fieldMappings['name'])); + $this->assertEquals('string', $class->fieldMappings['name']['type']); + $this->assertEquals(array('id'), $class->identifier); + $this->assertEquals(ClassMetadata::GENERATOR_TYPE_AUTO, $class->getIdGeneratorType()); + + $this->assertEquals(3, count($class->associationMappings)); + $this->assertEquals(1, count($class->inverseMappings)); + + $this->assertTrue($class->associationMappings['address'] instanceof \Doctrine\ORM\Mapping\OneToOneMapping); + $this->assertTrue(isset($class->associationMappings['address'])); + $this->assertTrue($class->associationMappings['address']->isOwningSide); + + $this->assertTrue($class->associationMappings['phonenumbers'] instanceof \Doctrine\ORM\Mapping\OneToManyMapping); + $this->assertTrue(isset($class->associationMappings['phonenumbers'])); + $this->assertFalse($class->associationMappings['phonenumbers']->isOwningSide); + $this->assertTrue($class->associationMappings['phonenumbers']->isInverseSide()); + $this->assertTrue($class->associationMappings['phonenumbers']->isCascadeSave); + + $this->assertTrue($class->associationMappings['groups'] instanceof \Doctrine\ORM\Mapping\ManyToManyMapping); + $this->assertTrue(isset($class->associationMappings['groups'])); + $this->assertTrue($class->associationMappings['groups']->isOwningSide); + } + + public function testPreloadMode() + { + $className = 'YamlMappingTest\User'; + $yamlDriver = new YamlDriver(__DIR__ . DIRECTORY_SEPARATOR . 'yaml'); + $class = new ClassMetadata($className); + + $classNames = $yamlDriver->preload(); + + $this->assertEquals($className, $classNames[0]); + $this->assertEquals(1, count($yamlDriver->getPreloadedElements())); + + $yamlDriver->loadMetadataForClass($className, $class); + + $this->assertEquals(0, count($yamlDriver->getPreloadedElements())); + } +} \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Mapping/xml/User.php b/tests/Doctrine/Tests/ORM/Mapping/xml/User.php index 9cd7ac40a..190a135ca 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/xml/User.php +++ b/tests/Doctrine/Tests/ORM/Mapping/xml/User.php @@ -10,4 +10,4 @@ class User { private $groups; // ... rest of code omitted, irrelevant for the mapping test -} +} \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Mapping/xml/XmlMappingTest.User.dcm.xml b/tests/Doctrine/Tests/ORM/Mapping/xml/XmlMappingTest.User.dcm.xml index d21c40e36..57abf84ea 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/xml/XmlMappingTest.User.dcm.xml +++ b/tests/Doctrine/Tests/ORM/Mapping/xml/XmlMappingTest.User.dcm.xml @@ -37,4 +37,4 @@ - + \ No newline at end of file diff --git a/tests/Doctrine/Tests/ORM/Mapping/yaml/User.php b/tests/Doctrine/Tests/ORM/Mapping/yaml/User.php new file mode 100644 index 000000000..13652659b --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Mapping/yaml/User.php @@ -0,0 +1,13 @@ +