Completed
Push — master ( 96d434...f2324b )
by Daniel
04:52 queued 55s
created

src/CollectionIdentifierUpdater.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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 Doctrine\ODM\PHPCR\Mapping\ClassMetadata as PhpcrMetadata;
9
use Doctrine\ODM\PHPCR\Mapping\ClassMetadataFactory;
10
use Metadata\MetadataFactory;
11
use Metadata\MetadataFactoryInterface;
12
use Psi\Component\ContentType\Metadata\ClassMetadata as CtMetadata;
13
14
/**
15
 * The collection identifier updater updates the IDs (paths) of any documents
16
 * mapped under a "CollectionField" to conform with the expected filter.
17
 *
18
 * This is necessary as it is not currently possible to achieve this in an
19
 * event subscriber within the PHPCR-ODM itself, see:
20
 *
21
 *     https://github.com/doctrine/phpcr-odm/issues/726
22
 *
23
 * Instead it is necessary to invoke this on any documents (at least those
24
 * which have a CollectionField mapping) before the DocumentManager#flush()
25
 * method is called. This could easily be done from the controller /
26
 * persistence agent of the consuming library.
27
 */
28
class CollectionIdentifierUpdater
29
{
30
    private $metadataFactory;
31
    private $encoder;
32
33
    public function __construct(
34
        MetadataFactoryInterface $metadataFactory,
35
        PropertyEncoder $encoder
36
    ) {
37
        $this->metadataFactory = $metadataFactory;
38
        $this->encoder = $encoder;
39
    }
40
41
    public function update(DocumentManagerInterface $documentManager, $document)
42
    {
43
        $metadataFactory = $documentManager->getMetadataFactory();
44
        $classFqn = ClassUtils::getRealClass(get_class($document));
45
46
        // PHPCR-ODM will throw an exception if the document is not mapped.
47
        $odmMetadata = $metadataFactory->getMetadataFor($classFqn);
48
49
        if (null === $ctMetadata = $this->metadataFactory->getMetadataForClass($classFqn)) {
50
            return;
51
        }
52
53
        $this->doUpdate($metadataFactory, $odmMetadata, $ctMetadata, $document);
0 ignored issues
show
$metadataFactory of type object<Doctrine\Common\P...g\ClassMetadataFactory> is not a sub-type of object<Doctrine\ODM\PHPC...g\ClassMetadataFactory>. It seems like you assume a concrete implementation of the interface Doctrine\Common\Persiste...ng\ClassMetadataFactory to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
$odmMetadata of type object<Doctrine\Common\P...\Mapping\ClassMetadata> is not a sub-type of object<Doctrine\ODM\PHPCR\Mapping\ClassMetadata>. It seems like you assume a concrete implementation of the interface Doctrine\Common\Persistence\Mapping\ClassMetadata to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
$ctMetadata is of type object<Metadata\ClassHie...MergeableClassMetadata>, but the function expects a object<Psi\Component\Con...Metadata\ClassMetadata>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
54
    }
55
56
    private function doUpdate(ClassMetadataFactory $metadataFactory, PhpcrMetadata $odmMetadata, CtMetadata $ctMetadata, $document)
57
    {
58
        $documentId = $odmMetadata->getIdentifierValue($document);
59
60
        foreach ($odmMetadata->childrenMappings as $childrenField) {
61
62
            // if the children field is not managed by the CT component,
63
            // continue
64
            if (!isset($ctMetadata->propertyMetadata[$childrenField])) {
65
                continue;
66
            }
67
68
            $children = $odmMetadata->getFieldValue($document, $childrenField);
69
70
            // note that we do not preserve array keys. PHPCR ODM will return a
71
            // children collection using the PHPCR property names as keys, so
72
            // we currently have no control over how these keys populated.
73
            $index = 0;
74
            foreach ($children as $child) {
75
                $childMetadata = $metadataFactory->getMetadataFor(ClassUtils::getRealClass(get_class($child)));
76
                $newId = sprintf(
77
                    '%s/%s',
78
                    $documentId,
79
                    $this->encoder->encode($childrenField, $index++)
80
                );
81
82
                $childMetadata->setIdentifierValue($child, $newId);
0 ignored issues
show
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...
83
            }
84
        }
85
    }
86
}
87