This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php declare(strict_types=1); |
||
2 | |||
3 | namespace Limoncello\Application\Data; |
||
4 | |||
5 | /** |
||
6 | * Copyright 2015-2020 [email protected] |
||
7 | * |
||
8 | * Licensed under the Apache License, Version 2.0 (the "License"); |
||
9 | * you may not use this file except in compliance with the License. |
||
10 | * You may obtain a copy of the License at |
||
11 | * |
||
12 | * http://www.apache.org/licenses/LICENSE-2.0 |
||
13 | * |
||
14 | * Unless required by applicable law or agreed to in writing, software |
||
15 | * distributed under the License is distributed on an "AS IS" BASIS, |
||
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||
17 | * See the License for the specific language governing permissions and |
||
18 | * limitations under the License. |
||
19 | */ |
||
20 | |||
21 | use DateTimeImmutable; |
||
22 | use Doctrine\DBAL\Connection; |
||
23 | use Doctrine\DBAL\DBALException; |
||
24 | use Doctrine\DBAL\Schema\AbstractSchemaManager; |
||
25 | use Doctrine\DBAL\Schema\Table; |
||
26 | use Doctrine\DBAL\Types\Type; |
||
27 | use Exception; |
||
28 | use Generator; |
||
29 | use Limoncello\Contracts\Commands\IoInterface; |
||
30 | use Limoncello\Contracts\Data\SeedInterface; |
||
31 | use Psr\Container\ContainerExceptionInterface; |
||
32 | use Psr\Container\ContainerInterface; |
||
33 | use Psr\Container\NotFoundExceptionInterface; |
||
34 | use function array_diff; |
||
35 | use function assert; |
||
36 | use function call_user_func; |
||
37 | |||
38 | /** |
||
39 | * @package Limoncello\Application |
||
40 | * |
||
41 | * @SuppressWarnings(PHPMD.CouplingBetweenObjects) |
||
42 | */ |
||
43 | abstract class BaseSeedRunner |
||
44 | { |
||
45 | /** Seed column name */ |
||
46 | const SEEDS_COLUMN_ID = 'id'; |
||
47 | |||
48 | /** Seed column name */ |
||
49 | const SEEDS_COLUMN_CLASS = 'class'; |
||
50 | |||
51 | /** Seed column name */ |
||
52 | const SEEDS_COLUMN_SEEDED_AT = 'seeded_at'; |
||
53 | |||
54 | /** |
||
55 | * @var string |
||
56 | */ |
||
57 | private $seedsTable; |
||
58 | |||
59 | /** |
||
60 | * @var null|callable |
||
61 | */ |
||
62 | private $seedInit = null; |
||
63 | |||
64 | /** |
||
65 | * @var IoInterface |
||
66 | */ |
||
67 | private $inOut; |
||
68 | |||
69 | /** |
||
70 | * @return string[] |
||
71 | */ |
||
72 | abstract protected function getSeedClasses(): array; |
||
73 | |||
74 | 2 | /** |
|
75 | * @param IoInterface $inOut |
||
76 | * @param callable $seedInit |
||
0 ignored issues
–
show
|
|||
77 | * @param string $seedsTable |
||
78 | */ |
||
79 | 2 | public function __construct( |
|
80 | IoInterface $inOut, |
||
81 | 2 | callable $seedInit = null, |
|
82 | 2 | string $seedsTable = BaseMigrationRunner::SEEDS_TABLE |
|
83 | ) { |
||
84 | 2 | assert(empty($seedsTable) === false); |
|
85 | |||
86 | $this->seedInit = $seedInit; |
||
87 | $this->seedsTable = $seedsTable; |
||
88 | |||
89 | $this->setIO($inOut); |
||
90 | } |
||
91 | |||
92 | /** |
||
93 | * @param ContainerInterface $container |
||
94 | * |
||
95 | * @return void |
||
96 | 1 | * |
|
97 | * @throws ContainerExceptionInterface |
||
98 | 1 | * @throws NotFoundExceptionInterface |
|
99 | 1 | * @throws DBALException |
|
100 | 1 | */ |
|
101 | public function run(ContainerInterface $container): void |
||
102 | 1 | { |
|
103 | 1 | foreach ($this->getSeeds($container) as $seederClass) { |
|
104 | 1 | $this->getIO()->writeInfo("Starting seed for `$seederClass`..." . PHP_EOL, IoInterface::VERBOSITY_VERBOSE); |
|
105 | $this->executeSeedInit($container, $seederClass); |
||
106 | /** @var SeedInterface $seeder */ |
||
107 | $seeder = new $seederClass(); |
||
108 | $seeder->init($container)->run(); |
||
109 | $this->getIO()->writeInfo("Seed finished for `$seederClass`." . PHP_EOL, IoInterface::VERBOSITY_NORMAL); |
||
110 | } |
||
111 | } |
||
112 | |||
113 | /** |
||
114 | * @param ContainerInterface $container |
||
115 | * |
||
116 | * @return Generator |
||
117 | * |
||
118 | * @throws ContainerExceptionInterface |
||
119 | 1 | * @throws NotFoundExceptionInterface |
|
120 | * |
||
121 | 1 | * @SuppressWarnings(PHPMD.ElseExpression) |
|
122 | 1 | * @throws DBALException |
|
123 | */ |
||
124 | 1 | protected function getSeeds(ContainerInterface $container): Generator |
|
125 | 1 | { |
|
126 | $connection = $this->getConnection($container); |
||
127 | 1 | $manager = $connection->getSchemaManager(); |
|
128 | 1 | ||
129 | if ($manager->tablesExist([$this->getSeedsTable()]) === true) { |
||
130 | $seeded = $this->readSeeded($connection); |
||
131 | 1 | } else { |
|
132 | $this->createSeedsTable($manager); |
||
133 | 1 | $seeded = []; |
|
134 | 1 | } |
|
135 | 1 | ||
136 | $notYetSeeded = array_diff($this->getSeedClasses(), $seeded); |
||
137 | |||
138 | foreach ($notYetSeeded as $class) { |
||
139 | yield $class; |
||
140 | $this->saveSeed($connection, $class); |
||
141 | } |
||
142 | } |
||
143 | |||
144 | /** |
||
145 | * @param ContainerInterface $container |
||
146 | * |
||
147 | 1 | * @return Connection |
|
148 | * |
||
149 | 1 | * @throws ContainerExceptionInterface |
|
150 | * @throws NotFoundExceptionInterface |
||
151 | */ |
||
152 | protected function getConnection(ContainerInterface $container): Connection |
||
153 | { |
||
154 | return $container->get(Connection::class); |
||
155 | } |
||
156 | |||
157 | /** |
||
158 | 1 | * @param ContainerInterface $container |
|
159 | * @param string $seedClass |
||
160 | 1 | * |
|
161 | 1 | * @return void |
|
162 | */ |
||
163 | protected function executeSeedInit(ContainerInterface $container, string $seedClass): void |
||
164 | { |
||
165 | if ($this->seedInit !== null) { |
||
166 | call_user_func($this->seedInit, $container, $seedClass); |
||
167 | } |
||
168 | 1 | } |
|
169 | |||
170 | 1 | /** |
|
171 | * @return IoInterface |
||
172 | */ |
||
173 | protected function getIO(): IoInterface |
||
174 | { |
||
175 | return $this->inOut; |
||
176 | } |
||
177 | |||
178 | 2 | /** |
|
179 | * @param IoInterface $inOut |
||
180 | 2 | * |
|
181 | * @return self |
||
182 | 2 | */ |
|
183 | private function setIO(IoInterface $inOut): self |
||
184 | { |
||
185 | $this->inOut = $inOut; |
||
186 | |||
187 | return $this; |
||
188 | } |
||
189 | |||
190 | /** |
||
191 | * @param AbstractSchemaManager $manager |
||
192 | 1 | * |
|
193 | * @return void |
||
194 | 1 | * |
|
195 | * @throws DBALException |
||
196 | */ |
||
197 | 1 | private function createSeedsTable(AbstractSchemaManager $manager): void |
|
198 | 1 | { |
|
199 | 1 | $table = new Table($this->getSeedsTable()); |
|
200 | |||
201 | 1 | $table |
|
202 | 1 | ->addColumn(static::SEEDS_COLUMN_ID, Type::INTEGER) |
|
0 ignored issues
–
show
The constant
Doctrine\DBAL\Types\Type::INTEGER has been deprecated with message: Use {@see Types::INTEGER} instead.
This class constant has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead. ![]() |
|||
203 | ->setUnsigned(true) |
||
204 | 1 | ->setAutoincrement(true); |
|
205 | $table |
||
206 | 1 | ->addColumn(static::SEEDS_COLUMN_CLASS, Type::STRING) |
|
0 ignored issues
–
show
The constant
Doctrine\DBAL\Types\Type::STRING has been deprecated with message: Use {@see Types::STRING} instead.
This class constant has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead. ![]() |
|||
207 | 1 | ->setLength(255); |
|
208 | $table |
||
209 | 1 | ->addColumn(static::SEEDS_COLUMN_SEEDED_AT, Type::DATETIME); |
|
0 ignored issues
–
show
The constant
Doctrine\DBAL\Types\Type::DATETIME has been deprecated with message: Use {@see Types::DATETIME_MUTABLE} instead.
This class constant has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead. ![]() |
|||
210 | |||
211 | $table->setPrimaryKey([static::SEEDS_COLUMN_ID]); |
||
212 | $table->addUniqueIndex([static::SEEDS_COLUMN_CLASS]); |
||
213 | |||
214 | $manager->createTable($table); |
||
215 | } |
||
216 | |||
217 | 1 | /** |
|
218 | * @param Connection $connection |
||
219 | 1 | * |
|
220 | 1 | * @return array |
|
221 | */ |
||
222 | 1 | private function readSeeded(Connection $connection): array |
|
223 | { |
||
224 | 1 | $builder = $connection->createQueryBuilder(); |
|
225 | 1 | $seeded = []; |
|
226 | 1 | ||
227 | 1 | if ($connection->getSchemaManager()->tablesExist([$this->getSeedsTable()]) === true) { |
|
228 | 1 | $seeds = $builder |
|
229 | 1 | ->select(static::SEEDS_COLUMN_ID, static::SEEDS_COLUMN_CLASS) |
|
230 | 1 | ->from($this->getSeedsTable()) |
|
231 | 1 | ->orderBy(static::SEEDS_COLUMN_ID) |
|
232 | 1 | ->execute() |
|
233 | ->fetchAll(); |
||
234 | foreach ($seeds as $seed) { |
||
235 | $index = $seed[static::SEEDS_COLUMN_ID]; |
||
236 | 1 | $class = $seed[static::SEEDS_COLUMN_CLASS]; |
|
237 | $seeded[$index] = $class; |
||
238 | } |
||
239 | } |
||
240 | |||
241 | return $seeded; |
||
242 | } |
||
243 | |||
244 | /** |
||
245 | * @param Connection $connection |
||
246 | * @param string $class |
||
247 | * |
||
248 | 1 | * @return void |
|
249 | * |
||
250 | 1 | * @throws DBALException |
|
251 | 1 | * @throws Exception |
|
252 | 1 | */ |
|
253 | 1 | private function saveSeed(Connection $connection, string $class): void |
|
254 | 1 | { |
|
255 | $format = $connection->getSchemaManager()->getDatabasePlatform()->getDateTimeFormatString(); |
||
256 | $now = (new DateTimeImmutable())->format($format); |
||
257 | $connection->insert($this->getSeedsTable(), [ |
||
258 | static::SEEDS_COLUMN_CLASS => $class, |
||
259 | static::SEEDS_COLUMN_SEEDED_AT => $now, |
||
260 | ]); |
||
261 | 1 | } |
|
262 | |||
263 | 1 | /** |
|
264 | * @return string |
||
265 | */ |
||
266 | private function getSeedsTable(): string |
||
267 | { |
||
268 | return $this->seedsTable; |
||
269 | } |
||
270 | } |
||
271 |
This check looks for
@param
annotations where the type inferred by our type inference engine differs from the declared type.It makes a suggestion as to what type it considers more descriptive. In addition it looks for parameters that have the generic type
array
and suggests a stricter type likearray<String>
.Most often this is a case of a parameter that can be null in addition to its declared types.