function GenerateTheme::execute
Same name in other branches
- 9 core/lib/Drupal/Core/Command/GenerateTheme.php \Drupal\Core\Command\GenerateTheme::execute()
- 10 core/lib/Drupal/Core/Command/GenerateTheme.php \Drupal\Core\Command\GenerateTheme::execute()
File
-
core/
lib/ Drupal/ Core/ Command/ GenerateTheme.php, line 80
Class
- GenerateTheme
- Generates a new theme based on latest default markup.
Namespace
Drupal\Core\CommandCode
protected function execute(InputInterface $input, OutputInterface $output) : int {
$io = new SymfonyStyle($input, $output);
$filesystem = new Filesystem();
$tmpDir = $this->getUniqueTmpDirPath();
$destination_theme = $input->getArgument('machine-name');
$starterkit_id = $input->getOption('starterkit');
$theme_label = $input->getOption('name');
$io->writeln("<info>Generating theme {$theme_label} ({$destination_theme}) from {$starterkit_id} starterkit.</info>");
$destination = trim($input->getOption('path'), '/') . '/' . $destination_theme;
if (is_dir($destination)) {
$io->getErrorStyle()
->error("Theme could not be generated because the destination directory {$destination} exists already.");
return 1;
}
$starterkit = $this->getThemeInfo($starterkit_id);
if ($starterkit === NULL) {
$io->getErrorStyle()
->error("Theme source theme {$starterkit_id} cannot be found.");
return 1;
}
$io->writeln("Trying to parse version for {$starterkit_id} starterkit.", OutputInterface::VERBOSITY_DEBUG);
try {
$starterkit_version = self::getStarterKitVersion($starterkit, $io);
} catch (\Exception $e) {
$io->getErrorStyle()
->error($e->getMessage());
return 1;
}
$io->writeln("Using version {$starterkit_version} for {$starterkit_id} starterkit.", OutputInterface::VERBOSITY_DEBUG);
$io->writeln("Loading starterkit config from {$starterkit_id}.starterkit.yml.", OutputInterface::VERBOSITY_DEBUG);
try {
$starterkit_config = self::loadStarterKitConfig($starterkit, $starterkit_version, $theme_label, $input->getOption('description'));
} catch (\Exception $e) {
$io->getErrorStyle()
->error($e->getMessage());
return 1;
}
$filesystem->mkdir($tmpDir);
$io->writeln("Copying starterkit to temporary directory for processing.", OutputInterface::VERBOSITY_DEBUG);
$mirror_iterator = (new Finder())->in($starterkit->getPath())
->files()
->ignoreDotFiles(FALSE)
->notName($starterkit_config['ignore'])
->notPath($starterkit_config['ignore']);
$filesystem->mirror($starterkit->getPath(), $tmpDir, $mirror_iterator);
$io->writeln("Modifying and renaming files from starterkit.", OutputInterface::VERBOSITY_DEBUG);
$patterns = [
'old' => self::namePatterns($starterkit->getName(), $starterkit->info['name']),
'new' => self::namePatterns($destination_theme, $theme_label),
];
$filesToEdit = self::createFilesFinder($tmpDir)->contains(array_values($patterns['old']))
->notPath($starterkit_config['no_edit']);
foreach ($filesToEdit as $file) {
$contents = file_get_contents($file->getRealPath());
$contents = str_replace($patterns['old'], $patterns['new'], $contents);
file_put_contents($file->getRealPath(), $contents);
}
$filesToRename = self::createFilesFinder($tmpDir)->name(array_map(static fn(string $pattern) => "*{$pattern}*", array_values($patterns['old'])))
->notPath($starterkit_config['no_rename']);
foreach ($filesToRename as $file) {
$filepath_segments = explode('/', $file->getRealPath());
$filename = array_pop($filepath_segments);
$filename = str_replace($patterns['old'], $patterns['new'], $filename);
$filepath_segments[] = $filename;
$filesystem->rename($file->getRealPath(), implode('/', $filepath_segments));
}
$io->writeln("Updating {$destination_theme}.info.yml.", OutputInterface::VERBOSITY_DEBUG);
$info_file = "{$tmpDir}/{$destination_theme}.info.yml";
$info = Yaml::decode(file_get_contents($info_file));
$info = array_filter(array_merge($info, $starterkit_config['info']), static fn(mixed $value) => $value !== NULL);
// Ensure the generated theme is not hidden.
unset($info['hidden']);
file_put_contents($info_file, Yaml::encode($info));
$loader = new ClassLoader();
$loader->addPsr4("Drupal\\{$starterkit->getName()}\\", "{$starterkit->getPath()}/src");
$loader->register();
$generator_classname = "Drupal\\{$starterkit->getName()}\\StarterKit";
if (class_exists($generator_classname)) {
if (is_a($generator_classname, StarterKitInterface::class, TRUE)) {
$io->writeln("Running post processing.", OutputInterface::VERBOSITY_DEBUG);
$generator_classname::postProcess($tmpDir, $destination_theme, $theme_label);
}
else {
$io->getErrorStyle()
->error("The {$generator_classname} does not implement \\Drupal\\Core\\Theme\\StarterKitInterface and cannot perform post-processing.");
return 1;
}
}
else {
$io->writeln("Skipping post processing, {$generator_classname} not defined.", OutputInterface::VERBOSITY_DEBUG);
}
// Move altered theme to final destination.
$io->writeln("Copying {$destination_theme} to {$destination}.", OutputInterface::VERBOSITY_DEBUG);
$filesystem->mirror($tmpDir, $destination);
$io->writeln(sprintf('Theme generated successfully to %s', $destination));
return 0;
}
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.