Collection::getObject()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ApiSkeletons\Doctrine\ORM\GraphQL\Hydrator\Strategy;
6
7
use Doctrine\Common\Collections\ArrayCollection;
8
use Doctrine\Common\Collections\Collection as DoctrineCollection;
9
use Doctrine\Inflector\Inflector;
10
use Doctrine\Inflector\InflectorFactory;
11
use Doctrine\Laminas\Hydrator\Strategy\CollectionStrategyInterface;
12
use Doctrine\Persistence\Mapping\ClassMetadata;
13
use InvalidArgumentException;
14
use LogicException;
15
use ReflectionException;
16
17
use function is_array;
18
use function method_exists;
19
use function spl_object_hash;
20
use function sprintf;
21
22
/**
23
 * Copied from Doctrine\Laminas\Hydrator\Strategy\AbstractCollectionStrategy
24
 *
25
 * @codeCoverageIgnore
26
 */
27
abstract class Collection implements CollectionStrategyInterface
28
{
29
    private string|null $collectionName = null;
30
31
    private ClassMetadata|null $metadata = null;
32
33
    private object|null $object = null;
34
35
    private Inflector $inflector;
36
37
    public function __construct(Inflector|null $inflector = null)
38
    {
39
        $this->inflector = $inflector ?? InflectorFactory::create()->build();
40
    }
41
42
    public function setCollectionName(string $collectionName): void
43
    {
44
        $this->collectionName = $collectionName;
45
    }
46
47
    public function getCollectionName(): string
48
    {
49
        if ($this->collectionName === null) {
50
            throw new LogicException('Collection name has not been set.');
51
        }
52
53
        return $this->collectionName;
54
    }
55
56
    public function setClassMetadata(ClassMetadata $classMetadata): void
57
    {
58
        $this->metadata = $classMetadata;
59
    }
60
61
    public function getClassMetadata(): ClassMetadata
62
    {
63
        if ($this->metadata === null) {
64
            throw new LogicException('Class metadata has not been set.');
65
        }
66
67
        return $this->metadata;
68
    }
69
70
    public function setObject(object $object): void
71
    {
72
        $this->object = $object;
73
    }
74
75
    public function getObject(): object
76
    {
77
        if ($this->object === null) {
78
            throw new LogicException('Object has not been set.');
79
        }
80
81
        return $this->object;
82
    }
83
84
    /**
85
     * Converts the given value so that it can be extracted by the hydrator.
86
     *
87
     * @param  mixed       $value  The original value.
88
     * @param  object|null $object (optional) The original object for context.
89
     *
90
     * @return mixed       Returns the value that should be extracted.
91
     */
92
    public function extract(mixed $value, object|null $object = null): mixed
93
    {
94
        return $value;
95
    }
96
97
    protected function getInflector(): Inflector
98
    {
99
        return $this->inflector;
100
    }
101
102
    /**
103
     * Return the collection by value (using the public API)
104
     *
105
     * @return DoctrineCollection<array-key,object>
106
     *
107
     * @throws InvalidArgumentException
108
     */
109
    protected function getCollectionFromObjectByValue(): DoctrineCollection
110
    {
111
        $object = $this->getObject();
112
        $getter = 'get' . $this->getInflector()->classify($this->getCollectionName());
113
114
        if (! method_exists($object, $getter)) {
115
            throw new InvalidArgumentException(
116
                sprintf(
117
                    'The getter %s to access collection %s in object %s does not exist',
118
                    $getter,
119
                    $this->getCollectionName(),
120
                    $object::class,
121
                ),
122
            );
123
        }
124
125
        $collection = $object->$getter();
126
127
        if (is_array($collection)) {
128
            $collection = new ArrayCollection($collection);
129
        }
130
131
        return $collection;
132
    }
133
134
    /**
135
     * Return the collection by reference (not using the public API)
136
     *
137
     * @return DoctrineCollection<array-key,object>
138
     *
139
     * @throws InvalidArgumentException|ReflectionException
140
     */
141
    protected function getCollectionFromObjectByReference(): DoctrineCollection
142
    {
143
        $object       = $this->getObject();
144
        $refl         = $this->getClassMetadata()->getReflectionClass();
145
        $reflProperty = $refl->getProperty($this->getCollectionName());
146
147
        $reflProperty->setAccessible(true);
148
149
        return $reflProperty->getValue($object);
150
    }
151
152
    /**
153
     * This method is used internally by array_udiff to check if two objects are equal, according to their
154
     * SPL hash. This is needed because the native array_diff only compare strings
155
     */
156
    protected function compareObjects(object $a, object $b): int
157
    {
158
        return spl_object_hash($a) <=> spl_object_hash($b);
159
    }
160
}
161