feature #27981 [TwigBridge] Added template "name" argument to debug:twig command to find their paths (yceruto)
This PR was squashed before being merged into the 4.2-dev branch (closes #27981).
Discussion
----------
[TwigBridge] Added template "name" argument to debug:twig command to find their paths
| Q | A
| ------------- | ---
| Branch? | master
| Bug fix? | no
| New feature? | yes
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #27911
| License | MIT
| Doc PR | https://github.com/symfony/symfony-docs/pull/10232
Find the template file (to load by Twig) from a given template name (useful to know which file will be loaded exactly and which ones don't):
![debug-twig-loader-overridden](https://user-images.githubusercontent.com/2028198/42849959-81a8c49a-89f3-11e8-8d93-21581fe606a9.png)
This will also show the overridden files if they exist and the paths corresponding to their namespace.
In addition, the command suggests alternatives if you made a typo (this way you can check your template name quickly):
| namespace typo | template name typo |
| --- | --- |
| ![debug-twig-loader-ns-typo-alt](https://user-images.githubusercontent.com/2028198/42850624-81803e3c-89f6-11e8-8a92-11f09c99d13c.png) | ![debug-twig-loader-typo-alt](https://user-images.githubusercontent.com/2028198/42850644-99571238-89f6-11e8-9cf7-ed9b880f3d81.png) |
<details>
<summary><strong>Other outputs</strong></summary>
Discovering more alternatives:
![debug-twig-loader-not-found-many-alt](https://user-images.githubusercontent.com/2028198/42850815-82a30eb0-89f7-11e8-8d23-530f8ff325bc.png)
Unknown template name:
![debug-twig-loader-not-found](https://user-images.githubusercontent.com/2028198/42850882-d647aad0-89f7-11e8-9735-94149895437f.png)
</details>
## Update
The feature was introduced into `debug:twig` command and the `filter` argument was converted to `--filter` option. The `name` argument is now the first one of the command.
Commits
-------
7ef3d39a4c
[TwigBridge] Added template \"name\" argument to debug:twig command to find their paths
This commit is contained in:
commit
e54dd4e600
@ -5,6 +5,7 @@ CHANGELOG
|
||||
-----
|
||||
|
||||
* add bundle name suggestion on wrongly overridden templates paths
|
||||
* added `name` argument in `debug:twig` command and changed `filter` argument as `--filter` option
|
||||
|
||||
4.1.0
|
||||
-----
|
||||
|
@ -12,11 +12,13 @@
|
||||
namespace Symfony\Bridge\Twig\Command;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Twig\Environment;
|
||||
use Twig\Loader\FilesystemLoader;
|
||||
|
||||
@ -50,19 +52,24 @@ class DebugCommand extends Command
|
||||
{
|
||||
$this
|
||||
->setDefinition(array(
|
||||
new InputArgument('filter', InputArgument::OPTIONAL, 'Show details for all entries matching this filter'),
|
||||
new InputArgument('name', InputArgument::OPTIONAL, 'The template name'),
|
||||
new InputOption('filter', null, InputOption::VALUE_REQUIRED, 'Show details for all entries matching this filter'),
|
||||
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (text or json)', 'text'),
|
||||
))
|
||||
->setDescription('Shows a list of twig functions, filters, globals and tests')
|
||||
->setHelp(<<<'EOF'
|
||||
The <info>%command.name%</info> command outputs a list of twig functions,
|
||||
filters, globals and tests. Output can be filtered with an optional argument.
|
||||
filters, globals and tests.
|
||||
|
||||
<info>php %command.full_name%</info>
|
||||
|
||||
The command lists all functions, filters, etc.
|
||||
|
||||
<info>php %command.full_name% date</info>
|
||||
<info>php %command.full_name% @Twig/Exception/error.html.twig</info>
|
||||
|
||||
The command lists all paths that match the given template name.
|
||||
|
||||
<info>php %command.full_name% --filter=date</info>
|
||||
|
||||
The command lists everything that contains the word date.
|
||||
|
||||
@ -77,28 +84,107 @@ EOF
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$types = array('functions', 'filters', 'tests', 'globals');
|
||||
$name = $input->getArgument('name');
|
||||
$filter = $input->getOption('filter');
|
||||
|
||||
if ('json' === $input->getOption('format')) {
|
||||
$data = array();
|
||||
foreach ($types as $type) {
|
||||
foreach ($this->twig->{'get'.ucfirst($type)}() as $name => $entity) {
|
||||
$data[$type][$name] = $this->getMetadata($type, $entity);
|
||||
}
|
||||
}
|
||||
$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;
|
||||
if (null !== $name && !$this->twig->getLoader() instanceof FilesystemLoader) {
|
||||
throw new InvalidArgumentException(sprintf('Argument "name" not supported, it requires the Twig loader "%s"', FilesystemLoader::class));
|
||||
}
|
||||
|
||||
$filter = $input->getArgument('filter');
|
||||
switch ($input->getOption('format')) {
|
||||
case 'text':
|
||||
return $name ? $this->displayPathsText($io, $name) : $this->displayGeneralText($io, $filter);
|
||||
case 'json':
|
||||
return $name ? $this->displayPathsJson($io, $name) : $this->displayGeneralJson($io, $filter);
|
||||
default:
|
||||
throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $input->getOption('format')));
|
||||
}
|
||||
}
|
||||
|
||||
private function displayPathsText(SymfonyStyle $io, string $name)
|
||||
{
|
||||
$files = $this->findTemplateFiles($name);
|
||||
$paths = $this->getLoaderPaths($name);
|
||||
|
||||
$io->section('Matched File');
|
||||
if ($files) {
|
||||
$io->success(array_shift($files));
|
||||
|
||||
if ($files) {
|
||||
$io->section('Overridden Files');
|
||||
$io->listing($files);
|
||||
}
|
||||
} else {
|
||||
$alternatives = array();
|
||||
|
||||
if ($paths) {
|
||||
$shortnames = array();
|
||||
$dirs = array();
|
||||
foreach (current($paths) as $path) {
|
||||
$dirs[] = $this->isAbsolutePath($path) ? $path : $this->projectDir.'/'.$path;
|
||||
}
|
||||
foreach (Finder::create()->files()->followLinks()->in($dirs) as $file) {
|
||||
$shortnames[] = str_replace('\\', '/', $file->getRelativePathname());
|
||||
}
|
||||
|
||||
list($namespace, $shortname) = $this->parseTemplateName($name);
|
||||
$alternatives = $this->findAlternatives($shortname, $shortnames);
|
||||
if (FilesystemLoader::MAIN_NAMESPACE !== $namespace) {
|
||||
$alternatives = array_map(function ($shortname) use ($namespace) {
|
||||
return '@'.$namespace.'/'.$shortname;
|
||||
}, $alternatives);
|
||||
}
|
||||
}
|
||||
|
||||
$this->error($io, sprintf('Template name "%s" not found', $name), $alternatives);
|
||||
}
|
||||
|
||||
$io->section('Configured Paths');
|
||||
if ($paths) {
|
||||
$io->table(array('Namespace', 'Paths'), $this->buildTableRows($paths));
|
||||
} else {
|
||||
$alternatives = array();
|
||||
$namespace = $this->parseTemplateName($name)[0];
|
||||
|
||||
if (FilesystemLoader::MAIN_NAMESPACE === $namespace) {
|
||||
$message = 'No template paths configured for your application';
|
||||
} else {
|
||||
$message = sprintf('No template paths configured for "@%s" namespace', $namespace);
|
||||
$namespaces = $this->twig->getLoader()->getNamespaces();
|
||||
foreach ($this->findAlternatives($namespace, $namespaces) as $namespace) {
|
||||
$alternatives[] = '@'.$namespace;
|
||||
}
|
||||
}
|
||||
|
||||
$this->error($io, $message, $alternatives);
|
||||
|
||||
if (!$alternatives && $paths = $this->getLoaderPaths()) {
|
||||
$io->table(array('Namespace', 'Paths'), $this->buildTableRows($paths));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function displayPathsJson(SymfonyStyle $io, string $name)
|
||||
{
|
||||
$files = $this->findTemplateFiles($name);
|
||||
$paths = $this->getLoaderPaths($name);
|
||||
|
||||
if ($files) {
|
||||
$data['matched_file'] = array_shift($files);
|
||||
if ($files) {
|
||||
$data['overridden_files'] = $files;
|
||||
}
|
||||
} else {
|
||||
$data['matched_file'] = sprintf('Template name "%s" not found', $name);
|
||||
}
|
||||
$data['loader_paths'] = $paths;
|
||||
|
||||
$io->writeln(json_encode($data));
|
||||
}
|
||||
|
||||
private function displayGeneralText(SymfonyStyle $io, string $filter = null)
|
||||
{
|
||||
$types = array('functions', 'filters', 'tests', 'globals');
|
||||
foreach ($types as $index => $type) {
|
||||
$items = array();
|
||||
foreach ($this->twig->{'get'.ucfirst($type)}() as $name => $entity) {
|
||||
@ -117,46 +203,56 @@ EOF
|
||||
$io->listing($items);
|
||||
}
|
||||
|
||||
$rows = array();
|
||||
$firstNamespace = true;
|
||||
$prevHasSeparator = false;
|
||||
foreach ($this->getLoaderPaths() as $namespace => $paths) {
|
||||
if (!$firstNamespace && !$prevHasSeparator && \count($paths) > 1) {
|
||||
$rows[] = array('', '');
|
||||
}
|
||||
$firstNamespace = false;
|
||||
foreach ($paths as $path) {
|
||||
$rows[] = array($namespace, $path.\DIRECTORY_SEPARATOR);
|
||||
$namespace = '';
|
||||
}
|
||||
if (\count($paths) > 1) {
|
||||
$rows[] = array('', '');
|
||||
$prevHasSeparator = true;
|
||||
} else {
|
||||
$prevHasSeparator = false;
|
||||
}
|
||||
}
|
||||
if ($prevHasSeparator) {
|
||||
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);
|
||||
if (!$filter && $paths = $this->getLoaderPaths()) {
|
||||
$io->section('Loader Paths');
|
||||
$io->table(array('Namespace', 'Paths'), $this->buildTableRows($paths));
|
||||
}
|
||||
|
||||
return 0;
|
||||
if ($wronBundles = $this->findWrongBundleOverrides()) {
|
||||
foreach ($this->buildWarningMessages($wronBundles) as $message) {
|
||||
$io->warning($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getLoaderPaths()
|
||||
private function displayGeneralJson(SymfonyStyle $io, $filter)
|
||||
{
|
||||
if (!($loader = $this->twig->getLoader()) instanceof FilesystemLoader) {
|
||||
return array();
|
||||
$types = array('functions', 'filters', 'tests', 'globals');
|
||||
$data = array();
|
||||
foreach ($types as $type) {
|
||||
foreach ($this->twig->{'get'.ucfirst($type)}() as $name => $entity) {
|
||||
if (!$filter || false !== strpos($name, $filter)) {
|
||||
$data[$type][$name] = $this->getMetadata($type, $entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($data['tests'])) {
|
||||
$data['tests'] = array_keys($data['tests']);
|
||||
}
|
||||
|
||||
if (!$filter && $paths = $this->getLoaderPaths($filter)) {
|
||||
$data['loader_paths'] = $paths;
|
||||
}
|
||||
|
||||
if ($wronBundles = $this->findWrongBundleOverrides()) {
|
||||
$data['warnings'] = $this->buildWarningMessages($wronBundles);
|
||||
}
|
||||
|
||||
$io->writeln(json_encode($data));
|
||||
}
|
||||
|
||||
private function getLoaderPaths(string $name = null): array
|
||||
{
|
||||
/** @var FilesystemLoader $loader */
|
||||
$loader = $this->twig->getLoader();
|
||||
$loaderPaths = array();
|
||||
foreach ($loader->getNamespaces() as $namespace) {
|
||||
$namespaces = $loader->getNamespaces();
|
||||
if (null !== $name) {
|
||||
$namespace = $this->parseTemplateName($name)[0];
|
||||
$namespaces = array_intersect(array($namespace), $namespaces);
|
||||
}
|
||||
|
||||
foreach ($namespaces as $namespace) {
|
||||
$paths = array_map(function ($path) {
|
||||
if (null !== $this->projectDir && 0 === strpos($path, $this->projectDir)) {
|
||||
$path = ltrim(substr($path, \strlen($this->projectDir)), \DIRECTORY_SEPARATOR);
|
||||
@ -345,4 +441,119 @@ EOF
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
private function error(SymfonyStyle $io, string $message, array $alternatives = array()): void
|
||||
{
|
||||
if ($alternatives) {
|
||||
if (1 === \count($alternatives)) {
|
||||
$message .= "\n\nDid you mean this?\n ";
|
||||
} else {
|
||||
$message .= "\n\nDid you mean one of these?\n ";
|
||||
}
|
||||
$message .= implode("\n ", $alternatives);
|
||||
}
|
||||
|
||||
$io->block($message, null, 'fg=white;bg=red', ' ', true);
|
||||
}
|
||||
|
||||
private function findTemplateFiles(string $name): array
|
||||
{
|
||||
/** @var FilesystemLoader $loader */
|
||||
$loader = $this->twig->getLoader();
|
||||
$files = array();
|
||||
list($namespace, $shortname) = $this->parseTemplateName($name);
|
||||
|
||||
foreach ($loader->getPaths($namespace) as $path) {
|
||||
if (!$this->isAbsolutePath($path)) {
|
||||
$path = $this->projectDir.'/'.$path;
|
||||
}
|
||||
$filename = $path.'/'.$shortname;
|
||||
|
||||
if (is_file($filename)) {
|
||||
if (false !== $realpath = realpath($filename)) {
|
||||
$files[] = $this->getRelativePath($realpath);
|
||||
} else {
|
||||
$files[] = $this->getRelativePath($filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
private function parseTemplateName(string $name, string $default = FilesystemLoader::MAIN_NAMESPACE): array
|
||||
{
|
||||
if (isset($name[0]) && '@' === $name[0]) {
|
||||
if (false === ($pos = strpos($name, '/')) || $pos === \strlen($name) - 1) {
|
||||
throw new InvalidArgumentException(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name));
|
||||
}
|
||||
|
||||
$namespace = substr($name, 1, $pos - 1);
|
||||
$shortname = substr($name, $pos + 1);
|
||||
|
||||
return array($namespace, $shortname);
|
||||
}
|
||||
|
||||
return array($default, $name);
|
||||
}
|
||||
|
||||
private function buildTableRows(array $loaderPaths): array
|
||||
{
|
||||
$rows = array();
|
||||
$firstNamespace = true;
|
||||
$prevHasSeparator = false;
|
||||
|
||||
foreach ($loaderPaths as $namespace => $paths) {
|
||||
if (!$firstNamespace && !$prevHasSeparator && \count($paths) > 1) {
|
||||
$rows[] = array('', '');
|
||||
}
|
||||
$firstNamespace = false;
|
||||
foreach ($paths as $path) {
|
||||
$rows[] = array($namespace, $path.\DIRECTORY_SEPARATOR);
|
||||
$namespace = '';
|
||||
}
|
||||
if (\count($paths) > 1) {
|
||||
$rows[] = array('', '');
|
||||
$prevHasSeparator = true;
|
||||
} else {
|
||||
$prevHasSeparator = false;
|
||||
}
|
||||
}
|
||||
if ($prevHasSeparator) {
|
||||
array_pop($rows);
|
||||
}
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
private function findAlternatives(string $name, array $collection): array
|
||||
{
|
||||
$alternatives = array();
|
||||
foreach ($collection as $item) {
|
||||
$lev = levenshtein($name, $item);
|
||||
if ($lev <= \strlen($name) / 3 || false !== strpos($item, $name)) {
|
||||
$alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
|
||||
}
|
||||
}
|
||||
|
||||
$threshold = 1e3;
|
||||
$alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; });
|
||||
ksort($alternatives, SORT_NATURAL | SORT_FLAG_CASE);
|
||||
|
||||
return array_keys($alternatives);
|
||||
}
|
||||
|
||||
private function getRelativePath(string $path): string
|
||||
{
|
||||
if (null !== $this->projectDir && 0 === strpos($path, $this->projectDir)) {
|
||||
return ltrim(substr($path, \strlen($this->projectDir)), \DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
private function isAbsolutePath(string $file): bool
|
||||
{
|
||||
return strspn($file, '/\\', 0, 1) || (\strlen($file) > 3 && ctype_alpha($file[0]) && ':' === $file[1] && strspn($file, '/\\', 2, 1)) || null !== parse_url($file, PHP_URL_SCHEME);
|
||||
}
|
||||
}
|
||||
|
@ -29,51 +29,224 @@ class DebugCommandTest extends TestCase
|
||||
$this->assertContains('Functions', trim($tester->getDisplay()));
|
||||
}
|
||||
|
||||
public function testLineSeparatorInLoaderPaths()
|
||||
public function testFilterAndJsonFormatOptions()
|
||||
{
|
||||
// these paths aren't realistic,
|
||||
// they're configured to force the line separator
|
||||
$tester = $this->createCommandTester(array(
|
||||
'Acme' => array('extractor', 'extractor'),
|
||||
'!Acme' => array('extractor', 'extractor'),
|
||||
FilesystemLoader::MAIN_NAMESPACE => array('extractor', 'extractor'),
|
||||
));
|
||||
$ret = $tester->execute(array(), array('decorated' => false));
|
||||
$ds = \DIRECTORY_SEPARATOR;
|
||||
$loaderPaths = <<<TXT
|
||||
Loader Paths
|
||||
------------
|
||||
$tester = $this->createCommandTester();
|
||||
$ret = $tester->execute(array('--filter' => 'abs', '--format' => 'json'), array('decorated' => false));
|
||||
|
||||
----------- ------------
|
||||
Namespace Paths
|
||||
----------- ------------
|
||||
@Acme extractor$ds
|
||||
extractor$ds
|
||||
|
||||
@!Acme extractor$ds
|
||||
extractor$ds
|
||||
|
||||
(None) extractor$ds
|
||||
extractor$ds
|
||||
----------- ------------
|
||||
TXT;
|
||||
$expected = array(
|
||||
'filters' => array('abs' => array()),
|
||||
);
|
||||
|
||||
$this->assertEquals(0, $ret, 'Returns 0 in case of success');
|
||||
$this->assertContains($loaderPaths, trim($tester->getDisplay(true)));
|
||||
$this->assertEquals($expected, json_decode($tester->getDisplay(true), true));
|
||||
}
|
||||
|
||||
private function createCommandTester(array $paths = array())
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Console\Exception\InvalidArgumentException
|
||||
* @expectedExceptionMessage Malformed namespaced template name "@foo" (expecting "@namespace/template_name").
|
||||
*/
|
||||
public function testMalformedTemplateName()
|
||||
{
|
||||
$filesystemLoader = new FilesystemLoader(array(), \dirname(__DIR__).'/Fixtures');
|
||||
foreach ($paths as $namespace => $relDirs) {
|
||||
foreach ($relDirs as $relDir) {
|
||||
$filesystemLoader->addPath($relDir, $namespace);
|
||||
$this->createCommandTester()->execute(array('name' => '@foo'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getDebugTemplateNameTestData
|
||||
*/
|
||||
public function testDebugTemplateName(array $input, string $output, array $paths)
|
||||
{
|
||||
$tester = $this->createCommandTester($paths);
|
||||
$ret = $tester->execute($input, array('decorated' => false));
|
||||
|
||||
$this->assertEquals(0, $ret, 'Returns 0 in case of success');
|
||||
$this->assertStringMatchesFormat($output, $tester->getDisplay(true));
|
||||
}
|
||||
|
||||
public function getDebugTemplateNameTestData()
|
||||
{
|
||||
$defaultPaths = array(
|
||||
'templates/' => null,
|
||||
'templates/bundles/TwigBundle/' => 'Twig',
|
||||
'vendors/twig-bundle/Resources/views/' => 'Twig',
|
||||
);
|
||||
|
||||
yield 'no template paths configured for your application' => array(
|
||||
'input' => array('name' => 'base.html.twig'),
|
||||
'output' => <<<TXT
|
||||
|
||||
Matched File
|
||||
------------
|
||||
|
||||
Template name "base.html.twig" not found%A
|
||||
|
||||
Configured Paths
|
||||
----------------
|
||||
|
||||
No template paths configured for your application%s
|
||||
|
||||
----------- -------------------------------------%A
|
||||
Namespace Paths%A
|
||||
----------- -------------------------------------%A
|
||||
@Twig vendors/twig-bundle/Resources/views%e%A
|
||||
----------- -------------------------------------%A
|
||||
|
||||
|
||||
TXT
|
||||
,
|
||||
'paths' => array('vendors/twig-bundle/Resources/views/' => 'Twig'),
|
||||
);
|
||||
|
||||
yield 'no matched template' => array(
|
||||
'input' => array('name' => '@App/foo.html.twig'),
|
||||
'output' => <<<TXT
|
||||
|
||||
Matched File
|
||||
------------
|
||||
|
||||
Template name "@App/foo.html.twig" not found%A
|
||||
|
||||
Configured Paths
|
||||
----------------
|
||||
|
||||
No template paths configured for "@App" namespace%A
|
||||
|
||||
----------- -------------------------------------%A
|
||||
Namespace Paths%A
|
||||
----------- -------------------------------------%A
|
||||
(None) templates%e%A
|
||||
%A
|
||||
@Twig templates/bundles/TwigBundle%e%A
|
||||
vendors/twig-bundle/Resources/views%e%A
|
||||
----------- -------------------------------------%A
|
||||
|
||||
|
||||
TXT
|
||||
,
|
||||
'paths' => $defaultPaths,
|
||||
);
|
||||
|
||||
yield 'matched file' => array(
|
||||
'input' => array('name' => 'base.html.twig'),
|
||||
'output' => <<<TXT
|
||||
|
||||
Matched File
|
||||
------------
|
||||
|
||||
[OK] templates%ebase.html.twig%A
|
||||
|
||||
Configured Paths
|
||||
----------------
|
||||
|
||||
----------- ------------%A
|
||||
Namespace Paths%A
|
||||
----------- ------------%A
|
||||
(None) templates%e%A
|
||||
----------- ------------%A
|
||||
|
||||
|
||||
TXT
|
||||
,
|
||||
'paths' => $defaultPaths,
|
||||
);
|
||||
|
||||
yield 'overridden files' => array(
|
||||
'input' => array('name' => '@Twig/error.html.twig'),
|
||||
'output' => <<<TXT
|
||||
|
||||
Matched File
|
||||
------------
|
||||
|
||||
[OK] templates%ebundles%eTwigBundle%eerror.html.twig%A
|
||||
|
||||
Overridden Files
|
||||
----------------
|
||||
|
||||
* vendors%etwig-bundle%eResources%eviews%eerror.html.twig
|
||||
|
||||
Configured Paths
|
||||
----------------
|
||||
|
||||
----------- --------------------------------------
|
||||
Namespace Paths%A
|
||||
----------- --------------------------------------
|
||||
@Twig templates/bundles/TwigBundle%e%A
|
||||
vendors/twig-bundle/Resources/views%e%A
|
||||
----------- --------------------------------------
|
||||
|
||||
|
||||
TXT
|
||||
,
|
||||
'paths' => $defaultPaths,
|
||||
);
|
||||
|
||||
yield 'template namespace alternative' => array(
|
||||
'input' => array('name' => '@Twg/error.html.twig'),
|
||||
'output' => <<<TXT
|
||||
|
||||
Matched File
|
||||
------------
|
||||
|
||||
Template name "@Twg/error.html.twig" not found%A
|
||||
|
||||
Configured Paths
|
||||
----------------
|
||||
|
||||
No template paths configured for "@Twg" namespace%A
|
||||
%A
|
||||
%wDid you mean this?%A
|
||||
%w@Twig%A
|
||||
|
||||
|
||||
TXT
|
||||
,
|
||||
'paths' => $defaultPaths,
|
||||
);
|
||||
|
||||
yield 'template name alternative' => array(
|
||||
'input' => array('name' => '@Twig/eror.html.twig'),
|
||||
'output' => <<<TXT
|
||||
|
||||
Matched File
|
||||
------------
|
||||
|
||||
Template name "@Twig/eror.html.twig" not found%A
|
||||
%A
|
||||
%wDid you mean one of these?%A
|
||||
%w@Twig/base.html.twig%A
|
||||
%w@Twig/error.html.twig%A
|
||||
|
||||
Configured Paths
|
||||
----------------
|
||||
|
||||
----------- --------------------------------------
|
||||
Namespace Paths
|
||||
----------- --------------------------------------
|
||||
@Twig templates/bundles/TwigBundle%e%A
|
||||
vendors/twig-bundle/Resources/views%e%A
|
||||
----------- --------------------------------------
|
||||
|
||||
|
||||
TXT
|
||||
,
|
||||
'paths' => $defaultPaths,
|
||||
);
|
||||
}
|
||||
|
||||
private function createCommandTester(array $paths = array()): CommandTester
|
||||
{
|
||||
$projectDir = \dirname(__DIR__).\DIRECTORY_SEPARATOR.'Fixtures';
|
||||
$loader = new FilesystemLoader(array(), $projectDir);
|
||||
foreach ($paths as $path => $namespace) {
|
||||
if (null === $namespace) {
|
||||
$loader->addPath($path);
|
||||
} else {
|
||||
$loader->addPath($path, $namespace);
|
||||
}
|
||||
}
|
||||
$command = new DebugCommand(new Environment($filesystemLoader));
|
||||
|
||||
$application = new Application();
|
||||
$application->add($command);
|
||||
$application->add(new DebugCommand(new Environment($loader), $projectDir));
|
||||
$command = $application->find('debug:twig');
|
||||
|
||||
return new CommandTester($command);
|
||||
|
0
src/Symfony/Bridge/Twig/Tests/Fixtures/vendors/twig-bundle/Resources/views/base.html.twig
vendored
Normal file
0
src/Symfony/Bridge/Twig/Tests/Fixtures/vendors/twig-bundle/Resources/views/base.html.twig
vendored
Normal file
Reference in New Issue
Block a user