Skip to content

Commit

Permalink
feature #26919 [TwigBridge] Added bundle name suggestion on wrongly o…
Browse files Browse the repository at this point in the history
…verrided templates paths (pmontoya, Pascal Montoya)

This PR was merged into the 4.2-dev branch.

Discussion
----------

[TwigBridge] Added bundle name suggestion on wrongly overrided templates paths

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #26898
| License       | MIT

Report unknown folders in templates/bundles in debug:twig and make suggestions if any

Developped with @bricejulia

Commits
-------

acfb325 refs #26898 Remove unnecessary loop Trim messages on build rather than on display
da42b3e refs #26898 Check if projectDir is not null before loop
da0c589 refs #26898 Move changelog entry to 4.1.0 to 4.2.0
7d9467a Add an entry on json export format
bab9d99 Use %twig.default_path% parameter and search in old folder structure too
1758de2 [TwigBridge] Added bundle name suggestion on wrongly overrided templates paths
  • Loading branch information
nicolas-grekas committed Jun 19, 2018
2 parents f065873 + acfb325 commit d148fa7
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/Symfony/Bridge/Twig/CHANGELOG.md
@@ -1,6 +1,11 @@
CHANGELOG
=========

4.2.0
-----

* add bundle name suggestion on wrongly overridden templates paths

4.1.0
-----

Expand Down
97 changes: 96 additions & 1 deletion src/Symfony/Bridge/Twig/Command/DebugCommand.php
Expand Up @@ -31,13 +31,19 @@ class DebugCommand extends Command

private $twig;
private $projectDir;
private $bundlesMetadata;
private $twigDefaultPath;
private $rootDir;

public function __construct(Environment $twig, string $projectDir = null)
public function __construct(Environment $twig, string $projectDir = null, array $bundlesMetadata = array(), string $twigDefaultPath = null, string $rootDir = null)
{
parent::__construct();

$this->twig = $twig;
$this->projectDir = $projectDir;
$this->bundlesMetadata = $bundlesMetadata;
$this->twigDefaultPath = $twigDefaultPath;
$this->rootDir = $rootDir;
}

protected function configure()
Expand Down Expand Up @@ -82,6 +88,10 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
$data['tests'] = array_keys($data['tests']);
$data['loader_paths'] = $this->getLoaderPaths();
if ($wrongBundles = $this->findWrongBundleOverrides()) {
$data['warnings'] = $this->buildWarningMessages($wrongBundles);
}

$io->writeln(json_encode($data));

return 0;
Expand Down Expand Up @@ -123,6 +133,10 @@ protected function execute(InputInterface $input, OutputInterface $output)
array_pop($rows);
$io->section('Loader Paths');
$io->table(array('Namespace', 'Paths'), $rows);
$messages = $this->buildWarningMessages($this->findWrongBundleOverrides());
foreach ($messages as $message) {
$io->warning($message);
}

return 0;
}
Expand Down Expand Up @@ -242,4 +256,85 @@ private function getPrettyMetadata($type, $entity)
return $meta ? '('.implode(', ', $meta).')' : '';
}
}

private function findWrongBundleOverrides(): array
{
$alternatives = array();
$bundleNames = array();

if ($this->rootDir && $this->projectDir) {
$folders = glob($this->rootDir.'/Resources/*/views', GLOB_ONLYDIR);
$relativePath = ltrim(substr($this->rootDir.'/Resources/', \strlen($this->projectDir)), DIRECTORY_SEPARATOR);
$bundleNames = array_reduce(
$folders,
function ($carry, $absolutePath) use ($relativePath) {
if (0 === strpos($absolutePath, $this->projectDir)) {
$name = basename(\dirname($absolutePath));
$path = $relativePath.$name;
$carry[$name] = $path;
}

return $carry;
},
$bundleNames
);
}

if ($this->twigDefaultPath && $this->projectDir) {
$folders = glob($this->twigDefaultPath.'/bundles/*', GLOB_ONLYDIR);
$relativePath = ltrim(substr($this->twigDefaultPath.'/bundles', \strlen($this->projectDir)), DIRECTORY_SEPARATOR);
$bundleNames = array_reduce(
$folders,
function ($carry, $absolutePath) use ($relativePath) {
if (0 === strpos($absolutePath, $this->projectDir)) {
$path = ltrim(substr($absolutePath, \strlen($this->projectDir)), DIRECTORY_SEPARATOR);
$name = ltrim(substr($path, \strlen($relativePath)), DIRECTORY_SEPARATOR);
$carry[$name] = $path;
}

return $carry;
},
$bundleNames
);
}

if (\count($bundleNames)) {
$notFoundBundles = array_diff_key($bundleNames, $this->bundlesMetadata);
if (\count($notFoundBundles)) {
$alternatives = array();
foreach ($notFoundBundles as $notFoundBundle => $path) {
$alternatives[$path] = array();
foreach ($this->bundlesMetadata as $name => $bundle) {
$lev = levenshtein($notFoundBundle, $name);
if ($lev <= \strlen($notFoundBundle) / 3 || false !== strpos($name, $notFoundBundle)) {
$alternatives[$path][] = $name;
}
}
}
}
}

return $alternatives;
}

private function buildWarningMessages(array $wrongBundles): array
{
$messages = array();
foreach ($wrongBundles as $path => $alternatives) {
$message = sprintf('Path "%s" not matching any bundle found', $path);
if ($alternatives) {
if (1 === \count($alternatives)) {
$message .= sprintf(", did you mean \"%s\"?\n", $alternatives[0]);
} else {
$message .= ", did you mean one of these:\n";
foreach ($alternatives as $bundle) {
$message .= sprintf(" - %s\n", $bundle);
}
}
}
$messages[] = trim($message);
}

return $messages;
}
}
3 changes: 3 additions & 0 deletions src/Symfony/Bundle/TwigBundle/Resources/config/console.xml
Expand Up @@ -10,6 +10,9 @@
<service id="twig.command.debug" class="Symfony\Bridge\Twig\Command\DebugCommand">
<argument type="service" id="twig" />
<argument>%kernel.project_dir%</argument>
<argument>%kernel.bundles_metadata%</argument>
<argument>%twig.default_path%</argument>
<argument>%kernel.root_dir%</argument>
<tag name="console.command" command="debug:twig" />
</service>

Expand Down

0 comments on commit d148fa7

Please sign in to comment.