123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- <?php
- declare(strict_types = 1);
- namespace Fgm\Drupal\Composer;
- use Symfony\Component\Console\Input\InputInterface;
- use Symfony\Component\Console\Output\OutputInterface;
- use Symfony\Component\Yaml\Yaml;
- /**
- * Merge params.local.yml into dist.params.local.yml.
- *
- * The former overrides the latter.
- *
- * @package Fgm\Drupal\Composer
- */
- class MergeParamsCommand extends BaseBuilderCommand {
- const DEFAULT_SITE = '_default';
- /**
- * The event triggering this command.
- *
- * @var string
- */
- protected $eventName;
- /**
- * Configures the current command.
- */
- public function configure() {
- parent::configure();
- $this->eventName = $this->getName();
- $this
- ->setName('build:merge_params')
- ->setDescription('Step 1: merges the params.local.yml with dist.params.local.yml.')
- ->setDefinition([])
- ->setHelp(
- <<<EOT
- Step 1 of a build, the build:merge_params command combines shared and per-environment
- parameters and generates merged.params.local.yml containing the merged result.
- EOT
- );
- }
- /**
- * Perform merging.
- *
- * @param array $dist
- * Distribution parameters (default).
- * @param array $local
- * Local parameters (overrides).
- *
- * @return array
- * The merge result.
- */
- protected function merge(array $dist, array $local): array {
- if (empty($local)) {
- return $dist;
- }
- // Merge local into defaults.
- $merged = static::mergeDeepArray([$dist, $local], TRUE);
- // Generate per-site data from settings/_default.
- $default = $merged['sites'][static::DEFAULT_SITE] ?? [];
- $sites = array_diff_key($merged['sites'], [static::DEFAULT_SITE => NULL]);
- $merged['sites'] = [];
- foreach ($sites as $name => $params) {
- $merged['sites'][$name] = static::mergeDeepArray([$default, $params]);
- }
- return $merged;
- }
- /**
- * Executes the current command.
- *
- * {@inheritDoc}
- */
- public function execute(InputInterface $input, OutputInterface $output) {
- $settingsPath = $this->getSettingsPath();
- $yaml = new Yaml();
- // Load defaults.
- $defaultsPath = "${settingsPath}/dist.params.local.yml";
- $realDefaultsPath = realpath($defaultsPath);
- if (empty($realDefaultsPath)) {
- $output->writeln("Failed to open $defaultsPath");
- return 1;
- }
- $defaults = $yaml->parseFile($realDefaultsPath);
- // Load local.
- $localPath = "${settingsPath}/params.local.yml";
- $realLocalPath = realpath($localPath);
- if (empty($realLocalPath)) {
- if ($output->isVerbose()) {
- $output->writeln("File $localPath not found, using only defaults");
- }
- $local = [];
- }
- else {
- $local = $yaml->parseFile($realLocalPath);
- }
- // Merge.
- $merged = $this->merge($defaults, $local);
- // Write.
- $ok = file_put_contents("${settingsPath}/merged.params.local.yml",
- $yaml->dump($merged, 10, 2));
- if (!$ok) {
- $output->writeln("Failed to write merged params.");
- return 2;
- }
- }
- /**
- * Merges multiple arrays, recursively, and returns the merged array.
- *
- * Only keyed arrays are merged recursivelly, indexed arrays are not merged :
- * the deepest array replace the less deep array.
- *
- * @param array $arrays
- * An arrays of arrays to merge.
- *
- * @return array
- * The merged array.
- *
- * @see NestedArray::mergeDeep()
- */
- public static function mergeDeepArray(array $arrays) {
- $result = [];
- foreach ($arrays as $array) {
- foreach ($array as $key => $value) {
- // Remove keys having NULL value to allow deletion of key previously
- // defined.
- if ($value === NULL) {
- unset($result[$key]);
- continue;
- }
- // Renumber integer keys as array_merge_recursive() does. Note that
- // PHP automatically converts array keys that are integer strings
- // (e.g., '1') to integers.
- if (is_int($key)) {
- // When an indexed array is overrided, the new values replace
- // all overrided values (no merge).
- if ($key === 0) {
- $result = [];
- }
- $result[] = $value;
- }
- // Recurse when both values are arrays.
- elseif (isset($result[$key]) && is_array($result[$key]) && is_array($value)) {
- $result[$key] = static::mergeDeepArray([$result[$key], $value]);
- }
- // Otherwise, use the latter value, overriding any previous value.
- else {
- $result[$key] = $value;
- }
- }
- }
- return $result;
- }
- }
|