From 4b67aac4f9e8cfe9f4d1027368f25212a1161b5b Mon Sep 17 00:00:00 2001 From: Saem Ghani Date: Thu, 27 Sep 2012 10:51:22 -0700 Subject: [PATCH 1/2] Update lib/Doctrine/ODM/CouchDB/Mapping/MappingException.php Add missing method static factory method for MappingException. This is used by DoctrineCouchDBBundle in the XML and YAML drivers. --- lib/Doctrine/ODM/CouchDB/Mapping/MappingException.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/Doctrine/ODM/CouchDB/Mapping/MappingException.php b/lib/Doctrine/ODM/CouchDB/Mapping/MappingException.php index b7b996a8..7daaeae7 100644 --- a/lib/Doctrine/ODM/CouchDB/Mapping/MappingException.php +++ b/lib/Doctrine/ODM/CouchDB/Mapping/MappingException.php @@ -60,4 +60,11 @@ public static function invalidInheritanceRoot($className, $parents) "parent classes: " . implode(", ", $parents) ); } + + public static function mappingFileNotFound($className, $filename) + { + return new self( + "Mapping file: '" . $filename . "' not found, for class: '" . $className . "'." + ); + } } From 593b6fc509c377bf95e0ee642cebbd4a8f52c569 Mon Sep 17 00:00:00 2001 From: Saem Ghani Date: Wed, 26 Sep 2012 09:45:48 -0700 Subject: [PATCH 2/2] Updated Metadata collection to the latest doctrine libraries * Remove composer.lock file which precluded pulling down dependencies -- this lets you now work on the project * A number of tests still fail or error out, they did the same thing before, so no change (I will get to those in another commit) ** There is a performance test which runs just slightly over 1 second on my machine and is failing, there needs to be a better way * Updated Configuration to use new Metadata Driver implementation ** This means that rather than have . separated FQCN for file names, now short names are used * Updated ClassMetadata, ClassMetadataInfo, and ClassMetadata to new doctrine infrastructure ** This has introduced a failing test InheritenceTest::testPersistInheritanceReferenceOne, but I think the test doesn't make sense, even with a reference one you inherit from multiple classes and you can't have multiple inheritence, so the proxy should only extend the abstract class, as a parameter it's covariant, but the returned type is covariant ** The ClassMetadataFactoryTest::testGetMetadataForDocumentWithMappedSuperclass the test doesn't make sense, the rootDocumentName should be Super, as everything else is extending it? Known Issues: * I am doing a simple insert and then using findBy to pull it out, it's only inserting one (verified by futon), and but a count on the returned array shows 3, this was busted before and after. =( --- composer.json | 5 +- composer.lock | 35 --- lib/Doctrine/ODM/CouchDB/Configuration.php | 6 +- .../ODM/CouchDB/Mapping/ClassMetadata.php | 11 +- .../CouchDB/Mapping/ClassMetadataFactory.php | 212 +++++------------ .../ODM/CouchDB/Mapping/ClassMetadataInfo.php | 11 +- .../Mapping/Driver/AbstractFileDriver.php | 213 ------------------ .../Mapping/Driver/AnnotationDriver.php | 182 ++------------- .../ODM/CouchDB/Mapping/Driver/Driver.php | 59 ----- .../ODM/CouchDB/Mapping/Driver/PHPDriver.php | 114 +--------- .../ODM/CouchDB/Mapping/Driver/XmlDriver.php | 40 +++- .../ODM/CouchDB/Mapping/Driver/YamlDriver.php | 34 ++- .../ODM/CouchDB/CouchDBFunctionalTestCase.php | 4 +- .../Mapping/ClassMetadataFactoryTest.php | 7 +- 14 files changed, 166 insertions(+), 767 deletions(-) delete mode 100644 composer.lock delete mode 100644 lib/Doctrine/ODM/CouchDB/Mapping/Driver/AbstractFileDriver.php delete mode 100644 lib/Doctrine/ODM/CouchDB/Mapping/Driver/Driver.php diff --git a/composer.json b/composer.json index d658d71e..5fa038af 100644 --- a/composer.json +++ b/composer.json @@ -16,8 +16,11 @@ "symfony/console": ">=2.0" }, "minimum-stability": "dev", + "require-dev": { + "symfony/yaml": ">=2.0.0,<2.2.0-dev" + }, "suggest": { - "symfony/yaml": ">=2.0" + "symfony/yaml": ">=2.0.0,<2.2.0-dev" }, "autoload": { "psr-0": { diff --git a/composer.lock b/composer.lock deleted file mode 100644 index 1dd44b51..00000000 --- a/composer.lock +++ /dev/null @@ -1,35 +0,0 @@ -{ - "hash": "4343dff215c65b110968c521ec0e5f2e", - "packages": [ - { - "package": "doctrine/common", - "version": "2.2.2" - }, - { - "package": "doctrine/couchdb", - "version": "dev-master", - "source-reference": "bd5911054f39504c884606db6e290a10b7f05f75", - "commit-date": "1345228208" - }, - { - "package": "symfony/console", - "version": "dev-master", - "alias-pretty-version": "2.1.x-dev", - "alias-version": "2.1.9999999.9999999-dev" - }, - { - "package": "symfony/console", - "version": "dev-master", - "source-reference": "3b66f1056f5ac37146d3b755964e8a43a205f2f5", - "commit-date": "1344349441" - } - ], - "packages-dev": null, - "aliases": [ - - ], - "minimum-stability": "dev", - "stability-flags": [ - - ] -} diff --git a/lib/Doctrine/ODM/CouchDB/Configuration.php b/lib/Doctrine/ODM/CouchDB/Configuration.php index a47e06da..0b4c0b84 100644 --- a/lib/Doctrine/ODM/CouchDB/Configuration.php +++ b/lib/Doctrine/ODM/CouchDB/Configuration.php @@ -23,7 +23,7 @@ use Doctrine\CouchDB\HTTP\Client; use Doctrine\CouchDB\HTTP\SocketClient; use Doctrine\CouchDB\HTTP\LoggingClient; -use Doctrine\ODM\CouchDB\Mapping\Driver\Driver; +use Doctrine\Common\Persistence\Mapping\Driver\MappingDriver; use Doctrine\ODM\CouchDB\Mapping\MetadataResolver\MetadataResolver; use Doctrine\ODM\CouchDB\Mapping\MetadataResolver\DoctrineResolver; @@ -144,11 +144,11 @@ public function setDocumentNamespaces(array $documentNamespaces) /** * Sets the cache driver implementation that is used for metadata caching. * - * @param Driver $driverImpl + * @param MappingDriver $driverImpl * @todo Force parameter to be a Closure to ensure lazy evaluation * (as soon as a metadata cache is in effect, the driver never needs to initialize). */ - public function setMetadataDriverImpl(Driver $driverImpl) + public function setMetadataDriverImpl(MappingDriver $driverImpl) { $this->attributes['metadataDriverImpl'] = $driverImpl; } diff --git a/lib/Doctrine/ODM/CouchDB/Mapping/ClassMetadata.php b/lib/Doctrine/ODM/CouchDB/Mapping/ClassMetadata.php index b5c1e411..b2e05405 100644 --- a/lib/Doctrine/ODM/CouchDB/Mapping/ClassMetadata.php +++ b/lib/Doctrine/ODM/CouchDB/Mapping/ClassMetadata.php @@ -2,7 +2,9 @@ namespace Doctrine\ODM\CouchDB\Mapping; -use Doctrine\Common\Persistence\Mapping\ClassMetadata AS IClassMetadata; +use Doctrine\Common\Persistence\Mapping\ClassMetadata AS IClassMetadata, + ReflectionClass, + ReflectionProperty; /** * Metadata class @@ -67,6 +69,7 @@ public function deriveChildMetadata($childName) $cm->reflClass = new \ReflectionClass($childName); $cm->name = $cm->reflClass->getName(); $cm->namespace = $cm->reflClass->getNamespaceName(); + if ($this->isMappedSuperclass) { $cm->rootDocumentName = $cm->name; } @@ -296,14 +299,14 @@ public function getIdentifierValue($document) { return (string) $this->reflFields[$this->identifier]->getValue($document); } - + /** * Get identifier values of this document. - * + * * Since CouchDB only allows exactly one identifier field this is a proxy * to {@see getIdentifierValue()} and returns an array with the identifier * field as a key. - * + * * @param object $document * @return array */ diff --git a/lib/Doctrine/ODM/CouchDB/Mapping/ClassMetadataFactory.php b/lib/Doctrine/ODM/CouchDB/Mapping/ClassMetadataFactory.php index f1fd730e..9e855c94 100644 --- a/lib/Doctrine/ODM/CouchDB/Mapping/ClassMetadataFactory.php +++ b/lib/Doctrine/ODM/CouchDB/Mapping/ClassMetadataFactory.php @@ -20,9 +20,13 @@ namespace Doctrine\ODM\CouchDB\Mapping; use Doctrine\ODM\CouchDB\DocumentManager, - Doctrine\ODM\CouchDB\Mapping\ClassMetadata, Doctrine\ODM\CouchDB\CouchDBException, - Doctrine\Common\Cache\Cache; + Doctrine\ODM\CouchDB\Mapping\ClassMetadata, + Doctrine\Common\Persistence\Mapping\Driver\MappingDriver, + Doctrine\Common\Persistence\Mapping\ClassMetadata as ClassMetadataInterface, + Doctrine\Common\Persistence\Mapping\ReflectionService, + Doctrine\Common\Persistence\Mapping\RuntimeReflectionService, + Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory; /** * The ClassMetadataFactory is used to create ClassMetadata objects that contain all the @@ -35,76 +39,58 @@ * @author Benjamin Eberlei * @author Lukas Kahwe Smith */ -class ClassMetadataFactory implements \Doctrine\Common\Persistence\Mapping\ClassMetadataFactory +class ClassMetadataFactory extends AbstractClassMetadataFactory { /** * @var DocumentManager */ private $dm; - /** - * @var array - */ - private $loadedMetadata; - /** * The used metadata driver. * - * @var Doctrine\ODM\CouchDB\Mapping\Driver\Driver + * @var MappingDriver */ private $driver; - /** - * The used cache driver. - * - * @var Cache - */ - private $cacheDriver; - /** * Creates a new factory instance that uses the given DocumentManager instance. * - * @param $dm The DocumentManager instance + * @param DocumentManager $dm The DocumentManager instance */ public function __construct(DocumentManager $dm) { $this->dm = $dm; $config = $this->dm->getConfiguration(); + $this->setCacheDriver($config->getMetadataCacheImpl()); $this->driver = $config->getMetadataDriverImpl(); - $this->cacheDriver = $config->getMetadataCacheImpl(); if (!$this->driver) { - throw new \RuntimeException("No metadata driver was configured."); + throw new \RuntimeException('No metadata driver was configured.'); } } /** - * Sets the cache driver used by the factory to cache ClassMetadata instances. - * - * @param Doctrine\Common\Cache\Cache $cacheDriver + * {@inheritdoc} */ - public function setCacheDriver($cacheDriver) + protected function doLoadMetadata($class, $parent, $rootEntityFound, array $nonSuperclassParents) { - $this->cacheDriver = $cacheDriver; - } + /** @var $parent ClassMetaData */ + if ($parent) { + $parent->deriveChildMetadata($class->getName()); + $class->setParentClasses($nonSuperclassParents); + } - /** - * Gets the cache driver used by the factory to cache ClassMetadata instances. - * - * @return Doctrine\Common\Cache\Cache - */ - public function getCacheDriver() - { - return $this->cacheDriver; + if ($this->getDriver()) { + $this->getDriver()->loadMetadataForClass($class->getName(), $class); + } } /** - * Gets the array of loaded ClassMetadata instances. - * - * @return array $loadedMetadata The loaded metadata. + * {@inheritdoc} */ - public function getLoadedMetadata() + protected function getFqcnFromAlias($namespaceAlias, $simpleClassName) { - return $this->loadedMetadata; + return $this->dm->getConfiguration()->getDocumentNamespace($namespaceAlias) . '\\' . $simpleClassName; } /** @@ -127,63 +113,15 @@ public function getAllMetadata() * Gets the class metadata descriptor for a class. * * @param string $className The name of the class. - * @return Doctrine\ODM\CouchDB\Mapping\ClassMetadata + * @return ClassMetadata */ public function getMetadataFor($className) { - if ( ! isset($this->loadedMetadata[$className])) { - $realClassName = $className; - - // Check for namespace alias - if (strpos($className, ':') !== false) { - list($namespaceAlias, $simpleClassName) = explode(':', $className); - $realClassName = $this->dm->getConfiguration()->getDocumentNamespace($namespaceAlias) . '\\' . $simpleClassName; - - if (isset($this->loadedMetadata[$realClassName])) { - // We do not have the alias name in the map, include it - $this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName]; - - return $this->loadedMetadata[$realClassName]; - } - } - - if ($this->cacheDriver) { - if (($cached = $this->cacheDriver->fetch("$realClassName\$COUCHDBCLASSMETADATA")) !== false) { - $this->loadedMetadata[$realClassName] = $cached; - } else { - foreach ($this->loadMetadata($realClassName) as $loadedClassName) { - $this->cacheDriver->save( - "$loadedClassName\$COUCHDBCLASSMETADATA", $this->loadedMetadata[$loadedClassName], null - ); - } - } - } else { - $this->loadMetadata($realClassName); - } - - if ($className != $realClassName) { - // We do not have the alias name in the map, include it - $this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName]; - } - } - - if (!isset($this->loadedMetadata[$className])) { - throw MappingException::classNotMapped(); - } - - return $this->loadedMetadata[$className]; - } - - protected function getParentClasses($className) - { - // Collect parent classes, ignoring transient (not-mapped) classes. - $parentClasses = array(); - foreach (array_reverse(class_parents($className)) as $parentClass) { - if ( ! $this->driver->isTransient($parentClass)) { - $parentClasses[] = $parentClass; - } + $metadata = parent::getMetadataFor($className); + if ($metadata) { + return $metadata; } - return $parentClasses; + throw MappingException::classNotMapped($className); } /** @@ -192,92 +130,60 @@ protected function getParentClasses($className) * * @param string $className The name of the class for which the metadata should get loaded. */ - private function loadMetadata($name) + protected function loadMetadata($className) { - if (!class_exists($name)) { - throw MappingException::classNotFound($name); + if (class_exists($className)) { + return parent::loadMetadata($className); } - - $parentClasses = $this->getParentClasses($name); - $parentClasses[] = $name; - - $loaded = array(); - $parent = null; - /* @var $parent ClassMetadata */ - foreach ($parentClasses AS $className) { - if (isset($this->loadedMetadata[$className])) { - $parent = $this->loadedMetadata[$className]; - continue; - } - - // original class was checked above already - if ($className != $name && !class_exists($className)) { - throw MappingException::classNotFound($className); - } - - if ($parent) { - $class = $parent->deriveChildMetadata($className); - $class->setParentClasses($parentClasses); - } else { - $class = new ClassMetadata($className); - } - - $this->loadedMetadata[$className] = $class; - $this->driver->loadMetadataForClass($className, $this->loadedMetadata[$className]); - - $parent = $class; - $loaded[] = $className; - } - - return $loaded; + throw MappingException::classNotFound($className); } /** - * Checks whether the factory has the metadata for a class loaded already. + * Creates a new ClassMetadata instance for the given class name. * * @param string $className - * @return boolean TRUE if the metadata of the class in question is already loaded, FALSE otherwise. + * @return ClassMetadata */ - public function hasMetadataFor($className) + protected function newClassMetadataInstance($className) { - return isset($this->loadedMetadata[$className]); + return new ClassMetadata($className); } /** - * Sets the metadata descriptor for a specific class. - * - * NOTE: This is only useful in very special cases, like when generating proxy classes. - * - * @param string $className - * @param ClassMetadata $class + * {@inheritdoc} */ - public function setMetadataFor($className, $class) + protected function getDriver() { - $this->loadedMetadata[$className] = $class; + return $this->driver; } /** - * Creates a new ClassMetadata instance for the given class name. - * - * @param string $className - * @return Doctrine\ODM\CouchDB\Mapping\ClassMetadata + * {@inheritdoc} */ - protected function newClassMetadataInstance($className) + protected function initialize() { - return new ClassMetadata($className); + $this->initialized = true; } /** - * 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 + * {@inheritdoc} */ - public function isTransient($className) + protected function initializeReflection(ClassMetadataInterface $class, ReflectionService $reflService) { - return $this->driver->isTransient($className); } + /** + * {@inheritdoc} + */ + protected function wakeupReflection(ClassMetadataInterface $class, ReflectionService $reflService) + { + } + + /** + * {@inheritDoc} + */ + protected function isEntity(ClassMetadataInterface $class) + { + return isset($class->isMappedSuperclass) && $class->isMappedSuperclass === false; + } } diff --git a/lib/Doctrine/ODM/CouchDB/Mapping/ClassMetadataInfo.php b/lib/Doctrine/ODM/CouchDB/Mapping/ClassMetadataInfo.php index 74e4bdab..66eb43e3 100644 --- a/lib/Doctrine/ODM/CouchDB/Mapping/ClassMetadataInfo.php +++ b/lib/Doctrine/ODM/CouchDB/Mapping/ClassMetadataInfo.php @@ -2,6 +2,8 @@ namespace Doctrine\ODM\CouchDB\Mapping; +use ReflectionClass, + Doctrine\DBAL\Types\Type; /** * Metadata class @@ -464,7 +466,7 @@ public function getFieldMapping($fieldName) * Gets the type of a field. * * @param string $fieldName - * @return Doctrine\DBAL\Types\Type + * @return Type */ public function getTypeOfField($fieldName) { @@ -548,7 +550,7 @@ public function isInheritedField($field) return isset($this->fieldMappings[$field]['declared']); } - public function isInheritedAssocation($field) + public function isInheritedAssociation($field) { return isset($this->associationsMappings[$field]['declared']); } @@ -557,6 +559,9 @@ public function setParentClasses($classes) { $this->parentClasses = $classes; $this->inInheritanceHierachy = true; + if (count($classes) > 0) { + $this->rootDocumentName = array_pop($classes); + } } public function markInheritanceRoot() @@ -564,7 +569,7 @@ public function markInheritanceRoot() if ($this->parentClasses) { throw MappingException::invalidInheritanceRoot($this->name, $this->parentClasses); } - $htis->inInheritanceHierachy = true; + $this->inInheritanceHierachy = true; } } diff --git a/lib/Doctrine/ODM/CouchDB/Mapping/Driver/AbstractFileDriver.php b/lib/Doctrine/ODM/CouchDB/Mapping/Driver/AbstractFileDriver.php deleted file mode 100644 index 6adc78a0..00000000 --- a/lib/Doctrine/ODM/CouchDB/Mapping/Driver/AbstractFileDriver.php +++ /dev/null @@ -1,213 +0,0 @@ -. - */ - -namespace Doctrine\ODM\CouchDB\Mapping\Driver; - -use Doctrine\ODM\CouchDB\Mapping\MappingException; - -/** - * Base driver for file-based metadata drivers. - * - * A file driver operates in a mode 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 '.'. - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.com - * @since 1.0 - * @author Jonathan H. Wage - * @author Roman Borschel - */ -abstract class AbstractFileDriver implements Driver -{ - /** - * The paths where to look for mapping files. - * - * @var array - */ - protected $paths = array(); - - /** - * The file extension of mapping documents. - * - * @var string - */ - protected $fileExtension; - - /** - * 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. - */ - public function __construct($paths) - { - $this->addPaths((array) $paths); - } - - /** - * Append lookup paths to metadata driver. - * - * @param array $paths - */ - public function addPaths(array $paths) - { - $this->paths = array_unique(array_merge($this->paths, $paths)); - } - - /** - * Retrieve the defined metadata lookup paths. - * - * @return array - */ - public function getPaths() - { - return $this->paths; - } - - /** - * 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 (!($file = $this->findMappingFile($className))) { - return false; - } - - $result = $this->loadMappingFile($file); - if (!isset($result[$className])) { - return false; - } - - return $result[$className]; - } - - /** - * 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 = str_replace('\\', '.', $className) . $this->fileExtension; - - // Check whether file exists - foreach ((array) $this->paths as $path) { - if (file_exists($path . DIRECTORY_SEPARATOR . $fileName)) { - return $path . DIRECTORY_SEPARATOR . $fileName; - } - } - - return false; - } - - - /** - * 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) - { - $fileName = str_replace('\\', '.', $className) . $this->fileExtension; - - // Check whether file exists - foreach ((array) $this->paths as $path) { - if (file_exists($path . DIRECTORY_SEPARATOR . $fileName)) { - return false; - } - } - - return true; - } - - /** - * Gets the names of all mapped classes known to this driver. - * - * @return array The names of all mapped classes known to this driver. - */ - public function getAllClassNames() - { - $classes = array(); - - if ($this->paths) { - foreach ((array) $this->paths as $path) { - if ( ! is_dir($path)) { - throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath(); - } - - $iterator = new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator($path), - \RecursiveIteratorIterator::LEAVES_ONLY - ); - - foreach ($iterator as $file) { - if (($fileName = $file->getBasename($this->fileExtension)) == $file->getBasename()) { - continue; - } - - // NOTE: All files found here means classes are not transient! - $classes[] = str_replace('.', '\\', $fileName); - } - } - } - - return $classes; - } - - /** - * Loads a mapping file with the given name and returns a map - * from class/document names to their corresponding elements. - * - * @param string $file The mapping file to load. - * @return array - */ - abstract protected function loadMappingFile($file); -} diff --git a/lib/Doctrine/ODM/CouchDB/Mapping/Driver/AnnotationDriver.php b/lib/Doctrine/ODM/CouchDB/Mapping/Driver/AnnotationDriver.php index db8b0e89..d3686bd7 100644 --- a/lib/Doctrine/ODM/CouchDB/Mapping/Driver/AnnotationDriver.php +++ b/lib/Doctrine/ODM/CouchDB/Mapping/Driver/AnnotationDriver.php @@ -19,8 +19,13 @@ namespace Doctrine\ODM\CouchDB\Mapping\Driver; -use Doctrine\ODM\CouchDB\Mapping\ClassMetadata, +use Doctrine\Common\Annotations\AnnotationReader, + Doctrine\Common\Annotations\AnnotationRegistry, Doctrine\Common\Annotations\Reader, + Doctrine\Common\Persistence\Mapping\ClassMetadata, + Doctrine\Common\Persistence\Mapping\Driver\AnnotationDriver as AbstractAnnotationDriver, + Doctrine\ODM\CouchDB\Mapping\Annotations as ODM, + Doctrine\ODM\CouchDB\Mapping\ClassMetadata as ClassMetaDataInfo, Doctrine\ODM\CouchDB\Mapping\MappingException; /** @@ -32,68 +37,13 @@ * @author Jonathan H. Wage * @author Roman Borschel */ -class AnnotationDriver implements Driver +class AnnotationDriver extends AbstractAnnotationDriver { - /** - * The AnnotationReader. - * - * @var AnnotationReader - */ - private $reader; - - /** - * The paths where to look for mapping files. - * - * @var array - */ - private $paths = array(); - - /** - * The file extension of mapping documents. - * - * @var string - */ - private $fileExtension = '.php'; - - /** - * @param array - */ - private $classNames; - - /** - * Initializes a new AnnotationDriver that uses the given AnnotationReader for reading - * docblock annotations. - * - * @param $reader The AnnotationReader to use. - * @param string|array $paths One or multiple paths where mapping classes can be found. - */ - public function __construct(Reader $reader, $paths = null) - { - $this->reader = $reader; - if ($paths) { - $this->addPaths((array) $paths); - } - } - - /** - * Append lookup paths to metadata driver. - * - * @param array $paths - */ - public function addPaths(array $paths) - { - $this->paths = array_unique(array_merge($this->paths, $paths)); - } - - /** - * Retrieve the defined metadata lookup paths. - * - * @return array - */ - public function getPaths() - { - return $this->paths; - } + protected $entityAnnotationClasses = array( + 'Doctrine\\ODM\\CouchDB\\Mapping\\Annotations\\Document' => 0, + 'Doctrine\\ODM\\CouchDB\\Mapping\\Annotations\\MappedSuperclass' => 1, + 'Doctrine\\ODM\\CouchDB\\Mapping\\Annotations\\EmbeddedDocument' => 2, + ); /** * {@inheritdoc} @@ -102,34 +52,29 @@ public function loadMetadataForClass($className, ClassMetadata $class) { $reflClass = $class->getReflectionClass(); - $classAnnotations = $this->reader->getClassAnnotations($reflClass); - $isValidDocument = false; - foreach ($classAnnotations AS $classAnnotation) { - if ($classAnnotation instanceof \Doctrine\ODM\CouchDB\Mapping\Annotations\Document) { - if ($classAnnotation->indexed) { - $class->indexed = true; + $documentAnnotations = array(); + foreach ($this->reader->getClassAnnotations($reflClass) AS $annotation) { + foreach ($this->entityAnnotationClasses as $annotationClass => $i) { + if ($annotation instanceof $annotationClass) { + $documentAnnotations[$i] = $annotation; + continue 2; } - $class->setCustomRepositoryClass($classAnnotation->repositoryClass); - $isValidDocument = true; - } elseif ($classAnnotation instanceof \Doctrine\ODM\CouchDB\Mapping\Annotations\EmbeddedDocument) { - $class->isEmbeddedDocument = true; - $isValidDocument = true; - } else if ($classAnnotation instanceof \Doctrine\ODM\CouchDB\Mapping\Annotations\MappedSuperclass) { - $class->isMappedSuperclass = true; - $isValidDocument = true; - } else if ($classAnnotation instanceof \Doctrine\ODM\CouchDB\Mapping\Annotations\Index) { + } + + //non-document class annotations + if ($annotation instanceof \Doctrine\ODM\CouchDB\Mapping\Annotations\Index) { $class->indexed = true; - } else if ($classAnnotation instanceof \Doctrine\ODM\CouchDB\Mapping\Annotations\InheritanceRoot) { + } else if ($annotation instanceof \Doctrine\ODM\CouchDB\Mapping\Annotations\InheritanceRoot) { $class->markInheritanceRoot(); } } - if (!$isValidDocument) { + if (!$documentAnnotations) { throw MappingException::classIsNotAValidDocument($className); } foreach ($reflClass->getProperties() as $property) { - if ($class->isInheritedAssocation($property->name) || $class->isInheritedField($property->name)) { + if ($class->isInheritedAssociation($property->name) || $class->isInheritedField($property->name)) { continue; } @@ -182,81 +127,4 @@ public function loadMetadataForClass($className, ClassMetadata $class) } } } - - /** - * Whether the class with the specified name is transient. Only non-transient - * classes, that is entities and mapped superclasses, should have their metadata loaded. - * A class is non-transient if it is annotated with either @Entity or - * @MappedSuperclass in the class doc block. - * - * @param string $className - * @return boolean - */ - public function isTransient($className) - { - $classAnnotations = $this->reader->getClassAnnotations(new \ReflectionClass($className)); - - foreach ($classAnnotations AS $classAnnotation) { - if ($classAnnotation instanceof \Doctrine\ODM\CouchDB\Mapping\Annotations\Document) { - return false; - } else if ($classAnnotation instanceof \Doctrine\ODM\CouchDB\Mapping\Annotations\MappedSuperclass) { - return false; - } else if ($classAnnotation instanceof \Doctrine\ODM\CouchDB\Mapping\Annotations\EmbeddedDocument) { - return false; - } - } - return true; - } - - /** - * {@inheritDoc} - */ - public function getAllClassNames() - { - if ($this->classNames !== null) { - return $this->classNames; - } - - if ( ! $this->paths) { - throw MappingException::pathRequired(); - } - - $classes = array(); - $includedFiles = array(); - - foreach ($this->paths as $path) { - if ( ! is_dir($path)) { - throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath(); - } - - $iterator = new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator($path), - \RecursiveIteratorIterator::LEAVES_ONLY - ); - - foreach ($iterator as $file) { - if (($fileName = $file->getBasename($this->fileExtension)) == $file->getBasename()) { - continue; - } - - $sourceFile = realpath($file->getPathName()); - require_once $sourceFile; - $includedFiles[] = $sourceFile; - } - } - - $declared = get_declared_classes(); - - foreach ($declared as $className) { - $rc = new \ReflectionClass($className); - $sourceFile = $rc->getFileName(); - if (in_array($sourceFile, $includedFiles) && ! $this->isTransient($className)) { - $classes[] = $className; - } - } - - $this->classNames = $classes; - - return $classes; - } } diff --git a/lib/Doctrine/ODM/CouchDB/Mapping/Driver/Driver.php b/lib/Doctrine/ODM/CouchDB/Mapping/Driver/Driver.php deleted file mode 100644 index 90ec262b..00000000 --- a/lib/Doctrine/ODM/CouchDB/Mapping/Driver/Driver.php +++ /dev/null @@ -1,59 +0,0 @@ -. - */ - -namespace Doctrine\ODM\CouchDB\Mapping\Driver; - -use Doctrine\ODM\CouchDB\Mapping\ClassMetadata; - -/** - * Contract for metadata drivers. - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.org - * @since 1.0 - * @author Jonathan H. Wage - * @author Roman Borschel - */ -interface Driver -{ - /** - * Loads the metadata for the specified class into the provided container. - * - * @param string $className - * @param ClassMetadataInfo $metadata - */ - function loadMetadataForClass($className, ClassMetadata $metadata); - - /** - * Gets the names of all mapped classes known to this driver. - * - * @return array The names of all mapped classes known to this driver. - */ - function getAllClassNames(); - - /** - * Whether the class with the specified name should have its metadata loaded. - * This is only the case if it is either mapped as an Document or a - * MappedSuperclass. - * - * @param string $className - * @return boolean - */ - function isTransient($className); -} diff --git a/lib/Doctrine/ODM/CouchDB/Mapping/Driver/PHPDriver.php b/lib/Doctrine/ODM/CouchDB/Mapping/Driver/PHPDriver.php index 7b5502a1..028ad558 100644 --- a/lib/Doctrine/ODM/CouchDB/Mapping/Driver/PHPDriver.php +++ b/lib/Doctrine/ODM/CouchDB/Mapping/Driver/PHPDriver.php @@ -19,7 +19,7 @@ namespace Doctrine\ODM\CouchDB\Mapping\Driver; -use Doctrine\ODM\CouchDB\Mapping\ClassMetadata; +use Doctrine\Common\Persistence\Mapping\Driver\PHPDriver as CommonPHPDriver; /** * The PHPDriver invokes a static PHP function on the document class itself passing @@ -31,116 +31,6 @@ * @author Jonathan H. Wage * @author Roman Borschel */ -class PHPDriver implements Driver +class PHPDriver extends CommonPHPDriver { - /** - * The paths where to look for mapping files. - * - * @var array - */ - private $paths = array(); - - /** - * The file extension of mapping documents. - * - * @var string - */ - private $fileExtension = '.php'; - - /** - * @param array - */ - private $classNames; - - /** - * Initializes a new AnnotationDriver that uses the given AnnotationReader for reading - * docblock annotations. - * - * @param string|array $paths One or multiple paths where mapping classes can be found. - */ - public function __construct($paths = null) - { - if ($paths) { - $this->addPaths((array) $paths); - } - } - - /** - * Append lookup paths to metadata driver. - * - * @param array $paths - */ - public function addPaths(array $paths) - { - $this->paths = array_unique(array_merge($this->paths, $paths)); - } - - /** - * {@inheritdoc} - */ - public function loadMetadataForClass($className, ClassMetadata $metadata) - { - $className::loadMetadata($metadata); - } - - /** - * {@inheritDoc} - * @todo Same code exists in AnnotationDriver, should we re-use it somehow or not worry about it? - */ - public function getAllClassNames() - { - if ($this->classNames !== null) { - return $this->classNames; - } - - if (!$this->paths) { - throw MappingException::pathRequired(); - } - - $classes = array(); - $includedFiles = array(); - - foreach ($this->paths as $path) { - if ( ! is_dir($path)) { - throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath(); - } - - $iterator = new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator($path), - \RecursiveIteratorIterator::LEAVES_ONLY - ); - - foreach ($iterator as $file) { - if (($fileName = $file->getBasename($this->fileExtension)) == $file->getBasename()) { - continue; - } - - $sourceFile = realpath($file->getPathName()); - require_once $sourceFile; - $includedFiles[] = $sourceFile; - } - } - - $declared = get_declared_classes(); - - foreach ($declared as $className) { - $rc = new \ReflectionClass($className); - $sourceFile = $rc->getFileName(); - if (in_array($sourceFile, $includedFiles) && ! $this->isTransient($className)) { - $classes[] = $className; - } - } - - $this->classNames = $classes; - - return $classes; - } - - /** - * {@inheritdoc} - */ - public function isTransient($className) - { - return method_exists($className, 'loadMetadata') ? false : true; - } } diff --git a/lib/Doctrine/ODM/CouchDB/Mapping/Driver/XmlDriver.php b/lib/Doctrine/ODM/CouchDB/Mapping/Driver/XmlDriver.php index 6291f97c..c1dfeb58 100644 --- a/lib/Doctrine/ODM/CouchDB/Mapping/Driver/XmlDriver.php +++ b/lib/Doctrine/ODM/CouchDB/Mapping/Driver/XmlDriver.php @@ -19,9 +19,11 @@ namespace Doctrine\ODM\CouchDB\Mapping\Driver; -use Doctrine\ODM\CouchDB\Mapping\ClassMetadata, - SimpleXmlElement, - Doctrine\ODM\CouchDB\Mapping\MappingException; +use Doctrine\Common\Persistence\Mapping\Driver\FileDriver, + Doctrine\Common\Persistence\Mapping\ClassMetadata, + Doctrine\ODM\CouchDB\Mapping\MappingException, + Doctrine\Common\Persistence\Mapping\MappingException as DoctrineMappingException, + SimpleXmlElement; /** * XmlDriver is a metadata driver that enables mapping through XML files. @@ -30,25 +32,39 @@ * @link www.doctrine-project.org * @since 1.0 * @author Benjamin Eberlei + * @author Jonathan H. Wage + * @author Roman Borschel */ -class XmlDriver extends AbstractFileDriver +class XmlDriver extends FileDriver { + const DEFAULT_FILE_EXTENSION = '.dcm.yml'; + /** - * The file extension of mapping documents. - * - * @var string + * {@inheritDoc} */ - protected $fileExtension = '.dcm.xml'; + public function __construct($locator, $fileExtension = self::DEFAULT_FILE_EXTENSION) + { + parent::__construct($locator, $fileExtension); + } /** * {@inheritdoc} */ public function loadMetadataForClass($className, ClassMetadata $class) { - /* @var $xmlRoot SimpleXMLElement */ - $xmlRoot = $this->getElement($className); + /** @var $class \Doctrine\ODM\CouchDB\Mapping\ClassMetadata */ + try { + $xmlRoot = $this->getElement($className); + } catch (DoctrineMappingException $e) { + // Convert Exception type for consistency with other drivers + throw new MappingException($e->getMessage(), $e->getCode(), $e); + } + + if (!$xmlRoot) { + return; + } - if ($xmlRoot->getName() == "document") { + if ($xmlRoot->getName() == 'document') { $class->setCustomRepositoryClass( isset($xmlRoot['repository-class']) ? (string)$xmlRoot['repository-class'] : null ); @@ -100,7 +116,7 @@ public function loadMetadataForClass($className, ClassMetadata $class) if (isset($xmlRoot->{"reference-one"})) { foreach ($xmlRoot->{"reference-one"} as $referenceOneElement) { $class->mapManyToOne(array( - 'cascade' => (isset($referenceManyElement->cascade)) ? $this->getCascadeMode($referenceManyElement->cascade) : 0, + 'cascade' => (isset($referenceOneElement->cascade)) ? $this->getCascadeMode($referenceOneElement->cascade) : 0, 'targetDocument' => (string)$referenceOneElement['target-document'], 'fieldName' => (string)$referenceOneElement['field'], 'jsonName' => (isset($referenceOneElement['json-name'])) ? (string)$referenceOneElement['json-name'] : null, diff --git a/lib/Doctrine/ODM/CouchDB/Mapping/Driver/YamlDriver.php b/lib/Doctrine/ODM/CouchDB/Mapping/Driver/YamlDriver.php index da9e2493..4503bbd6 100644 --- a/lib/Doctrine/ODM/CouchDB/Mapping/Driver/YamlDriver.php +++ b/lib/Doctrine/ODM/CouchDB/Mapping/Driver/YamlDriver.php @@ -19,8 +19,11 @@ namespace Doctrine\ODM\CouchDB\Mapping\Driver; -use Doctrine\ODM\CouchDB\Mapping\ClassMetadata, - Doctrine\ODM\CouchDB\Mapping\MappingException; +use Doctrine\Common\Persistence\Mapping\Driver\FileDriver, + Doctrine\Common\Persistence\Mapping\ClassMetadata, + Doctrine\ODM\CouchDB\Mapping\MappingException, + Doctrine\Common\Persistence\Mapping\MappingException as DoctrineMappingException, + Symfony\Component\Yaml\Yaml; /** * The YamlDriver reads the mapping metadata from yaml schema files. @@ -31,21 +34,34 @@ * @author Jonathan H. Wage * @author Roman Borschel */ -class YamlDriver extends AbstractFileDriver +class YamlDriver extends FileDriver { + const DEFAULT_FILE_EXTENSION = '.dcm.yml'; + /** - * The file extension of mapping documents. - * - * @var string + * {@inheritDoc} */ - protected $fileExtension = '.dcm.yml'; + public function __construct($locator, $fileExtension = self::DEFAULT_FILE_EXTENSION) + { + parent::__construct($locator, $fileExtension); + } /** * {@inheritdoc} */ public function loadMetadataForClass($className, ClassMetadata $class) { - $element = $this->getElement($className); + /** @var $class \Doctrine\ODM\CouchDB\Mapping\ClassMetadata */ + try { + $element = $this->getElement($className); + } catch (DoctrineMappingException $e) { + // Convert Exception type for consistency with other drivers + throw new MappingException($e->getMessage(), $e->getCode(), $e); + } + + if (!$element) { + return; + } if ($element['type'] == 'document') { $class->setCustomRepositoryClass( @@ -148,6 +164,6 @@ public function loadMetadataForClass($className, ClassMetadata $class) protected function loadMappingFile($file) { - return \Symfony\Component\Yaml\Yaml::parse($file); + return Yaml::parse($file); } } diff --git a/tests/Doctrine/Tests/ODM/CouchDB/CouchDBFunctionalTestCase.php b/tests/Doctrine/Tests/ODM/CouchDB/CouchDBFunctionalTestCase.php index b0c5f7de..0ce97355 100644 --- a/tests/Doctrine/Tests/ODM/CouchDB/CouchDBFunctionalTestCase.php +++ b/tests/Doctrine/Tests/ODM/CouchDB/CouchDBFunctionalTestCase.php @@ -33,7 +33,7 @@ public function getTestDatabase() { return TestUtil::getTestDatabase(); } - + public function createCouchDBClient() { return new CouchDBClient($this->getHttpClient(), $this->getTestDatabase()); @@ -57,7 +57,7 @@ public function createDocumentManager() $config->setProxyDir(\sys_get_temp_dir()); $config->setAutoGenerateProxyClasses(true); $config->setMetadataDriverImpl($metaDriver); - $setMetadataCacheImpl = $config->setMetadataCacheImpl(new ArrayCache); + $config->setMetadataCacheImpl(new ArrayCache); $config->setLuceneHandlerName('_fti'); return DocumentManager::create($couchDBClient, $config); diff --git a/tests/Doctrine/Tests/ODM/CouchDB/Mapping/ClassMetadataFactoryTest.php b/tests/Doctrine/Tests/ODM/CouchDB/Mapping/ClassMetadataFactoryTest.php index 70356236..02c93474 100644 --- a/tests/Doctrine/Tests/ODM/CouchDB/Mapping/ClassMetadataFactoryTest.php +++ b/tests/Doctrine/Tests/ODM/CouchDB/Mapping/ClassMetadataFactoryTest.php @@ -49,13 +49,12 @@ public function testGetAllMetadata() public function testGetMetadataForDocumentWithMappedSuperclass() { $class = $this->dm->getMetadataFactory()->getMetadataFor(__NAMESPACE__ ."\\Child"); - $this->assertFalse($class->isMappedSuperclass, "Child is not a mapped superclass!"); - $this->assertEquals(__NAMESPACE__ ."\\Child", $class->rootDocumentName); + $this->assertEquals(__NAMESPACE__ ."\\Super", $class->rootDocumentName); $class = $this->dm->getMetadataFactory()->getMetadataFor(__NAMESPACE__ ."\\ChildChild"); $this->assertFalse($class->isMappedSuperclass, "ChildChild is not a mapped superclass!"); - $this->assertEquals(__NAMESPACE__ ."\\Child", $class->rootDocumentName); + $this->assertEquals(__NAMESPACE__ ."\\Super", $class->rootDocumentName); $class = $this->dm->getMetadataFactory()->getMetadataFor(__NAMESPACE__ ."\\Super"); $this->assertTrue($class->isMappedSuperclass); @@ -91,4 +90,4 @@ class ChildChild extends Child * @Field(type="string") */ private $var2; -} \ No newline at end of file +}