Completed
Push — master ( 2edd34...81ce9d )
by Oleg
02:56
created

AbstractTest::getHaveInRepoParams()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
ccs 3
cts 4
cp 0.75
crap 2.0625
1
<?php
2
declare(strict_types=1);
3
4
namespace SlayerBirden\DFCodeGeneration\Generator\Tests;
5
6
use SlayerBirden\DFCodeGeneration\Generator\GeneratorInterface;
7
8
abstract class AbstractTest implements GeneratorInterface
9
{
10
    /**
11
     * @var EntityProviderFactoryInterface
12
     */
13
    protected $entityProviderFactory;
14
    /**
15
     * @var string
16
     */
17
    protected $entityClassName;
18
    /**
19
     * @var EntityProviderInterface[]
20
     */
21
    protected $providers = [];
22
    private $innerProviders = [];
23
    private $appended = [];
24
    /**
25
     * The default probability of Nulled values being filled with data
26
     * @var float
27
     */
28
    private $probabilityOfFilledNullable;
29
30 10
    public function __construct(
31
        string $entityClassName,
32
        EntityProviderFactoryInterface $entityProviderFactory,
33
        float $probabilityOfFilledNullable = .5
34
    ) {
35 10
        $this->entityProviderFactory = $entityProviderFactory;
36 10
        $this->entityClassName = $entityClassName;
37 10
        $this->probabilityOfFilledNullable = $probabilityOfFilledNullable;
38 10
    }
39
40 5
    protected function getLatestProvider()
41
    {
42 5
        if (count($this->providers)) {
43 5
            return end($this->providers);
44
        } else {
45 5
            return $this->entityProviderFactory->create($this->entityClassName);
46
        }
47
    }
48
49 10
    protected function generateHaveInRepo(int $count = 1): string
50
    {
51 10
        $generated = 0;
52 10
        $body = '';
53 10
        while ($generated < $count) {
54 10
            $provider = $this->entityProviderFactory->create($this->entityClassName);
55 10
            $body .= $this->getHaveInRepoPhrase($provider);
56 10
            $this->providers[] = $provider;
57 10
            $generated++;
58
        }
59 10
        return $body;
60
    }
61
62 3
    private function getInnerProvider(string $entity): EntityProviderInterface
63
    {
64 3
        if (!isset($this->innerProviders[$entity])) {
65 3
            $this->innerProviders[$entity] = $this->entityProviderFactory->create($entity);
66
        }
67
68 3
        return $this->innerProviders[$entity];
69
    }
70
71 3
    private function appendOnce(string $content, string $to)
72
    {
73 3
        if (in_array($content, $this->appended, true)) {
74 2
            return $to;
75
        }
76 3
        $this->appended[] = $content;
77 3
        return $to . $content;
78
    }
79
80 10
    private function getHaveInRepoPhrase(EntityProviderInterface $provider): string
81
    {
82 10
        $body = '';
83
84 10
        $params = [];
85 10
        foreach ($provider->getEntitySpec() as $item) {
86 10
            $key = $item['name'];
87 10
            $type = $item['type'];
88 10
            $reference = $item['reference'] ?? [];
89 10
            $nullable = $item['nullable'] ?? false;
90
            // Skip 50% of nullable values (by default)
91 10
            if ($nullable && rand(0,100)/100 > $this->probabilityOfFilledNullable) {
92 6
                continue;
93
            }
94 10
            if ($reference) {
95 3
                $referenceColumn = $reference['ref_column_key'] ?? 'id';
96 3
                $entity = $reference['entity'];
97
98
                switch ($type) {
99 3
                    case 'manytoone':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
100 2
                        $innerProvider = $this->getInnerProvider($entity);
101 2
                        $body = $this->appendOnce(
102 2
                            $this->getHaveInRepoPhrase($innerProvider) . $this->getUsagePhrase($innerProvider, $referenceColumn),
103 2
                            $body
104
                        );
105 2
                        $params[$key] = '$' . $innerProvider->getShortName();
106 2
                        break;
107 1
                    case 'manytomany':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
108 1
                        $innerProvider = $this->getInnerProvider($entity);
109 1
                        $body = $this->appendOnce(
110 1
                            $this->getHaveInRepoPhrase($innerProvider) . $this->getUsagePhrase($innerProvider, $referenceColumn),
111 1
                            $body
112
                        );
113 1
                        $params[$key] = '[$' . $innerProvider->getShortName() . ']';
114 1
                        break;
115
                    case 'onetoone':
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
116
                        $innerProvider = $this->entityProviderFactory->create($entity);
117
                        $body .= $this->getHaveInRepoPhrase($innerProvider) . $this->getUsagePhrase($innerProvider, $referenceColumn);
118
                        $params[$key] = '$' . $innerProvider->getShortName();
119 3
                        break;
120
                }
121
            } else {
122 10
                $params[$key] = new ProviderValuePromise($provider, $key);
123
            }
124
        }
125
126 10
        $params = $this->resolvePromises($params);
127
128 10
        $body .= '$I->haveInRepository(%1$s, %2$s);';
129
        $args = [
130 10
            '\'' . $provider->getEntityClassName() . '\'',
131 10
            var_export($params, true),
132
        ];
133 10
        $body = sprintf($body, ...$args);
134 10
        $body = preg_replace("/'(\\[?\\$\w*\\]?)'/", '$1', $body);
135
136 10
        return $body . PHP_EOL;
137
    }
138
139
    private function resolvePromises(array $params): array
140
    {
141 10
        return array_map(function ($item) {
142 10
            if ($item instanceof ProviderValuePromise) {
143 10
                return $item->resolve();
144
            }
145 3
            return $item;
146 10
        }, $params);
147
    }
148
149 3
    protected function getHaveInRepoParams(int $idx = 0): array
150
    {
151 3
        if (isset($this->providers[$idx])) {
152 3
            return $this->providers[$idx]->getPostParams();
153
        }
154
155
        throw new \InvalidArgumentException('Wrong id provided.');
156
    }
157
158 3
    protected function getUsagePhrase(EntityProviderInterface $provider, string $referenceColumn): string
159
    {
160 3
        $body = '$%s = $I->grabEntityFromRepository(%s, [\'' . $referenceColumn . '\' => %d]);';
161
162
        $args = [
163 3
            $provider->getShortName(),
164 3
            '\'' . $provider->getEntityClassName() . '\'',
165 3
            $provider->getId(),
166
        ];
167 3
        $body = sprintf($body, ...$args);
168
169 3
        return $body . PHP_EOL;
170
    }
171
}
172