3 namespace Drush\Drupal\Commands\core;
5 use Consolidation\OutputFormatters\StructuredData\RowsOfFields;
6 use Drupal\Core\PhpStorage\PhpStorageFactory;
7 use Drupal\Core\Template\TwigEnvironment;
8 use Drush\Commands\DrushCommands;
9 use Drupal\Core\Extension\ModuleHandlerInterface;
11 use Drush\Utils\StringUtils;
12 use Symfony\Component\Finder\Finder;
13 use Webmozart\PathUtil\Path;
15 class TwigCommands extends DrushCommands
18 * @var \Drupal\Core\Template\TwigEnvironment
23 * @var \Drupal\Core\Extension\ModuleHandlerInterface
25 protected $moduleHandler;
28 * @return \Drupal\Core\Template\TwigEnvironment
30 public function getTwig()
36 * @return \Drupal\Core\Extension\ModuleHandlerInterface
38 public function getModuleHandler()
40 return $this->moduleHandler;
44 * @param \Drupal\Core\Template\TwigEnvironment $twig
45 * @param ModuleHandlerInterface $moduleHandler
47 public function __construct(TwigEnvironment $twig, ModuleHandlerInterface $moduleHandler)
50 $this->moduleHandler = $moduleHandler;
54 * Find potentially unused Twig templates.
56 * Immediately before running this command, crawl your entire web site. Or
57 * use your Production PHPStorage dir for comparison.
59 * @param $searchpaths A comma delimited list of paths to recursively search
60 * @usage drush twig:unused --field=template /var/www/mass.local/docroot/modules/custom,/var/www/mass.local/docroot/themes/custom
61 * Output a simple list of potentially unused templates.
62 * @table-style default
66 * @default-fields template,compiled
67 * @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
69 * @command twig:unused
71 public function unused($searchpaths)
74 $phpstorage = PhpStorageFactory::get('twig');
76 // Find all templates in the codebase.
77 $files = Finder::create()
81 ->in(StringUtils::csvToArray($searchpaths));
82 $this->logger()->notice(dt('Found !count templates', ['!count' => count($files)]));
84 // Check to see if a compiled equivalent exists in PHPStorage
85 foreach ($files as $file) {
86 $relative = Path::makeRelative($file->getRealPath(), Drush::bootstrapManager()->getRoot());
87 $mainCls = $this->getTwig()->getTemplateClass($relative);
88 $key = $this->getTwig()->getCache()->generateKey($relative, $mainCls);
89 if (!$phpstorage->exists($key)) {
91 'template' => $relative,
96 $this->logger()->notice(dt('Found !count unused', ['!count' => count($unused)]));
97 return new RowsOfFields($unused);
101 * Compile all Twig template(s).
103 * @command twig:compile
104 * @aliases twigc,twig-compile
106 public function twigCompile()
108 require_once DRUSH_DRUPAL_CORE . "/themes/engines/twig/twig.engine";
109 // Scan all enabled modules and themes.
110 $modules = array_keys($this->getModuleHandler()->getModuleList());
111 foreach ($modules as $module) {
112 $searchpaths[] = drupal_get_path('module', $module);
115 $themes = \Drupal::service('theme_handler')->listInfo();
116 foreach ($themes as $name => $theme) {
117 $searchpaths[] = $theme->getPath();
120 $files = Finder::create()
122 ->name('*.html.twig')
125 foreach ($files as $file) {
126 $relative = Path::makeRelative($file->getRealPath(), Drush::bootstrapManager()->getRoot());
127 // @todo Dynamically disable twig debugging since there is no good info there anyway.
128 twig_render_template($relative, ['theme_hook_original' => '']);
129 $this->logger()->success(dt('Compiled twig template !path', ['!path' => $relative]));