Voir le code source de n'importe quel fichier d'un projet Symfony

Publié le 08/02/2019 • Mis à jour le 10/02/2019

English language detected! 🇬🇧

  We noticed that your browser is using English. Do you want to read this post in this language?

Read the english version 🇬🇧

C'est en fait le helper Twig que j'utilise sur ce site pour afficher tous les snippets. Il existe déjà un helper Twig natif source() mais il peut uniquement être utilisé pour afficher des templates. Celui-ci est plus générique et vous permet de voir le contenu de n'importe quel fichier de votre projet. (il est donc important de sécuriser les paramètres qui lui sont passés). En haut, vous pouvez voir le contenu du template _15.html.twig grâce au helper natif. En dessous, le source du nouveau helper qui est donc utilisé pour afficher son propre contenu.
PS : Vous pouvez supprimer la partie str_replace() qui est spécifique à ce projet. Jetez un coup d'œil au code d'un des snippets exécutables pour comprendre pourquoi. 😉


{{ source('snippet/code/_15.html.twig')|escape }}
{{ source_php('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\TwigFunction;

/**
 * Source helpers for snippets.
 */
class SourceExtension extends AbstractExtension
{
    protected $kernel;
    protected $translator;

    public function __construct(KernelInterface $kernel, TranslatorInterface $translator)
    {
        $this->kernel = $kernel;
        $this->translator = $translator;
    }

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

    /**
     * @deprecate Use source_part
     */
    public function getSource(string $file, bool $replaceDocBlock = true, int $linesLimit = null): string
    {
        $filename = $this->kernel->getProjectDir().'/'.$file;
        if (!file_exists($filename)) {
            throw new \InvalidArgumentException(sprintf('File "%s" not found.', $file));
        }

        // Only get x first lines only
        if (is_int($linesLimit)) {
            $lines = file($filename);
            $source = implode('', array_slice(is_array($lines) ? $lines : [], 0, $linesLimit));
        } else {
            $source = file_get_contents($filename);
        }

        if ($source && $replaceDocBlock) {
            $this->replaceDocBlocks($source);
        }

        return (string) $source;
    }

    /**
     * Can show a exact part of a file.
     */
    public function getSourcePart(string $file, bool $replaceDocBlock = true, int $start = 1, int $end = null): string
    {
        $filename = $this->kernel->getProjectDir().'/'.$file;
        if (!file_exists($filename)) {
            throw new \InvalidArgumentException(sprintf('File "%s" not found.', $file));
        }
        $sourceArr = file($filename);

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

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

        return (string) $source;
    }

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

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

 Plus sur Stackoverflow