feature #26919 [TwigBridge] Added bundle name suggestion on wrongly overrided 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
-------

acfb325a35 refs #26898 Remove unnecessary loop Trim messages on build rather than on display
da42b3e23c refs #26898 Check if projectDir is not null before loop
da0c589385 refs #26898 Move changelog entry to 4.1.0 to 4.2.0
7d9467a319 Add an entry on json export format
bab9d99032 Use %twig.default_path% parameter and search in old folder structure too
1758de24a5 [TwigBridge] Added bundle name suggestion on wrongly overrided templates paths
This commit is contained in:
Nicolas Grekas 2018-06-19 14:50:24 +02:00
commit d148fa708a
3 changed files with 104 additions and 1 deletions

View File

@ -1,6 +1,11 @@
CHANGELOG
=========
4.2.0
-----
* add bundle name suggestion on wrongly overridden templates paths
4.1.0
-----

View File

@ -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()
@ -82,6 +88,10 @@ EOF
}
$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;
@ -123,6 +133,10 @@ EOF
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;
}
@ -242,4 +256,85 @@ EOF
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;
}
}

View File

@ -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>