directories = $directories; } /** * {@inheritdoc} */ public function getDefinitions() { $plugins = $this->findAll(); // Flatten definitions into what's expected from plugins. $definitions = []; foreach ($plugins as $list) { foreach ($list as $id => $definition) { $definitions[$id] = $definition; } } return $definitions; } /** * Returns an array of discoverable items. * * @return array * An array of discovered data keyed by provider. * * @throws \Drupal\Component\Discovery\DiscoveryException * Exception thrown if there is a problem during discovery. */ public function findAll() { $all = []; $files = $this->findFiles(); $file_cache = FileCacheFactory::get('help_topic_discovery:help_topics'); // Try to load from the file cache first. foreach ($file_cache->getMultiple(array_keys($files)) as $file => $data) { $all[$files[$file]][$data['id']] = $data; unset($files[$file]); } // If there are files left that were not returned from the cache, load and // parse them now. This list was flipped above and is keyed by filename. if ($files) { foreach ($files as $file => $provider) { $plugin_id = substr(basename($file), 0, -10); // The plugin ID begins with provider. [$file_name_provider] = explode('.', $plugin_id, 2); $data = [ // The plugin ID is derived from the filename. The extension // '.html.twig' is removed. 'id' => $plugin_id, 'provider' => $file_name_provider, 'class' => HelpTopicTwig::class, static::FILE_KEY => $file, ]; // Get the rest of the plugin definition from front matter contained in // the help topic Twig file. try { $front_matter = FrontMatter::create(file_get_contents($file), Yaml::class)->getData(); } catch (InvalidDataTypeException $e) { throw new DiscoveryException(sprintf('Malformed YAML in help topic "%s": %s.', $file, $e->getMessage())); } foreach ($front_matter as $key => $value) { switch ($key) { case 'related': if (!is_array($value)) { throw new DiscoveryException("$file contains invalid value for 'related' key, the value must be an array of strings"); } $data[$key] = $value; break; case 'top_level': if (!is_bool($value)) { throw new DiscoveryException("$file contains invalid value for 'top_level' key, the value must be a Boolean"); } $data[$key] = $value; break; case 'label': $data[$key] = new TranslatableMarkup($value); break; default: throw new DiscoveryException("$file contains invalid key='$key'"); } } if (!isset($data['label'])) { throw new DiscoveryException("$file does not contain the required key with name='label'"); } $all[$provider][$data['id']] = $data; $file_cache->set($file, $data); } } return $all; } /** * Returns an array of providers keyed by file path. * * @return array * An array of providers keyed by file path. */ protected function findFiles() { $file_list = []; foreach ($this->directories as $provider => $directories) { $directories = (array) $directories; foreach ($directories as $directory) { if (is_dir($directory)) { /** @var \SplFileInfo $fileInfo */ $iterator = new RegexDirectoryIterator($directory, '/\.html\.twig$/i'); foreach ($iterator as $fileInfo) { $file_list[$fileInfo->getPathname()] = $provider; } } } } return $file_list; } }