Fix DebugCommand when chain loader is involved

This commit is contained in:
Yonel Ceruto 2019-03-04 07:20:52 -05:00
parent 675c45850c
commit f647b4a29d
3 changed files with 77 additions and 35 deletions

View File

@ -20,6 +20,7 @@ use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Finder\Finder;
use Twig\Environment;
use Twig\Loader\ChainLoader;
use Twig\Loader\FilesystemLoader;
/**
@ -36,6 +37,7 @@ class DebugCommand extends Command
private $bundlesMetadata;
private $twigDefaultPath;
private $rootDir;
private $filesystemLoaders;
public function __construct(Environment $twig, string $projectDir = null, array $bundlesMetadata = [], string $twigDefaultPath = null, string $rootDir = null)
{
@ -87,7 +89,7 @@ EOF
$name = $input->getArgument('name');
$filter = $input->getOption('filter');
if (null !== $name && !$this->twig->getLoader() instanceof FilesystemLoader) {
if (null !== $name && [] === $this->getFilesystemLoaders()) {
throw new InvalidArgumentException(sprintf('Argument "name" not supported, it requires the Twig loader "%s"', FilesystemLoader::class));
}
@ -150,9 +152,11 @@ EOF
$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;
foreach ($this->getFilesystemLoaders() as $loader) {
$namespaces = $loader->getNamespaces();
foreach ($this->findAlternatives($namespace, $namespaces) as $namespace) {
$alternatives[] = '@'.$namespace;
}
}
}
@ -243,25 +247,25 @@ EOF
private function getLoaderPaths(string $name = null): array
{
/** @var FilesystemLoader $loader */
$loader = $this->twig->getLoader();
$loaderPaths = [];
$namespaces = $loader->getNamespaces();
if (null !== $name) {
$namespace = $this->parseTemplateName($name)[0];
$namespaces = array_intersect([$namespace], $namespaces);
}
foreach ($namespaces as $namespace) {
$paths = array_map([$this, 'getRelativePath'], $loader->getPaths($namespace));
if (FilesystemLoader::MAIN_NAMESPACE === $namespace) {
$namespace = '(None)';
} else {
$namespace = '@'.$namespace;
foreach ($this->getFilesystemLoaders() as $loader) {
$namespaces = $loader->getNamespaces();
if (null !== $name) {
$namespace = $this->parseTemplateName($name)[0];
$namespaces = array_intersect([$namespace], $namespaces);
}
$loaderPaths[$namespace] = $paths;
foreach ($namespaces as $namespace) {
$paths = array_map([$this, 'getRelativePath'], $loader->getPaths($namespace));
if (FilesystemLoader::MAIN_NAMESPACE === $namespace) {
$namespace = '(None)';
} else {
$namespace = '@'.$namespace;
}
$loaderPaths[$namespace] = $paths;
}
}
return $loaderPaths;
@ -437,22 +441,22 @@ EOF
private function findTemplateFiles(string $name): array
{
/** @var FilesystemLoader $loader */
$loader = $this->twig->getLoader();
$files = [];
list($namespace, $shortname) = $this->parseTemplateName($name);
foreach ($loader->getPaths($namespace) as $path) {
if (!$this->isAbsolutePath($path)) {
$path = $this->projectDir.'/'.$path;
}
$filename = $path.'/'.$shortname;
$files = [];
foreach ($this->getFilesystemLoaders() as $loader) {
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);
if (is_file($filename)) {
if (false !== $realpath = realpath($filename)) {
$files[] = $this->getRelativePath($realpath);
} else {
$files[] = $this->getRelativePath($filename);
}
}
}
}
@ -535,4 +539,28 @@ EOF
{
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);
}
/**
* @return FilesystemLoader[]
*/
private function getFilesystemLoaders(): array
{
if (null !== $this->filesystemLoaders) {
return $this->filesystemLoaders;
}
$this->filesystemLoaders = [];
$loader = $this->twig->getLoader();
if ($loader instanceof FilesystemLoader) {
$this->filesystemLoaders[] = $loader;
} elseif ($loader instanceof ChainLoader) {
foreach ($loader->getLoaders() as $l) {
if ($l instanceof FilesystemLoader) {
$this->filesystemLoaders[] = $l;
}
}
}
return $this->filesystemLoaders;
}
}

View File

@ -16,6 +16,7 @@ use Symfony\Bridge\Twig\Command\DebugCommand;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;
use Twig\Environment;
use Twig\Loader\ChainLoader;
use Twig\Loader\FilesystemLoader;
class DebugCommandTest extends TestCase
@ -279,7 +280,16 @@ TXT
];
}
private function createCommandTester(array $paths = [], array $bundleMetadata = [], string $defaultPath = null, string $rootDir = null): CommandTester
public function testDebugTemplateNameWithChainLoader()
{
$tester = $this->createCommandTester(['templates/' => null], [], null, null, true);
$ret = $tester->execute(['name' => 'base.html.twig'], ['decorated' => false]);
$this->assertEquals(0, $ret, 'Returns 0 in case of success');
$this->assertContains('[OK]', $tester->getDisplay());
}
private function createCommandTester(array $paths = [], array $bundleMetadata = [], string $defaultPath = null, string $rootDir = null, bool $useChainLoader = false): CommandTester
{
$projectDir = \dirname(__DIR__).\DIRECTORY_SEPARATOR.'Fixtures';
$loader = new FilesystemLoader([], $projectDir);
@ -291,6 +301,10 @@ TXT
}
}
if ($useChainLoader) {
$loader = new ChainLoader([$loader]);
}
$application = new Application();
$application->add(new DebugCommand(new Environment($loader), $projectDir, $bundleMetadata, $defaultPath, $rootDir));
$command = $application->find('debug:twig');

View File

@ -18,7 +18,7 @@
"require": {
"php": "^7.1.3",
"symfony/contracts": "^1.0.2",
"twig/twig": "^1.37.1|^2.6.2"
"twig/twig": "^1.38.1|^2.7.1"
},
"require-dev": {
"symfony/asset": "~3.4|~4.0",