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
Push — master ( 0a6f96...b0c756 )
by Ross
12s queued 10s
created

TestEntityGenerator::assertInArray()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
nc 2
nop 3
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\Entity\Testing;
4
5
use Doctrine\Common\Collections\ArrayCollection;
6
use Doctrine\ORM\EntityManager;
7
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\NamespaceHelper;
8
use EdmondsCommerce\DoctrineStaticMeta\Entity\Interfaces\EntityInterface;
9
use EdmondsCommerce\DoctrineStaticMeta\Entity\Savers\EntitySaverFactory;
10
use EdmondsCommerce\DoctrineStaticMeta\Exception\ConfigException;
11
use Faker;
12
use Faker\ORM\Doctrine\Populator;
13
14
/**
15
 * Class TestEntityGenerator
16
 *
17
 * This class handles utilising Faker to build up an Entity and then also possible build associated entities and handle
18
 * the association
19
 *
20
 * Unique columns are guaranteed to have a totally unique value in this particular process, but not between processes
21
 *
22
 * @package EdmondsCommerce\DoctrineStaticMeta\Entity\Testing
23
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
24
 */
25
class TestEntityGenerator
26
{
27
    /**
28
     * @var Faker\Generator
29
     */
30
    protected $generator;
31
32
33
    /**
34
     * @var EntityManager
35
     */
36
    protected $entityManager;
37
38
    /**
39
     * These two are used to keep track of unique fields and ensure we dont accidently make apply none unique values
40
     *
41
     * @var array
42
     */
43
    private static $uniqueStrings = [];
44
    /**
45
     * @var int
46
     */
47
    private static $uniqueInt;
48
49
50
    /**
51
     * An array of fieldNames to class names that are to be instantiated as column formatters as required
52
     *
53
     * @var array
54
     */
55
    protected $fakerDataProviderClasses;
56
57
    /**
58
     * A cache of instantiated column data providers
59
     *
60
     * @var array
61
     */
62
    protected $fakerDataProviderObjects = [];
63
64
    /**
65
     * Reflection of the tested entity
66
     *
67
     * @var \ReflectionClass
68
     */
69
    protected $testedEntityReflectionClass;
70
    /**
71
     * @var EntitySaverFactory
72
     */
73
    protected $entitySaverFactory;
74
75
    /**
76
     * TestEntityGenerator constructor.
77
     *
78
     * @param EntityManager      $entityManager
79
     * @param float|null         $seed
80
     * @param array              $fakerDataProviderClasses
81
     * @param \ReflectionClass   $testedEntityReflectionClass
82
     * @param EntitySaverFactory $entitySaverFactory
83
     * @SuppressWarnings(PHPMD.StaticAccess)
84
     */
85
    public function __construct(
86
        EntityManager $entityManager,
87
        ?float $seed,
88
        array $fakerDataProviderClasses,
89
        \ReflectionClass $testedEntityReflectionClass,
90
        EntitySaverFactory $entitySaverFactory
91
    ) {
92
        $this->entityManager = $entityManager;
93
        $this->generator     = Faker\Factory::create();
94
        if (null !== $seed) {
95
            $this->generator->seed($seed);
96
        }
97
        $this->fakerDataProviderClasses    = $fakerDataProviderClasses;
98
        $this->testedEntityReflectionClass = $testedEntityReflectionClass;
99
        $this->entitySaverFactory          = $entitySaverFactory;
100
    }
101
102
    /**
103
     * @param string $class
104
     *
105
     * @return EntityInterface
106
     * @throws ConfigException
107
     * @throws \Exception
108
     * @SuppressWarnings(PHPMD.StaticAccess)
109
     */
110
    public function generateEntity(string $class): EntityInterface
111
    {
112
        $customColumnFormatters = $this->generateColumnFormatters($this->entityManager, $class);
113
        $populator              = new Populator($this->generator, $this->entityManager);
114
        $populator->addEntity($class, 1, $customColumnFormatters);
115
116
        return $populator->execute(null, false)[$class][0];
117
    }
118
119
    /**
120
     * @param EntityManager   $entityManager
121
     * @param EntityInterface $generated
122
     *
123
     * @throws ConfigException
124
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
125
     * @throws \ReflectionException
126
     * @SuppressWarnings(PHPMD.ElseExpression)
127
     * @throws \ErrorException
128
     */
129
    public function addAssociationEntities(
130
        EntityManager $entityManager,
131
        EntityInterface $generated
132
    ): void {
133
        $class    = $this->testedEntityReflectionClass->getName();
134
        $meta     = $entityManager->getClassMetadata($class);
135
        $mappings = $meta->getAssociationMappings();
136
        if (empty($mappings)) {
137
            return;
138
        }
139
        $namespaceHelper = new NamespaceHelper();
140
        $methods         = array_map('strtolower', get_class_methods($generated));
141
        foreach ($mappings as $mapping) {
142
            $mappingEntityClass = $mapping['targetEntity'];
143
            $mappingEntity      = $this->generateEntity($mappingEntityClass);
144
            $errorMessage       = "Error adding association entity $mappingEntityClass to $class: %s";
145
            $this->entitySaverFactory->getSaverForEntity($mappingEntity)->save($mappingEntity);
146
            $mappingEntityPluralInterface = $namespaceHelper->getHasPluralInterfaceFqnForEntity($mappingEntityClass);
147
            if ($this->testedEntityReflectionClass->implementsInterface($mappingEntityPluralInterface)) {
148
                $this->assertEquals(
149
                    $mappingEntityClass::getPlural(),
150
                    $mapping['fieldName'],
151
                    sprintf($errorMessage, ' mapping should be plural')
152
                );
153
                $method = 'add'.$mappingEntityClass::getSingular();
154
            } else {
155
                $this->assertEquals(
156
                    $mappingEntityClass::getSingular(),
157
                    $mapping['fieldName'],
158
                    sprintf($errorMessage, ' mapping should be singular')
159
                );
160
                $method = 'set'.$mappingEntityClass::getSingular();
161
            }
162
            $this->assertInArray(
163
                strtolower($method),
164
                $methods,
165
                sprintf($errorMessage, $method.' method is not defined')
166
            );
167
            $generated->$method($mappingEntity);
168
        }
169
    }
170
171
    /**
172
     * Stub of PHPUnit Assertion method
173
     *
174
     * @param mixed  $expected
175
     * @param mixed  $actual
176
     * @param string $error
177
     *
178
     * @throws \ErrorException
179
     */
180
    protected function assertEquals($expected, $actual, string $error): void
181
    {
182
        if ($expected !== $actual) {
183
            throw new \ErrorException($error);
184
        }
185
    }
186
187
    /**
188
     * Stub of PHPUnit Assertion method
189
     *
190
     * @param mixed  $needle
191
     * @param array  $haystack
192
     * @param string $error
193
     *
194
     * @throws \ErrorException
195
     */
196
    protected function assertInArray($needle, array $haystack, string $error): void
197
    {
198
        if (false === \in_array($needle, $haystack, true)) {
199
            throw new \ErrorException($error);
200
        }
201
    }
202
203
    /**
204
     * @param EntityManager $entityManager
205
     * @param string        $class
206
     *
207
     * @return array
208
     * @throws \Doctrine\ORM\Mapping\MappingException
209
     */
210
    protected function generateColumnFormatters(EntityManager $entityManager, string $class): array
211
    {
212
        $columnFormatters = [];
213
        $meta             = $entityManager->getClassMetadata($class);
214
        $mappings         = $meta->getAssociationMappings();
215
        foreach ($mappings as $mapping) {
216
            if ($meta->isCollectionValuedAssociation($mapping['fieldName'])) {
217
                $columnFormatters[$mapping['fieldName']] = new ArrayCollection();
218
                continue;
219
            }
220
            $columnFormatters[$mapping['fieldName']] = null;
221
        }
222
        $fieldNames = $meta->getFieldNames();
223
224
        foreach ($fieldNames as $fieldName) {
225
            if (!isset($columnFormatters[$fieldName])) {
226
                if (true === $this->setFakerDataProvider($columnFormatters, $fieldName)) {
227
                    continue;
228
                }
229
            }
230
            $fieldMapping = $meta->getFieldMapping($fieldName);
231
            if (true === ($fieldMapping['unique'] ?? false)) {
232
                switch ($fieldMapping['type']) {
233
                    case 'string':
234
                        $columnFormatters[$fieldName] = $this->getUniqueString();
235
                        break;
236
                    case 'integer':
237
                        $columnFormatters[$fieldName] = $this->getUniqueInt();
238
                        break;
239
                    default:
240
                        throw new \InvalidArgumentException('unique field has an unsupported type: '
241
                                                            .print_r($fieldMapping, true));
242
                }
243
            }
244
        }
245
246
        return $columnFormatters;
247
    }
248
249
    protected function getUniqueString(): string
250
    {
251
        $string = 'unique string: '.$this->getUniqueInt().md5((string)time());
252
        while (isset(self::$uniqueStrings[$string])) {
253
            $string                       = md5((string)time());
254
            self::$uniqueStrings[$string] = true;
255
        }
256
257
        return $string;
258
    }
259
260
    protected function getUniqueInt(): int
261
    {
262
        return ++self::$uniqueInt;
263
    }
264
265
    /**
266
     * Add a faker data provider to the columnFormatters array (by reference) if there is one available
267
     *
268
     * Handles instantiating and caching of the data providers
269
     *
270
     * @param array  $columnFormatters
271
     * @param string $fieldName
272
     *
273
     * @return bool
274
     */
275
    protected function setFakerDataProvider(array &$columnFormatters, string $fieldName): bool
276
    {
277
        if (!isset($this->fakerDataProviderClasses[$fieldName])) {
278
            return false;
279
        }
280
        if (!isset($this->fakerDataProviderObjects[$fieldName])) {
281
            $class                                      = $this->fakerDataProviderClasses[$fieldName];
282
            $this->fakerDataProviderObjects[$fieldName] = new $class($this->generator);
283
        }
284
        $columnFormatters[$fieldName] = $this->fakerDataProviderObjects[$fieldName];
285
286
        return true;
287
    }
288
}
289