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 (#57)
by Ross
16:56
created

FieldGeneratorIntegrationTest::getPathFromFqn()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 13
nc 2
nop 1
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator;
4
5
use EdmondsCommerce\DoctrineStaticMeta\AbstractIntegrationTest;
6
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\Field\EntityFieldSetter;
7
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\Field\FieldGenerator;
8
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\NamespaceHelper;
9
use EdmondsCommerce\DoctrineStaticMeta\MappingHelper;
10
11
/**
12
 * Class FieldGeneratorIntegrationTest
13
 *
14
 * @package EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator
15
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
16
 */
17
class FieldGeneratorIntegrationTest extends AbstractIntegrationTest
18
{
19
    public const WORK_DIR = AbstractIntegrationTest::VAR_PATH.'/'.self::TEST_TYPE.'/FieldGeneratorTest/';
20
21
    private const TEST_ENTITY_CAR = self::TEST_PROJECT_ROOT_NAMESPACE.'\\'
22
                                    .AbstractGenerator::ENTITIES_FOLDER_NAME.'\\Car';
23
24
    private const TEST_FIELD_NAMESPACE = self::TEST_PROJECT_ROOT_NAMESPACE.'\\'
25
                                         .AbstractGenerator::ENTITY_FIELD_TRAIT_NAMESPACE;
26
27
    private const CAR_FIELDS_TO_TYPES = [
28
        [self::TEST_FIELD_NAMESPACE.'\\Brand', MappingHelper::TYPE_STRING],
29
        [self::TEST_FIELD_NAMESPACE.'\\EngineCC', MappingHelper::TYPE_INTEGER],
30
        [self::TEST_FIELD_NAMESPACE.'\\Manufactured', MappingHelper::TYPE_DATETIME],
31
        [self::TEST_FIELD_NAMESPACE.'\\Mpg', MappingHelper::TYPE_FLOAT],
32
        [self::TEST_FIELD_NAMESPACE.'\\Description', MappingHelper::TYPE_TEXT],
33
        [self::TEST_FIELD_NAMESPACE.'\\IsCar', MappingHelper::TYPE_BOOLEAN],
34
    ];
35
36
    private const UNIQUE_FIELDS_TO_TYPES = [
37
        [self::TEST_FIELD_NAMESPACE.'\\UniqueString', MappingHelper::TYPE_STRING],
38
        [self::TEST_FIELD_NAMESPACE.'\\UniqueInt', MappingHelper::TYPE_INTEGER],
39
    ];
40
41
    /**
42
     * @var FieldGenerator
43
     */
44
    private $fieldGenerator;
45
    /**
46
     * @var EntityFieldSetter
47
     */
48
    private $entityFieldSetter;
49
    /**
50
     * @var NamespaceHelper
51
     */
52
    private $namespaceHelper;
53
54
    public function setup()
55
    {
56
        parent::setup();
57
        $this->getEntityGenerator()->generateEntity(self::TEST_ENTITY_CAR);
58
        $this->fieldGenerator    = $this->getFieldGenerator();
59
        $this->entityFieldSetter = $this->container->get(EntityFieldSetter::class);
60
        $this->namespaceHelper   = $this->container->get(NamespaceHelper::class);
61
    }
62
63
    public function testArchetypeFieldCanBeStandardLibraryField(): void
64
    {
65
        foreach (FieldGenerator::STANDARD_FIELDS as $standardField) {
66
            $fieldFqn = \str_replace(
67
                [
68
                    'EdmondsCommerce\\DoctrineStaticMeta',
69
                    $this->namespaceHelper->getClassShortName($standardField),
70
                ],
71
                [
72
                    self::TEST_PROJECT_ROOT_NAMESPACE,
73
                    'Copied'.$this->namespaceHelper->getClassShortName($standardField),
74
                ],
75
                $standardField
76
            );
77
            $this->buildAndCheck(
78
                $fieldFqn,
79
                $standardField
80
            );
81
        }
82
    }
83
84
    public function testArchetypeFieldCanBeNonStandardLibraryField(): void
85
    {
86
        $args         = current(self::CAR_FIELDS_TO_TYPES);
87
        $archetypeFqn = $this->fieldGenerator->generateField($args[0], $args[1]);
88
        $this->buildAndCheck(self::TEST_FIELD_NAMESPACE.'\\BrandCopied', $archetypeFqn);
89
    }
90
91
92
    public function testFieldMustContainEntityNamespace()
93
    {
94
        $this->expectException(\InvalidArgumentException::class);
95
        $this->fieldGenerator->generateField(
96
            '\\Blah\\Foop',
97
            MappingHelper::TYPE_STRING,
98
            null,
99
            null,
100
            true
101
        );
102
    }
103
104
    public function testFieldTypeMustBeValid()
105
    {
106
        $this->expectException(\InvalidArgumentException::class);
107
        $this->fieldGenerator->generateField(
108
            self::CAR_FIELDS_TO_TYPES[0][0],
109
            'invalid',
110
            null,
111
            null,
112
            true
113
        );
114
    }
115
116
    public function testPHPTypeMustBeValid()
117
    {
118
        $this->expectException(\InvalidArgumentException::class);
119
        $this->fieldGenerator->generateField(
120
            self::CAR_FIELDS_TO_TYPES[0][0],
121
            MappingHelper::PHP_TYPE_FLOAT,
122
            'invalid',
123
            null,
124
            true
125
        );
126
    }
127
128
    public function testDefaultTypeMustBeValid()
129
    {
130
        $this->expectException(\InvalidArgumentException::class);
131
        $this->fieldGenerator->generateField(
132
            self::CAR_FIELDS_TO_TYPES[0][0],
133
            MappingHelper::PHP_TYPE_FLOAT,
134
            'invalid',
135
            'clearly not a float',
136
            true
137
        );
138
    }
139
140
    /**
141
     * Default values passed in by CLI could come through quite dirty and need to be normalised     *
142
     */
143
    public function testDefaultValueIsNormalised()
144
    {
145
        $defaultValuesToTypes = [
146
            MappingHelper::TYPE_INTEGER => [
147
                1,
148
                '1',
149
                ' 1',
150
                ' 1 ',
151
            ],
152
            MappingHelper::TYPE_FLOAT   => [
153
                1,
154
                1.0,
155
                '1',
156
                '1.1',
157
                ' 1.1 ',
158
                ' 1.1 ',
159
            ],
160
            MappingHelper::TYPE_BOOLEAN => [
161
                'true',
162
                'false',
163
                'TRUE',
164
                'FALSE',
165
                ' TRue ',
166
                ' FaLse ',
167
            ],
168
        ];
169
        $errors               = [];
170
        foreach ($defaultValuesToTypes as $type => $defaultValues) {
171
            foreach ($defaultValues as $key => $defaultValue) {
172
                try {
173
                    $this->buildAndCheck(
174
                        self::TEST_FIELD_NAMESPACE.'\\normalisedDefault'.$type.$key,
175
                        $type,
176
                        $defaultValue
177
                    );
178
                } catch (\Throwable $e) {
179
                    $errors[] = [
180
                        'type'    => $type,
181
                        'default' => $defaultValue,
182
                        'error'   => $e->getMessage(),
183
                    ];
184
                }
185
            }
186
        }
187
        $this->assertSame([], $errors, print_r($errors, true));
188
    }
189
190
    /**
191
     * Build and then test a field
192
     *
193
     * @param string $name
194
     * @param string $type
195
     *
196
     * @param mixed  $default
197
     * @param bool   $isUnique
198
     *
199
     * @return string
200
     * @throws \EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException
201
     * @throws \ReflectionException
202
     * @SuppressWarnings(PHPMD.StaticAccess)
203
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
204
     */
205
    protected function buildAndCheck(
206
        string $name,
207
        string $type,
208
        $default = null,
209
        bool $isUnique = false
210
    ): string {
211
        $fieldTraitFqn = $this->fieldGenerator->generateField(
212
            $name,
213
            $type,
214
            null,
215
            $default,
216
            $isUnique
217
        );
218
219
        $this->qaGeneratedCode();
220
        $interfacePath = $this->getPathFromFqn(
221
            \str_replace(
222
                '\\Fields\\Traits\\',
223
                '\\Fields\\Interfaces\\',
224
                $this->namespaceHelper->cropSuffix($fieldTraitFqn, 'Trait').'Interface'
225
            )
226
        );
227
        $this->assertNoMissedReplacements($interfacePath);
228
229
        $traitPath = $this->getPathFromFqn($fieldTraitFqn);
230
        $this->assertNoMissedReplacements($traitPath);
231
232
        $interfaceContents = file_get_contents($interfacePath);
233
        $traitContents     = file_get_contents($traitPath);
234
235
        $isArchetype = !\in_array($type, MappingHelper::ALL_DBAL_TYPES, true);
236
        if (true === $isArchetype) {
237
            //TODO - some more validation for archetype fields
238
            return $fieldTraitFqn;
239
        }
240
241
        if (!\in_array($type, [MappingHelper::TYPE_TEXT, MappingHelper::TYPE_STRING], true)) {
242
            $this->assertNotContains(': string', $interfaceContents);
243
            $this->assertNotContains('(string', $interfaceContents);
244
            $this->assertNotContains(': string', $traitContents);
245
            $this->assertNotContains('(string', $traitContents);
246
            $phpType = MappingHelper::COMMON_TYPES_TO_PHP_TYPES[$type];
247
            if (null === $default) {
248
                $phpType = "?$phpType";
249
            }
250
            $this->assertContains(': '.$phpType, $interfaceContents);
251
            $this->assertContains('('.$phpType, $interfaceContents);
252
            $this->assertContains(': '.$phpType, $traitContents);
253
            $this->assertContains('('.$phpType, $traitContents);
254
        }
255
256
        if ($type === MappingHelper::TYPE_BOOLEAN) {
257
            $this->assertNotContains('public function get', $interfaceContents);
258
            $this->assertNotContains('public function isIs', $interfaceContents, '', true);
259
            $this->assertNotContains('public function get', $traitContents);
260
            $this->assertNotContains('public function isIs', $traitContents, '', true);
261
        }
262
263
        return $fieldTraitFqn;
264
    }
265
266
    protected function getPathFromFqn(string $fqn): string
267
    {
268
        $path = self::WORK_DIR.'src/Entity/Fields';
269
        $exp  = explode(
270
            '\\',
271
            \substr(
272
                $fqn,
273
                strpos(
274
                    $fqn,
275
                    '\\Entity\\Fields\\'
276
                ) + \strlen('\\Entity\\Fields\\')
277
            )
278
        );
279
        foreach ($exp as $item) {
280
            $path .= '/'.$item;
281
        }
282
        $path .= '.php';
283
284
        return $path;
285
    }
286
287
    public function testBuildFieldsAndSetToEntity()
288
    {
289
        foreach (self::CAR_FIELDS_TO_TYPES as $args) {
290
            $fieldFqn = $this->buildAndCheck($args[0], $args[1], null);
291
            $this->entityFieldSetter->setEntityHasField(self::TEST_ENTITY_CAR, $fieldFqn);
292
        }
293
        $this->qaGeneratedCode();
294
    }
295
296
    public function testBuildFieldsWithSuffixAndSetToEntity()
297
    {
298
        foreach (self::CAR_FIELDS_TO_TYPES as $args) {
299
            $fieldFqn = $this->buildAndCheck($args[0].FieldGenerator::FIELD_TRAIT_SUFFIX, $args[1], null);
300
            $this->entityFieldSetter->setEntityHasField(self::TEST_ENTITY_CAR, $fieldFqn);
301
        }
302
        $this->qaGeneratedCode();
303
    }
304
305
    public function testBuildNullableFieldsAndSetToEntity()
306
    {
307
        foreach (self::CAR_FIELDS_TO_TYPES as $args) {
308
            $fieldFqn = $this->buildAndCheck($args[0], $args[1], null);
309
            $this->entityFieldSetter->setEntityHasField(self::TEST_ENTITY_CAR, $fieldFqn);
310
        }
311
        $this->qaGeneratedCode();
312
    }
313
314
    public function testBuildUniqueFieldsAndSetToEntity()
315
    {
316
        foreach (self::UNIQUE_FIELDS_TO_TYPES as $args) {
317
            $fieldFqn = $this->buildAndCheck($args[0], $args[1], null, true);
318
            $this->entityFieldSetter->setEntityHasField(self::TEST_ENTITY_CAR, $fieldFqn);
319
        }
320
        $this->qaGeneratedCode();
321
    }
322
}
323