Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/Doctrine/ODM/PHPCR/DocumentManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
24 changes: 24 additions & 0 deletions lib/Doctrine/ODM/PHPCR/Id/AssignedPathGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Doctrine\ODM\PHPCR\Id;

use Doctrine\ODM\PHPCR\DocumentManager;
use Doctrine\ODM\PHPCR\Mapping\ClassMetadata;

class AssignedPathGenerator extends IdGenerator
{
/**
* @param object $document
* @param ClassMetadata $cm
* @param DocumentManager $dm
* @return string
*/
public function generate($document, ClassMetadata $cm, DocumentManager $dm)
{
$id = $cm->getFieldValue($document, $cm->path);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inside the Doctrine code you can use $cm->reflFields->getValue($document, $cm->path); for performance reasons.

if (!$id) {
throw new \Exception("no id");
}
return $id;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont get this id generator at all. You can with this generate a ndoe that is at any place in the object graph without it even being connected to that entities at that position. Plus you have to provide the full path, which means your domain code has to know the full path to the object and work with path + id/shortname. This is not really "hiding" persistence.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think there is a misunderstanding here. the path defines where the node is and obviously if you want to determine the full path, you need to factor in the parent path.

like i said on the list the node path is: parent node path + relative node path

}
}
44 changes: 44 additions & 0 deletions lib/Doctrine/ODM/PHPCR/Id/IdGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace Doctrine\ODM\PHPCR\Id;

use Doctrine\ODM\PHPCR\DocumentManager;
use Doctrine\ODM\PHPCR\Mapping\ClassMetadata;

/**
* Used to abstract ID generation
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 1.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Lukas Kahwe Smith <smith@pooteeweet.org>
*/
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_REPOSITORY:
$instance = new RepositoryPathGenerator();
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);
}
30 changes: 30 additions & 0 deletions lib/Doctrine/ODM/PHPCR/Id/RepositoryPathGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Doctrine\ODM\PHPCR\Id;

use Doctrine\ODM\PHPCR\DocumentManager;
use Doctrine\ODM\PHPCR\Mapping\ClassMetadata;

class RepositoryPathGenerator extends IdGenerator
{
/**
* @param object $document
* @param ClassMetadata $cm
* @param DocumentManager $dm
* @return string
*/
public function generate($document, ClassMetadata $cm, DocumentManager $dm)
{
$repository = $dm->getRepository($cm->class);
if (!($repository instanceof RepositoryPathInterface)) {
throw new \Exception("no id");
}

// TODO: should we have some default implementation (parent path + some md5/object id)?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not have the object provide some slug + the parent path?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think its nicer to have the logic on the repository rather than the document. the repository would then read the document instance and then do what it needs (aka read some date property, a title and the parent) to generate the path

$id = $repository->generatePath($document);
if (!$id) {
throw new \Exception("no id");
}
return $id;
}
}
12 changes: 12 additions & 0 deletions lib/Doctrine/ODM/PHPCR/Id/RepositoryPathInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Doctrine\ODM\PHPCR\Id;

interface RepositoryPathGenerator
{
/**
* @param object $document
* @return string
*/
function generatePath($document);
}
5 changes: 5 additions & 0 deletions lib/Doctrine/ODM/PHPCR/Mapping/ClassMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
*/
class ClassMetadata
{
const IDGENERATOR_REPOSITORY = 1;
const IDGENERATOR_ASSIGNED = 2;

const TO_ONE = 5;
const TO_MANY = 10;
const ONE_TO_ONE = 1;
Expand All @@ -27,6 +30,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.
*/
Expand Down
41 changes: 33 additions & 8 deletions lib/Doctrine/ODM/PHPCR/UnitOfWork.php
Original file line number Diff line number Diff line change
Expand Up @@ -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])) {
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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.
*
Expand Down