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
{
public function __construct(
readonly private KernelInterface $kernel,
readonly private TranslatorInterface $translator,
readonly private bool $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);
if (!\is_array($sourceArr)) {
throw new \RuntimeException("Can't get file.");
}
// Take the last line
if ($end === null) {
$end = \count($sourceArr);
}
$source = implode('', \array_slice($sourceArr, $start - 1, $end - $start + 1));
if ($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 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
Call to action
Did you like this post? You can help me back in several ways: (use the "reply" link on the right to comment or to contact me )
- Report any error/typo.
- Report something that could be improved.
- Like and repost!
- Follow me on Bluesky 🦋
- Subscribe to the RSS feed.
- Click on the More on Stackoverflow buttons to make me win "Announcer" badges 🏅.
Thank you for reading! And see you soon on Strangebuzz! 😉
