• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In
Build has been canceled!

FastyBird / simple-auth / 7822099561

07 Feb 2024 10:39PM UTC coverage: 74.633% (-3.5%) from 78.119%
7822099561

push

github

akadlec
Use native enum

3 of 7 new or added lines in 3 files covered. (42.86%)

29 existing lines in 5 files now uncovered.

356 of 477 relevant lines covered (74.63%)

4.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

52.0
/src/Subscribers/User.php
1
<?php declare(strict_types = 1);
2

3
/**
4
 * User.php
5
 *
6
 * @license        More in LICENSE.md
7
 * @copyright      https://www.fastybird.com
8
 * @author         Adam Kadlec <adam.kadlec@fastybird.com>
9
 * @package        FastyBird:SimpleAuth!
10
 * @subpackage     Subscribers
11
 * @since          0.1.0
12
 *
13
 * @date           14.07.20
14
 */
15

16
namespace FastyBird\SimpleAuth\Subscribers;
17

18
use Doctrine\Common;
19
use Doctrine\ORM;
20
use Doctrine\Persistence;
21
use FastyBird\SimpleAuth\Exceptions;
22
use FastyBird\SimpleAuth\Mapping;
23
use FastyBird\SimpleAuth\Security;
24
use Nette;
25
use ReflectionException;
26
use function array_key_exists;
27
use function is_array;
28

29
/**
30
 * Doctrine entities events
31
 *
32
 * @template T of object
33
 *
34
 * @package        FastyBird:SimpleAuth!
35
 * @subpackage     Subscribers
36
 * @author         Adam Kadlec <adam.kadlec@fastybird.com>
37
 */
