GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#196)
by joseph
28:03
created

setEntityCollectionAndNotify()   B

Complexity

Conditions 8
Paths 11

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72

Importance

Changes 0
Metric Value
cc 8
eloc 12
nc 11
nop 2
dl 0
loc 23
ccs 0
cts 13
cp 0
crap 72
rs 8.4444
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\Entity\Traits;
4
5
use Doctrine\Common\Collections\ArrayCollection;
6
use Doctrine\Common\Collections\Collection;
7
use Doctrine\Common\PropertyChangedListener;
8
use Doctrine\ORM\EntityManagerInterface;
9
use Doctrine\ORM\Mapping\ClassMetadata;
10
use Doctrine\ORM\PersistentCollection;
11
use EdmondsCommerce\DoctrineStaticMeta\Entity\Interfaces\EntityInterface;
12
use EdmondsCommerce\DoctrineStaticMeta\Exception\ValidationException;
13
14
/**
15
 * Trait ImplementNotifyChangeTrackingPolicy
16
 *
17
 * @see https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/change-tracking-policies.html#notify
18
 */
19
trait ImplementNotifyChangeTrackingPolicy
20
{
21
22
    /**
23
     * @var array PropertyChangedListener[]
24
     */
25
    private $notifyChangeTrackingListeners = [];
26
27
    /**
28
     * Set a notify change tracking listener (Unit of Work basically). Use the spl_object_hash to protect against
29
     * registering the same UOW more than once
30
     *
31
     * @param PropertyChangedListener $listener
32
     */
33
    public function addPropertyChangedListener(PropertyChangedListener $listener): void
34
    {
35
        $this->notifyChangeTrackingListeners[spl_object_hash($listener)] = $listener;
36
    }
37
38
    /**
39
     * If we want to totally disable the notify change, for example in bulk operations
40
     */
41
    public function removePropertyChangedListeners()
42
    {
43
        $this->notifyChangeTrackingListeners = [];
44
    }
45
46
    /**
47
     * The meta data is set to the entity when the meta data is loaded, however if metadata is cached that wont happen
48
     * This call ensures that the meta data is set
49
     *
50
     * @param EntityManagerInterface $entityManager
51
     *
52
     */
53
    public function ensureMetaDataIsSet(EntityManagerInterface $entityManager): void
54
    {
55
        self::getDoctrineStaticMeta()->setMetaData($entityManager->getClassMetadata(self::class));
56
    }
57
58
    /**
59
     * This notifies the embeddable properties on the owning Entity
60
     *
61
     * @param string      $embeddablePropertyName
62
     * @param null|string $propName
63
     * @param null        $oldValue
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $oldValue is correct as it would always require null to be passed?
Loading history...
64
     * @param null        $newValue
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $newValue is correct as it would always require null to be passed?
Loading history...
65
     */
66
    public function notifyEmbeddablePrefixedProperties(
67
        string $embeddablePropertyName,
68
        ?string $propName = null,
69
        $oldValue = null,
70
        $newValue = null
71
    ): void {
72
        if ($oldValue !== null && $oldValue === $newValue) {
0 ignored issues
show
introduced by
The condition $oldValue !== null is always false.
Loading history...
73
            return;
74
        }
75
        /**
76
         * @var ClassMetadata $metaData
77
         */
78
        $metaData = self::getDoctrineStaticMeta()->getMetaData();
79
        foreach ($metaData->getFieldNames() as $fieldName) {
80
            if (true === \ts\stringStartsWith($fieldName, $embeddablePropertyName)
81
                && false !== \ts\stringContains($fieldName, '.')
82
            ) {
83
                if ($fieldName !== null && $fieldName !== "$embeddablePropertyName.$propName") {
84
                    continue;
85
                }
86
                foreach ($this->notifyChangeTrackingListeners as $listener) {
87
                    //wondering if we can get away with not passing in the values?
88
                    $listener->propertyChanged($this, $fieldName, $oldValue, $newValue);
89
                }
90
            }
91
        }
92
    }
93
94
95
    /**
96
     * To be called from all set methods
97
     *
98
     * This method updates the property value, then it runs this through validation
99
     * If validation fails, it sets the old value back and throws the caught exception
100
     * If validation passes, it then performs the Doctrine notification for property change
101
     *
102
     * @param string $propName
103
     * @param mixed  $newValue
104
     *
105
     * @throws ValidationException
106
     */
107
    private function updatePropertyValue(string $propName, $newValue): void
108
    {
109
        if ($this->$propName === $newValue) {
110
            return;
111
        }
112
        $oldValue        = $this->$propName;
113
        $this->$propName = $newValue;
114
        foreach ($this->notifyChangeTrackingListeners as $listener) {
115
            $listener->propertyChanged($this, $propName, $oldValue, $newValue);
116
        }
117
    }
118
119
    /**
120
     * Called from the Has___Entities Traits
121
     *
122
     * @param string                       $propName
123
     * @param Collection|EntityInterface[] $entities
124
     */
125
    private function setEntityCollectionAndNotify(string $propName, Collection $entities): void
126
    {
127
        //If you are trying to set an empty collection, we need to actually loop through and remove them all
128
        if ($entities->count() === 0 && $this->$propName->count() > 0) {
129
            foreach ($this->$propName as $entity) {
130
                $this->removeFromEntityCollectionAndNotify($propName, $entity);
131
            }
132
133
            return;
134
        }
135
        //otherwise, we need to loop through and add everything from the new collection
136
        foreach ($entities as $entity) {
137
            if ($this->$propName->contains($entity)) {
138
                continue;
139
            }
140
            $this->addToEntityCollectionAndNotify($propName, $entity);
141
        }
142
        //and then remove everything in our colletion that is not in the new collection
143
        foreach ($this->$propName as $entity) {
144
            if ($entities->contains($entity)) {
145
                continue;
146
            }
147
            $this->removeFromEntityCollectionAndNotify($propName, $entity);
148
        }
149
    }
150
151
    /**
152
     * Called from the Has___Entities Traits
153
     *
154
     * @param string          $propName
155
     * @param EntityInterface $entity
156
     */
157
    private function removeFromEntityCollectionAndNotify(string $propName, EntityInterface $entity): void
158
    {
159
        if ($this->$propName === null) {
160
            $this->$propName = new ArrayCollection();
161
        }
162
        if ($this->$propName instanceof PersistentCollection) {
163
            $this->$propName->initialize();
164
        }
165
        if (!$this->$propName->contains($entity)) {
166
            return;
167
        }
168
        $oldValue = $this->$propName;
169
        $this->$propName->removeElement($entity);
170
        $newValue = $this->$propName;
171
        foreach ($this->notifyChangeTrackingListeners as $listener) {
172
            $listener->propertyChanged($this, $propName, $oldValue, $newValue);
173
        }
174
    }
175
176
    /**
177
     * Called from the Has___Entities Traits
178
     *
179
     * @param string          $propName
180
     * @param EntityInterface $entity
181
     */
182
    private function addToEntityCollectionAndNotify(string $propName, EntityInterface $entity): void
183
    {
184
        if ($this->$propName === null) {
185
            $this->$propName = new ArrayCollection();
186
        }
187
        if ($this->$propName->contains($entity)) {
188
            return;
189
        }
190
        $oldValue = $this->$propName;
191
        $this->$propName->add($entity);
192
        $newValue = $this->$propName;
193
        foreach ($this->notifyChangeTrackingListeners as $listener) {
194
            $listener->propertyChanged($this, $propName, $oldValue, $newValue);
195
        }
196
    }
197
198
    /**
199
     * Called from the Has___Entity Traits
200
     *
201
     * @param string               $propName
202
     * @param EntityInterface|null $entity
203
     */
204
    private function setEntityAndNotify(string $propName, ?EntityInterface $entity): void
205
    {
206
        if ($this->$propName === $entity) {
207
            return;
208
        }
209
        $oldValue        = $this->$propName;
210
        $this->$propName = $entity;
211
        foreach ($this->notifyChangeTrackingListeners as $listener) {
212
            $listener->propertyChanged($this, $propName, $oldValue, $entity);
213
        }
214
    }
215
}
216