ide-twig.json
landsman opened this issue · 1 comments
landsman commented
Hi, can you please help me with correct syntax of this file?
I don't get it from an example.
I have this folder structure:
src/Modules/Warehouse/Stocktaking/View/index.html.twig
Which is working just fine in terms of configuration of the project. So I want to resolve IntelliJ highlighter and code, file navigation. From what I saw I can define my aliases with paths and IDE should pick it up automatically without any custom settings, is that right?
Is this syntax correct?
This is my generated file:
{
"namespaces": [
{
"namespace": "@Warehouse",
"path": "%kernel.project_dir%/src/Modules/Warehouse"
},
{
"namespace": "@Warehouse/Stocktaking",
"path": "%kernel.project_dir%/src/Modules/Warehouse/Stocktaking"
},
{
"namespace": "@Warehouse/Stocktaking/Crud",
"path": "%kernel.project_dir%/src/Modules/Warehouse/Stocktaking/Crud"
},
{
"namespace": "@Warehouse/Stocktaking/Crud/View",
"path": "%kernel.project_dir%/src/Modules/Warehouse/Stocktaking/Crud/View"
}
]
}
Problem:
landsman commented
So backslashes was a problem I see.
This is working:
{
"namespaces": [
{
"namespace": "Warehouse_Stocktaking_Crud_View",
"path": "/src/Modules/Warehouse/Stocktaking/Crud/View"
}
]
}
Usage:
/**
* @Route("/", name="warehouse_stocktaking_index", methods={"GET"})
*/
public function index(): Response
{
return $this->render('@Warehouse_Stocktaking_Crud_View/index.html.twig', [
'who' => 'world',
]);
}
Here is the code for automatic generation:
<?php
namespace App\Service;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpKernel\KernelInterface;
use Twig\Environment;
use Twig\Loader\FilesystemLoader;
/**
* Loads Twig paths for our custom modules.
*/
class TwigDynamicPathLoader
{
private ParameterBagInterface $parameterBag;
private Environment $twig;
private KernelInterface $kernel;
private bool $pathsLoaded = false;
public function __construct(ParameterBagInterface $parameterBag, Environment $twig, KernelInterface $kernel)
{
$this->parameterBag = $parameterBag;
$this->twig = $twig;
$this->kernel = $kernel;
}
public function loadPaths(): void
{
if ($this->pathsLoaded) {
return;
}
$modulesDir = $this->parameterBag->get('kernel.project_dir') . '/src/Modules';
$loader = $this->twig->getLoader();
if (!$loader instanceof FilesystemLoader) {
throw new \LogicException('Twig loader is not an instance of FilesystemLoader.');
}
$directoryIterator = new \RecursiveDirectoryIterator($modulesDir, \FilesystemIterator::SKIP_DOTS);
$iterator = new \RecursiveIteratorIterator($directoryIterator, \RecursiveIteratorIterator::SELF_FIRST);
// log
$pathsAdded = [];
foreach ($iterator as $file) {
if ($file->isDir()) {
$path = $file->getPathname();
$relativePath = str_replace($modulesDir . DIRECTORY_SEPARATOR, '', $path);
// usage of the alias
$alias = str_replace('/', '_', $relativePath);
// Check for .twig files in the directory
$hasTwigFiles = false;
$files = new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS);
foreach ($files as $fileInfo) {
if ($fileInfo->isFile() && 'twig' === $fileInfo->getExtension()) {
$hasTwigFiles = true;
break;
}
}
if ($hasTwigFiles) {
$loader->addPath($path, $alias);
$relativeProjectPath = str_replace($this->parameterBag->get('kernel.project_dir'), '', $path);
$pathsAdded[] = [
'namespace' => $alias,
'path' => $relativeProjectPath,
];
}
}
}
$this->pathsLoaded = true;
// Run this code only in the dev environment
if ('dev' === $this->kernel->getEnvironment()) {
// Final dump of paths added with a label
dump(['label' => 'Twig Paths from Modules', 'data' => $pathsAdded]);
// Generate JSON for IDE
$this->generateJsonForIde($pathsAdded);
}
}
/**
* Generate a JSON file to help the IDE recognize Twig namespaces.
*/
private function generateJsonForIde(array $paths): void
{
$jsonFile = $this->parameterBag->get('kernel.project_dir') . '/ide-twig.json';
$jsonContent = [
'namespaces' => $paths,
];
file_put_contents($jsonFile, json_encode($jsonContent, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
}
}