These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Kunstmaan\GeneratorBundle\Command; |
||
4 | |||
5 | use Kunstmaan\AdminBundle\Form\WysiwygType; |
||
6 | use Kunstmaan\GeneratorBundle\Helper\CommandAssistant; |
||
7 | use Kunstmaan\GeneratorBundle\Helper\GeneratorUtils; |
||
8 | use Kunstmaan\GeneratorBundle\Helper\Sf4AppBundle; |
||
9 | use Kunstmaan\MediaBundle\Form\Type\MediaType; |
||
10 | use Kunstmaan\NodeBundle\Form\Type\URLChooserType; |
||
11 | use Sensio\Bundle\GeneratorBundle\Command\GenerateDoctrineCommand; |
||
12 | use Symfony\Bridge\Doctrine\Form\Type\EntityType; |
||
13 | use Symfony\Component\Console\Input\InputInterface; |
||
14 | use Symfony\Component\Console\Output\OutputInterface; |
||
15 | use Symfony\Component\DependencyInjection\Container; |
||
16 | use Symfony\Component\Finder\Finder; |
||
17 | use Symfony\Component\Form\Extension\Core\Type\CheckboxType; |
||
18 | use Symfony\Component\Form\Extension\Core\Type\DateTimeType; |
||
19 | use Symfony\Component\Form\Extension\Core\Type\IntegerType; |
||
20 | use Symfony\Component\Form\Extension\Core\Type\NumberType; |
||
21 | use Symfony\Component\Form\Extension\Core\Type\TextareaType; |
||
22 | use Symfony\Component\Form\Extension\Core\Type\TextType; |
||
23 | use Symfony\Component\HttpKernel\Bundle\BundleInterface; |
||
24 | use Symfony\Component\HttpKernel\Kernel; |
||
25 | use Symfony\Component\Yaml\Exception\ParseException; |
||
26 | use Symfony\Component\Yaml\Yaml; |
||
27 | |||
28 | abstract class KunstmaanGenerateCommand extends GenerateDoctrineCommand |
||
29 | { |
||
30 | /** |
||
31 | * @var CommandAssistant |
||
32 | */ |
||
33 | protected $assistant; |
||
34 | |||
35 | /** |
||
36 | * Interacts with the user. |
||
37 | * |
||
38 | * @param InputInterface $input An InputInterface instance |
||
39 | * @param OutputInterface $output An OutputInterface instance |
||
40 | */ |
||
41 | protected function interact(InputInterface $input, OutputInterface $output) |
||
42 | { |
||
43 | $this->setInputAndOutput($input, $output); |
||
44 | |||
45 | $welcomeText = $this->getWelcomeText(); |
||
46 | if (!empty($welcomeText)) { |
||
47 | $this->assistant->writeSection($this->getWelcomeText()); |
||
48 | } |
||
49 | |||
50 | $this->doInteract(); |
||
51 | } |
||
52 | |||
53 | /** |
||
54 | * @param InputInterface $input |
||
55 | * @param OutputInterface $output |
||
56 | * |
||
57 | * @return int|null |
||
58 | */ |
||
59 | protected function execute(InputInterface $input, OutputInterface $output) |
||
60 | { |
||
61 | $this->setInputAndOutput($input, $output); |
||
62 | |||
63 | return $this->doExecute(); |
||
64 | } |
||
65 | |||
66 | /** |
||
67 | * Create the CommandAssistant. |
||
68 | * |
||
69 | * @param InputInterface $input |
||
70 | * @param OutputInterface $output |
||
71 | */ |
||
72 | View Code Duplication | private function setInputAndOutput(InputInterface $input, OutputInterface $output) |
|
73 | { |
||
74 | if (is_null($this->assistant)) { |
||
75 | $this->assistant = new CommandAssistant(); |
||
76 | $this->assistant->setQuestionHelper($this->getQuestionHelper()); |
||
77 | $this->assistant->setKernel($this->getApplication()->getKernel()); |
||
78 | } |
||
79 | $this->assistant->setOutput($output); |
||
80 | $this->assistant->setInput($input); |
||
81 | } |
||
82 | |||
83 | /** |
||
84 | * Do the interaction with the end user. |
||
85 | */ |
||
86 | abstract protected function doInteract(); |
||
87 | |||
88 | /** |
||
89 | * This function implements the final execution of the Generator. |
||
90 | * It calls the execute function with the correct parameters. |
||
91 | */ |
||
92 | abstract protected function doExecute(); |
||
93 | |||
94 | /** |
||
95 | * The text to be displayed on top of the generator. |
||
96 | * |
||
97 | * @return string|array |
||
98 | */ |
||
99 | abstract protected function getWelcomeText(); |
||
100 | |||
101 | /** |
||
102 | * Get an array with all the bundles the user has created. |
||
103 | * |
||
104 | * @return array |
||
105 | */ |
||
106 | protected function getOwnBundles() |
||
107 | { |
||
108 | $bundles = []; |
||
109 | $counter = 1; |
||
110 | $dir = dirname($this->getContainer()->getParameter('kernel.root_dir').'/').'/src/'; |
||
111 | $finder = new Finder(); |
||
112 | $finder->in($dir)->name('*Bundle.php'); |
||
113 | |||
114 | foreach ($finder as $file) { |
||
115 | $bundles[$counter++] = [ |
||
116 | 'name' => basename($file->getFilename(), '.php'), |
||
117 | 'namespace' => $file->getRelativePath(), |
||
118 | 'dir' => $file->getPath(), |
||
119 | ]; |
||
120 | } |
||
121 | |||
122 | return $bundles; |
||
123 | } |
||
124 | |||
125 | /** |
||
126 | * Check that a bundle is available (loaded in AppKernel) |
||
127 | * |
||
128 | * @param string $bundleName |
||
129 | * |
||
130 | * @return bool |
||
131 | */ |
||
132 | protected function isBundleAvailable($bundleName) |
||
133 | { |
||
134 | $allBundles = array_keys($this->assistant->getKernel()->getBundles()); |
||
135 | |||
136 | return in_array($bundleName, $allBundles); |
||
137 | } |
||
138 | |||
139 | /** |
||
140 | * Asks for the prefix and sets it on the InputInterface as the 'prefix' option, if this option is not set yet. |
||
141 | * Will set the default to a snake_cased namespace when the namespace has been set on the InputInterface. |
||
142 | * |
||
143 | * @param array $text What you want printed before the prefix is asked. If null is provided it'll write a default text. |
||
144 | * @param string $namespace An optional namespace. If this is set it'll create the default based on this prefix. |
||
145 | * If it's not provided it'll check if the InputInterface already has the namespace option. |
||
146 | * |
||
147 | * @return string The prefix. But it's also been set on the InputInterface. |
||
148 | */ |
||
149 | protected function askForPrefix(array $text = null, $namespace = null) |
||
150 | { |
||
151 | $prefix = $this->assistant->getOptionOrDefault('prefix', null); |
||
152 | |||
153 | if (is_null($text)) { |
||
154 | $text = [ |
||
155 | 'You can add a prefix to the table names of the generated entities for example: '. |
||
156 | '<comment>projectname_bundlename_</comment>', |
||
157 | 'Enter an underscore \'_\' if you don\'t want a prefix.', |
||
158 | '', |
||
159 | ]; |
||
160 | } |
||
161 | |||
162 | while (is_null($prefix)) { |
||
163 | if (count($text) > 0) { |
||
164 | $this->assistant->writeLine($text); |
||
165 | } |
||
166 | |||
167 | if (is_null($namespace) || empty($namespace)) { |
||
168 | $namespace = $this->assistant->getOption('namespace'); |
||
169 | } else { |
||
170 | $namespace = $this->fixNamespace($namespace); |
||
171 | } |
||
172 | $defaultPrefix = GeneratorUtils::cleanPrefix($this->convertNamespaceToSnakeCase($namespace)); |
||
173 | $prefix = GeneratorUtils::cleanPrefix($this->assistant->ask('Tablename prefix', $defaultPrefix)); |
||
174 | |||
175 | if ($prefix == '') { |
||
176 | break; |
||
177 | } |
||
178 | |||
179 | $output = $this->assistant->getOutput(); |
||
180 | View Code Duplication | if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $prefix)) { |
|
181 | $output->writeln(sprintf('<bg=red> "%s" contains invalid characters</>', $prefix)); |
||
182 | $prefix = $text = null; |
||
183 | |||
184 | continue; |
||
185 | } |
||
186 | |||
187 | $this->assistant->setOption('prefix', $prefix); |
||
188 | } |
||
189 | |||
190 | return $prefix; |
||
191 | } |
||
192 | |||
193 | /** |
||
194 | * Converts something like Namespace\BundleNameBundle to namespace_bundlenamebundle. |
||
195 | * |
||
196 | * @param string $namespace |
||
197 | * |
||
198 | * @return string |
||
199 | */ |
||
200 | View Code Duplication | private function convertNamespaceToSnakeCase($namespace) |
|
201 | { |
||
202 | if (is_null($namespace)) { |
||
203 | return null; |
||
204 | } |
||
205 | |||
206 | return str_replace('/', '_', strtolower($this->fixNamespace($namespace))); |
||
207 | } |
||
208 | |||
209 | /** |
||
210 | * Replaces '\' with '/'. |
||
211 | * |
||
212 | * @param $namespace |
||
213 | * |
||
214 | * @return mixed |
||
215 | */ |
||
216 | private function fixNamespace($namespace) |
||
217 | { |
||
218 | return str_replace('\\', '/', $namespace); |
||
219 | } |
||
220 | |||
221 | /** |
||
222 | * Ask for which bundle we need to generate something. It there is only one custom bundle |
||
223 | * created by the user, we don't ask anything and just use that bundle. If the user provided |
||
224 | * a namespace as input option, we try to get that bundle first. |
||
225 | * |
||
226 | * @param string $objectName The thing we are going to create (pagepart, bundle, layout, ...) |
||
227 | * @param string|null $namespace The namespace provided as input option |
||
228 | * @param string $questionMoreBundles |
||
229 | * @param string $questionOneBundle |
||
230 | * |
||
231 | * @return BundleInterface |
||
232 | */ |
||
233 | protected function askForBundleName( |
||
234 | $objectName, |
||
235 | $namespace = null, |
||
236 | $questionMoreBundles = "\nIn which bundle do you want to create the %s", |
||
237 | $questionOneBundle = "The %s will be created for the <comment>%s</comment> bundle.\n" |
||
238 | ) { |
||
239 | if (Kernel::VERSION_ID >= 40000) { |
||
240 | return new Sf4AppBundle($this->getContainer()->getParameter('kernel.project_dir')); |
||
241 | } |
||
242 | |||
243 | $ownBundles = $this->getOwnBundles(); |
||
244 | if (count($ownBundles) <= 0) { |
||
245 | $this->assistant->writeError("Looks like you don't have created any bundles for your project...", true); |
||
246 | } |
||
247 | |||
248 | // If the user provided the namespace as input option |
||
249 | if (!is_null($namespace)) { |
||
250 | foreach ($ownBundles as $key => $bundleInfo) { |
||
251 | if (GeneratorUtils::fixNamespace($namespace) == GeneratorUtils::fixNamespace( |
||
252 | $bundleInfo['namespace'] |
||
253 | ) |
||
254 | ) { |
||
255 | $bundleName = $bundleInfo['name']; |
||
256 | |||
257 | break; |
||
258 | } |
||
259 | } |
||
260 | |||
261 | // When the provided namespace was not found, we show an error on the screen and ask the bundle again |
||
262 | if (empty($bundleName)) { |
||
263 | $this->assistant->writeError("The provided bundle namespace '$namespace' was not found..."); |
||
264 | } |
||
265 | } |
||
266 | |||
267 | if (empty($bundleName)) { |
||
268 | // If we only have 1 bundle, we don't need to ask |
||
269 | if (count($ownBundles) > 1) { |
||
270 | $bundleSelect = []; |
||
271 | foreach ($ownBundles as $key => $bundleInfo) { |
||
272 | $bundleSelect[$key] = $bundleInfo['name']; |
||
273 | } |
||
274 | $bundleId = $this->assistant->askSelect( |
||
275 | sprintf($questionMoreBundles, $objectName), |
||
276 | $bundleSelect |
||
277 | ); |
||
278 | $bundleName = $ownBundles[$bundleId]['name']; |
||
279 | |||
280 | $this->assistant->writeLine(''); |
||
281 | } else { |
||
282 | $bundleName = $ownBundles[1]['name']; |
||
283 | $this->assistant->writeLine( |
||
284 | [sprintf($questionOneBundle, $objectName, $bundleName)] |
||
285 | ); |
||
286 | } |
||
287 | } |
||
288 | |||
289 | $bundle = $this->assistant->getKernel()->getBundle($bundleName); |
||
290 | |||
291 | return $bundle; |
||
292 | } |
||
293 | |||
294 | /** |
||
295 | * Ask the end user to select one (or more) section configuration(s). |
||
296 | * |
||
297 | * @param string $question |
||
298 | * @param BundleInterface $bundle |
||
299 | * @param bool $multiple |
||
300 | * @param string|null $context |
||
301 | * @param array $defaultSections |
||
302 | * |
||
303 | * @return array|null |
||
304 | */ |
||
305 | protected function askForSections( |
||
306 | $question, |
||
307 | BundleInterface $bundle, |
||
308 | $multiple = false, |
||
309 | $context = null, |
||
310 | $defaultSections = [] |
||
311 | ) { |
||
312 | $allSections = $this->getAvailableSections($bundle, $context, $defaultSections); |
||
313 | $sections = []; |
||
314 | |||
315 | // If there are more options to choose from, we ask the end user |
||
316 | if (count($allSections) > 0) { |
||
317 | $sectionSelect = []; |
||
318 | foreach ($allSections as $key => $sectionInfo) { |
||
319 | $sectionSelect[$key] = $sectionInfo['name'].' ('.$sectionInfo['file'].')'; |
||
320 | } |
||
321 | $this->assistant->writeLine(''); |
||
322 | $sectionIds = $this->assistant->askSelect($question, $sectionSelect, null, $multiple); |
||
323 | if (is_array($sectionIds)) { |
||
324 | foreach ($sectionIds as $id) { |
||
325 | $sections[] = $allSections[$id]['file']; |
||
326 | } |
||
327 | } else { |
||
328 | $sections[] = $allSections[$sectionIds]['file']; |
||
329 | } |
||
330 | } |
||
331 | |||
332 | if ($multiple) { |
||
333 | return $sections; |
||
334 | } else { |
||
335 | return count($sections) > 0 ? $sections[0] : null; |
||
336 | } |
||
337 | } |
||
338 | |||
339 | /** |
||
340 | * Get an array with the available page sections. We also parse the yaml files to get more information about |
||
341 | * the sections. |
||
342 | * |
||
343 | * @param BundleInterface $bundle The bundle for which we want to get the section configuration |
||
344 | * @param string|null $context If provided, only return configurations with this context |
||
345 | * @param array $defaultSections The default section configurations that are always available |
||
346 | * |
||
347 | * @return array |
||
348 | */ |
||
349 | protected function getAvailableSections(BundleInterface $bundle, $context = null, $defaultSections = []) |
||
350 | { |
||
351 | $configs = []; |
||
352 | $counter = 1; |
||
353 | |||
354 | // Get the available sections from disc |
||
355 | $dir = Kernel::VERSION_ID >= 40000 ? |
||
356 | $this->getContainer()->getParameter('kernel.project_dir').'/config/kunstmaancms/pageparts/' : |
||
357 | $bundle->getPath().'/Resources/config/pageparts/' |
||
358 | ; |
||
359 | if (file_exists($dir) && is_dir($dir)) { |
||
360 | $finder = new Finder(); |
||
361 | $finder->files()->in($dir)->depth('== 0'); |
||
362 | foreach ($finder as $file) { |
||
363 | $info = $this->getSectionInfo($dir, $file->getFileName()); |
||
364 | |||
365 | if (is_array($info) && (is_null($context) || $info['context'] == $context)) { |
||
366 | $configs[$counter++] = $info; |
||
367 | if (array_key_exists($info['file'], $defaultSections)) { |
||
368 | unset($defaultSections[$info['file']]); |
||
369 | } |
||
370 | } |
||
371 | } |
||
372 | } |
||
373 | |||
374 | // Add the default sections |
||
375 | foreach ($defaultSections as $file => $info) { |
||
376 | if (is_null($context) || $info['context'] == $context) { |
||
377 | $configs[$counter++] = $info; |
||
378 | } |
||
379 | } |
||
380 | |||
381 | return $configs; |
||
382 | } |
||
383 | |||
384 | /** |
||
385 | * Get the information about a pagepart section configuration file. |
||
386 | * |
||
387 | * @param string $dir |
||
388 | * @param string $file |
||
389 | * |
||
390 | * @return array|null |
||
391 | */ |
||
392 | private function getSectionInfo($dir, $file) |
||
393 | { |
||
394 | $info = null; |
||
395 | |||
396 | try { |
||
397 | $data = Yaml::parse(file_get_contents($dir.$file)); |
||
398 | |||
399 | View Code Duplication | if (array_key_exists('kunstmaan_page_part', $data)) { |
|
400 | //Get rid of the bundle config lines |
||
401 | $data = array_values(array_values(array_values($data)[0])[0])[0]; |
||
402 | } |
||
403 | |||
404 | $info = [ |
||
405 | 'name' => $data['name'], |
||
406 | 'context' => $data['context'], |
||
407 | 'file' => $file, |
||
408 | //'file_clean' => substr($file, 0, strlen($file)-4) |
||
409 | ]; |
||
410 | } catch (ParseException $e) { |
||
411 | } |
||
412 | |||
413 | return $info; |
||
414 | } |
||
415 | |||
416 | /** |
||
417 | * Get an array of fields that need to be added to the entity. |
||
418 | * |
||
419 | * @param BundleInterface $bundle |
||
420 | * @param array $reservedFields |
||
421 | * |
||
422 | * @return array |
||
423 | */ |
||
424 | protected function askEntityFields(BundleInterface $bundle, array $reservedFields = ['id']) |
||
425 | { |
||
426 | $this->assistant->writeLine('<info>Available field types:</info> '); |
||
427 | $typeSelect = $this->getTypes(true); |
||
428 | foreach ($typeSelect as $type) { |
||
429 | $this->assistant->writeLine(sprintf('<comment>- %s</comment>', $type)); |
||
430 | } |
||
431 | |||
432 | $fields = []; |
||
433 | $typeStrings = $this->getTypes(); |
||
434 | $mediaTypeSelect = $this->getMediaTypes(); |
||
435 | $generator = $this->getGenerator(); |
||
436 | $container = $this->getContainer(); |
||
437 | |||
438 | while (true) { |
||
439 | $this->assistant->writeLine(''); |
||
440 | |||
441 | $fieldName = $this->assistant->askAndValidate( |
||
442 | 'New field name (press <return> to stop adding fields)', |
||
443 | function ($name) use ($fields, $reservedFields, $generator) { |
||
444 | // The fields cannot exist in the reserved field list |
||
445 | if (in_array($name, $reservedFields)) { |
||
446 | throw new \InvalidArgumentException(sprintf('Field "%s" is already defined in the parent class', $name)); |
||
447 | } |
||
448 | |||
449 | // The fields cannot exist already |
||
450 | if (isset($fields[$name])) { |
||
451 | throw new \InvalidArgumentException(sprintf('Field "%s" is already defined', $name)); |
||
452 | } |
||
453 | |||
454 | // Check reserved words |
||
455 | if ($generator->isReservedKeyword($name)) { |
||
456 | throw new \InvalidArgumentException(sprintf('Name "%s" is a reserved word', $name)); |
||
457 | } |
||
458 | |||
459 | // Only accept a-z |
||
460 | if (!preg_match('/^[a-zA-Z][a-zA-Z_0-9]+$/', $name) && $name != '') { |
||
461 | throw new \InvalidArgumentException(sprintf('Name "%s" is invalid', $name)); |
||
462 | } |
||
463 | |||
464 | return $name; |
||
465 | } |
||
466 | ); |
||
467 | |||
468 | // When <return> is entered |
||
469 | if (!$fieldName) { |
||
470 | break; |
||
471 | } |
||
472 | |||
473 | $typeId = $this->assistant->askSelect('Field type', $typeSelect); |
||
474 | |||
475 | // If single -or multipe entity reference in chosen, we need to ask for the entity name |
||
476 | if (in_array($typeStrings[$typeId], ['single_ref', 'multi_ref'])) { |
||
477 | $bundleName = $bundle->getName(); |
||
478 | $egName = $this->isSymfony4() ? 'App\Entity\FaqItem' : "$bundleName:FaqItem, $bundleName:Blog/Comment"; |
||
479 | $question = sprintf('Reference entity name (eg. %s)', $egName); |
||
480 | $name = $this->assistant->askAndValidate( |
||
481 | $question, |
||
482 | function ($name) use ($generator, $container) { |
||
483 | /* |
||
484 | * Replace slash to backslash. Eg: CmsBundle:Blog/Comment --> CmsBundle:Blog\Comment |
||
485 | * |
||
486 | * @see \Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory::getMetadataFor() |
||
487 | * @see \Doctrine\ORM\Mapping\ClassMetadataFactory::getFqcnFromAlias() |
||
488 | */ |
||
489 | if (!$this->isSymfony4()) { |
||
490 | $name = strtr($name, '/', '\\'); |
||
491 | |||
492 | $parts = explode(':', $name); |
||
493 | |||
494 | // Should contain colon |
||
495 | if (count($parts) != 2) { |
||
496 | throw new \InvalidArgumentException(sprintf('"%s" is an invalid entity name', $name)); |
||
497 | } |
||
498 | } else { |
||
499 | $parts = explode('\\', $name); |
||
500 | } |
||
501 | |||
502 | // Check reserved words |
||
503 | if ($generator->isReservedKeyword(end($parts))) { |
||
504 | throw new \InvalidArgumentException(sprintf('"%s" contains a reserved word', $name)); |
||
505 | } |
||
506 | |||
507 | $em = $container->get('doctrine')->getManager(); |
||
508 | |||
509 | try { |
||
510 | $em->getClassMetadata($name); |
||
511 | } catch (\Exception $e) { |
||
512 | throw new \InvalidArgumentException(sprintf('Entity "%s" not found', $name)); |
||
513 | } |
||
514 | |||
515 | return $name; |
||
516 | }, |
||
517 | null, |
||
518 | [$bundleName] |
||
519 | ); |
||
520 | |||
521 | $extra = $name; |
||
522 | } else { |
||
523 | $extra = null; |
||
524 | } |
||
525 | |||
526 | // If image type, force image media filter |
||
527 | if ($typeStrings[$typeId] == 'image') { |
||
528 | $extra = 'image'; |
||
529 | } |
||
530 | |||
531 | // If media type, ask for media filter |
||
532 | if ($typeStrings[$typeId] == 'media') { |
||
533 | $mediaTypeId = $this->assistant->askSelect('Media filter', $mediaTypeSelect); |
||
534 | $extra = strtolower($mediaTypeSelect[$mediaTypeId]); |
||
535 | } |
||
536 | |||
537 | if ($typeStrings[$typeId] == 'image' || $typeStrings[$typeId] == 'media') { |
||
538 | // Ask the allowed mimetypes for the media ojbect |
||
539 | $mimeTypes = $this->assistant->ask('Do you want to limit the possible file types? Then specify a comma-seperated list of types (example: image/png,image/svg+xml), otherwise press ENTER', |
||
540 | null |
||
541 | ); |
||
542 | if (isset($mimeTypes)) { |
||
543 | $mimeTypes = explode(',', $mimeTypes); |
||
544 | } |
||
545 | $data = [ |
||
546 | 'name' => $fieldName, |
||
547 | 'type' => $typeStrings[$typeId], |
||
548 | 'extra' => $extra, |
||
549 | 'mimeTypes' => $mimeTypes, |
||
550 | 'minHeight' => null, |
||
551 | 'maxHeight' => null, |
||
552 | 'minWidth' => null, |
||
553 | 'maxWidth' => null, |
||
554 | ]; |
||
555 | |||
556 | if ($extra == 'image') { |
||
557 | $minHeight = $maxHeight = $minWidth = $maxWidth = null; |
||
558 | if ($this->assistant->askConfirmation('Do you want to add validation of the dimensions of the media object? (y/n)', |
||
559 | 'n', |
||
560 | '?', |
||
561 | false |
||
562 | )) { |
||
563 | // Ask the minimum height allowed for the image |
||
564 | $lengthValidation = function ($length) { |
||
565 | if ((is_numeric($length) && $length < 0) || (!is_numeric($length) && !empty($length))) { |
||
566 | throw new \InvalidArgumentException(sprintf('"%s" is not a valid length', $length)); |
||
567 | } else { |
||
568 | return $length; |
||
569 | } |
||
570 | }; |
||
571 | |||
572 | $minHeight = $this->assistant->askAndValidate('What is the minimum height for the media object? (in pixels)', |
||
573 | $lengthValidation |
||
574 | ); |
||
575 | |||
576 | // Ask the maximum height allowed for the image |
||
577 | $maxHeight = $this->assistant->askAndValidate('What is the maximum height for the media object? (in pixels)', |
||
578 | $lengthValidation |
||
579 | ); |
||
580 | |||
581 | // Ask the minimum width allowed for the image |
||
582 | $minWidth = $this->assistant->askAndValidate('What is the minimum width for the media object? (in pixels)', |
||
583 | $lengthValidation |
||
584 | ); |
||
585 | |||
586 | //Ask the maximum width allowed for the image |
||
587 | $maxWidth = $this->assistant->askAndValidate('What is the maximum width for the media object? (in pixels)', |
||
588 | $lengthValidation |
||
589 | ); |
||
590 | } |
||
591 | $data = [ |
||
592 | 'name' => $fieldName, |
||
593 | 'type' => 'image', |
||
594 | 'extra' => $extra, |
||
595 | 'minHeight' => $minHeight, |
||
596 | 'maxHeight' => $maxHeight, |
||
597 | 'minWidth' => $minWidth, |
||
598 | 'maxWidth' => $maxWidth, |
||
599 | 'mimeTypes' => $mimeTypes, |
||
600 | ]; |
||
601 | } |
||
602 | } else { |
||
603 | $data = [ |
||
604 | 'name' => $fieldName, |
||
605 | 'type' => $typeStrings[$typeId], |
||
606 | 'extra' => $extra, |
||
607 | 'minHeight' => null, |
||
608 | 'maxHeight' => null, |
||
609 | 'minWidth' => null, |
||
610 | 'maxWidth' => null, |
||
611 | 'mimeTypes' => null, |
||
612 | ]; |
||
613 | } |
||
614 | |||
615 | $fields[$fieldName] = $data; |
||
616 | } |
||
617 | |||
618 | return $fields; |
||
619 | } |
||
620 | |||
621 | /** |
||
622 | * Get all the available types. |
||
623 | * |
||
624 | * @param bool $niceNames |
||
625 | * |
||
626 | * @return array |
||
627 | */ |
||
628 | private function getTypes($niceNames = false) |
||
629 | { |
||
630 | $counter = 1; |
||
631 | |||
632 | $types = []; |
||
633 | $types[$counter++] = $niceNames ? 'Single line text' : 'single_line'; |
||
634 | $types[$counter++] = $niceNames ? 'Multi line text' : 'multi_line'; |
||
635 | $types[$counter++] = $niceNames ? 'Wysiwyg' : 'wysiwyg'; |
||
636 | $types[$counter++] = $niceNames ? 'Link (url, text, new window)' : 'link'; |
||
637 | if ($this->isBundleAvailable('KunstmaanMediaPagePartBundle')) { |
||
638 | $types[$counter++] = $niceNames ? 'Image (media, alt text)' : 'image'; |
||
639 | $types[$counter++] = $niceNames ? 'Media (File or Video or Slideshow)' : 'media'; |
||
640 | } |
||
641 | $types[$counter++] = $niceNames ? 'Single entity reference' : 'single_ref'; |
||
642 | $types[$counter++] = $niceNames ? 'Multi entity reference' : 'multi_ref'; |
||
643 | $types[$counter++] = $niceNames ? 'Boolean' : 'boolean'; |
||
644 | $types[$counter++] = $niceNames ? 'Integer' : 'integer'; |
||
645 | $types[$counter++] = $niceNames ? 'Decimal number' : 'decimal'; |
||
646 | $types[$counter++] = $niceNames ? 'DateTime' : 'datetime'; |
||
647 | |||
648 | return $types; |
||
649 | } |
||
650 | |||
651 | /** |
||
652 | * Get all available media types. |
||
653 | * |
||
654 | * @return array |
||
655 | */ |
||
656 | private function getMediaTypes() |
||
657 | { |
||
658 | $counter = 1; |
||
659 | |||
660 | $types = []; |
||
661 | $types[$counter++] = 'None'; |
||
662 | $types[$counter++] = 'File'; |
||
663 | $types[$counter++] = 'Image'; |
||
664 | $types[$counter++] = 'Video'; |
||
665 | |||
666 | return $types; |
||
667 | } |
||
668 | |||
669 | /** |
||
670 | * Get all the entity fields for a specific type. |
||
671 | * |
||
672 | * @param BundleInterface $bundle |
||
673 | * @param $objectName |
||
674 | * @param $prefix |
||
675 | * @param $name |
||
676 | * @param $type |
||
677 | * @param null $extra |
||
678 | * @param bool $allNullable |
||
679 | * @param null $minHeight |
||
680 | * @param null $maxHeight |
||
681 | * @param null $minWidth |
||
682 | * @param null $maxWidth |
||
683 | * @param null $mimeTypes |
||
684 | * |
||
685 | * @return array |
||
686 | */ |
||
687 | protected function getEntityFields( |
||
688 | BundleInterface $bundle, |
||
689 | $objectName, |
||
690 | $prefix, |
||
691 | $name, |
||
692 | $type, |
||
693 | $extra = null, |
||
694 | $allNullable = false, |
||
695 | $minHeight = null, |
||
696 | $maxHeight = null, |
||
697 | $minWidth = null, |
||
698 | $maxWidth = null, |
||
699 | $mimeTypes = null |
||
700 | ) { |
||
701 | $fields = []; |
||
702 | switch ($type) { |
||
703 | View Code Duplication | case 'single_line': |
|
704 | $fields[$type][] = [ |
||
705 | 'fieldName' => lcfirst(Container::camelize($name)), |
||
706 | 'type' => 'string', |
||
707 | 'length' => '255', |
||
708 | 'formType' => TextType::class, |
||
709 | 'nullable' => $allNullable, |
||
710 | ]; |
||
711 | |||
712 | break; |
||
713 | View Code Duplication | case 'multi_line': |
|
714 | $fields[$type][] = [ |
||
715 | 'fieldName' => lcfirst(Container::camelize($name)), |
||
716 | 'type' => 'text', |
||
717 | 'formType' => TextareaType::class, |
||
718 | 'nullable' => $allNullable, |
||
719 | ]; |
||
720 | |||
721 | break; |
||
722 | View Code Duplication | case 'wysiwyg': |
|
0 ignored issues
–
show
|
|||
723 | $fields[$type][] = [ |
||
724 | 'fieldName' => lcfirst(Container::camelize($name)), |
||
725 | 'type' => 'text', |
||
726 | 'formType' => WysiwygType::class, |
||
727 | 'nullable' => $allNullable, |
||
728 | ]; |
||
729 | |||
730 | break; |
||
731 | case 'link': |
||
732 | foreach (['url', 'text'] as $subField) { |
||
733 | $fields[$type][$subField] = [ |
||
734 | 'fieldName' => lcfirst(Container::camelize($name.'_'.$subField)), |
||
735 | 'type' => 'string', |
||
736 | 'formType' => $subField == 'url' ? URLChooserType::class : TextType::class, |
||
737 | 'nullable' => $allNullable, |
||
738 | ]; |
||
739 | } |
||
740 | $fields[$type]['new_window'] = [ |
||
741 | 'fieldName' => lcfirst(Container::camelize($name.'_new_window')), |
||
742 | 'type' => 'boolean', |
||
743 | 'nullable' => true, |
||
744 | 'formType' => CheckboxType::class, |
||
745 | ]; |
||
746 | |||
747 | break; |
||
748 | case 'image': |
||
749 | $fields[$type]['image'] = [ |
||
750 | 'fieldName' => lcfirst(Container::camelize($name)), |
||
751 | 'type' => 'image', |
||
752 | 'formType' => MediaType::class, |
||
753 | 'mediaType' => $extra, |
||
754 | 'minHeight' => $minHeight, |
||
755 | 'maxHeight' => $maxHeight, |
||
756 | 'minWidth' => $minWidth, |
||
757 | 'maxWidth' => $maxWidth, |
||
758 | 'mimeTypes' => $mimeTypes, |
||
759 | 'targetEntity' => 'Kunstmaan\MediaBundle\Entity\Media', |
||
760 | 'joinColumn' => [ |
||
761 | 'name' => str_replace('.', '_', Container::underscore($name.'_id')), |
||
762 | 'referencedColumnName' => 'id', |
||
763 | ], |
||
764 | 'nullable' => $allNullable, |
||
765 | ]; |
||
766 | $fields[$type]['alt_text'] = [ |
||
767 | 'fieldName' => lcfirst(Container::camelize($name.'_alt_text')), |
||
768 | 'type' => 'text', |
||
769 | 'nullable' => true, |
||
770 | 'formType' => TextType::class, |
||
771 | ]; |
||
772 | |||
773 | break; |
||
774 | case 'media': |
||
775 | $fields[$type][] = [ |
||
776 | 'fieldName' => lcfirst(Container::camelize($name)), |
||
777 | 'type' => 'media', |
||
778 | 'formType' => MediaType::class, |
||
779 | 'mediaType' => $extra, |
||
780 | 'mimeTypes' => $mimeTypes, |
||
781 | 'targetEntity' => 'Kunstmaan\MediaBundle\Entity\Media', |
||
782 | 'joinColumn' => [ |
||
783 | 'name' => str_replace('.', '_', Container::underscore($name.'_id')), |
||
784 | 'referencedColumnName' => 'id', |
||
785 | ], |
||
786 | 'nullable' => $allNullable, |
||
787 | ]; |
||
788 | |||
789 | break; |
||
790 | case 'single_ref': |
||
791 | $em = $this->getContainer()->get('doctrine')->getManager(); |
||
792 | $entityName = $em->getClassMetadata($extra)->getName(); |
||
793 | $fields[$type][] = [ |
||
794 | 'fieldName' => lcfirst(Container::camelize($name)), |
||
795 | 'type' => 'entity', |
||
796 | 'formType' => EntityType::class, |
||
797 | 'targetEntity' => $entityName, |
||
798 | 'joinColumn' => [ |
||
799 | 'name' => str_replace('.', '_', Container::underscore($name.'_id')), |
||
800 | 'referencedColumnName' => 'id', |
||
801 | ], |
||
802 | 'nullable' => $allNullable, |
||
803 | ]; |
||
804 | |||
805 | break; |
||
806 | case 'multi_ref': |
||
807 | $em = $this->getContainer()->get('doctrine')->getManager(); |
||
808 | $entityName = $em->getClassMetadata($extra)->getName(); |
||
809 | $parts = explode('\\', $entityName); |
||
810 | $joinTableName = strtolower( |
||
811 | $prefix.Container::underscore($objectName).'_'.Container::underscore( |
||
812 | $parts[count($parts) - 1] |
||
813 | ) |
||
814 | ); |
||
815 | $fields[$type][] = [ |
||
816 | 'fieldName' => lcfirst(Container::camelize($name)), |
||
817 | 'type' => 'entity', |
||
818 | 'formType' => EntityType::class, |
||
819 | 'targetEntity' => $entityName, |
||
820 | 'joinTable' => [ |
||
821 | 'name' => $joinTableName, |
||
822 | 'joinColumns' => [ |
||
823 | [ |
||
824 | 'name' => strtolower(Container::underscore($objectName)).'_id', |
||
825 | 'referencedColumnName' => 'id', |
||
826 | ], |
||
827 | ], |
||
828 | 'inverseJoinColumns' => [ |
||
829 | [ |
||
830 | 'name' => strtolower( |
||
831 | Container::underscore($parts[count($parts) - 1]) |
||
832 | ).'_id', |
||
833 | 'referencedColumnName' => 'id', |
||
834 | 'unique' => true, |
||
835 | ], |
||
836 | ], |
||
837 | ], |
||
838 | 'nullable' => $allNullable, |
||
839 | ]; |
||
840 | |||
841 | break; |
||
842 | View Code Duplication | case 'boolean': |
|
843 | $fields[$type][] = [ |
||
844 | 'fieldName' => lcfirst(Container::camelize($name)), |
||
845 | 'type' => 'boolean', |
||
846 | 'formType' => CheckboxType::class, |
||
847 | 'nullable' => $allNullable, |
||
848 | ]; |
||
849 | |||
850 | break; |
||
851 | View Code Duplication | case 'integer': |
|
852 | $fields[$type][] = [ |
||
853 | 'fieldName' => lcfirst(Container::camelize($name)), |
||
854 | 'type' => 'integer', |
||
855 | 'formType' => IntegerType::class, |
||
856 | 'nullable' => $allNullable, |
||
857 | ]; |
||
858 | |||
859 | break; |
||
860 | View Code Duplication | case 'decimal': |
|
861 | $fields[$type][] = [ |
||
862 | 'fieldName' => lcfirst(Container::camelize($name)), |
||
863 | 'type' => 'decimal', |
||
864 | 'precision' => 10, |
||
865 | 'scale' => 2, |
||
866 | 'formType' => NumberType::class, |
||
867 | 'nullable' => $allNullable, |
||
868 | ]; |
||
869 | |||
870 | break; |
||
871 | View Code Duplication | case 'datetime': |
|
872 | $fields[$type][] = [ |
||
873 | 'fieldName' => lcfirst(Container::camelize($name)), |
||
874 | 'type' => 'datetime', |
||
875 | 'formType' => DateTimeType::class, |
||
876 | 'nullable' => $allNullable, |
||
877 | ]; |
||
878 | |||
879 | break; |
||
880 | } |
||
881 | |||
882 | return $fields; |
||
883 | } |
||
884 | |||
885 | /** |
||
886 | * Get an array with the available page templates. |
||
887 | * |
||
888 | * @param BundleInterface $bundle The bundle for which we want to get the template configurations |
||
889 | * |
||
890 | * @return array |
||
891 | */ |
||
892 | protected function getAvailableTemplates(BundleInterface $bundle) |
||
893 | { |
||
894 | $configs = []; |
||
895 | $counter = 1; |
||
896 | |||
897 | // Get the available sections from disc |
||
898 | if (Kernel::VERSION_ID >= 40000) { |
||
899 | $dir = $this->getContainer()->getParameter('kernel.project_dir').'/config/kunstmaancms/pagetemplates/'; |
||
900 | } else { |
||
901 | $dir = $bundle->getPath().'/Resources/config/pagetemplates/'; |
||
902 | } |
||
903 | |||
904 | if (file_exists($dir) && is_dir($dir)) { |
||
905 | $finder = new Finder(); |
||
906 | $finder->files()->in($dir)->depth('== 0'); |
||
907 | foreach ($finder as $file) { |
||
908 | $info = $this->getTemplateInfo($dir, $file->getFileName()); |
||
909 | if (is_array($info)) { |
||
910 | $configs[$counter++] = $info; |
||
911 | } |
||
912 | } |
||
913 | } |
||
914 | |||
915 | return $configs; |
||
916 | } |
||
917 | |||
918 | /** |
||
919 | * Get the information about a pagepart section configuration file. |
||
920 | * |
||
921 | * @param string $dir |
||
922 | * @param string $file |
||
923 | * |
||
924 | * @return array|null |
||
925 | */ |
||
926 | protected function getTemplateInfo($dir, $file) |
||
927 | { |
||
928 | $info = null; |
||
929 | |||
930 | try { |
||
931 | $data = Yaml::parse(file_get_contents($dir.$file)); |
||
932 | |||
933 | View Code Duplication | if (array_key_exists('kunstmaan_page_part', $data)) { |
|
934 | //Get rid of the bundle config lines |
||
935 | $data = array_values(array_values(array_values($data)[0])[0])[0]; |
||
936 | } |
||
937 | |||
938 | // Parse contexts |
||
939 | $contexts = []; |
||
940 | foreach ($data['rows'] as $row) { |
||
941 | foreach ($row['regions'] as $region) { |
||
942 | $contexts[] = $region['name']; |
||
943 | } |
||
944 | } |
||
945 | $info = [ |
||
946 | 'name' => $data['name'], |
||
947 | 'contexts' => $contexts, |
||
948 | 'file' => $file, |
||
949 | ]; |
||
950 | } catch (ParseException $e) { |
||
951 | } |
||
952 | |||
953 | return $info; |
||
954 | } |
||
955 | |||
956 | /** |
||
957 | * Get an array with the available page templates. |
||
958 | * |
||
959 | * @param BundleInterface $bundle The bundle for which we want to get the template configurations |
||
960 | * |
||
961 | * @return array |
||
962 | */ |
||
963 | protected function getAvailablePages(BundleInterface $bundle) |
||
964 | { |
||
965 | $pages = []; |
||
966 | $counter = 1; |
||
967 | |||
968 | // Get the available pages from disc |
||
969 | $dir = $bundle->getPath().'/Entity/Pages/'; |
||
970 | if (file_exists($dir) && is_dir($dir)) { |
||
971 | $finder = new Finder(); |
||
972 | $finder->files()->in($dir)->depth('== 0'); |
||
973 | foreach ($finder as $file) { |
||
974 | $pages[$counter++] = [ |
||
975 | 'name' => substr($file->getFileName(), 0, strlen($file->getFileName()) - 4), |
||
976 | 'path' => $file->getPathName(), |
||
977 | ]; |
||
978 | } |
||
979 | } |
||
980 | |||
981 | return $pages; |
||
982 | } |
||
983 | |||
984 | /** |
||
985 | * Check that it is possible to generate the behat tests. |
||
986 | * |
||
987 | * @param BundleInterface $bundle |
||
988 | * |
||
989 | * @return bool |
||
990 | */ |
||
991 | protected function canGenerateBehatTests(BundleInterface $bundle) |
||
992 | { |
||
993 | $behatFile = dirname($this->getContainer()->getParameter('kernel.root_dir').'/').'/behat.yml'; |
||
994 | $pagePartContext = $bundle->getPath().'/Features/Context/PagePartContext.php'; |
||
995 | $behatTestPage = $bundle->getPath().'/Entity/Pages/BehatTestPage.php'; |
||
996 | |||
997 | // Make sure behat is configured and the PagePartContext and BehatTestPage exits |
||
998 | return file_exists($behatFile) && file_exists($pagePartContext) && file_exists($behatTestPage); |
||
999 | } |
||
1000 | |||
1001 | /** |
||
1002 | * @internal |
||
1003 | */ |
||
1004 | protected function isSymfony4() |
||
1005 | { |
||
1006 | return Kernel::VERSION_ID >= 40000; |
||
1007 | } |
||
1008 | } |
||
1009 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.