<commit_before><?php declare(strict_types=1);

namespace Symplify\Statie\Renderable;

use Symplify\Statie\Configuration\Configuration;
use Symplify\Statie\Contract\Renderable\FileDecoratorInterface;
use Symplify\Statie\Generator\Configuration\GeneratorElement;
use Symplify\Statie\Renderable\File\AbstractFile;
use Symplify\Statie\Utils\PathNormalizer;

final class RouteFileDecorator implements FileDecoratorInterface
{
    /**
     * @var Configuration
     */
    private $configuration;

    /**
     * @var PathNormalizer
     */
    private $pathNormalizer;

    public function __construct(Configuration $configuration, PathNormalizer $pathNormalizer)
    {
        $this->configuration = $configuration;
        $this->pathNormalizer = $pathNormalizer;
    }

    /**
     * @param AbstractFile[] $files
     * @return AbstractFile[]
     */
    public function decorateFiles(array $files): array
    {
        foreach ($files as $file) {
            $this->decorateFile($file);
        }

        return $files;
    }

    /**
     * @param AbstractFile[] $files
     * @return AbstractFile[]
     */
    public function decorateFilesWithGeneratorElement(array $files, GeneratorElement $generatorElement): array
    {
        foreach ($files as $file) {
            $outputPath = $generatorElement->getRoutePrefix()
                ? $generatorElement->getRoutePrefix() . DIRECTORY_SEPARATOR
                : '';
            $outputPath = $this->prefixWithDateIfFound($file, $outputPath);
            $outputPath .= $file->getFilenameWithoutDate();
            $outputPath = $this->pathNormalizer->normalize($outputPath);

            $file->setRelativeUrl($outputPath);
            $file->setOutputPath($outputPath . DIRECTORY_SEPARATOR . 'index.html');
        }

        return $files;
    }

    private function decorateFile(AbstractFile $file): void
    {
        // manual config override has preference
        if ($file->getOption('outputPath')) {
            $file->setOutputPath((string) $file->getOption('outputPath'));
            $file->setRelativeUrl((string) $file->getOption('outputPath'));
            return;
        }

        // index file
        if ($file->getBaseName() === 'index') {
            $file->setOutputPath('index.html');
            $file->setRelativeUrl('/');
            return;
        }

        // special files
        if (in_array($file->getPrimaryExtension(), ['xml', 'rss', 'json', 'atom', 'css', 'js'], true)) {
            $outputPath = $file->getBaseName();
            // trim file.xml.latte => file.xml
            if ($file->getExtension() !== 'latte') {
                $outputPath .= '.' . $file->getPrimaryExtension();
            }

            $file->setOutputPath($outputPath);
            $file->setRelativeUrl($outputPath);
            return;
        }

        // fallback
        $relativeDirectory = $this->getRelativeDirectory($file);
        $relativeOutputDirectory = $relativeDirectory . DIRECTORY_SEPARATOR . $file->getBaseName();
        $outputPath = $relativeOutputDirectory . DIRECTORY_SEPARATOR . 'index.html';

        $file->setOutputPath($outputPath);
        $file->setRelativeUrl($relativeDirectory . DIRECTORY_SEPARATOR . $file->getBaseName());
    }

    private function getRelativeDirectory(AbstractFile $file): string
    {
        $sourceParts = explode(DIRECTORY_SEPARATOR, $this->configuration->getSourceDirectory());
        $sourceDirectory = array_pop($sourceParts);

        $relativeParts = explode($sourceDirectory, $file->getRelativeDirectory());

        return array_pop($relativeParts);
    }

