Passed
Push — master ( 6f905d...2edd34 )
by Oleg
02:55
created

AbstractTest::getLatestProvider()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
ccs 4
cts 4
cp 1
crap 2
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
            $entity = $item['entity'] ?? '';
89 10
            $nullable = $item['nullable'] ?? false;
90 10
            $referenceColumn = $item['ref_column_key'] ?? 'id';
91
            // Skip 50% of nullable values (by default)
92 10
            if ($nullable && rand(0,100)/100 > $this->probabilityOfFilledNullable) {
93 7
                continue;
94
            }
95
            switch ($type) {
96 10
                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...
97 2
                    $innerProvider = $this->getInnerProvider($entity);
98 2
                    $body = $this->appendOnce(
99 2
                        $this->getHaveInRepoPhrase($innerProvider) . $this->getUsagePhrase($innerProvider, $referenceColumn),
100 2
                        $body
101
                    );
102 2
                    $params[$key] = '$' . $innerProvider->getShortName();
103 2
                    break;
104 10
                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...
105 1
                    $innerProvider = $this->getInnerProvider($entity);
106 1
                    $body = $this->appendOnce(
107 1
                        $this->getHaveInRepoPhrase($innerProvider) . $this->getUsagePhrase($innerProvider, $referenceColumn),
108 1
                        $body
109
                    );
110 1
                    $params[$key] = '[$' . $innerProvider->getShortName() . ']';
111 1
                    break;
112 10
                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...
113
                    $innerProvider = $this->entityProviderFactory->create($entity);
114
                    $body .= $this->getHaveInRepoPhrase($innerProvider) . $this->getUsagePhrase($innerProvider, $referenceColumn);
115
                    $params[$key] = '$' . $innerProvider->getShortName();
116
                    break;
117
                default:
0 ignored issues
show
Coding Style introduced by
DEFAULT statements must be defined using a colon

As per the PSR-2 coding standard, default statements should not be wrapped in curly braces.

switch ($expr) {
    default: { //wrong
        doSomething();
        break;
    }
}

switch ($expr) {
    default: //right
        doSomething();
        break;
}

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

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