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 ( 647edc...edf045 )
by joseph
18s queued 16s
created

FullProjectBuildFunctionalTest::setFields()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 3
nc 3
nop 2
1
<?php declare(strict_types=1);
2
3
namespace EdmondsCommerce\DoctrineStaticMeta;
4
5
use Doctrine\Common\Inflector\Inflector;
6
use EdmondsCommerce\DoctrineStaticMeta\AbstractIntegrationTest;
7
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Command\GenerateFieldCommand;
8
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\AbstractGenerator;
9
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\FieldGenerator;
10
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\Generator\RelationsGenerator;
11
use EdmondsCommerce\DoctrineStaticMeta\Config;
12
use EdmondsCommerce\DoctrineStaticMeta\ConfigInterface;
13
use EdmondsCommerce\DoctrineStaticMeta\Exception\DoctrineStaticMetaException;
14
use EdmondsCommerce\DoctrineStaticMeta\MappingHelper;
15
use EdmondsCommerce\PHPQA\Constants;
16
17
/**
18
 * Class GeneratedCodeTest
19
 *
20
 * @package EdmondsCommerce\DoctrineStaticMeta\GeneratedCode
21
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
22
 */
23
class FullProjectBuildFunctionalTest extends AbstractIntegrationTest
24
{
25
    public const TEST_PROJECT_ROOT_NAMESPACE = 'My\\GeneratedCodeTest\\Project';
26
27
    public const TEST_ENTITY_NAMESPACE_BASE = self::TEST_PROJECT_ROOT_NAMESPACE
28
                                              .'\\'.AbstractGenerator::ENTITIES_FOLDER_NAME;
29
30
    public const TEST_FIELD_TRAIT_NAMESPACE = self::TEST_FIELD_NAMESPACE_BASE.'\\Traits\\';
31
32
    public const TEST_ENTITY_PERSON        = self::TEST_ENTITY_NAMESPACE_BASE.'\\Person';
33
    public const TEST_ENTITY_ADDRESS       = self::TEST_ENTITY_NAMESPACE_BASE.'\\Attributes\\Address';
34
    public const TEST_ENTITY_EMAIL         = self::TEST_ENTITY_NAMESPACE_BASE.'\\Attributes\\Email';
35
    public const TEST_ENTITY_COMPANY       = self::TEST_ENTITY_NAMESPACE_BASE.'\\Company';
36
    public const TEST_ENTITY_DIRECTOR      = self::TEST_ENTITY_NAMESPACE_BASE.'\\Company\\Director';
37
    public const TEST_ENTITY_ORDER         = self::TEST_ENTITY_NAMESPACE_BASE.'\\Order';
38
    public const TEST_ENTITY_ORDER_ADDRESS = self::TEST_ENTITY_NAMESPACE_BASE.'\\Order\\Address';
39
40
    public const TEST_ENTITY_NAME_SPACING_COMPANY        = self::TEST_ENTITY_NAMESPACE_BASE.'\\Company';
41
    public const TEST_ENTITY_NAME_SPACING_SOME_CLIENT    = self::TEST_ENTITY_NAMESPACE_BASE.'\\Some\\Client';
42
    public const TEST_ENTITY_NAME_SPACING_ANOTHER_CLIENT = self::TEST_ENTITY_NAMESPACE_BASE
43
                                                           .'\\Another\\Deeply\\Nested\\Client';
44
45
    public const TEST_ENTITIES = [
46
        self::TEST_ENTITY_PERSON,
47
        self::TEST_ENTITY_ADDRESS,
48
        self::TEST_ENTITY_EMAIL,
49
        self::TEST_ENTITY_COMPANY,
50
        self::TEST_ENTITY_DIRECTOR,
51
        self::TEST_ENTITY_ORDER,
52
        self::TEST_ENTITY_ORDER_ADDRESS,
53
        self::TEST_ENTITY_NAME_SPACING_COMPANY,
54
        self::TEST_ENTITY_NAME_SPACING_SOME_CLIENT,
55
        self::TEST_ENTITY_NAME_SPACING_ANOTHER_CLIENT,
56
    ];
57
58
    public const TEST_RELATIONS = [
59
        [self::TEST_ENTITY_PERSON, RelationsGenerator::HAS_UNIDIRECTIONAL_MANY_TO_ONE, self::TEST_ENTITY_ADDRESS],
60
        [self::TEST_ENTITY_PERSON, RelationsGenerator::HAS_ONE_TO_MANY, self::TEST_ENTITY_EMAIL],
61
        [self::TEST_ENTITY_COMPANY, RelationsGenerator::HAS_MANY_TO_MANY, self::TEST_ENTITY_DIRECTOR],
62
        [self::TEST_ENTITY_COMPANY, RelationsGenerator::HAS_ONE_TO_MANY, self::TEST_ENTITY_ADDRESS],
63
        [self::TEST_ENTITY_COMPANY, RelationsGenerator::HAS_UNIDIRECTIONAL_ONE_TO_MANY, self::TEST_ENTITY_EMAIL],
64
        [self::TEST_ENTITY_DIRECTOR, RelationsGenerator::HAS_ONE_TO_ONE, self::TEST_ENTITY_PERSON],
65
        [self::TEST_ENTITY_ORDER, RelationsGenerator::HAS_MANY_TO_ONE, self::TEST_ENTITY_PERSON],
66
        [self::TEST_ENTITY_ORDER, RelationsGenerator::HAS_ONE_TO_MANY, self::TEST_ENTITY_ORDER_ADDRESS],
67
        [self::TEST_ENTITY_ORDER_ADDRESS, RelationsGenerator::HAS_UNIDIRECTIONAL_ONE_TO_ONE, self::TEST_ENTITY_ADDRESS],
68
        [
69
            self::TEST_ENTITY_NAME_SPACING_COMPANY,
70
            RelationsGenerator::HAS_ONE_TO_ONE,
71
            self::TEST_ENTITY_NAME_SPACING_SOME_CLIENT,
72
        ],
73
        [
74
            self::TEST_ENTITY_NAME_SPACING_COMPANY,
75
            RelationsGenerator::HAS_ONE_TO_ONE,
76
            self::TEST_ENTITY_NAME_SPACING_ANOTHER_CLIENT,
77
        ],
78
    ];
79
80
    public const TEST_FIELD_NAMESPACE_BASE = self::TEST_PROJECT_ROOT_NAMESPACE.'\\Entity\\Fields';
81
82
    public const UNIQUEABLE_FIELD_TYPES = [
83
        MappingHelper::TYPE_INTEGER,
84
        MappingHelper::TYPE_STRING,
85
    ];
86
87
    protected function assertWeCheckAllPossibleRelationTypes()
88
    {
89
        $included = $toTest = [];
90
        foreach (RelationsGenerator::HAS_TYPES as $hasType) {
91
            if (0 === \strpos($hasType, RelationsGenerator::PREFIX_INVERSE)) {
92
                continue;
93
            }
94
            $toTest[$hasType] = true;
95
        }
96
        \ksort($toTest);
97
        foreach (self::TEST_RELATIONS as $relation) {
98
            $included[$relation[1]] = true;
99
        }
100
        \ksort($included);
101
        $missing = \array_diff(\array_keys($toTest), \array_keys($included));
102
        $this->assertEmpty(
103
            $missing,
104
            'We are not testing all relation types - '
105
            .'these ones have not been included: '
106
            .print_r($missing, true)
107
        );
108
    }
109
110
    public const BASH_PHPNOXDEBUG_FUNCTION = <<<'BASH'
111
function phpNoXdebug {
112
    debugMode="off"
113
    if [[ "$-" == *x* ]]
114
    then
115
        debugMode='on'
116
    fi
117
    if [[ "$debugMode" == "on" ]]
118
    then
119
        set +x
120
    fi
121
    local returnCode;
122
    local temporaryPath="$(mktemp -t php.XXXX).ini"
123
    # Using awk to ensure that files ending without newlines do not lead to configuration error
124
    /usr/bin/php -i | grep "\.ini" | grep -o -e '\(/[a-z0-9._-]\+\)\+\.ini' | grep -v xdebug \
125
        | xargs awk 'FNR==1{print ""}1' > "$temporaryPath"
126
    #Run PHP with temp config with no xdebug, display errors on stderr
127
    set +e
128
    /usr/bin/php -n -c "$temporaryPath" "$@"    
129
    returnCode=$?
130
    set -e
131
    rm -f "$temporaryPath"
132
    if [[ "$debugMode" == "on" ]]
133
    then
134
        set -x
135
    fi
136
    return ${returnCode};    
137
}
138
139
BASH;
140
    /**
141
     * @var string
142
     */
143
    private $workDir;
144
145
    /**
146
     * We need to check for uncommited changes in the main project. If there are, then the generated code tests will
147
     * not get them as it works by cloning this repo via the filesystem
148
     */
149
    protected function assertNoUncommitedChanges()
150
    {
151
        if ($this->isTravis()) {
152
            return;
153
        }
154
        exec("git status | grep -E 'nothing to commit, working .*? clean' ", $output, $exitCode);
155
        if (0 !== $exitCode) {
156
            $this->fail(
157
                'uncommitted changes detected in this project, '
158
                .'there is no point running the generated code test as it will not have your uncommitted changes.'
159
                ."\n\n".implode("\n", $output)
160
            );
161
        }
162
    }
163
164
    /**
165
     * @throws \Exception
166
     * @throws \Psr\Container\ContainerExceptionInterface
167
     * @throws \Psr\Container\NotFoundExceptionInterface
168
     * @SuppressWarnings(PHPMD.Superglobals)
169
     * @SuppressWarnings(PHPMD.StaticAccess)
170
     */
171
    public function setup()
172
    {
173
        if (isset($_SERVER[Constants::QA_QUICK_TESTS_KEY])
174
            && (int)$_SERVER[Constants::QA_QUICK_TESTS_KEY] === Constants::QA_QUICK_TESTS_ENABLED
175
        ) {
176
            return;
177
        }
178
        $this->assertNoUncommitedChanges();
179
        $this->workDir      = $this->isTravis() ?
180
            AbstractIntegrationTest::VAR_PATH.'/GeneratedCodeTest'
181
            : sys_get_temp_dir().'/dsm/test-project';
182
        $this->entitiesPath = $this->workDir.'/src/Entities';
183
        $this->getFileSystem()->mkdir($this->workDir);
184
        $this->emptyDirectory($this->workDir);
185
        $this->getFileSystem()->mkdir($this->entitiesPath);
186
        $this->setupContainer($this->entitiesPath);
187
        $this->initRebuildFile();
188
        $this->setupGeneratedDb();
189
        $this->initComposerAndInstall();
190
        $fileSystem = $this->getFileSystem();
191
        $fileSystem->mkdir(
192
            [
193
                $this->workDir.'/tests/',
194
                $this->workDir.'/cache/Proxies',
195
                $this->workDir.'/cache/qa',
196
                $this->workDir.'/qaConfig',
197
            ]
198
        );
199
        $fileSystem->copy(
200
            __DIR__.'/../../qaConfig/phpunit.xml',
201
            $this->workDir.'/qaConfig/phpunit.xml'
202
        );
203
        $fileSystem->symlink($this->workDir.'/qaConfig/phpunit.xml', $this->workDir.'/phpunit.xml');
204
        $fileSystem->copy(
205
            __DIR__.'/../../qaConfig/qaConfig.inc.bash',
206
            $this->workDir.'/qaConfig/qaConfig.inc.bash'
207
        );
208
        $fileSystem->copy(__DIR__.'/../../cli-config.php', $this->workDir.'/cli-config.php');
209
        file_put_contents($this->workDir.'/README.md', '#Generated Code');
210
211
        $this->addToRebuildFile(self::BASH_PHPNOXDEBUG_FUNCTION);
212
213
        $entities            = $this->generateEntities();
214
        $standardFieldEntity = $this->generateStandardFieldEntity();
215
        $this->generateRelations();
216
        $this->generateFields();
217
        $this->setFields(
218
            $entities,
219
            $this->getFieldFqns()
220
        );
221
        $this->setFields(
222
            [$standardFieldEntity],
223
            FieldGenerator::STANDARD_FIELDS
224
        );
225
    }
226
227
    protected function initRebuildFile()
228
    {
229
        $bash =
230
            <<<'BASH'
231
#!/usr/bin/env bash
232
readonly DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )";
233
cd "$DIR";
234
set -e
235
set -u
236
set -o pipefail
237
standardIFS="$IFS"
238
IFS=$'\n\t'
239
echo "
240
===========================================
241
$(hostname) $0 $@
242
===========================================
243
"
244
# Error Handling
245
backTraceExit () {
246
    local err=$?
247
    set +o xtrace
248
    local code="${1:-1}"
249
    printf "\n\nError in ${BASH_SOURCE[1]}:${BASH_LINENO[0]}. '${BASH_COMMAND}'\n\n exited with status: \n\n$err\n\n"
250
    # Print out the stack trace described by $function_stack
251
    if [ ${#FUNCNAME[@]} -gt 2 ]
252
    then
253
        echo "Call tree:"
254
        for ((i=1;i<${#FUNCNAME[@]}-1;i++))
255
        do
256
            echo " $i: ${BASH_SOURCE[$i+1]}:${BASH_LINENO[$i]} ${FUNCNAME[$i]}(...)"
257
        done
258
    fi
259
    echo "Exiting with status ${code}"
260
    exit "${code}"
261
}
262
trap 'backTraceExit' ERR
263
set -o errtrace
264
# Error Handling Ends
265
266
echo "clearing out generated code"
267
rm -rf src/* tests/*
268
269
echo "preparing empty Entities directory"
270
mkdir src/Entities
271
272
echo "making sure we have the latest version of code"
273
(cd vendor/edmondscommerce/doctrine-static-meta && git pull)
274
275
BASH;
276
        if (!$this->isTravis()) {
277
            $bash .= self::BASH_PHPNOXDEBUG_FUNCTION;
278
        }
279
        file_put_contents(
280
            $this->workDir.'/rebuild.bash',
281
            "\n\n".$bash
282
        );
283
    }
284
285
286
    /**
287
     * @return string Generated Database Name
288
     * @throws \Exception
289
     * @throws \Psr\Container\ContainerExceptionInterface
290
     * @throws \Psr\Container\NotFoundExceptionInterface
291
     */
292
    protected function setupGeneratedDb(): string
293
    {
294
        $dbHost = $this->container->get(Config::class)->get(ConfigInterface::PARAM_DB_HOST);
295
        $dbUser = $this->container->get(Config::class)->get(ConfigInterface::PARAM_DB_USER);
296
        $dbPass = $this->container->get(Config::class)->get(ConfigInterface::PARAM_DB_PASS);
297
        $dbName = $this->container->get(Config::class)->get(ConfigInterface::PARAM_DB_NAME);
298
        $link   = mysqli_connect($dbHost, $dbUser, $dbPass);
299
        if (!$link) {
0 ignored issues
show
introduced by
$link is of type mysqli, thus it always evaluated to true.
Loading history...
300
            throw new DoctrineStaticMetaException('Failed getting connection in '.__METHOD__);
301
        }
302
        $generatedDbName = $dbName.'_generated';
303
        mysqli_query($link, "DROP DATABASE IF EXISTS $generatedDbName");
304
        mysqli_query($link, "CREATE DATABASE $generatedDbName 
305
        CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci");
306
        mysqli_close($link);
307
308
        $rebuildBash = <<<BASH
309
echo "Dropping and creating the DB $generatedDbName"        
310
mysql -u $dbUser -p$dbPass -h $dbHost -e "DROP DATABASE IF EXISTS $generatedDbName";
311
mysql -u $dbUser -p$dbPass -h $dbHost -e "CREATE DATABASE $generatedDbName 
312
CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci";
313
BASH;
314
        $this->addToRebuildFile($rebuildBash);
315
        file_put_contents(
316
            $this->workDir.'/.env',
317
            <<<EOF
318
export dbUser="{$dbUser}"
319
export dbPass="{$dbPass}"
320
export dbHost="{$dbHost}"
321
export dbName="$generatedDbName"
322
EOF
323
        );
324
325
        return $generatedDbName;
326
    }
327
328
    /**
329
     * @param string $bash
330
     *
331
     * @return bool
332
     * @throws \Exception
333
     */
334
    protected function addToRebuildFile(string $bash): bool
335
    {
336
        $result = file_put_contents(
337
            $this->workDir.'/rebuild.bash',
338
            "\n\n".$bash."\n\n",
339
            FILE_APPEND
340
        );
341
        if (!$result) {
342
            throw new \RuntimeException('Failed writing to rebuild file');
343
        }
344
345
        return true;
346
    }
347
348
    protected function initComposerAndInstall()
349
    {
350
        $vcsPath = realpath(__DIR__.'/../../../doctrine-static-meta/');
351
352
        $composerJson = <<<'JSON'
353
{
354
  "require": {
355
    "edmondscommerce/doctrine-static-meta": "dev-%s"
356
  },
357
  "repositories": [
358
    {
359
      "type": "vcs",
360
      "url": "%s"
361
    },
362
    {
363
      "type": "vcs",
364
      "url": "https://github.com/edmondscommerce/Faker.git"
365
    }
366
  ],
367
  "minimum-stability": "stable",
368
  "require-dev": {
369
    "fzaninotto/faker": "dev-dsm-patches@dev",
370
    "edmondscommerce/phpqa": "dev-master@dev"
371
  },
372
  "autoload": {
373
    "psr-4": {
374
      "My\\GeneratedCodeTest\\Project\\": [
375
        "src/"
376
      ]
377
    }
378
  },
379
  "autoload-dev": {
380
    "psr-4": {
381
      "My\\GeneratedCodeTest\\Project\\": [
382
        "tests/"
383
      ]
384
    }
385
  },
386
  "config": {
387
    "bin-dir": "bin",
388
    "preferred-install": {
389
      "edmondscommerce/*": "source",
390
      "fzaninotto/faker": "source",
391
      "*": "dist"
392
    },
393
    "optimize-autoloader": true
394
  }
395
}
396
JSON;
397
398
        $gitCurrentBranchName = trim(shell_exec("git branch | grep '*' | cut -d ' ' -f 2"));
399
        file_put_contents(
400
            $this->workDir.'/composer.json',
401
            sprintf($composerJson, $gitCurrentBranchName, $vcsPath)
402
        );
403
404
        $phpCmd   = $this->isTravis() ? 'php' : 'phpNoXdebug';
405
        $bashCmds = <<<BASH
406
           
407
$phpCmd $(which composer) install \
408
    --prefer-dist
409
410
$phpCmd $(which composer) dump-autoload --optimize
411
412
BASH;
413
        $this->execBash($bashCmds);
414
    }
415
416
    /**
417
     * Runs bash with strict error handling and verbose logging
418
     *
419
     * Will ensure the phpNoXdebugFunction is available and will CD into the correct directory before running commands
420
     *
421
     * Asserts that the command returns with an exit code of 0
422
     *
423
     * Appends to the rebuild file allowing easy rerunning of the commmands in the test project
424
     *
425
     * @param string $bashCmds
426
     *
427
     * @throws \Exception
428
     */
429
    protected function execBash(string $bashCmds)
430
    {
431
        fwrite(STDERR, "\n\t# Executing:\n\t$bashCmds");
432
        $startTime = microtime(true);
433
434
        $fullCmds = '';
435
        if (!$this->isTravis()) {
436
            $fullCmds .= "\n".self::BASH_PHPNOXDEBUG_FUNCTION."\n\n";
437
        }
438
        $fullCmds .= "set -xe;\n";
439
        $fullCmds .= "cd {$this->workDir};\n";
440
        #$fullCmds .= "exec 2>&1;\n";
441
        $fullCmds .= "$bashCmds\n";
442
443
        $output   = [];
444
        $exitCode = 0;
445
        exec($fullCmds, $output, $exitCode);
446
447
        if (0 !== $exitCode) {
448
            throw new \RuntimeException(
449
                "Error running bash commands:\n\nOutput:\n----------\n\n"
450
                .implode("\n", $output)
451
                ."\n\nCommands:\n----------\n"
452
                .str_replace(
453
                    "\n",
454
                    "\n\t",
455
                    "\n$bashCmds"
456
                )."\n\n"
457
            );
458
        }
459
460
        $seconds = round(microtime(true) - $startTime, 2);
461
        fwrite(STDERR, "\n\t\t#Completed in $seconds seconds\n");
462
    }
463
464
    protected function generateEntity(string $entityFqn)
465
    {
466
        $namespace   = self::TEST_PROJECT_ROOT_NAMESPACE;
467
        $doctrineCmd = <<<DOCTRINE
468
 dsm:generate:entity \
469
    --project-root-namespace="{$namespace}" \
470
    --entity-fully-qualified-name="{$entityFqn}"
471
DOCTRINE;
472
        $this->execDoctrine($doctrineCmd);
473
    }
474
475
    protected function generateUuidEntity(string $entityFqn)
476
    {
477
        $namespace   = self::TEST_PROJECT_ROOT_NAMESPACE;
478
        $doctrineCmd = <<<DOCTRINE
479
 dsm:generate:entity \
480
    --project-root-namespace="{$namespace}" \
481
    --entity-fully-qualified-name="{$entityFqn}" \
482
    --uuid-primary-key
483
DOCTRINE;
484
        $this->execDoctrine($doctrineCmd);
485
    }
486
487
    /**
488
     * @param string     $propertyName
489
     * @param string     $type
490
     * @param mixed|null $default
491
     * @param bool       $isUnique
492
     * @SuppressWarnings(PHPMD.BooleanArgumentFlag)
493
     */
494
    protected function generateField(
495
        string $propertyName,
496
        string $type,
497
        $default = null,
498
        bool $isUnique = false
499
    ) {
500
        $namespace   = self::TEST_PROJECT_ROOT_NAMESPACE;
501
        $doctrineCmd = <<<DOCTRINE
502
 dsm:generate:field \
503
    --project-root-path="{$this->workDir}" \
504
    --project-root-namespace="{$namespace}" \
505
    --field-fully-qualified-name="{$propertyName}" \
506
    --field-property-doctrine-type="{$type}"
507
DOCTRINE;
508
        if (null !== $default) {
509
            $doctrineCmd .= ' --'.GenerateFieldCommand::OPT_DEFAULT_VALUE.'="'.$default.'"'."\\\n";
510
        }
511
        if (true === $isUnique) {
512
            $doctrineCmd .= ' --'.GenerateFieldCommand::OPT_IS_UNIQUE."\\\n";
513
        }
514
        $this->execDoctrine($doctrineCmd);
515
    }
516
517
    protected function setField(string $entityFqn, string $fieldFqn)
518
    {
519
        $namespace   = self::TEST_PROJECT_ROOT_NAMESPACE;
520
        $doctrineCmd = <<<DOCTRINE
521
 dsm:set:field \
522
    --project-root-path="{$this->workDir}" \
523
    --project-root-namespace="{$namespace}" \
524
    --entity="{$entityFqn}" \
525
    --field="{$fieldFqn}"
526
DOCTRINE;
527
        $this->execDoctrine($doctrineCmd);
528
    }
529
530
    protected function execDoctrine(string $doctrineCmds)
531
    {
532
        $phpCmd  = $this->isTravis() ? 'php' : 'phpNoXdebug';
533
        $bash    = <<<BASH
534
$phpCmd bin/doctrine $doctrineCmds    
535
BASH;
536
        $error   = false;
537
        $message = '';
538
        try {
539
            $this->execBash($bash);
540
        } catch (\RuntimeException $e) {
541
            $this->addToRebuildFile("\n\nexit 0;\n\n#The command below failed...\n\n");
542
            $error   = true;
543
            $message = $e->getMessage();
544
        }
545
        $this->addToRebuildFile($bash);
546
        $this->assertFalse($error, $message);
547
    }
548
549
    protected function setRelation(string $entity1, string $type, string $entity2)
550
    {
551
        $namespace = self::TEST_PROJECT_ROOT_NAMESPACE;
552
        $this->execDoctrine(
553
            <<<DOCTRINE
554
dsm:set:relation \
555
    --project-root-path="{$this->workDir}" \
556
    --project-root-namespace="{$namespace}" \
557
    --entity1="{$entity1}" \
558
    --hasType="{$type}" \
559
    --entity2="{$entity2}"    
560
DOCTRINE
561
        );
562
    }
563
564
    /**
565
     * @SuppressWarnings(PHPMD.Superglobals)
566
     * @throws \Exception
567
     */
568
    public function testRunTests()
569
    {
570
        $this->assertWeCheckAllPossibleRelationTypes();
571
        if (isset($_SERVER[Constants::QA_QUICK_TESTS_KEY])
572
            && (int)$_SERVER[Constants::QA_QUICK_TESTS_KEY] === Constants::QA_QUICK_TESTS_ENABLED
573
        ) {
574
            $this->markTestSkipped('Quick tests is enabled');
575
        }
576
        /** @lang bash */
577
        $bashCmds = <<<BASH
578
579
set +x
580
581
echo "
582
583
--------------------------------------------------
584
STARTS Running Tests In {$this->workDir}
585
--------------------------------------------------
586
587
"
588
589
#Prevent the retry tool dialogue etc
590
export CI=true
591
592
bash -x bin/qa
593
594
echo "
595
596
--------------------------------------------------
597
DONE Running Tests In {$this->workDir}
598
--------------------------------------------------
599
600
"
601
set -x
602
BASH;
603
        $this->execBash($bashCmds);
604
    }
605
606
    /**
607
     * Generate all test entities
608
     *
609
     * @return array
610
     */
611
    protected function generateEntities(): array
612
    {
613
        foreach (self::TEST_ENTITIES as $entityFqn) {
614
            $this->generateEntity($entityFqn);
615
        }
616
617
        return self::TEST_ENTITIES;
618
    }
619
620
    /**
621
     * @return string
622
     */
623
    protected function generateStandardFieldEntity(): string
624
    {
625
        $entityFqn = self::TEST_ENTITY_NAMESPACE_BASE.'\\Standard\\Field';
626
        $this->generateUuidEntity($entityFqn);
627
628
        return $entityFqn;
629
    }
630
631
    /**
632
     * Generate all test relations
633
     *
634
     * @return void
635
     */
636
    protected function generateRelations(): void
637
    {
638
        foreach (self::TEST_RELATIONS as $relation) {
639
            $this->setRelation(...$relation);
0 ignored issues
show
Bug introduced by
The call to EdmondsCommerce\Doctrine...onalTest::setRelation() has too few arguments starting with type. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

639
            $this->/** @scrutinizer ignore-call */ 
640
                   setRelation(...$relation);

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
640
        }
641
    }
642
643
    /**
644
     * Generate one field per common type
645
     *
646
     * @return void
647
     */
648
    protected function generateFields(): void
649
    {
650
        foreach (MappingHelper::COMMON_TYPES as $type) {
651
            $fieldFqn = self::TEST_FIELD_TRAIT_NAMESPACE.'\\'.$type;
652
            $this->generateField($fieldFqn, $type);
653
        }
654
        foreach (self::UNIQUEABLE_FIELD_TYPES as $uniqueableType) {
655
            $fieldFqn = self::TEST_FIELD_TRAIT_NAMESPACE.'\\Unique'.ucwords($uniqueableType);
656
            $this->generateField($fieldFqn, $uniqueableType, null, true);
657
        }
658
    }
659
660
    /**
661
     * Set each field type on each entity type
662
     *
663
     * @param array $entities
664
     * @param array $fields
665
     *
666
     * @return void
667
     */
668
    protected function setFields(array $entities, array $fields): void
669
    {
670
        foreach ($entities as $entityFqn) {
671
            foreach ($fields as $fieldFqn) {
672
                $this->setField($entityFqn, $fieldFqn);
673
            }
674
        }
675
    }
676
677
    /**
678
     * @return array
679
     * @SuppressWarnings(PHPMD.StaticAccess)
680
     */
681
    protected function getFieldFqns(): array
682
    {
683
        $fieldFqns = [];
684
        foreach (MappingHelper::COMMON_TYPES as $type) {
685
            $fieldFqns[] = self::TEST_FIELD_TRAIT_NAMESPACE.Inflector::classify($type).'FieldTrait';
686
        }
687
        foreach (self::UNIQUEABLE_FIELD_TYPES as $type) {
688
            $fieldFqns[] = self::TEST_FIELD_TRAIT_NAMESPACE.Inflector::classify('unique_'.$type).'FieldTrait';
689
        }
690
691
        return $fieldFqns;
692
    }
693
}
694