| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 | <?phpdeclare(strict_types = 1);namespace Fgm\Drupal\Composer;use Drupal\Component\Utility\NestedArray;use Symfony\Component\Console\Input\InputArgument;use Symfony\Component\Console\Input\InputDefinition;use Symfony\Component\Console\Input\InputInterface;use Symfony\Component\Console\Output\OutputInterface;use Symfony\Component\Yaml\Exception\ParseException;use Symfony\Component\Yaml\Yaml;use Twig\Environment;use Twig\Extension\DebugExtension;use Twig\Loader\FilesystemLoader;use Twig\TemplateWrapper;class BuildSettingsCommand extends BaseBuilderCommand{    /**     * The name of the argument defining the file to generate.     */    const ARG_FILE = 'file';    /**     * @var string     */    protected $eventName;    /**     * {@inheritDoc}     */    public function configure()    {        parent::configure();        $this->eventName = $this->getName();        $this            ->setName('build:settings')            ->setDescription('Builds the *.settings.local.php files.')            ->setDefinition(                new InputDefinition([                new InputArgument(static::ARG_FILE, InputArgument::OPTIONAL),                ])            )            ->setHelp(                <<<EOTThe build:settings command combines shared and per-environment parameters and passesthem to the settings.local.php.twig template to build the settings/(build|run).settings.local.php files.EOT            );    }    /**     * {@inheritDoc}     */    public function execute(InputInterface $input, OutputInterface $output)    {        [$templateName, $err] = $this->validateTemplateName($input, $output);        if ($err) {          return 1;        };        $settingsPath = $this->getSettingsPath();        $templatePath = "${settingsPath}/${templateName}";        $realTemplatePath = realpath($templatePath);        if (empty($realTemplatePath)) {            $output->writeln(sprintf("Could not load template %s: no such file", $templateName));            return 2;        }        $paramsPath = "${settingsPath}/merged.params.local.yml";        $realParamsPath = realpath($paramsPath);        if (empty($realTemplatePath)) {            $output->writeln(sprintf("Could not load parameters %s: no such file", $paramsPath));            return 3;        }        $yaml = new Yaml();        try {            $params = $yaml->parseFile($realParamsPath);        } catch (ParseException $e) {            $output->writeln(sprintf("Could not parse %s: %s", $realParamsPath, $e->getMessage()));            return 4;        }        $loader = new FilesystemLoader($settingsPath, $settingsPath);        $twig = new Environment($loader, [          'auto_reload' => true,          'cache' => false,          'debug' => true,          'strict_variables' => true,        ]);        $twig->addExtension(new DebugExtension());        $wrapper = $twig->load($templateName);        foreach ($params['sites'] as $name => $siteParams) {            foreach (['build', 'run'] as $stage) {                $stageSettings = NestedArray::mergeDeepArray([                  $siteParams['settings']['both'] ?? [],                  $siteParams['settings'][$stage] ?? []                ], true);                $stageParams = $siteParams;                $stageParams['settings'] = $stageSettings;                $context = [                  'instance' => $params['instance'],                  'name' => $name,                  'stage' => $stage,                  'site' => $stageParams,                ];                $error = $this->render($wrapper, $context, $output);                if ($error) {                    $output->writeln(sprintf("Failed rendering %s settings for site %s", $stage, $name));                    return 5;                }            }        }    }    protected function render(TemplateWrapper $wrapper, array $context, OutputInterface $output): int    {        $settingsPath = "web/sites/${context['name']}/${context['stage']}.settings.local.php";        if (file_exists($settingsPath)) {            $ok = unlink($settingsPath);            if (!$ok) {                $output->writeln(sprintf(                    "Could not remove old %s file",                    $settingsPath                ));                return 1;            }        }        $rendered = $wrapper->render($context);        $ok = file_put_contents($settingsPath, $rendered, LOCK_EX);        if (!$ok) {            $output->writeln(sprintf('Could not write new %s file', $settingsPath));            return 2;        }        return 0;    }  /**   * @param \Symfony\Component\Console\Input\InputInterface $input   * @param \Symfony\Component\Console\Output\OutputInterface $output   *   * @return array   *   - string Template name   *   - int Error   */  protected function validateTemplateName(InputInterface $input, OutputInterface $output): array {    $file = $input->getArgument(static::ARG_FILE);    $conf = $this->getBuilderConfig();    $templateName = $conf['templates'][$file] ?? '';    if (empty($templateName)) {      $output->writeln(sprintf(        'Could not build file %s: no such template in composer.json extra section',        $file      ));      return ["", 1];    }    return [$templateName, 0];  }}
 |