Skip to content

Loading…

References (request for comments) #52

Merged
merged 28 commits into from

4 participants

@starkj

No description provided.

@lsmith77

this looks like a typo

@lsmith77

would be good to split the condition over several lines

@lsmith77

missing a space after if

@lsmith77

{ needs to be on this line

@lsmith77 lsmith77 commented on an outdated diff
lib/Doctrine/ODM/PHPCR/Proxy/ReferenceProxyFactory.php
((285 lines not shown))
+ {
+ if (!$this->__isInitialized__ && $this->__doctrineDocumentManager__) {
+ $this->__isInitialized__ = true;
+ $this->__doctrineDocumentManager__->createDocumentForProxy($this);
+ unset($this->__doctrineDocumentManager__);
+ }
+ }
+
+ <methods>
+
+ public function __sleep()
+ {
+ <sleepImpl>
+ }
+
+ public function __set($name, $value) {
@lsmith77 Doctrine member

{` needs to be on the next line ..

aside from this .. @beberlei what do you think of this? @starkj said that the other ODM's do not handle __set() and __get()

@beberlei Doctrine member

They do handle it, because it naturally appears in $reflClass->getMethods().

@starkj
starkj added a note

the old proxy classes that were created didn't contain get and __set methods. but we need to adjust them so that they will execute __doctrineLoad()
in adition to that, I had to unset the document classes attributes.
it's working, but is this a nice solution? or could it be done better?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@lsmith77

maybe add a TODO item that these (__set() and __get()) should actually not be needed

@lsmith77 lsmith77 commented on the diff
...octrine/ODM/PHPCR/Mapping/Driver/AnnotationDriver.php
@@ -142,6 +142,11 @@ class AnnotationDriver implements Driver
}
$class->setNodeType($documentAnnot->nodeType);
+ if (isset($documentAnnot->referenceable) && $documentAnnot->referenceable)
@lsmith77 Doctrine member

one more CS violation :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@lsmith77 lsmith77 commented on an outdated diff
...Doctrine/Tests/ODM/PHPCR/Functional/ReferenceTest.php
((25 lines not shown))
+ $root->getNode('functional')->remove();
+ $this->session->save();
+ }
+
+ $this->node = $root->addNode('functional');
+
+ $this->session->save();
+ }
+
+ public function testCreate()
+ {
+ $refTestObj = new RefTestObj();
+ $refRefTestObj = new RefRefTestObj();
+
+ $refTestObj->id = "/functional/refTestObj";
+ $refRefTestObj->id = "/functional/refRefTestObj";
@lsmith77 Doctrine member

one more CS violation :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@lsmith77 lsmith77 commented on an outdated diff
lib/Doctrine/ODM/PHPCR/UnitOfWork.php
@@ -458,7 +544,7 @@ class UnitOfWork
$changed = false;
foreach ($actualData as $fieldName => $fieldValue) {
- if (!isset($class->fieldMappings[$fieldName]) && !isset($class->childMappings[$fieldName])) {
+ if (!isset($class->fieldMappings[$fieldName]) && !isset($class->childMappings[$fieldName]) && !isset($class->associationsMappings[$fieldName])) {
@lsmith77 Doctrine member

maybe break this condition on multiple lines

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@lsmith77
Doctrine member

@beberlei: it would be great if you could do a final review before we merge this.

Johannes Stark and others added some commits
@starkj starkj commented on an outdated diff
cli-config.php.dist
@@ -7,7 +7,9 @@ $user = 'admin';
$pass = 'admin';
/* bootstrapping the repository implementation. for jackalope, do this: */
-$repository = new \Jackalope\Repository(new \Jackalope\Factory, $url);
+$factory = new \Jackalope\Factory;
+$transport = new \Jackalope\Transport\Davex\Client($factory, $url);
+$repository = new \Jackalope\Repository($factory, $transport);
@starkj
starkj added a note

or would it be better to use the factory instead to get the transport and repository object?

@lsmith77 Doctrine member
lsmith77 added a note

yes .. you might want to rebase to master when you do that, since some things changed there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@beberlei beberlei commented on the diff
lib/Doctrine/ODM/PHPCR/Proxy/ReferenceProxyFactory.php
((285 lines not shown))
+ {
+ if (!$this->__isInitialized__ && $this->__doctrineDocumentManager__) {
+ $this->__isInitialized__ = true;
+ $this->__doctrineDocumentManager__->createDocumentForProxy($this);
+ unset($this->__doctrineDocumentManager__);
+ }
+ }
+
+ <methods>
+
+ public function __sleep()
+ {
+ <sleepImpl>
+ }
+
+ public function __set($name, $value)
@beberlei Doctrine member
beberlei added a note

This is still not necessary. __set/__get are overloaded if they are present in the proxied class, otherwise this just leads to weird behavior.

@starkj
starkj added a note

What I wanted to achieve exactly is that you are able to use the references in this way:

a)
$referrer = $this->dm->find($this->referrerType, '/functional/refTestObj');
echo $referrer->reference->name;

and in that way:

b)
echo $referrer->reference->getName();

Did I get you right, that if I want to do it like in a) it's better to define __set() and __get() already in the main class? And so we have to give users a hint in the doc that they have to define the magic methods themselves.

@lsmith77 Doctrine member
lsmith77 added a note

ok .. this seems to be the last remaining open question.

@starkj
starkj added a note

while adding some more tests i just found an other issue concerning deleting one out of many references (testcase testDeleteOneInMany)
but its fixed now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@beberlei beberlei commented on an outdated diff
lib/Doctrine/ODM/PHPCR/UnitOfWork.php
((28 lines not shown))
// TODO figure this one out which collection should be used
- $documentState[$class->associationsMappings[$assocName]['fieldName']] = null;
+
+ $config = new Configuration();
@beberlei Doctrine member
beberlei added a note

What is this for?

@starkj
starkj added a note

yes, $this->dm->getConfiguration() is better.
still not fully aware of the whole architecture ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@beberlei beberlei commented on an outdated diff
lib/Doctrine/ODM/PHPCR/UnitOfWork.php
((40 lines not shown))
+ $referencedId = $referencedNode->getPath();
+
+ $referencedClass = $this->dm->getMetadataFactory()->getMetadataFor(ltrim($assocOptions['targetDocument'], '\\'));
+ $proxyDocument = $this->referenceProxyFactory->getProxy($referencedClass->name, $referencedId);
+
+ // register the referenced document under its own id
+ $this->registerManaged($proxyDocument, $referencedId, null);
+
+ $documentState[$class->associationsMappings[$assocName]['fieldName']] = $proxyDocument;
+
+ // save node for the case that the referenced document will be created
+ $proxyOid = spl_object_hash($proxyDocument);
+ $this->nodesMap[$proxyOid] = $referencedNode;
+
+ } elseif ($assocOptions['type'] & ClassMetadata::MANY_TO_MANY) {
+ $config = new Configuration();
@beberlei Doctrine member
beberlei added a note

here again, why not grab the config from $this->dm->getConfiguration() ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@beberlei beberlei commented on the diff
lib/Doctrine/ODM/PHPCR/UnitOfWork.php
((48 lines not shown))
+ $documentState[$class->associationsMappings[$assocName]['fieldName']] = $proxyDocument;
+
+ // save node for the case that the referenced document will be created
+ $proxyOid = spl_object_hash($proxyDocument);
+ $this->nodesMap[$proxyOid] = $referencedNode;
+
+ } elseif ($assocOptions['type'] & ClassMetadata::MANY_TO_MANY) {
+ $config = new Configuration();
+ $this->referenceProxyFactory = new Proxy\ReferenceProxyFactory($this->dm, $config->getProxyDir(), $config->getProxyNamespace(), true);
+
+ if (! $node->hasProperty($assocOptions['fieldName'])) {
+ continue;
+ }
+
+ // get the already cached referenced nodes
+ $proxyNodes = $node->getPropertyValue($assocOptions['fieldName']);
@beberlei Doctrine member
beberlei added a note

Shouldn't there be a type check for is_array here or similar?

@starkj
starkj added a note

yes i will observe this again, and a test needs to be added for a reference-many-property with just one reference

@starkj
starkj added a note

Properties that references many nodes will always return the nodes as array, even if just one node is referenced.
I added an additional check in line 416 to make that definitely sure.
And if the repository is inconsistent, it's checked here again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@beberlei beberlei commented on the diff
lib/Doctrine/ODM/PHPCR/UnitOfWork.php
((5 lines not shown))
foreach ($class->childMappings as $name => $childMapping) {
if ($this->originalData[$oid][$name]) {
$this->computeChildChanges($childMapping, $this->originalData[$oid][$name], $id);
}
}
+
+ foreach ($class->associationsMappings as $assocName => $assoc) {
+ if ($actualData[$assocName]) {
@beberlei Doctrine member
beberlei added a note

Can you guarantee this exists?

@starkj
starkj added a note

yes, I think so
$actualData is filled with values from the reflection class.
so if the document has a reference property, the field in $actualData is set
at least with null, as there is no reference

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@beberlei beberlei commented on the diff
lib/Doctrine/ODM/PHPCR/UnitOfWork.php
@@ -515,6 +615,26 @@ class UnitOfWork
}
/**
+ * Computes the changes of a reference.
+ *
+ * @param mixed $reference the referenced document.
+ */
+ private function computeReferenceChanges($mapping, $reference, $referrerId)
+ {
+ $targetClass = $this->dm->getClassMetadata(get_class($reference));
+ $state = $this->getDocumentState($reference);
+ $oid = spl_object_hash($reference);
+ if ($state == self::STATE_NEW) {
@beberlei Doctrine member
beberlei added a note

Shouldnt that be done if ccasce persist is set only?

@starkj
starkj added a note

I removed the option to cascade as I don't think it's necessary
If you're working with references and do some changes on them, why shouldn't that be persisted as well?
Correct me, if I'm wrong :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@beberlei beberlei commented on the diff
lib/Doctrine/ODM/PHPCR/UnitOfWork.php
@@ -608,6 +733,12 @@ class UnitOfWork
$node->addMixin("mix:versionable");
}
+ if ($class->referenceable) {
+ $node->addMixin("mix:referenceable");
+ // TODO make shure uuid is unique
@beberlei Doctrine member
beberlei added a note

arent uuids unique by definition?

@starkj
starkj added a note

yes they are
but we calculate them ourselves and don't let Jackrabbit do that for us
so it might be possible to calculate a UUID twice

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@beberlei beberlei commented on an outdated diff
lib/Doctrine/ODM/PHPCR/UnitOfWork.php
((10 lines not shown))
- } elseif ($class->associationsMappings[$fieldName]['type'] & ClassMetadata::TO_MANY) {
- if ($class->associationsMappings[$fieldName]['isOwning']) {
- // TODO: Optimize when not initialized yet! In ManyToMany case we can keep track of ALL ids
- $ids = array();
- if (is_array($fieldValue) || $fieldValue instanceof \Doctrine\Common\Collections\Collection) {
- foreach ($fieldValue as $relatedObject) {
- $ids[] = $this->getDocumentId($relatedObject);
- }
+
+ if ($node->hasProperty($class->associationsMappings[$fieldName]['fieldName']) && is_null($fieldValue)) {
+ $node->getProperty($class->associationsMappings[$fieldName]['fieldName'])->remove();
+ continue;
+ }
+
+ if($class->associationsMappings[$fieldName]['weak']) {
+ $type = \PHPCR\PropertyType::valueFromName('weakreference');
@beberlei Doctrine member
beberlei added a note

Why not use the constants here directly?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@beberlei
Doctrine member

Generally looks good. I fear the number of functional tests might be a bit small for such large features. Additionally i am a bit concerned about the "createDocumentforPRoxy" method naming and that its public from the DocumentManager. This is nothing more than a refresh but the naming sort of implies something new is created.

@starkj

@beberlei
Thank you very much for having a close look on my pull request! Yes, there needs to be more unit test definitely. I will work on that. And I will make up my mind about createDocumentforProxy.

@starkj

so, well I remove createDocumentForProxy from the DocumentManager and renamed the remaining methods to refreshDocumentForProxy

Johannes Stark added some commits
@dbu
Doctrine member
dbu commented

is this now ready to be merged or any open things?
@beberlei: would you mind checking if all concerns you noted are aptly handled now?

@starkj

no, there are still a few things open
need to wait for benjamin's answer

@dbu
Doctrine member
dbu commented

once this is merged, we should close the following issues in the issue tracker:

annotation for referrers is not covered by this pull request, right? http://www.doctrine-project.org/jira/browse/PHPCR-16

@starkj

no, referrers are not coverd

all right, i will remember the issue closing

@starkj

@beberlei guess you're very busy at the moment but would you mind to give again some feedback on my changes and on the remaining questions? thanks a lot!

@starkj

sorry guys, I screwed the commit history up a little bit.
Some commits appear twice but luckily it seems that this has no effect on the code.
I'm a little bit afraid to repair it using git rebase as the sequence of the commits listed by git is shuffled. :-(

btw referrer annotation is almost done. once this here is merged I can open another pull request for it

@dbu dbu merged commit 1083b50 into doctrine:master
@dbu
Doctrine member

thanks a lot for this feature, johannes!

@starkj

No worries, it was a pleasure for me! :-)

@lsmith77
Doctrine member

@starkj .. did you do this commit?

meaning in that case you are http://dlm.beberlei.de/licenses/author/346 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 27, 2011
  1. References with using proxy objects

    Johannes Stark committed
Commits on Jul 30, 2011
  1. typo fixed, TODO added

    zwerg committed
  2. Merge remote branch 'upstream/master' into references

    Johannes Stark committed
  3. get referenced nodes within one call to increase performance

    Johannes Stark committed
  4. updating to latest jackalope

    Johannes Stark committed
  5. cv fixing

    Johannes Stark committed
Commits on Aug 1, 2011
  1. adjusted to latest jackalope api

    Johannes Stark committed
Commits on Aug 3, 2011
  1. some changes according to the comments of beberlei

    Johannes Stark committed
Commits on Aug 4, 2011
  1. Merge remote branch 'doctrine/master' into references

    Johannes Stark committed
    Conflicts:
    	lib/Doctrine/ODM/PHPCR/Configuration.php
  2. adjusted to latest jackalope api using factory

    Johannes Stark committed
Commits on Aug 5, 2011
Commits on Aug 8, 2011
  1. some more test and bug fixes

    Johannes Stark committed
Commits on Aug 15, 2011
  1. bugfix, load referenced documents only once if you access them by the…

    Johannes Stark committed
    …ir id and later by their reference
Commits on Aug 16, 2011
  1. trailing whitespaces removed ;-)

    Johannes Stark committed
Commits on Aug 19, 2011
  1. References with using proxy objects

    Johannes Stark committed
  2. typo fixed, TODO added

    zwerg committed with Johannes Stark
  3. get referenced nodes within one call to increase performance

    Johannes Stark committed with Johannes Stark
  4. cv fixing

    Johannes Stark committed with Johannes Stark
  5. adjusted to latest jackalope api

    Johannes Stark committed
  6. some changes according to the comments of beberlei

    Johannes Stark committed
  7. adjusted to latest jackalope api using factory

    Johannes Stark committed
  8. some more test and bug fixes

    Johannes Stark committed
  9. bugfix, load referenced documents only once if you access them by the…

    Johannes Stark committed
    …ir id and later by their reference
  10. trailing whitespaces removed ;-)

    Johannes Stark committed
  11. Merge remote branch 'origin/references' into references

    Johannes Stark committed
  12. removing comma again

    Johannes Stark committed
Commits on Aug 23, 2011
  1. Merge remote branch 'doctrine/master' into references

    Johannes Stark committed
Something went wrong with that request. Please try again.