Completed
Push — master ( d11b01...1c170b )
by Daniel
17:01 queued 13:33
created

CollectionIdentifierUpdater   A

Complexity

Total Complexity 6

Size/Duplication

Total Lines 54
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
wmc 6
lcom 1
cbo 5
dl 0
loc 54
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
B update() 0 40 5
1
<?php
2
3
namespace Psi\Bridge\ContentType\Doctrine\PhpcrOdm;
4
5
use Doctrine\Common\Util\ClassUtils;
6
use Doctrine\ODM\PHPCR\DocumentManagerInterface;
7
use Doctrine\ODM\PHPCR\Event;
8
use Metadata\MetadataFactory;
9
use Metadata\MetadataFactoryInterface;
10
11
/**
12
 * The collection identifier updater updates the IDs (paths) of any documents
13
 * mapped under a "CollectionField" to conform with the expected filter.
14
 *
15
 * This is necessary as it is not currently possible to achieve this in an
16
 * event subscriber within the PHPCR-ODM itself, see:
17
 *
18
 *     https://github.com/doctrine/phpcr-odm/issues/726
19
 *
20
 * Instead it is necessary to invoke this on any documents (at least those
21
 * which have a CollectionField mapping) before the DocumentManager#flush()
22
 * method is called. This could easily be done from the controller /
23
 * persistence agent of the consuming library.
24
 */
25
class CollectionIdentifierUpdater
26
{
27
    private $metadataFactory;
28
    private $encoder;
29
30
    public function __construct(
31
        MetadataFactoryInterface $metadataFactory,
32
        PropertyEncoder $encoder
33
    ) {
34
        $this->metadataFactory = $metadataFactory;
35
        $this->encoder = $encoder;
36
    }
37
38
    public function update(DocumentManagerInterface $documentManager, $document)
39
    {
40
        $metadataFactory = $documentManager->getMetadataFactory();
41
        $classFqn = ClassUtils::getRealClass(get_class($document));
42
43
        // PHPCR-ODM will throw an exception if the document is not mapped.
44
        $odmMetadata = $metadataFactory->getMetadataFor($classFqn);
45
46
        if (null === $ctMetadata = $this->metadataFactory->getMetadataForClass($classFqn)) {
47
            return;
48
        }
49
50
        $documentId = $odmMetadata->getIdentifierValue($document);
0 ignored issues
show
Bug introduced by
The method getIdentifierValue() does not exist on Doctrine\Common\Persistence\Mapping\ClassMetadata. Did you maybe mean getIdentifier()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
51
52
        foreach ($odmMetadata->childrenMappings as $childrenField) {
0 ignored issues
show
Bug introduced by
Accessing childrenMappings on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
53
54
            // if the children field is not managed by the CT component,
55
            // continue
56
            if (!isset($ctMetadata->propertyMetadata[$childrenField])) {
57
                continue;
58
            }
59
60
            $children = $odmMetadata->getFieldValue($document, $childrenField);
61
62
            // note that we do not preserve array keys. PHPCR ODM will return a
63
            // children collection using the PHPCR property names as keys, so
64
            // we currently have no control over how these keys populated.
65
            $index = 0;
66
            foreach ($children as $child) {
67
                $childMetadata = $metadataFactory->getMetadataFor(ClassUtils::getRealClass(get_class($child)));
68
                $newId = sprintf(
69
                    '%s/%s',
70
                    $documentId,
71
                    $this->encoder->encode($childrenField, $index++)
72
                );
73
74
                $childMetadata->setIdentifierValue($child, $newId);
0 ignored issues
show
Bug introduced by
The method setIdentifierValue() does not exist on Doctrine\Common\Persistence\Mapping\ClassMetadata. Did you maybe mean getIdentifierValues()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
75
            }
76
        }
77
    }
78
}
79