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 (#154)
by joseph
33:02
created

EntityUpserterCreatorTest::getCreator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 8
nc 1
nop 0
dl 0
loc 11
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\Tests\Small\CodeGeneration\Creation\Src\Entity\Savers;
4
5
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Creation\Src\Entity\Savers\EntityUpserterCreator;
6
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Filesystem\Factory\FileFactory;
7
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Filesystem\Factory\FindReplaceFactory;
8
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Filesystem\File\Writer;
9
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\NamespaceHelper;
10
use EdmondsCommerce\DoctrineStaticMeta\Config;
11
use EdmondsCommerce\DoctrineStaticMeta\Tests\Small\ConfigTest;
12
use PHPUnit\Framework\TestCase;
13
14
/**
15
 * @covers \EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Creation\Src\Entity\Savers\EntityUpserterCreator
16
 * @small
17
 */
18
class EntityUpserterCreatorTest extends TestCase
19
{
20
    private const BASE_NAMESPACE = 'EdmondsCommerce\DoctrineStaticMeta';
21
22
    private const UPSERTER=<<<'PHP'
23
<?php
24
25
namespace EdmondsCommerce\DoctrineStaticMeta\Entity\Savers;
26
27
use EdmondsCommerce\DoctrineStaticMeta\Entity\Interfaces\DataTransferObjectInterface;
28
use EdmondsCommerce\DoctrineStaticMeta\Entity\Savers\EntitySaver;
29
use EdmondsCommerce\DoctrineStaticMeta\Entity\Savers\NewUpsertDtoDataModifierInterface;
30
use EdmondsCommerce\DoctrineStaticMeta\Entity\DataTransferObjects\TestEntityDto;
31
use EdmondsCommerce\DoctrineStaticMeta\Entity\Factories\TestEntityDtoFactory;
32
use EdmondsCommerce\DoctrineStaticMeta\Entity\Factories\TestEntityFactory;
33
use EdmondsCommerce\DoctrineStaticMeta\Entity\Interfaces\TestEntityInterface;
34
use EdmondsCommerce\DoctrineStaticMeta\Entity\Repositories\TestEntityRepository;
35
36
class TestEntityUpserter
37
{
38
    /**
39
     * @var TestEntityDtoFactory
40
     */
41
    private $dtoFactory;
42
    /**
43
     * @var TestEntityFactory
44
     */
45
    private $entityFactory;
46
    /**
47
     * @var TestEntityRepository
48
     */
49
    private $repository;
50
    /**
51
     * @var EntitySaver
52
     */
53
    private $saver;
54
    /**
55
     * @var TestEntityUnitOfWorkHelper
56
     */
57
    private $unitOfWorkHelper;
58
59
    public function __construct(
60
        TestEntityRepository $repository,
61
        TestEntityDtoFactory $dtoFactory,
62
        TestEntityFactory $entityFactory,
63
        EntitySaver $saver,
64
        TestEntityUnitOfWorkHelper $unitOfWorkHelper
65
    ) {
66
        $this->repository       = $repository;
67
        $this->dtoFactory       = $dtoFactory;
68
        $this->entityFactory    = $entityFactory;
69
        $this->saver            = $saver;
70
        $this->unitOfWorkHelper = $unitOfWorkHelper;
71
    }
72
73
    public function getUpsertDtoByProperties(array $propertiesToValues): TestEntityDto
74
    {
75
        $modifier = $this->getModifierClass($propertiesToValues);
76
77
        return $this->getUpsertDtoByCriteria($propertiesToValues, $modifier);
78
    }
79
80
    private function getModifierClass(array $propertiesToValues): NewUpsertDtoDataModifierInterface
81
    {
82
        return new class($propertiesToValues) implements NewUpsertDtoDataModifierInterface
83
        {
84
            private $propertiesToValues;
85
86
            public function __construct(array $propertiesToValues)
87
            {
88
                $this->propertiesToValues = $propertiesToValues;
89
            }
90
91
            public function addDataToNewlyCreatedDto(DataTransferObjectInterface $dto): void
92
            {
93
                foreach ($this->propertiesToValues as $property => $value) {
94
                    $setter = 'set' . ucfirst($property);
95
                    $dto->$setter($value);
96
                }
97
            }
98
        };
99
    }
100
101
    /**
102
     * This method is used to get a DTO using search criteria, when you are not certain if the entity exists or not.
103
     * The criteria is passed through to the repository findOneBy method, if an entity is found then a DTO will be
104
     * created from it and returned.
105
     *
106
     * If an entity is not found then a new empty DTO will be created and returned instead.
107
     *
108
     * @param array                             $criteria
109
     * @param NewUpsertDtoDataModifierInterface $modifier
110
     *
111
     * @return TestEntityDto
112
     * @see \Doctrine\ORM\EntityRepository::findOneBy for how to use the crietia
113
     */
114
    public function getUpsertDtoByCriteria(
115
        array $criteria,
116
        NewUpsertDtoDataModifierInterface $modifier
117
    ): TestEntityDto {
118
        $entity = $this->repository->findOneBy($criteria);
119
        if ($entity === null) {
120
            $dto = $this->dtoFactory->create();
121
            $modifier->addDataToNewlyCreatedDto($dto);
122
123
            return $dto;
124
        }
125
126
        return $this->dtoFactory->createDtoFromTestEntity($entity);
127
    }
128
129
    public function getUpsertDtoByProperty(string $propertyName, $value): TestEntityDto
130
    {
131
        $modifier = $this->getModifierClass([$propertyName => $value]);
132
133
        return $this->getUpsertDtoByCriteria([$propertyName => $value], $modifier);
134
    }
135
136
    /**
137
     * This is used to persist the DTO to the database. If the DTO is for a new entity then it will be created, if it
138
     * is for an existing Entity then it will be updated.
139
     *
140
     * Be aware that this method should __only__ be used with DTOs that have been created using the
141
     * self::getUpsertDtoByCriteria method, as if they come from elsewhere we will not not if the entity needs to be
142
     * created or updated
143
     *
144
     * @param TestEntityDto $dto
145
     *
146
     * @return TestEntityInterface
147
     * @throws \Doctrine\DBAL\DBALException
148
     */
149
    public function persistUpsertDto(TestEntityDto $dto): TestEntityInterface
150
    {
151
        if ($this->unitOfWorkHelper->hasRecordOfDto($dto) === false) {
152
            $entity = $this->entityFactory->create($dto);
153
            $this->saver->save($entity);
154
155
            return $entity;
156
        }
157
        $entity = $this->unitOfWorkHelper->getEntityFromUnitOfWorkUsingDto($dto);
158
        $entity->update($dto);
159
        $this->saver->save($entity);
160
161
        return $entity;
162
    }
163
}
164
165
PHP;
166
167
    public const NESTED_UPSERTER=<<<'PHP'
168
<?php
169
170
namespace EdmondsCommerce\DoctrineStaticMeta\Entity\Savers\Deeply\Ne\S\ted;
171
172
use EdmondsCommerce\DoctrineStaticMeta\Entity\Interfaces\Deeply\Ne\S\ted\DataTransferObjectInterface;
173
use EdmondsCommerce\DoctrineStaticMeta\Entity\Savers\Deeply\Ne\S\ted\EntitySaver;
174
use EdmondsCommerce\DoctrineStaticMeta\Entity\Savers\Deeply\Ne\S\ted\NewUpsertDtoDataModifierInterface;
175
use EdmondsCommerce\DoctrineStaticMeta\Entity\DataTransferObjects\Deeply\Ne\S\ted\TestEntityDto;
176
use EdmondsCommerce\DoctrineStaticMeta\Entity\Factories\Deeply\Ne\S\ted\TestEntityDtoFactory;
177
use EdmondsCommerce\DoctrineStaticMeta\Entity\Factories\Deeply\Ne\S\ted\TestEntityFactory;
178
use EdmondsCommerce\DoctrineStaticMeta\Entity\Interfaces\Deeply\Ne\S\ted\TestEntityInterface;
179
use EdmondsCommerce\DoctrineStaticMeta\Entity\Repositories\Deeply\Ne\S\ted\TestEntityRepository;
180
181
class TestEntityUpserter
182
{
183
    /**
184
     * @var TestEntityDtoFactory
185
     */
186
    private $dtoFactory;
187
    /**
188
     * @var TestEntityFactory
189
     */
190
    private $entityFactory;
191
    /**
192
     * @var TestEntityRepository
193
     */
194
    private $repository;
195
    /**
196
     * @var EntitySaver
197
     */
198
    private $saver;
199
    /**
200
     * @var TestEntityUnitOfWorkHelper
201
     */
202
    private $unitOfWorkHelper;
203
204
    public function __construct(
205
        TestEntityRepository $repository,
206
        TestEntityDtoFactory $dtoFactory,
207
        TestEntityFactory $entityFactory,
208
        EntitySaver $saver,
209
        TestEntityUnitOfWorkHelper $unitOfWorkHelper
210
    ) {
211
        $this->repository       = $repository;
212
        $this->dtoFactory       = $dtoFactory;
213
        $this->entityFactory    = $entityFactory;
214
        $this->saver            = $saver;
215
        $this->unitOfWorkHelper = $unitOfWorkHelper;
216
    }
217
218
    public function getUpsertDtoByProperties(array $propertiesToValues): TestEntityDto
219
    {
220
        $modifier = $this->getModifierClass($propertiesToValues);
221
222
        return $this->getUpsertDtoByCriteria($propertiesToValues, $modifier);
223
    }
224
225
    private function getModifierClass(array $propertiesToValues): NewUpsertDtoDataModifierInterface
226
    {
227
        return new class($propertiesToValues) implements NewUpsertDtoDataModifierInterface
228
        {
229
            private $propertiesToValues;
230
231
            public function __construct(array $propertiesToValues)
232
            {
233
                $this->propertiesToValues = $propertiesToValues;
234
            }
235
236
            public function addDataToNewlyCreatedDto(DataTransferObjectInterface $dto): void
237
            {
238
                foreach ($this->propertiesToValues as $property => $value) {
239
                    $setter = 'set' . ucfirst($property);
240
                    $dto->$setter($value);
241
                }
242
            }
243
        };
244
    }
245
246
    /**
247
     * This method is used to get a DTO using search criteria, when you are not certain if the entity exists or not.
248
     * The criteria is passed through to the repository findOneBy method, if an entity is found then a DTO will be
249
     * created from it and returned.
250
     *
251
     * If an entity is not found then a new empty DTO will be created and returned instead.
252
     *
253
     * @param array                             $criteria
254
     * @param NewUpsertDtoDataModifierInterface $modifier
255
     *
256
     * @return TestEntityDto
257
     * @see \Doctrine\ORM\EntityRepository::findOneBy for how to use the crietia
258
     */
259
    public function getUpsertDtoByCriteria(
260
        array $criteria,
261
        NewUpsertDtoDataModifierInterface $modifier
262
    ): TestEntityDto {
263
        $entity = $this->repository->findOneBy($criteria);
264
        if ($entity === null) {
265
            $dto = $this->dtoFactory->create();
266
            $modifier->addDataToNewlyCreatedDto($dto);
267
268
            return $dto;
269
        }
270
271
        return $this->dtoFactory->createDtoFromTestEntity($entity);
272
    }
273
274
    public function getUpsertDtoByProperty(string $propertyName, $value): TestEntityDto
275
    {
276
        $modifier = $this->getModifierClass([$propertyName => $value]);
277
278
        return $this->getUpsertDtoByCriteria([$propertyName => $value], $modifier);
279
    }
280
281
    /**
282
     * This is used to persist the DTO to the database. If the DTO is for a new entity then it will be created, if it
283
     * is for an existing Entity then it will be updated.
284
     *
285
     * Be aware that this method should __only__ be used with DTOs that have been created using the
286
     * self::getUpsertDtoByCriteria method, as if they come from elsewhere we will not not if the entity needs to be
287
     * created or updated
288
     *
289
     * @param TestEntityDto $dto
290
     *
291
     * @return TestEntityInterface
292
     * @throws \Doctrine\DBAL\DBALException
293
     */
294
    public function persistUpsertDto(TestEntityDto $dto): TestEntityInterface
295
    {
296
        if ($this->unitOfWorkHelper->hasRecordOfDto($dto) === false) {
297
            $entity = $this->entityFactory->create($dto);
298
            $this->saver->save($entity);
299
300
            return $entity;
301
        }
302
        $entity = $this->unitOfWorkHelper->getEntityFromUnitOfWorkUsingDto($dto);
303
        $entity->update($dto);
304
        $this->saver->save($entity);
305
306
        return $entity;
307
    }
308
}
309
310
PHP;
311
312
313
314
    /**
315
     * @test
316
     */
317
    public function itCanCreateANewDeeplyNestedEntityUpserter(): void
318
    {
319
        $entityName      = 'TestEntity';
320
        $nestedNamespace = '\\Deeply\\Ne\\S\\ted';
321
        $newObjectFqn    = self::BASE_NAMESPACE . "\\Entity\\Savers$nestedNamespace\\${entityName}Upserter";
322
        $file            = $this->getCreator()->createTargetFileObject($newObjectFqn)->getTargetFile();
323
        $expected=self::NESTED_UPSERTER;
324
        $actual          = $file->getContents();
325
        self::assertSame($expected, $actual);
326
    }
327
328
    /**
329
     * @test
330
     */
331
    public function itCanCreateANewDeeplyNestedEntityUpserterFromEntityFqn(): void
332
    {
333
        $entityName      = 'TestEntity';
334
        $nestedNamespace = '\\Deeply\\Ne\\S\\ted';
335
        $entityFqn       = self::BASE_NAMESPACE . "\\Entities$nestedNamespace\\$entityName";
336
        $file            = $this->getCreator()
337
                                ->setNewObjectFqnFromEntityFqn($entityFqn)
338
                                ->createTargetFileObject()
339
                                ->getTargetFile();
340
        $expected=self::NESTED_UPSERTER;
341
        $actual          = $file->getContents();
342
        self::assertSame($expected, $actual);
343
    }
344
345
    /**
346
     * @test
347
     */
348
    public function itCanCreateANewEntityUpserter(): void
349
    {
350
        $entityName   = 'TestEntity';
351
        $newObjectFqn = self::BASE_NAMESPACE . "\\Entity\\Savers\\${entityName}Upserter";
352
        $file         = $this->getCreator()->createTargetFileObject($newObjectFqn)->getTargetFile();
353
        $expected     = self::UPSERTER;
354
        $actual       = $file->getContents();
355
        self::assertSame($expected, $actual);
356
    }
357
358
    /**
359
     * @test
360
     */
361
    public function itCanCreateANewEntityUpserterFromEntityFqn(): void
362
    {
363
        $entityName = 'TestEntity';
364
        $entityFqn  = self::BASE_NAMESPACE . "\\Entities\\${entityName}";
365
        $file       = $this->getCreator()
366
                           ->setNewObjectFqnFromEntityFqn($entityFqn)
367
                           ->createTargetFileObject()
368
                           ->getTargetFile();
369
        $expected   = self::UPSERTER;
370
        $actual     = $file->getContents();
371
        self::assertSame($expected, $actual);
372
    }
373
374
    private function getCreator(): EntityUpserterCreator
375
    {
376
        $namespaceHelper = new NamespaceHelper();
377
        $config          = new Config(ConfigTest::SERVER);
378
379
        return new EntityUpserterCreator(
380
            new FileFactory($namespaceHelper, $config),
381
            $namespaceHelper,
382
            new Writer(),
383
            $config,
384
            new FindReplaceFactory()
385
        );
386
    }
387
}
388