    /**
     * Only if the date is part of file name
     */
    private function prefixWithDateIfFound(AbstractFile $file, string $outputPath): string
    {
        if ($file->getDate() === null) {
            return $outputPath;
        }

        $outputPath = preg_replace('#:year#', $file->getDateInFormat('Y'), $outputPath);
        $outputPath = preg_replace('#:month#', $file->getDateInFormat('m'), $outputPath);
        $outputPath = preg_replace('#:day#', $file->getDateInFormat('d'), $outputPath);

        return $outputPath;
    }
}
<commit_msg>[Statie] fix non-root index route [closes #638]<commit_after><?php declare(strict_types=1);

namespace Symplify\Statie\Renderable;

use Nette\Utils\Strings;
use Symplify\Statie\Configuration\Configuration;
use Symplify\Statie\Contract\Renderable\FileDecoratorInterface;
use Symplify\Statie\Generator\Configuration\GeneratorElement;
use Symplify\Statie\Renderable\File\AbstractFile;
use Symplify\Statie\Utils\PathNormalizer;

final class RouteFileDecorator implements FileDecoratorInterface
{
    /**
     * @var Configuration
     */
    private $configuration;

    /**
     * @var PathNormalizer
     */
    private $pathNormalizer;

    public function __construct(Configuration $configuration, PathNormalizer $pathNormalizer)
    {
        $this->configuration = $configuration;
        $this->pathNormalizer = $pathNormalizer;
    }

    /**
     * @param AbstractFile[] $files
     * @return AbstractFile[]
     */
    public function decorateFiles(array $files): array
    {
        foreach ($files as $file) {
            $this->decorateFile($file);
        }

        return $files;
    }

    /**
     * @param AbstractFile[] $files
     * @return AbstractFile[]
     */
    public function decorateFilesWithGeneratorElement(array $files, GeneratorElement $generatorElement): array
    {
        foreach ($files as $file) {
            $outputPath = $generatorElement->getRoutePrefix()
                ? $generatorElement->getRoutePrefix() . DIRECTORY_SEPARATOR
                : '';
            $outputPath = $this->prefixWithDateIfFound($file, $outputPath);
            $outputPath .= $file->getFilenameWithoutDate();
            $outputPath = $this->pathNormalizer->normalize($outputPath);

            $file->setRelativeUrl($outputPath);
            $file->setOutputPath($outputPath . DIRECTORY_SEPARATOR . 'index.html');
        }

        return $files;
    }

    private function decorateFile(AbstractFile $file): void
    {
        // manual config override has preference
        if ($file->getOption('outputPath')) {
            $file->setOutputPath((string) $file->getOption('outputPath'));
            $file->setRelativeUrl((string) $file->getOption('outputPath'));
            return;
        }

        if ($this->isRootIndex($file)) {
            $file->setOutputPath('index.html');
            $file->setRelativeUrl('/');
            return;
        }

        // special files
        if (in_array($file->getPrimaryExtension(), ['xml', 'rss', 'json', 'atom', 'css', 'js'], true)) {
            $outputPath = $file->getBaseName();
            // trim file.xml.latte => file.xml
            if ($file->getExtension() !== 'latte') {
                $outputPath .= '.' . $file->getPrimaryExtension();
            }

            $file->setOutputPath($outputPath);
            $file->setRelativeUrl($outputPath);
            return;
        }

        // fallback
        $relativeDirectory = $this->getRelativeDirectory($file);
        $relativeOutputDirectory = $relativeDirectory . DIRECTORY_SEPARATOR . $file->getBaseName();

        if ($file->getBaseName() === 'index') { // index.* file
            $outputPath = $relativeOutputDirectory . '.html';
        } else {
            $outputPath = $relativeOutputDirectory . DIRECTORY_SEPARATOR . 'index.html';
        }

        $file->setOutputPath($outputPath);
        $file->setRelativeUrl($relativeDirectory . DIRECTORY_SEPARATOR . $file->getBaseName());
    }

    private function getRelativeDirectory(AbstractFile $file): string
    {
        $sourceParts = explode(DIRECTORY_SEPARATOR, $this->configuration->getSourceDirectory());
        $sourceDirectory = array_pop($sourceParts);

        $relativeParts = explode($sourceDirectory, $file->getRelativeDirectory());

        return array_pop($relativeParts);
    }

    /**
     * Only if the date is part of file name
     */
    private function prefixWithDateIfFound(AbstractFile $file, string $outputPath): string
    {
        if ($file->getDate() === null) {
            return $outputPath;
        }

        $outputPath = preg_replace('#:year#', $file->getDateInFormat('Y'), $outputPath);
        $outputPath = preg_replace('#:month#', $file->getDateInFormat('m'), $outputPath);
        $outputPath = preg_replace('#:day#', $file->getDateInFormat('d'), $outputPath);

        return $outputPath;
    }

    private function isRootIndex(AbstractFile $file): bool
    {
        return Strings::contains(
            $file->getFilePath(),
            $this->configuration->getSourceDirectory() . DIRECTORY_SEPARATOR . 'index'
        );
    }
}

{'fraction_non_alphanumeric': 0.136238846945779, 'fraction_numerical': 0.0005719514985129262, 'mean_word_length': 2.6535729210196406, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 83, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3222256', 'n_tokens_mistral': 2402, 'n_tokens_neox': 2331, 'n_words': 427}