X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs-website;a=blobdiff_plain;f=vendor%2Fdrupal%2Fconsole-core%2Fsrc%2FUtils%2FChainDiscovery.php;fp=vendor%2Fdrupal%2Fconsole-core%2Fsrc%2FUtils%2FChainDiscovery.php;h=6116474d85744b0ca0640da9d9b557f94922f538;hp=306fb45382cb31708c4ba4517ac74f7b3f87d127;hb=9917807b03b64faf00f6a1f29dcb6eafc454efa5;hpb=aea91e65e895364e460983b890e295aa5d5540a5 diff --git a/vendor/drupal/console-core/src/Utils/ChainDiscovery.php b/vendor/drupal/console-core/src/Utils/ChainDiscovery.php index 306fb4538..6116474d8 100644 --- a/vendor/drupal/console-core/src/Utils/ChainDiscovery.php +++ b/vendor/drupal/console-core/src/Utils/ChainDiscovery.php @@ -16,41 +16,89 @@ use Symfony\Component\Yaml\Yaml; */ class ChainDiscovery { + /** + * @var string + */ + protected $appRoot; + /** * @var ConfigurationManager */ protected $configurationManager; /** - * @var string + * @var MessageManager */ - protected $appRoot; + protected $messageManager; + + /** + * @var TranslatorManagerInterface + */ + protected $translatorManager; /** * @var array */ private $directories = []; + /** + * @var array + */ + private $files = []; + + /** + * @var array + */ + private $filesPerDirectory = []; + + const INLINE_REGEX = '/{{(.*?)}}/'; + const ENV_REGEX = '/%env\((.*?)\)%/'; + + /** + * @var array + */ + private $inlineRegexLegacy = [ + '/%{{(.*?)}}/', + '/%{{ (.*?) }}/', + ]; + + /** + * @var array + */ + private $envRegexLegacy = [ + '/\${{(.*?)}}/', + '/\${{ (.*?) }}/', + '/%env\((.*?)\)%/', + '/% env\((.*?)\) %/' + ]; + /** * ChainDiscovery constructor. * - * @param string $appRoot - * @param ConfigurationManager $configurationManager + * @param string $appRoot + * @param ConfigurationManager $configurationManager + * @param MessageManager $messageManager + * @param TranslatorManagerInterface $translatorManager */ public function __construct( $appRoot, - ConfigurationManager $configurationManager + ConfigurationManager $configurationManager, + MessageManager $messageManager, + TranslatorManagerInterface $translatorManager ) { $this->appRoot = $appRoot; $this->configurationManager = $configurationManager; + $this->messageManager = $messageManager; + $this->translatorManager = $translatorManager; - $this->addDirectories( - [ - $this->configurationManager->getHomeDirectory() . DIRECTORY_SEPARATOR . '.console'. DIRECTORY_SEPARATOR .'chain', - $this->appRoot . DIRECTORY_SEPARATOR . 'console'. DIRECTORY_SEPARATOR .'chain', - $this->appRoot . DIRECTORY_SEPARATOR . '.console'. DIRECTORY_SEPARATOR .'chain', - ] + $directories = array_map( + function ($item) { + return $item . 'chain/'; + }, + $configurationManager->getConfigurationDirectories(true) ); + + $this->addDirectories($directories); } /** @@ -62,12 +110,24 @@ class ChainDiscovery } /** - * @param bool $onlyFiles + * @deprecated + * + * @return array + */ + public function getChainFiles() + { + return $this->getFiles(); + } + + /** * @return array */ - public function getChainFiles($onlyFiles = false) + public function getFiles() { - $chainFiles = []; + if ($this->files) { + return $this->files; + } + foreach ($this->directories as $directory) { if (!is_dir($directory)) { continue; @@ -77,23 +137,50 @@ class ChainDiscovery ->name('*.yml') ->in($directory); foreach ($finder as $file) { - $chainFiles[$file->getPath()][] = sprintf( - '%s/%s', - $directory, - $file->getBasename() - ); - } - } - if ($onlyFiles) { - $files = []; - foreach ($chainFiles as $chainDirectory => $chainFileList) { - $files = array_merge($files, $chainFileList); + $filePath = $file->getRealPath(); + if (empty($filePath)) { + $filePath = $directory . $file->getBasename(); + } + + if (!is_file($filePath)) { + continue; + } + $this->files[$filePath] = [ + 'directory' => $directory, + 'file_name' => $file->getBasename(), + 'messages' => [] + ]; + + $this->getFileContents($filePath); + $this->getFileMetadata($filePath); + + if ($this->files[$filePath]['messages']) { + $this->messageManager->comment( + $filePath, + 0, + 'list' + ); + $this->messageManager->listing( + $this->files[$filePath]['messages'], + 0, + 'list' + ); + } + + $this->filesPerDirectory[$directory][] = $file->getBasename(); } - return $files; } - return $chainFiles; + return $this->files; + } + + /** + * @return array + */ + public function getFilesPerDirectory() + { + return $this->filesPerDirectory; } /** @@ -102,26 +189,291 @@ class ChainDiscovery public function getChainCommands() { $chainCommands = []; - $files = $this->getChainFiles(true); + $files = array_keys($this->getFiles()); foreach ($files as $file) { - $chain = Yaml::parse(file_get_contents($file)); - if (!array_key_exists('command', $chain)) { - continue; - } - if (!array_key_exists('name', $chain['command'])) { + $chainMetadata = $this->getFileMetadata($file); + + if (!$chainMetadata) { continue; } - $name = $chain['command']['name']; - $description = ''; - if (array_key_exists('description', $chain['command'])) { - $description = $chain['command']['description']; - } + + $name = $chainMetadata['command']['name']; + $description = $chainMetadata['command']['description']; + $chainCommands[$name] = [ 'description' => $description, 'file' => $file, ]; + + $this->files[$file]['command'] = $name; + $this->files[$file]['description'] = $description; } return $chainCommands; } + + public function parseContent($file, $placeholders) + { + $placeholders = array_filter( + $placeholders, + function ($element) { + return $element !== null; + } + ); + + unset($placeholders['file']); + unset($placeholders['placeholder']); + + $contents = $this->getFileContents($file); + + $loader = new \Twig_Loader_Array( + [ + 'chain' => $contents, + ] + ); + + $twig = new \Twig_Environment($loader); + $envFunction = new \Twig_SimpleFunction( + 'env', + function ($variableName) { + $variableValue = getenv($variableName); + if (!empty($variableValue)) { + return $variableValue; + } + + return '%env('.$variableName.')%'; + } + ); + $twig->addFunction($envFunction); + + $variables = $this->extractInlinePlaceHolderNames($contents); + + foreach ($variables as $variable) { + if (!array_key_exists($variable, $placeholders)) { + $placeholders[$variable] = '{{ ' . $variable . ' }}'; + } + } + + return $twig->render('chain', $placeholders); + } + + public function getFileMetadata($file) + { + if ($metadata = $this->getCacheMetadata($file)) { + return $metadata; + } + + $contents = $this->getFileContents($file); + + $line = strtok($contents, PHP_EOL); + $index = 0; + while ($line !== false) { + $index++; + + if ($index === 1 && $line !== 'command:') { + break; + } + + if ($index > 1 && substr($line, 0, 2) !== " ") { + break; + } + + $metadata .= $line . PHP_EOL; + $line = strtok(PHP_EOL); + } + + $chainMetadata = $this->processMetadata($metadata); + + if (!$chainMetadata) { + $this->files[$file]['messages'][] = $this->translatorManager + ->trans('commands.chain.messages.metadata-registration'); + return []; + } + + $this->files[$file]['metadata'] = $chainMetadata; + + return $chainMetadata; + } + + private function processMetadata($metadata) { + if (!$metadata) { + return []; + } + + $chainMetadata = Yaml::parse($metadata); + + if (!$chainMetadata || !is_array($chainMetadata)) { + return []; + } + + if (!array_key_exists('command', $chainMetadata) || !is_array($chainMetadata['command'])) { + return []; + } + + if (!array_key_exists('name', $chainMetadata['command'])) { + return []; + } + + if (!array_key_exists('description', $chainMetadata['command'])) { + $chainMetadata['command']['description'] = ''; + } + + return $chainMetadata; + } + + /** + * Helper to load and clean up the chain file. + * + * @param string $file The file name + * + * @return string $contents The contents of the file + */ + public function getFileContents($file) + { + if (empty($file)) { + return ''; + } + + if ($contents = $this->getCacheContent($file)) { + return $contents; + } + + $contents = file_get_contents($file); + + // Support BC for legacy inline variables. + $inlineLegacyContent = preg_replace( + $this->inlineRegexLegacy, + '{{ $1 }}', + $contents + ); + + if ($contents !== $inlineLegacyContent) { + $this->files[$file]['messages'][] = $this->translatorManager + ->trans('commands.chain.messages.legacy-inline'); + $contents = $inlineLegacyContent; + } + + // Support BC for legacy environment variables. + $envLegacyContent = preg_replace( + $this->envRegexLegacy, + '{{ env("$1") }}', + $contents + ); + + if ($contents !== $envLegacyContent) { + $this->files[$file]['messages'][] = $this->translatorManager + ->trans('commands.chain.messages.legacy-environment'); + $contents = $envLegacyContent; + } + + // Remove lines with comments. + $contents = preg_replace( + '![ \t]*#.*[ \t]*[\r|\r\n|\n]!', + PHP_EOL, + $contents + ); + + // Strip blank lines + $contents = preg_replace( + "/(^[\r\n]*|[\r\n]+)[\t]*[\r\n]+/", + PHP_EOL, + $contents + ); + + $this->files[$file]['content'] = $contents; + + return $contents; + } + + private function getCacheContent($file) + { + if (!array_key_exists($file, $this->files)) { + return null; + } + + if (!array_key_exists('content', $this->files[$file])) { + return null; + } + + return $this->files[$file]['content']; + } + + private function getCacheMetadata($file) + { + if (!array_key_exists($file, $this->files)) { + return null; + } + + if (!array_key_exists('metadata', $this->files[$file])) { + return null; + } + + return $this->files[$file]['metadata']; + } + + private function extractPlaceHolders( + $chainContent, + $regex + ) { + $placeHoldersExtracted = []; + preg_match_all( + $regex, + $chainContent, + $placeHoldersExtracted + ); + + if (!$placeHoldersExtracted) { + return []; + } + + return array_unique($placeHoldersExtracted[1]); + } + + public function extractInlinePlaceHolderNames($content) + { + preg_match_all($this::INLINE_REGEX, $content, $matches); + + return array_map( + function ($item) { + return trim($item); + }, + $matches[1] + ); + } + + public function extractInlinePlaceHolders($chainContent) + { + $extractedInlinePlaceHolders = $this->extractPlaceHolders( + $chainContent, + $this::INLINE_REGEX + ); + $extractedVars = $this->extractVars($chainContent); + + $inlinePlaceHolders = []; + foreach ($extractedInlinePlaceHolders as $key => $inlinePlaceHolder) { + $inlinePlaceHolder = trim($inlinePlaceHolder); + $placeholderValue = null; + if (array_key_exists($inlinePlaceHolder, $extractedVars)) { + $placeholderValue = $extractedVars[$inlinePlaceHolder]; + } + $inlinePlaceHolders[$inlinePlaceHolder] = $placeholderValue; + } + + return $inlinePlaceHolders; + } + + public function extractEnvironmentPlaceHolders($chainContent) + { + return $this->extractPlaceHolders($chainContent, $this::ENV_REGEX); + } + + public function extractVars($chainContent) + { + $chain = Yaml::parse($chainContent); + if (!array_key_exists('vars', $chain)) { + return []; + } + + return $chain['vars']; + } }