38
final class User implements Common\EventSubscriber
39
{
40

41
        use Nette\SmartObject;
42

43
        /**
44
         * @param Mapping\Driver\Owner<T> $driver
45
         */
46
        public function __construct(
47
                private readonly Mapping\Driver\Owner $driver,
48
                private readonly Security\User $user,
49
        )
50
        {
51
        }
3✔
52

53
        /**
54
         * Register events
55
         *
56
         * @return array<string>
57
         */
58
        public function getSubscribedEvents(): array
59
        {
60
                return [
4✔
61
                        ORM\Events::loadClassMetadata,
4✔
62
                        ORM\Events::onFlush,
4✔
63
                ];
4✔
64
        }
65

66
        /**
67
         * @throws Exceptions\InvalidMapping
68
         * @throws ORM\Mapping\MappingException
69
         */
70
        public function loadClassMetadata(
71
                ORM\Event\LoadClassMetadataEventArgs $eventArgs,
72
        ): void
73
        {
74
                /** @var ORM\Mapping\ClassMetadata<T> $classMetadata */
75
                $classMetadata = $eventArgs->getClassMetadata();
3✔
76

77
                $this->driver->loadMetadataForObjectClass($eventArgs->getObjectManager(), $classMetadata);
3✔
78

79
                // Register pre persist event
80
                $this->registerEvent($classMetadata, ORM\Events::prePersist);
3✔
81
        }
82

83
        /**
84
         * @param ORM\Mapping\ClassMetadata<T> $classMetadata
85
         *
86
         * @throws ORM\Mapping\MappingException
87
         */
88
        private function registerEvent(
89
                ORM\Mapping\ClassMetadata $classMetadata,
90
                string $eventName,
91
        ): void
92
        {
93
                if (!$this->hasRegisteredListener($classMetadata, $eventName, self::class)) {
3✔
94
                        $classMetadata->addEntityListener($eventName, self::class, $eventName);
3✔
95
                }
96
        }
97

98
        /**
99
         * @param ORM\Mapping\ClassMetadata<T> $classMetadata
100
         */
101
        private function hasRegisteredListener(
102
                ORM\Mapping\ClassMetadata $classMetadata,
103
                string $eventName,
104
                string $listenerClass,
105
        ): bool
106
        {
107
                if (!isset($classMetadata->entityListeners[$eventName])) {
3✔
108
                        return false;
3✔
109
                }
110

111
                foreach ($classMetadata->entityListeners[$eventName] as $listener) {
3✔
112
                        if ($listener['class'] === $listenerClass && $listener['method'] === $eventName) {
3✔
113
                                return true;
3✔
114
                        }
115
                }
116

117
                return false;
×
118
        }
119

120
        /**
121
         * @throws Exceptions\InvalidMapping
122
         * @throws ORM\Mapping\MappingException
123
         * @throws ORM\ORMInvalidArgumentException
124
         * @throws Persistence\Mapping\MappingException
125
         * @throws ReflectionException
126
         */
127
        public function onFlush(ORM\Event\OnFlushEventArgs $eventArgs): void
128
        {
129
                $manager = $eventArgs->getObjectManager();
3✔
130
                $uow = $manager->getUnitOfWork();
3✔
131

132
                // Check all scheduled updates
133
                foreach ($uow->getScheduledEntityUpdates() as $object) {
3✔
134
                        /** @var ORM\Mapping\ClassMetadata<T> $classMetadata */
135
                        $classMetadata = $manager->getClassMetadata($object::class);
3✔
136

137
                        $config = $this->driver->getObjectConfigurations($manager, $classMetadata->getName());
3✔
138

139
                        if ($config !== []) {
3✔
UNCOV
140
                                $changeSet = $uow->getEntityChangeSet($object);
×
UNCOV
141
                                $needChanges = false;
×
142

UNCOV
143
                                if ($uow->isScheduledForInsert($object) && isset($config['create'])) {
×
144
                                        // @phpstan-ignore-next-line
145
                                        foreach ($config['create'] as $field) {
×
146
                                                // Field can not exist in change set, when persisting embedded document without parent for example
147
                                                // @phpstan-ignore-next-line
148
                                                $new = array_key_exists($field, $changeSet) ? $changeSet[$field][1] : false;
×
149

150
                                                if ($new === null) { // let manual values
×
151
                                                        $needChanges = true;
×
152
                                                        // @phpstan-ignore-next-line
153
                                                        $this->updateField($uow, $object, $classMetadata, $field);
×
154
                                                }
155
                                        }
156
                                }
157

UNCOV
158
                                if ($needChanges) {
×
159
                                        $uow->recomputeSingleEntityChangeSet($classMetadata, $object);
×
160
                                }
161
                        }
162
                }
163
        }
164

165
        /**
166
         * Updates a field
167
         *
168
         * @param ORM\Mapping\ClassMetadata<T> $classMetadata
169
         */
170
        private function updateField(
171
                ORM\UnitOfWork $uow,
172
                mixed $object,
173
                ORM\Mapping\ClassMetadata $classMetadata,
174
                string $field,
175
        ): void
176
        {
UNCOV
177
                $property = $classMetadata->getReflectionProperty($field);
×
178

179
                // @phpstan-ignore-next-line
UNCOV
180
                $oldValue = $property->getValue($object);
×
UNCOV
181
                $newValue = $this->user->getId()?->toString();
×
182

183
                // @phpstan-ignore-next-line
UNCOV
184
                $property->setValue($object, $newValue);
×
185

186
                // @phpstan-ignore-next-line
UNCOV
187
                $uow->propertyChanged($object, $field, $oldValue, $newValue);
×
188
                // @phpstan-ignore-next-line
UNCOV
189
                $uow->scheduleExtraUpdate($object, [
×
UNCOV
190
                        $field => [$oldValue, $newValue],
×
UNCOV
191
                ]);
×
192
        }
193

194
        /**
195
         * @throws Exceptions\InvalidMapping
196
         * @throws ORM\Mapping\MappingException
197
         * @throws Persistence\Mapping\MappingException
198
         * @throws ReflectionException
199
         */
200
        public function prePersist(
201
                mixed $entity,
202
                ORM\Event\PrePersistEventArgs $eventArgs,
203
        ): void
204
        {
205
                $manager = $eventArgs->getObjectManager();
3✔
206
                $uow = $manager->getUnitOfWork();
3✔
207
                /** @var ORM\Mapping\ClassMetadata<T> $classMetadata */
208
                $classMetadata = $manager->getClassMetadata($entity::class); // @phpstan-ignore-line
3✔
209

210
                $config = $this->driver->getObjectConfigurations($manager, $classMetadata->getName());
3✔
211

212
                if ($config !== []) {
3✔
UNCOV
213
                        if (isset($config['create']) && is_array($config['create'])) {
×
UNCOV
214
                                $this->updateFields($config['create'], $uow, $entity, $classMetadata);
×
215
                        }
216
                }
217
        }
218

219
        /**
220
         * @param array<string> $fields
221
         * @param ORM\Mapping\ClassMetadata<T> $classMetadata
222
         */
223
        private function updateFields(
224
                array $fields,
225
                ORM\UnitOfWork $uow,
226
                mixed $object,
227
                ORM\Mapping\ClassMetadata $classMetadata,
228
        ): void
229
        {
UNCOV
230
                foreach ($fields as $field) {
×
231
                        // @phpstan-ignore-next-line
UNCOV
232
                        if ($classMetadata->getReflectionProperty($field)->getValue($object) === null) { // let manual values
×
UNCOV
233
                                $this->updateField($uow, $object, $classMetadata, $field);
×
234
                        }
235
                }
236
        }
237

238
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc