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\Generator; |
||
4 | |||
5 | use Doctrine\Common\Inflector\Inflector; |
||
6 | use Doctrine\ORM\Mapping\ClassMetadataInfo; |
||
7 | use Doctrine\ORM\Mapping\UnderscoreNamingStrategy; |
||
8 | use Doctrine\ORM\Tools\EntityGenerator; |
||
9 | use Doctrine\ORM\Tools\EntityRepositoryGenerator; |
||
10 | use Kunstmaan\GeneratorBundle\Helper\CommandAssistant; |
||
11 | use Kunstmaan\GeneratorBundle\Helper\GeneratorUtils; |
||
12 | use Sensio\Bundle\GeneratorBundle\Generator\Generator; |
||
13 | use Symfony\Bridge\Doctrine\RegistryInterface; |
||
14 | use Symfony\Component\DependencyInjection\ContainerInterface; |
||
15 | use Symfony\Component\Filesystem\Filesystem; |
||
16 | use Symfony\Component\Finder\Finder; |
||
17 | use Symfony\Component\HttpKernel\Bundle\BundleInterface; |
||
18 | use Symfony\Component\HttpKernel\Kernel; |
||
19 | use Twig\Environment; |
||
20 | use Twig\Lexer; |
||
21 | use Twig\Loader\FilesystemLoader; |
||
22 | |||
23 | /** |
||
24 | * Class that contains all common generator logic. |
||
25 | */ |
||
26 | class KunstmaanGenerator extends Generator |
||
27 | { |
||
28 | /** |
||
29 | * @var Filesystem |
||
30 | */ |
||
31 | protected $filesystem; |
||
32 | |||
33 | /** |
||
34 | * @var RegistryInterface |
||
35 | */ |
||
36 | protected $registry; |
||
37 | |||
38 | /** |
||
39 | * @var string |
||
40 | */ |
||
41 | protected $skeletonDir; |
||
42 | |||
43 | /** |
||
44 | * @var CommandAssistant |
||
45 | */ |
||
46 | protected $assistant; |
||
47 | |||
48 | /** |
||
49 | * @var ContainerInterface |
||
50 | */ |
||
51 | protected $container; |
||
52 | |||
53 | /** |
||
54 | * @param Filesystem $filesystem The filesystem |
||
55 | * @param RegistryInterface $registry The registry |
||
56 | * @param string $skeletonDir The directory of the skeleton |
||
57 | * @param CommandAssistant $assistant The command assistant |
||
58 | * @param ContainerInterface $container The container |
||
59 | */ |
||
60 | 1 | public function __construct( |
|
61 | Filesystem $filesystem, |
||
62 | RegistryInterface $registry, |
||
63 | $skeletonDir, |
||
64 | CommandAssistant $assistant, |
||
65 | ContainerInterface $container = null |
||
66 | ) { |
||
67 | 1 | $this->filesystem = $filesystem; |
|
68 | 1 | $this->registry = $registry; |
|
69 | 1 | $this->skeletonDir = GeneratorUtils::getFullSkeletonPath($skeletonDir); |
|
70 | 1 | $this->assistant = $assistant; |
|
71 | 1 | $this->container = $container; |
|
72 | |||
73 | 1 | $this->setSkeletonDirs(array($this->skeletonDir, GeneratorUtils::getFullSkeletonPath('/common'))); |
|
74 | 1 | } |
|
75 | |||
76 | /** |
||
77 | * Check that the keyword is a reserved word for the database system. |
||
78 | * |
||
79 | * @param string $keyword |
||
80 | * |
||
81 | * @return bool |
||
82 | */ |
||
83 | public function isReservedKeyword($keyword) |
||
84 | { |
||
85 | return $this->registry->getConnection()->getDatabasePlatform()->getReservedKeywordsList()->isKeyword($keyword); |
||
86 | } |
||
87 | |||
88 | /** |
||
89 | * Generate the entity PHP code. |
||
90 | * |
||
91 | * @param BundleInterface $bundle |
||
92 | * @param string $name |
||
93 | * @param array $fields |
||
94 | * @param string $namePrefix |
||
95 | * @param string $dbPrefix |
||
96 | * @param string|null $extendClass |
||
97 | * @param bool $withRepository |
||
98 | * |
||
99 | * @return array |
||
100 | * |
||
101 | * @throws \RuntimeException |
||
102 | */ |
||
103 | protected function generateEntity( |
||
104 | BundleInterface $bundle, |
||
105 | $name, |
||
106 | $fields, |
||
107 | $namePrefix, |
||
108 | $dbPrefix, |
||
109 | $extendClass = null, |
||
110 | $withRepository = false |
||
111 | ) { |
||
112 | // configure the bundle (needed if the bundle does not contain any Entities yet) |
||
113 | $config = $this->registry->getManager(null)->getConfiguration(); |
||
0 ignored issues
–
show
|
|||
114 | $config->setEntityNamespaces( |
||
115 | array_merge( |
||
116 | array($bundle->getName() => $bundle->getNamespace() . '\\Entity' . ($namePrefix ? '\\' . $namePrefix : '')), |
||
117 | $config->getEntityNamespaces() |
||
118 | ) |
||
119 | ); |
||
120 | |||
121 | $entityClass = $this->registry->getAliasNamespace($bundle->getName()) . ($namePrefix ? '\\' . $namePrefix : '') . '\\' . $name; |
||
122 | $entityPath = $bundle->getPath() . '/Entity/' . ($namePrefix ? $namePrefix . '/' : '') . str_replace('\\', '/', $name) . '.php'; |
||
123 | if (file_exists($entityPath)) { |
||
124 | throw new \RuntimeException(sprintf('Entity "%s" already exists.', $entityClass)); |
||
125 | } |
||
126 | |||
127 | $class = new ClassMetadataInfo($entityClass, new UnderscoreNamingStrategy()); |
||
128 | if ($withRepository) { |
||
129 | if ($this->isSymfony4()) { |
||
130 | $repositoryClass = preg_replace('/\\\\Entity\\\\/', '\\Repository\\', $entityClass, 1) . 'Repository'; |
||
131 | $class->customRepositoryClassName = $repositoryClass; |
||
132 | $this->getSymfony4RepositoryGenerator()->writeEntityRepositoryClass($entityClass, $repositoryClass, $bundle->getPath()); |
||
133 | } else { |
||
134 | $entityClass = preg_replace('/\\\\Entity\\\\/', '\\Repository\\', $entityClass, 1); |
||
135 | $class->customRepositoryClassName = $entityClass.'Repository'; |
||
136 | $path = $bundle->getPath().str_repeat('/..', substr_count(get_class($bundle), '\\')); |
||
137 | $this->getRepositoryGenerator()->writeEntityRepositoryClass($class->customRepositoryClassName, $path); |
||
138 | } |
||
139 | } |
||
140 | |||
141 | foreach ($fields as $fieldSet) { |
||
142 | foreach ($fieldSet as $fieldArray) { |
||
143 | foreach ($fieldArray as $field) { |
||
144 | if (array_key_exists('joinColumn', $field)) { |
||
145 | $class->mapManyToOne($field); |
||
146 | } elseif (array_key_exists('joinTable', $field)) { |
||
147 | $class->mapManyToMany($field); |
||
148 | } else { |
||
149 | $class->mapField($field); |
||
150 | } |
||
151 | } |
||
152 | } |
||
153 | } |
||
154 | $class->setPrimaryTable( |
||
155 | array( |
||
156 | 'name' => strtolower($dbPrefix) . Inflector::tableize(Inflector::pluralize($name)), |
||
157 | ) |
||
158 | ); |
||
159 | $entityCode = $this->getEntityGenerator($extendClass)->generateEntityClass($class); |
||
160 | |||
161 | return array($entityCode, $entityPath); |
||
162 | } |
||
163 | |||
164 | /** |
||
165 | * Get a Doctrine EntityGenerator instance. |
||
166 | * |
||
167 | * @param string|null $classToExtend |
||
168 | * |
||
169 | * @return EntityGenerator |
||
170 | */ |
||
171 | protected function getEntityGenerator($classToExtend = null) |
||
172 | { |
||
173 | $entityGenerator = new EntityGenerator(); |
||
174 | if (!is_null($classToExtend)) { |
||
175 | $entityGenerator->setClassToExtend($classToExtend); |
||
176 | } |
||
177 | $entityGenerator->setGenerateAnnotations(true); |
||
178 | $entityGenerator->setGenerateStubMethods(true); |
||
179 | $entityGenerator->setRegenerateEntityIfExists(false); |
||
180 | $entityGenerator->setUpdateEntityIfExists(true); |
||
181 | $entityGenerator->setNumSpaces(4); |
||
182 | $entityGenerator->setAnnotationPrefix('ORM\\'); |
||
183 | |||
184 | return $entityGenerator; |
||
185 | } |
||
186 | |||
187 | /** |
||
188 | * Generate the entity admin type. |
||
189 | * |
||
190 | * @param $bundle |
||
191 | * @param $entityName |
||
192 | * @param $entityPrefix |
||
193 | * @param array $fields |
||
194 | * @param string $extendClass |
||
195 | */ |
||
196 | protected function generateEntityAdminType( |
||
197 | $bundle, |
||
198 | $entityName, |
||
199 | $entityPrefix, |
||
200 | array $fields, |
||
201 | $extendClass = '\Symfony\Component\Form\AbstractType' |
||
202 | ) { |
||
203 | $className = $entityName . 'AdminType'; |
||
204 | $savePath = $bundle->getPath() . '/Form/' . $entityPrefix . '/' . $className . '.php'; |
||
205 | $name = str_replace( |
||
206 | '\\', |
||
207 | '_', |
||
208 | strtolower($bundle->getNamespace()) |
||
209 | ) . '_' . strtolower($entityName) . 'type'; |
||
210 | |||
211 | $params = array( |
||
212 | 'className' => $className, |
||
213 | 'name' => $name, |
||
214 | 'namespace' => $bundle->getNamespace(), |
||
215 | 'entity' => '\\' . $bundle->getNamespace() . '\Entity\\' . $entityPrefix . '\\' . $entityName, |
||
216 | 'fields' => $fields, |
||
217 | 'entity_prefix' => $entityPrefix, |
||
218 | 'extend_class' => $extendClass, |
||
219 | ); |
||
220 | $this->renderFile('/Form/EntityAdminType.php', $savePath, $params); |
||
221 | } |
||
222 | |||
223 | /** |
||
224 | * Install the default page templates. |
||
225 | * |
||
226 | * @param BundleInterface $bundle |
||
227 | */ |
||
228 | protected function installDefaultPageTemplates($bundle) |
||
229 | { |
||
230 | // Configuration templates |
||
231 | View Code Duplication | if ($this->isSymfony4()) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
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.
Loading history...
|
|||
232 | $dirPath = $this->container->getParameter('kernel.project_dir') . '/config/kunstmaancms/pagetemplates/'; |
||
233 | } else { |
||
234 | $dirPath = sprintf('%s/Resources/config/pagetemplates/', $bundle->getPath()); |
||
235 | } |
||
236 | |||
237 | $skeletonDir = sprintf('%s/Resources/config/pagetemplates/', GeneratorUtils::getFullSkeletonPath('/common')); |
||
238 | |||
239 | // Only copy templates over when the folder does not exist yet... |
||
240 | if (!$this->filesystem->exists($dirPath)) { |
||
241 | $files = array( |
||
242 | 'default-one-column.yml', |
||
243 | 'default-two-column-left.yml', |
||
244 | 'default-two-column-right.yml', |
||
245 | 'default-three-column.yml', |
||
246 | ); |
||
247 | foreach ($files as $file) { |
||
248 | $this->filesystem->copy($skeletonDir . $file, $dirPath . $file, false); |
||
249 | GeneratorUtils::replace('~~~BUNDLE~~~', $bundle->getName(), $dirPath . $file); |
||
250 | } |
||
251 | } |
||
252 | |||
253 | // Twig templates |
||
254 | $dirPath = $this->getTemplateDir($bundle) . '/Pages/Common/'; |
||
255 | |||
256 | $skeletonDir = sprintf('%s/Resources/views/Pages/Common/', GeneratorUtils::getFullSkeletonPath('/common')); |
||
257 | |||
258 | if (!$this->filesystem->exists($dirPath)) { |
||
259 | $files = array( |
||
260 | 'one-column-pagetemplate.html.twig', |
||
261 | 'two-column-left-pagetemplate.html.twig', |
||
262 | 'two-column-right-pagetemplate.html.twig', |
||
263 | 'three-column-pagetemplate.html.twig', |
||
264 | ); |
||
265 | foreach ($files as $file) { |
||
266 | $this->filesystem->copy($skeletonDir . $file, $dirPath . $file, false); |
||
267 | } |
||
268 | $this->filesystem->copy($skeletonDir . 'view.html.twig', $dirPath . 'view.html.twig', false); |
||
269 | } |
||
270 | |||
271 | $contents = file_get_contents($dirPath . 'view.html.twig'); |
||
272 | |||
273 | $twigFile = $this->isSymfony4() ? |
||
274 | $twigFile = "{% extends 'Layout/layout.html.twig' %}\n" : |
||
275 | $twigFile = "{% extends '".$bundle->getName().":Layout:layout.html.twig' %}\n" |
||
276 | ; |
||
277 | |||
278 | if (strpos($contents, '{% extends ') === false) { |
||
279 | GeneratorUtils::prepend( |
||
280 | $twigFile, |
||
281 | $dirPath . 'view.html.twig' |
||
282 | ); |
||
283 | } |
||
284 | } |
||
285 | |||
286 | /** |
||
287 | * Install the default pagepart configuration. |
||
288 | * |
||
289 | * @param BundleInterface $bundle |
||
290 | */ |
||
291 | protected function installDefaultPagePartConfiguration($bundle) |
||
292 | { |
||
293 | // Pagepart configuration |
||
294 | View Code Duplication | if ($this->isSymfony4()) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
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.
Loading history...
|
|||
295 | $dirPath = $this->container->getParameter('kernel.project_dir') . '/config/kunstmaancms/pageparts/'; |
||
296 | } else { |
||
297 | $dirPath = sprintf('%s/Resources/config/pageparts/', $bundle->getPath()); |
||
298 | } |
||
299 | |||
300 | $skeletonDir = sprintf('%s/Resources/config/pageparts/', GeneratorUtils::getFullSkeletonPath('/common')); |
||
301 | |||
302 | // Only copy when folder does not exist yet |
||
303 | if (!$this->filesystem->exists($dirPath)) { |
||
304 | $files = array('footer.yml', 'main.yml', 'left-sidebar.yml', 'right-sidebar.yml'); |
||
305 | foreach ($files as $file) { |
||
306 | $this->filesystem->copy($skeletonDir . $file, $dirPath . $file, false); |
||
307 | } |
||
308 | } |
||
309 | } |
||
310 | |||
311 | /** |
||
312 | * Render all files in the source directory and copy them to the target directory. |
||
313 | * |
||
314 | * @param string $sourceDir The source directory where we need to look in |
||
315 | * @param string $targetDir The target directory where we need to copy the files too |
||
316 | * @param array $parameters The parameters that will be passed to the templates |
||
317 | * @param bool $override Whether to override an existing file or not |
||
318 | * @param bool $recursive Whether to render all files recursively or not |
||
319 | */ |
||
320 | 1 | public function renderFiles($sourceDir, $targetDir, array $parameters, $override = false, $recursive = true) |
|
321 | { |
||
322 | // Make sure the source -and target dir contain a trailing slash |
||
323 | 1 | $sourceDir = rtrim($sourceDir, '/') . '/'; |
|
324 | 1 | $targetDir = rtrim($targetDir, '/') . '/'; |
|
325 | |||
326 | 1 | $this->setSkeletonDirs(array($sourceDir)); |
|
327 | |||
328 | 1 | $finder = new Finder(); |
|
329 | 1 | $finder->files()->in($sourceDir); |
|
330 | 1 | if (!$recursive) { |
|
331 | $finder->depth('== 0'); |
||
332 | } |
||
333 | |||
334 | // Get all files in the source directory |
||
335 | 1 | foreach ($finder as $file) { |
|
336 | 1 | $name = $file->getRelativePathname(); |
|
337 | |||
338 | // Check that we are allowed to overwrite the file if it already exists |
||
339 | 1 | View Code Duplication | if (!is_file($targetDir . $name) || $override === true) { |
340 | 1 | $fileParts = explode('.', $name); |
|
341 | 1 | if (end($fileParts) === 'twig') { |
|
342 | 1 | $this->renderTwigFile($name, $targetDir . $name, $parameters, $sourceDir); |
|
343 | } else { |
||
344 | $this->renderFile($name, $targetDir . $name, $parameters); |
||
345 | } |
||
346 | } |
||
347 | } |
||
348 | 1 | } |
|
349 | |||
350 | /** |
||
351 | * Render all files in the source directory and copy them to the target directory. |
||
352 | * |
||
353 | * @param string $sourceDir The source directory where we need to look in |
||
354 | * @param string $targetDir The target directory where we need to copy the files too |
||
355 | * @param string $filename The name of the file that needs to be rendered |
||
356 | * @param array $parameters The parameters that will be passed to the templates |
||
357 | * @param bool $override Whether to override an existing file or not |
||
358 | * @param string|null $targetFilename The name of the target file (if null, then use $filename) |
||
359 | */ |
||
360 | 1 | public function renderSingleFile($sourceDir, $targetDir, $filename, array $parameters, $override = false, $targetFilename = null) |
|
361 | { |
||
362 | // Make sure the source -and target dir contain a trailing slash |
||
363 | 1 | $sourceDir = rtrim($sourceDir, '/') . '/'; |
|
364 | 1 | $targetDir = rtrim($targetDir, '/') . '/'; |
|
365 | 1 | if (is_null($targetFilename)) { |
|
366 | 1 | $targetFilename = $filename; |
|
367 | } |
||
368 | |||
369 | 1 | $this->setSkeletonDirs(array($sourceDir)); |
|
370 | |||
371 | 1 | View Code Duplication | if (is_file($sourceDir . $filename)) { |
372 | // Check that we are allowed the overwrite the file if it already exists |
||
373 | 1 | if (!is_file($targetDir . $targetFilename) || $override === true) { |
|
374 | 1 | $fileParts = explode('.', $filename); |
|
375 | 1 | if (end($fileParts) === 'twig') { |
|
376 | 1 | $this->renderTwigFile($filename, $targetDir . $targetFilename, $parameters, $sourceDir); |
|
377 | } else { |
||
378 | 1 | $this->renderFile($filename, $targetDir . $targetFilename, $parameters); |
|
379 | } |
||
380 | } |
||
381 | } |
||
382 | 1 | } |
|
383 | |||
384 | /** |
||
385 | * Render a file and make it executable. |
||
386 | * |
||
387 | * @param string $sourceDir The source directory where we need to look in |
||
388 | * @param string $targetDir The target directory where we need to copy the files too |
||
389 | * @param string $filename The name of the file that needs to be rendered |
||
390 | * @param array $parameters The parameters that will be passed to the templates |
||
391 | * @param bool $override Whether to override an existing file or not |
||
392 | * @param int $mode The mode |
||
393 | */ |
||
394 | public function renderExecutableFile($sourceDir, $targetDir, $filename, array $parameters, $override = false, $mode = 0774) |
||
395 | { |
||
396 | $this->renderSingleFile($sourceDir, $targetDir, $filename, $parameters, $override); |
||
397 | |||
398 | $targetDir = rtrim($targetDir, '/') . '/'; |
||
399 | $targetFile = $targetDir . $filename; |
||
400 | $this->filesystem->chmod($targetFile, $mode); |
||
401 | } |
||
402 | |||
403 | /** |
||
404 | * Copy all files in the source directory to the target directory. |
||
405 | * |
||
406 | * @param string $sourceDir The source directory where we need to look in |
||
407 | * @param string $targetDir The target directory where we need to copy the files too |
||
408 | * @param bool $override Whether to override an existing file or not |
||
409 | */ |
||
410 | public function copyFiles($sourceDir, $targetDir, $override = false) |
||
411 | { |
||
412 | // Make sure the source -and target dir contain a trailing slash |
||
413 | $sourceDir = rtrim($sourceDir, '/') . '/'; |
||
414 | $targetDir = rtrim($targetDir, '/') . '/'; |
||
415 | |||
416 | $this->filesystem->mirror($sourceDir, $targetDir, null, array('override' => $override)); |
||
417 | } |
||
418 | |||
419 | /** |
||
420 | * Remove a directory from the filesystem. |
||
421 | * |
||
422 | * @param string $targetDir |
||
423 | */ |
||
424 | public function removeDirectory($targetDir) |
||
425 | { |
||
426 | // Make sure the target dir contain a trailing slash |
||
427 | $targetDir = rtrim($targetDir, '/') . '/'; |
||
428 | |||
429 | $this->filesystem->remove($targetDir); |
||
430 | } |
||
431 | |||
432 | /** |
||
433 | * Remove a file from the filesystem. |
||
434 | * |
||
435 | * @param string $file |
||
436 | */ |
||
437 | public function removeFile($file) |
||
438 | { |
||
439 | $this->filesystem->remove($file); |
||
440 | } |
||
441 | |||
442 | /** |
||
443 | * Render a twig file with custom twig tags. |
||
444 | * |
||
445 | * @param string $template |
||
446 | * @param array $parameters |
||
447 | * @param string $sourceDir |
||
448 | * |
||
449 | * @return string |
||
450 | */ |
||
451 | 1 | public function renderTwig($template, array $parameters, $sourceDir) |
|
452 | { |
||
453 | 1 | $twig = new Environment( |
|
454 | 1 | new FilesystemLoader(array($sourceDir)), array( |
|
455 | 1 | 'debug' => true, |
|
456 | 'cache' => false, |
||
457 | 'strict_variables' => true, |
||
458 | 'autoescape' => false, |
||
459 | ) |
||
460 | ); |
||
461 | |||
462 | // Ruby erb template syntax |
||
463 | 1 | $lexer = new Lexer( |
|
464 | 1 | $twig, array( |
|
465 | 1 | 'tag_comment' => array('<%#', '%>'), |
|
466 | 'tag_block' => array('<%', '%>'), |
||
467 | 'tag_variable' => array('<%=', '%>'), |
||
468 | ) |
||
469 | ); |
||
470 | |||
471 | 1 | $twig->setLexer($lexer); |
|
472 | |||
473 | 1 | return $twig->render($template, $parameters); |
|
474 | } |
||
475 | |||
476 | /** |
||
477 | * Render a twig file, and save it to disk. |
||
478 | * |
||
479 | * @param string $template |
||
480 | * @param string $target |
||
481 | * @param array $parameters |
||
482 | * @param string $sourceDir |
||
483 | * |
||
484 | * @return int |
||
485 | */ |
||
486 | 1 | public function renderTwigFile($template, $target, array $parameters, $sourceDir) |
|
487 | { |
||
488 | 1 | if (!is_dir(dirname($target))) { |
|
489 | 1 | mkdir(dirname($target), 0777, true); |
|
490 | } |
||
491 | |||
492 | 1 | return file_put_contents($target, $this->renderTwig($template, $parameters, $sourceDir)); |
|
493 | } |
||
494 | |||
495 | /** |
||
496 | * @return \Doctrine\ORM\Tools\EntityRepositoryGenerator |
||
497 | */ |
||
498 | protected function getRepositoryGenerator() |
||
499 | { |
||
500 | return new EntityRepositoryGenerator(); |
||
501 | } |
||
502 | |||
503 | /** |
||
504 | * @return \Kunstmaan\GeneratorBundle\Generator\Symfony4EntityRepositoryGenerator |
||
505 | */ |
||
506 | protected function getSymfony4RepositoryGenerator() |
||
507 | { |
||
508 | return new \Kunstmaan\GeneratorBundle\Generator\Symfony4EntityRepositoryGenerator(); |
||
509 | } |
||
510 | |||
511 | /** |
||
512 | * @internal |
||
513 | */ |
||
514 | 1 | View Code Duplication | protected function getTemplateDir(BundleInterface $bundle) |
515 | { |
||
516 | 1 | if ($this->isSymfony4()) { |
|
517 | 1 | return $this->container->getParameter('kernel.project_dir') . '/templates'; |
|
518 | } |
||
519 | |||
520 | return $bundle->getPath() . '/Resources/views'; |
||
521 | } |
||
522 | |||
523 | /** |
||
524 | * @internal |
||
525 | */ |
||
526 | View Code Duplication | protected function getAssetsDir(BundleInterface $bundle) |
|
527 | { |
||
528 | if ($this->isSymfony4()) { |
||
529 | return $this->container->getParameter('kernel.project_dir') . '/assets'; |
||
530 | } |
||
531 | |||
532 | return $bundle->getPath() . '/Resources'; |
||
533 | } |
||
534 | |||
535 | /** |
||
536 | * @internal |
||
537 | */ |
||
538 | 1 | protected function isSymfony4() |
|
539 | { |
||
540 | 1 | return Kernel::VERSION_ID >= 40000; |
|
541 | } |
||
542 | } |
||
543 |
Let’s take a look at an example:
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.
Available Fixes
Change the type-hint for the parameter:
Add an additional type-check:
Add the method to the interface: