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