/
home
/
obinna
/
html
/
restaurants
/
vendor
/
symfony
/
flex
/
src
/
Configurator
/
Upload File
HOME
<?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Flex\Configurator; use Composer\Composer; use Composer\IO\IOInterface; use Symfony\Component\Filesystem\Filesystem; use Symfony\Flex\Lock; use Symfony\Flex\Options; use Symfony\Flex\Recipe; /** * Adds services and volumes to docker-compose.yml file. * * @author Kévin Dunglas <dunglas@gmail.com> */ class DockerComposeConfigurator extends AbstractConfigurator { private $filesystem; public function __construct(Composer $composer, IOInterface $io, Options $options) { parent::__construct($composer, $io, $options); $this->filesystem = new Filesystem(); } public function configure(Recipe $recipe, $config, Lock $lock, array $options = []) { $installDocker = $this->composer->getPackage()->getExtra()['symfony']['docker'] ?? false; if (!$installDocker) { return; } $rootDir = $this->options->get('root-dir'); foreach ($this->normalizeConfig($config) as $file => $extra) { if ( (null === $dockerComposeFile = $this->findDockerComposeFile($rootDir, $file)) || $this->isFileMarked($recipe, $dockerComposeFile) ) { continue; } $this->write(sprintf('Adding Docker Compose definitions to "%s"', $dockerComposeFile)); $offset = 8; $node = null; $endAt = []; $lines = []; foreach (file($dockerComposeFile) as $i => $line) { $lines[] = $line; $ltrimedLine = ltrim($line, ' '); // Skip blank lines and comments if (('' !== $ltrimedLine && 0 === strpos($ltrimedLine, '#')) || '' === trim($line)) { continue; } // Extract Docker Compose keys (usually "services" and "volumes") if (!preg_match('/^[\'"]?([a-zA-Z0-9]+)[\'"]?:\s*$/', $line, $matches)) { // Detect indentation to use $offestLine = \strlen($line) - \strlen($ltrimedLine); if ($offset > $offestLine && 0 !== $offestLine) { $offset = $offestLine; } continue; } // Keep end in memory (check break line on previous line) $endAt[$node] = '' !== trim($lines[$i - 1]) ? $i : $i - 1; $node = $matches[1]; } $endAt[$node] = \count($lines) + 1; foreach ($extra as $key => $value) { if (isset($endAt[$key])) { array_splice($lines, $endAt[$key], 0, $this->markData($recipe, $this->parse(1, $offset, $value))); continue; } $lines[] = sprintf("\n%s:", $key); $lines[] = $this->markData($recipe, $this->parse(1, $offset, $value)); } file_put_contents($dockerComposeFile, implode('', $lines)); } $this->write('Docker Compose definitions have been modified. Please run "docker-compose up --build" again to apply the changes.'); } public function unconfigure(Recipe $recipe, $config, Lock $lock) { $rootDir = $this->options->get('root-dir'); foreach ($this->normalizeConfig($config) as $file => $extra) { if (null === $dockerComposeFile = $this->findDockerComposeFile($rootDir, $file)) { continue; } $name = $recipe->getName(); // Remove recipe and add break line $contents = preg_replace(sprintf('{%s+###> %s ###.*?###< %s ###%s+}s', "\n", $name, $name, "\n"), \PHP_EOL.\PHP_EOL, file_get_contents($dockerComposeFile), -1, $count); if (!$count) { return; } foreach ($extra as $key => $value) { if (0 === preg_match(sprintf('{^%s:[ \t\r\n]*([ \t]+\w|#)}m', $key), $contents, $matches)) { $contents = preg_replace(sprintf('{\n?^%s:[ \t\r\n]*}sm', $key), '', $contents, -1, $count); } } $this->write(sprintf('Removing Docker Compose entries from "%s"', $dockerComposeFile)); file_put_contents($dockerComposeFile, ltrim($contents, "\n")); } $this->write('Docker Compose definitions have been modified. Please run "docker-compose up" again to apply the changes.'); } /** * Normalizes the config and return the name of the main Docker Compose file if applicable. */ private function normalizeConfig(array $config): array { foreach ($config as $val) { // Support for the short syntax recipe syntax that modifies docker-compose.yml only return isset($val[0]) ? ['docker-compose.yml' => $config] : $config; } return $config; } /** * Finds the Docker Compose file according to these rules: https://docs.docker.com/compose/reference/envvars/#compose_file. */ private function findDockerComposeFile(string $rootDir, string $file): ?string { if (isset($_SERVER['COMPOSE_FILE'])) { $separator = $_SERVER['COMPOSE_PATH_SEPARATOR'] ?? ('\\' === \DIRECTORY_SEPARATOR ? ';' : ':'); $files = explode($separator, $_SERVER['COMPOSE_FILE']); foreach ($files as $f) { if ($file !== basename($f)) { continue; } if (!$this->filesystem->isAbsolutePath($f)) { $f = realpath(sprintf('%s/%s', $rootDir, $f)); } if ($this->filesystem->exists($f)) { return $f; } } } // COMPOSE_FILE not set, or doesn't contain the file we're looking for $dir = $rootDir; $previousDir = null; do { // Test with the ".yaml" extension if the file doesn't end up with ".yml". if ( $this->filesystem->exists($dockerComposeFile = sprintf('%s/%s', $dir, $file)) || $this->filesystem->exists($dockerComposeFile = substr($dockerComposeFile, 0, -2).'aml') ) { return $dockerComposeFile; } $previousDir = $dir; $dir = \dirname($dir); } while ($dir !== $previousDir); return null; } private function parse($level, $indent, $services): string { $line = ''; foreach ($services as $key => $value) { $line .= str_repeat(' ', $indent * $level); if (!\is_array($value)) { if (\is_string($key)) { $line .= sprintf('%s:', $key); } $line .= sprintf("%s\n", $value); continue; } $line .= sprintf("%s:\n", $key).$this->parse($level + 1, $indent, $value); } return $line; } }