From b8a77f1887efd926d3e0039a96cf91ad2c89b117 Mon Sep 17 00:00:00 2001 From: Lukas Kahwe Smith Date: Mon, 7 Mar 2011 21:50:14 +0100 Subject: [PATCH 1/2] added id generator (WIP) --- lib/Doctrine/ODM/PHPCR/DocumentManager.php | 4 +- .../ODM/PHPCR/Id/AssignedPathGenerator.php | 24 ++++++++++ lib/Doctrine/ODM/PHPCR/Id/IdGenerator.php | 47 ++++++++++++++++++ .../ODM/PHPCR/Id/PHPCRUUIDGenerator.php | 48 +++++++++++++++++++ .../ODM/PHPCR/Id/SlugifiedGenerator.php | 34 +++++++++++++ .../ODM/PHPCR/Mapping/ClassMetadata.php | 6 +++ lib/Doctrine/ODM/PHPCR/UnitOfWork.php | 41 ++++++++++++---- 7 files changed, 194 insertions(+), 10 deletions(-) create mode 100644 lib/Doctrine/ODM/PHPCR/Id/AssignedPathGenerator.php create mode 100644 lib/Doctrine/ODM/PHPCR/Id/IdGenerator.php create mode 100644 lib/Doctrine/ODM/PHPCR/Id/PHPCRUUIDGenerator.php create mode 100644 lib/Doctrine/ODM/PHPCR/Id/SlugifiedGenerator.php diff --git a/lib/Doctrine/ODM/PHPCR/DocumentManager.php b/lib/Doctrine/ODM/PHPCR/DocumentManager.php index ea6db503a..5f316016f 100644 --- a/lib/Doctrine/ODM/PHPCR/DocumentManager.php +++ b/lib/Doctrine/ODM/PHPCR/DocumentManager.php @@ -167,9 +167,9 @@ public function getRepository($documentName) return $this->repositories[$documentName]; } - public function persist($object, $path) + public function persist($object) { - $this->unitOfWork->scheduleInsert($object, $path); + $this->unitOfWork->scheduleInsert($object); } public function remove($object) diff --git a/lib/Doctrine/ODM/PHPCR/Id/AssignedPathGenerator.php b/lib/Doctrine/ODM/PHPCR/Id/AssignedPathGenerator.php new file mode 100644 index 000000000..2cb12684a --- /dev/null +++ b/lib/Doctrine/ODM/PHPCR/Id/AssignedPathGenerator.php @@ -0,0 +1,24 @@ +getFieldValue($document, $cm->path); + if (!$id) { + throw new \Exception("no id"); + } + return $id; + } +} diff --git a/lib/Doctrine/ODM/PHPCR/Id/IdGenerator.php b/lib/Doctrine/ODM/PHPCR/Id/IdGenerator.php new file mode 100644 index 000000000..c9dfbdf69 --- /dev/null +++ b/lib/Doctrine/ODM/PHPCR/Id/IdGenerator.php @@ -0,0 +1,47 @@ + + * @author Lukas Kahwe Smith + */ +abstract class IdGenerator +{ + /** + * @param int $generatorType + * @return IdGenerator + */ + static public function create($generatorType) + { + switch ($generatorType) { + case ClassMetadata::IDGENERATOR_ASSIGNED: + $instance = new AssignedPathGenerator(); + break; + case ClassMetadata::IDGENERATOR_UUID: + $instance = new PHPCRUUIDGenerator(); + break; + case ClassMetadata::IDGENERATOR_SLUGIFIED: + $instance = new SlugifiedGenerator(); + break; + default: + throw \Exception("ID Generator does not exist!"); + } + return $instance; + } + + /** + * @param object $document + * @param ClassMetadata $cm + * @param DocumentManager $dm + */ + abstract public function generate($document, ClassMetadata $cm, DocumentManager $dm); +} diff --git a/lib/Doctrine/ODM/PHPCR/Id/PHPCRUUIDGenerator.php b/lib/Doctrine/ODM/PHPCR/Id/PHPCRUUIDGenerator.php new file mode 100644 index 000000000..e6a1952a2 --- /dev/null +++ b/lib/Doctrine/ODM/PHPCR/Id/PHPCRUUIDGenerator.php @@ -0,0 +1,48 @@ +. + */ + +namespace Doctrine\ODM\PHPCR\Id; + +use Doctrine\ODM\PHPCR\DocumentManager; +use Doctrine\ODM\PHPCR\Mapping\ClassMetadata; + +/** + * UUID generator class + * + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @link www.doctrine-project.com + * @since 1.0 + * @author Benjamin Eberlei + */ +class PHPCRUUIDGenerator extends IdGenerator +{ + private $uuids = array(); + + public function generate($document, ClassMetadata $cm, DocumentManager $dm) + { + if (empty($this->uuids)) { + $UUIDGenerationBufferSize = $dm->getConfiguration()->getUUIDGenerationBufferSize(); + $this->uuids = $dm->getCouchDBClient()->getUuids($UUIDGenerationBufferSize); + } + + $id = array_pop($this->uuids); + $cm->reflFields[$cm->identifier]->setValue($document, $id); + return $id; + } +} diff --git a/lib/Doctrine/ODM/PHPCR/Id/SlugifiedGenerator.php b/lib/Doctrine/ODM/PHPCR/Id/SlugifiedGenerator.php new file mode 100644 index 000000000..777e5143c --- /dev/null +++ b/lib/Doctrine/ODM/PHPCR/Id/SlugifiedGenerator.php @@ -0,0 +1,34 @@ +title) { + throw new \Exception("no id"); + } + + $parent = $document->node->getParent(); + if (!$parent) { + throw new \Exception("no id"); + } + + $id = $cm->getIdentifierValue($parent).'/'.$document->title; + if (!$id) { + throw new \Exception("no id"); + } + return $id; + } +} diff --git a/lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php b/lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php index 49b3cd5d5..e18c87d11 100644 --- a/lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php +++ b/lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php @@ -13,6 +13,10 @@ */ class ClassMetadata { + const IDGENERATOR_UUID = 1; + const IDGENERATOR_ASSIGNED = 2; + const IDGENERATOR_SLUGIFIED = 3; + const TO_ONE = 5; const TO_MANY = 10; const ONE_TO_ONE = 1; @@ -27,6 +31,8 @@ class ClassMetadata const CASCADE_REFRESH = 16; const CASCADE_ALL = 31; + public $idGenerator = self::IDGENERATOR_ASSIGNED; + /** * READ-ONLY: The field name of the document identifier. */ diff --git a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php index d93879931..de4267d99 100644 --- a/lib/Doctrine/ODM/PHPCR/UnitOfWork.php +++ b/lib/Doctrine/ODM/PHPCR/UnitOfWork.php @@ -283,13 +283,13 @@ public function getOriginalData($document) * @param object $document * @param string $path */ - public function scheduleInsert($document, $path) + public function scheduleInsert($document) { $visited = array(); - $this->doScheduleInsert($document, $path, $visited); + $this->doScheduleInsert($document, $visited); } - private function doScheduleInsert($document, $path, &$visited) + private function doScheduleInsert($document, &$visited) { $oid = spl_object_hash($document); if (isset($visited[$oid])) { @@ -302,11 +302,7 @@ private function doScheduleInsert($document, $path, &$visited) switch ($state) { case self::STATE_NEW: - $this->registerManaged($document, $path, null); - - if ($this->evm->hasListeners(Event::prePersist)) { - $this->evm->dispatchEvent(Event::prePersist, new Events\LifecycleEventArgs($document, $this->dm)); - } + $this->persistNew($class, $document); break; case self::STATE_MANAGED: // TODO: Change Tracking Deferred Explicit @@ -351,6 +347,14 @@ private function cascadeScheduleInsert($class, $document, &$visited) } } + private function getIdGenerator($type) + { + if (!isset($this->idGenerators[$type])) { + $this->idGenerators[$type] = Id\IdGenerator::create($type); + } + return $this->idGenerators[$type]; + } + public function scheduleRemove($document) { $oid = spl_object_hash($document); @@ -470,6 +474,27 @@ public function getDocumentChangeSet($document) return array(); } + /** + * Persist new document, marking it managed and generating the id. + * + * This method is either called through `DocumentManager#persist()` or during `DocumentManager#flush()`, + * when persistence by reachability is applied. + * + * @param ClassMetadata $class + * @param object $document + * @return void + */ + public function persistNew($class, $document) + { + $path = $this->getIdGenerator($class->idGenerator)->generate($document, $class, $this->dm); + + $this->registerManaged($document, $path, null); + + if ($this->evm->hasListeners(Event::prePersist)) { + $this->evm->dispatchEvent(Event::prePersist, new Events\LifecycleEventArgs($document, $this->dm)); + } + } + /** * Flush Operation - Write all dirty entries to the PHPCR. * From 44b94629fe268860dbe0f7491ab1402de8477eb1 Mon Sep 17 00:00:00 2001 From: Lukas Kahwe Smith Date: Tue, 8 Mar 2011 08:02:51 +0100 Subject: [PATCH 2/2] removed uuid generator (uuid is optional, path is required) and slugified (replaced by a repository callback). still needs support in mapping drivers, also can we provide a default implementation in the repository class (then we can remove the interface and default to the repository generator) --- .../ODM/PHPCR/Id/AssignedPathGenerator.php | 2 +- lib/Doctrine/ODM/PHPCR/Id/IdGenerator.php | 7 +-- .../ODM/PHPCR/Id/PHPCRUUIDGenerator.php | 48 ------------------- ...erator.php => RepositoryPathGenerator.php} | 16 +++---- .../ODM/PHPCR/Id/RepositoryPathInterface.php | 12 +++++ .../ODM/PHPCR/Mapping/ClassMetadata.php | 3 +- 6 files changed, 22 insertions(+), 66 deletions(-) delete mode 100644 lib/Doctrine/ODM/PHPCR/Id/PHPCRUUIDGenerator.php rename lib/Doctrine/ODM/PHPCR/Id/{SlugifiedGenerator.php => RepositoryPathGenerator.php} (56%) create mode 100644 lib/Doctrine/ODM/PHPCR/Id/RepositoryPathInterface.php diff --git a/lib/Doctrine/ODM/PHPCR/Id/AssignedPathGenerator.php b/lib/Doctrine/ODM/PHPCR/Id/AssignedPathGenerator.php index 2cb12684a..fa7156dd3 100644 --- a/lib/Doctrine/ODM/PHPCR/Id/AssignedPathGenerator.php +++ b/lib/Doctrine/ODM/PHPCR/Id/AssignedPathGenerator.php @@ -11,7 +11,7 @@ class AssignedPathGenerator extends IdGenerator * @param object $document * @param ClassMetadata $cm * @param DocumentManager $dm - * @return array + * @return string */ public function generate($document, ClassMetadata $cm, DocumentManager $dm) { diff --git a/lib/Doctrine/ODM/PHPCR/Id/IdGenerator.php b/lib/Doctrine/ODM/PHPCR/Id/IdGenerator.php index c9dfbdf69..6438fe787 100644 --- a/lib/Doctrine/ODM/PHPCR/Id/IdGenerator.php +++ b/lib/Doctrine/ODM/PHPCR/Id/IdGenerator.php @@ -26,11 +26,8 @@ static public function create($generatorType) case ClassMetadata::IDGENERATOR_ASSIGNED: $instance = new AssignedPathGenerator(); break; - case ClassMetadata::IDGENERATOR_UUID: - $instance = new PHPCRUUIDGenerator(); - break; - case ClassMetadata::IDGENERATOR_SLUGIFIED: - $instance = new SlugifiedGenerator(); + case ClassMetadata::IDGENERATOR_REPOSITORY: + $instance = new RepositoryPathGenerator(); break; default: throw \Exception("ID Generator does not exist!"); diff --git a/lib/Doctrine/ODM/PHPCR/Id/PHPCRUUIDGenerator.php b/lib/Doctrine/ODM/PHPCR/Id/PHPCRUUIDGenerator.php deleted file mode 100644 index e6a1952a2..000000000 --- a/lib/Doctrine/ODM/PHPCR/Id/PHPCRUUIDGenerator.php +++ /dev/null @@ -1,48 +0,0 @@ -. - */ - -namespace Doctrine\ODM\PHPCR\Id; - -use Doctrine\ODM\PHPCR\DocumentManager; -use Doctrine\ODM\PHPCR\Mapping\ClassMetadata; - -/** - * UUID generator class - * - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @link www.doctrine-project.com - * @since 1.0 - * @author Benjamin Eberlei - */ -class PHPCRUUIDGenerator extends IdGenerator -{ - private $uuids = array(); - - public function generate($document, ClassMetadata $cm, DocumentManager $dm) - { - if (empty($this->uuids)) { - $UUIDGenerationBufferSize = $dm->getConfiguration()->getUUIDGenerationBufferSize(); - $this->uuids = $dm->getCouchDBClient()->getUuids($UUIDGenerationBufferSize); - } - - $id = array_pop($this->uuids); - $cm->reflFields[$cm->identifier]->setValue($document, $id); - return $id; - } -} diff --git a/lib/Doctrine/ODM/PHPCR/Id/SlugifiedGenerator.php b/lib/Doctrine/ODM/PHPCR/Id/RepositoryPathGenerator.php similarity index 56% rename from lib/Doctrine/ODM/PHPCR/Id/SlugifiedGenerator.php rename to lib/Doctrine/ODM/PHPCR/Id/RepositoryPathGenerator.php index 777e5143c..990505527 100644 --- a/lib/Doctrine/ODM/PHPCR/Id/SlugifiedGenerator.php +++ b/lib/Doctrine/ODM/PHPCR/Id/RepositoryPathGenerator.php @@ -5,27 +5,23 @@ use Doctrine\ODM\PHPCR\DocumentManager; use Doctrine\ODM\PHPCR\Mapping\ClassMetadata; -class SlugifiedGenerator extends IdGenerator +class RepositoryPathGenerator extends IdGenerator { /** * @param object $document * @param ClassMetadata $cm * @param DocumentManager $dm - * @return array + * @return string */ public function generate($document, ClassMetadata $cm, DocumentManager $dm) { - // TODO this needs to be cleaned up: "title" needs to defined differently etc. - if (!$document->title) { + $repository = $dm->getRepository($cm->class); + if (!($repository instanceof RepositoryPathInterface)) { throw new \Exception("no id"); } - $parent = $document->node->getParent(); - if (!$parent) { - throw new \Exception("no id"); - } - - $id = $cm->getIdentifierValue($parent).'/'.$document->title; + // TODO: should we have some default implementation (parent path + some md5/object id)? + $id = $repository->generatePath($document); if (!$id) { throw new \Exception("no id"); } diff --git a/lib/Doctrine/ODM/PHPCR/Id/RepositoryPathInterface.php b/lib/Doctrine/ODM/PHPCR/Id/RepositoryPathInterface.php new file mode 100644 index 000000000..27801d943 --- /dev/null +++ b/lib/Doctrine/ODM/PHPCR/Id/RepositoryPathInterface.php @@ -0,0 +1,12 @@ +