Show the source code of any file in a Symfony project

Published on 2019-02-08 • Modified on 2019-02-10

Well, it's in fact the Twig helper that I am using on this website to show all the snippets. You already have a native source Twig helper but it can only be used to show source of templates. This one is more generic and will allow you to show the source of any file of your project. (therefore, be sure that the parameters you pass to it are secured). At top you see the content of the _15.html.twig template dumped with the native one and below the source of the new one which is therefore used to display it's own content.
PS: You can remove the str_replace() part as it is specific to this project. Check out the code of a Symfony runnable snippet to understand why. 😉


{{ source('snippet/code/_15.html.twig')|escape }}
{{ source_part('src/Twig/Extension/SourceExtension.php', false)|escape }}
{# End of _15.html.twig Twig template #}

<?php declare(strict_types=1);

namespace App\Twig\Extension;

use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
use Twig\TwigFunction;
use function Symfony\Component\String\u;

/**
 * Source helpers for snippets.
 */
final class SourceExtension extends AbstractExtension
{
    private KernelInterface $kernel;
    private TranslatorInterface $translator;
    private bool $emptySnippets;

    public function __construct(KernelInterface $kernel, TranslatorInterface $translator, bool $emptySnippets)
    {
        $this->kernel = $kernel;
        $this->translator = $translator;
        $this->emptySnippets = $emptySnippets; // config/services.yaml
    }

    public function getFunctions(): array
    {
        return [
            new TwigFunction('source_part', [$this, 'getSourcePart']),
        ];
    }

    public function getFilters(): array
    {
        return [
            new TwigFilter('post90_cleanup', [$this, 'post90Cleanup']),
        ];
    }

    /**
     * Can show a exact part of a file.
     */
    public function getSourcePart(string $file, bool $replaceDocBlock = true, int $start = 1, int $end = null): string
    {
        if ($this->emptySnippets) {
            return '';
        }

        $filename = $this->kernel->getProjectDir().'/'.$file;
        if (!is_file($filename)) {
            throw new \InvalidArgumentException(sprintf('File "%s" not found.', $file));
        }
        $sourceArr = file($filename);

        // Take the last line
        if ($end === null) {
            $end = \count($sourceArr ?: []);
        }

        $source = implode('', \array_slice(\is_array($sourceArr) ? $sourceArr : [], $start-1, $end-$start+1));
        if ($source && $replaceDocBlock) {
            $source = $this->replaceDocBlocks($source);
        }

        return u($source)->trimEnd()->toString();
    }

    private function replaceDocBlocks(string $source): string
    {
        $search = [
            '%docblock1%' => $this->translator->trans('docblock1', [], 'snippet'), // PHP
            '%docblock2%' => $this->translator->trans('docblock2', [], 'snippet'),
            '%docblock3%' => $this->translator->trans('docblock3', [], 'snippet'),
            '%docblock4%' => $this->translator->trans('docblock4', [], 'snippet'),

            '%jsDocblock1%' => $this->translator->trans('jsDocblock1', [], 'snippet'),
            '%jsDocblock2%' => $this->translator->trans('jsDocblock2', [], 'snippet'),
            '%jsDocblock3%' => $this->translator->trans('jsDocblock3', [], 'snippet'),
        ];

        return (string) str_replace(array_keys($search), $search, $source);
    }

    public function post90Cleanup(string $html): string
    {
        $search = [
            '<p>',
            '<ul>',
            '<table>',
            '<img ',
            'href="LICENSE"',
        ];
        $replace = [
            '<p class="h4 justify">',
            '<ul class="h4">',
            '<table class="table">',
            '<img width="500px" ',
            'href="https://github.com/strangebuzz/cache-watcher/blob/master/LICENSE"',
        ];

        return str_replace($search, $replace, $html);
    }
}

 More on Stackoverflow  Random snippet