BuildSettingsCommand.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. <?php
  2. declare(strict_types = 1);
  3. namespace Fgm\Drupal\Composer;
  4. use Symfony\Component\Console\Input\InputArgument;
  5. use Symfony\Component\Console\Input\InputDefinition;
  6. use Symfony\Component\Console\Input\InputInterface;
  7. use Symfony\Component\Console\Output\OutputInterface;
  8. use Symfony\Component\Yaml\Exception\ParseException;
  9. use Symfony\Component\Yaml\Yaml;
  10. use Twig\Environment;
  11. use Twig\Extension\DebugExtension;
  12. use Twig\Loader\FilesystemLoader;
  13. use Twig\TemplateWrapper;
  14. class BuildSettingsCommand extends BaseBuilderCommand
  15. {
  16. /**
  17. * The name of the argument defining the file to generate.
  18. */
  19. const ARG_FILE = 'file';
  20. /**
  21. * @var string
  22. */
  23. protected $eventName;
  24. /**
  25. * {@inheritDoc}
  26. */
  27. public function configure()
  28. {
  29. parent::configure();
  30. $this->eventName = $this->getName();
  31. $this
  32. ->setName('build:settings')
  33. ->setDescription('Builds the *.settings.local.php files.')
  34. ->setDefinition(
  35. new InputDefinition([
  36. new InputArgument(static::ARG_FILE, InputArgument::OPTIONAL),
  37. ])
  38. )
  39. ->setHelp(
  40. <<<EOT
  41. The build:settings command combines shared and per-environment parameters and passes
  42. them to the settings.local.php.twig template to build the settings/(build|run).settings.local.php files.
  43. EOT
  44. );
  45. }
  46. /**
  47. * {@inheritDoc}
  48. */
  49. public function execute(InputInterface $input, OutputInterface $output)
  50. {
  51. $file = $input->getArgument(static::ARG_FILE);
  52. $conf = $this->getBuilderConfig();
  53. $templateName = $conf['templates'][$file] ?? '';
  54. if (empty($templateName)) {
  55. $output->writeln(sprintf(
  56. 'Could not build file %s: no such template in composer.json extra section',
  57. $file
  58. ));
  59. return 1;
  60. }
  61. $settingsPath = $this->getSettingsPath();
  62. $templatePath = "${settingsPath}/${templateName}";
  63. $realTemplatePath = realpath($templatePath);
  64. if (empty($realTemplatePath)) {
  65. $output->writeln(sprintf("Could not load template %s: no such file", $templateName));
  66. return 2;
  67. }
  68. $paramsPath = "${settingsPath}/merged.params.local.yml";
  69. $realParamsPath = realpath($paramsPath);
  70. if (empty($realTemplatePath)) {
  71. $output->writeln(sprintf("Could not load parameters %s: no such file", $paramsPath));
  72. return 3;
  73. }
  74. $yaml = new Yaml();
  75. try {
  76. $params = $yaml->parseFile($realParamsPath);
  77. } catch (ParseException $e) {
  78. $output->writeln(sprintf("Could not parse %s: %s", $realParamsPath, $e->getMessage()));
  79. return 4;
  80. }
  81. $loader = new FilesystemLoader($settingsPath, $settingsPath);
  82. $twig = new Environment($loader, [
  83. 'auto_reload' => true,
  84. 'cache' => false,
  85. 'debug' => true,
  86. 'strict_variables' => true,
  87. ]);
  88. $twig->addExtension(new DebugExtension());
  89. $wrapper = $twig->load($templateName);
  90. foreach ($params['sites'] as $name => $siteParams) {
  91. foreach (['build', 'run'] as $stage) {
  92. $context = [
  93. 'instance' => $params['instance'],
  94. 'name' => $name,
  95. 'stage' => $stage,
  96. 'site' => $siteParams,
  97. ];
  98. $error = $this->render($wrapper, $context, $output);
  99. if ($error) {
  100. $output->writeln(sprintf("Failed rendering %s settings for site %s", $stage, $name));
  101. return 5;
  102. }
  103. }
  104. }
  105. }
  106. protected function render(TemplateWrapper $wrapper, array $context, OutputInterface $output): int
  107. {
  108. $settingsPath = "web/sites/${context['name']}/${context['stage']}.settings.local.php";
  109. if (file_exists($settingsPath)) {
  110. $ok = unlink($settingsPath);
  111. if (!$ok) {
  112. $output->writeln(sprintf(
  113. "Could not remove old %s file",
  114. $settingsPath
  115. ));
  116. return 1;
  117. }
  118. }
  119. $rendered = $wrapper->render($context);
  120. $ok = file_put_contents($settingsPath, $rendered, LOCK_EX);
  121. if (!$ok) {
  122. $output->writeln(sprintf('Could not write new %s file', $settingsPath));
  123. return 2;
  124. }
  125. return 0;
  126. }
  127. }