<?php declare(strict_types=1); namespace Doctrine\RST\Toc; use Doctrine\RST\Environment; use Doctrine\RST\Nodes\Node; use function array_filter; use function array_map; use function array_reverse; use function asort; use function explode; use function in_array; use function strpos; final class ToctreeBuilder { /** @var GlobSearcher */ private $globSearcher; public function __construct(GlobSearcher $globSearcher) { $this->globSearcher = $globSearcher; } /** * @param mixed[] $options * * @return string[] */ public function buildToctreeFiles( Environment $environment, Node $node, array $options ): array { $toctreeFiles = []; foreach ($this->parseToctreeFiles($node) as $file) { if ($this->isGlob($options, $file)) { $globPattern = $file; $globFiles = $this->globSearcher ->globSearch($environment, $globPattern); asort($globFiles); foreach ($globFiles as $globFile) { // if glob finds a file already explicitly defined // don't duplicate it in the toctree again if (in_array($globFile, $toctreeFiles, true)) { continue; } if ($globFile === $environment->absoluteUrl($environment->getCurrentFileName())) { // filter out the current file from being added as a glob continue; } $toctreeFiles[] = $globFile; } } else { $absoluteUrl = $environment->absoluteUrl($file); $toctreeFiles[] = $absoluteUrl; } } if ((bool) ($options['reversed'] ?? false)) { $toctreeFiles = array_reverse($toctreeFiles); } return $toctreeFiles; } /** @return string[] */ private function parseToctreeFiles(Node $node): array { return array_filter(array_map('trim', explode( "\n", $node->getValueString() )), static function (string $file): bool { return $file !== ''; }); } /** @param mixed[] $options */ private function isGlob(array $options, string $file): bool { return isset($options['glob']) && strpos($file, '*') !== false; } }