Allow including other snippets and update to symfony 6.4

This commit is contained in:
Tim 2023-12-12 22:51:08 +01:00
parent 9f5bb66ae9
commit 4989a9f7cc
5 changed files with 1261 additions and 1028 deletions

View File

@ -12,26 +12,26 @@
"doctrine/doctrine-migrations-bundle": "^3.2", "doctrine/doctrine-migrations-bundle": "^3.2",
"doctrine/orm": "^2.14", "doctrine/orm": "^2.14",
"league/pipeline": "^1.0", "league/pipeline": "^1.0",
"symfony/console": "6.2.*", "symfony/console": "6.4.*",
"symfony/dotenv": "6.2.*", "symfony/dotenv": "6.4.*",
"symfony/flex": "^2", "symfony/flex": "^2",
"symfony/form": "6.2.*", "symfony/form": "6.4.*",
"symfony/framework-bundle": "6.2.*", "symfony/framework-bundle": "6.4.*",
"symfony/monolog-bundle": "^3.0", "symfony/monolog-bundle": "^3.0",
"symfony/runtime": "6.2.*", "symfony/runtime": "6.4.*",
"symfony/security-bundle": "6.2.*", "symfony/security-bundle": "6.4.*",
"symfony/twig-bundle": "6.2.*", "symfony/twig-bundle": "6.4.*",
"symfony/validator": "6.2.*", "symfony/validator": "6.4.*",
"symfony/yaml": "6.2.*", "symfony/yaml": "6.4.*",
"twig/extra-bundle": "^2.12|^3.0", "twig/extra-bundle": "^2.12|^3.0",
"twig/twig": "^2.12|^3.0" "twig/twig": "^2.12|^3.0"
}, },
"require-dev": { "require-dev": {
"deployer/deployer": "^7.3", "deployer/deployer": "^7.3",
"symfony/debug-bundle": "6.2.*", "symfony/debug-bundle": "6.4.*",
"symfony/maker-bundle": "^1.48", "symfony/maker-bundle": "^1.48",
"symfony/stopwatch": "6.2.*", "symfony/stopwatch": "6.4.*",
"symfony/web-profiler-bundle": "6.2.*" "symfony/web-profiler-bundle": "6.4.*"
}, },
"config": { "config": {
"allow-plugins": { "allow-plugins": {
@ -78,7 +78,7 @@
"extra": { "extra": {
"symfony": { "symfony": {
"allow-contrib": false, "allow-contrib": false,
"require": "6.2.*" "require": "6.4.*"
} }
} }
} }

2206
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@
namespace App\Service\SnipParser; namespace App\Service\SnipParser;
use App\Service\SnipParser\Stages\HtmlEscapeStage; use App\Service\SnipParser\Stages\HtmlEscapeStage;
use App\Service\SnipParser\Stages\IncludeReferenceStage;
use App\Service\SnipParser\Stages\UrlReferenceStage; use App\Service\SnipParser\Stages\UrlReferenceStage;
use App\Service\SnipParser\Stages\ReplaceBlocksStage; use App\Service\SnipParser\Stages\ReplaceBlocksStage;
use App\Service\SnipParser\Stages\ReplaceStage; use App\Service\SnipParser\Stages\ReplaceStage;
@ -11,7 +12,8 @@ use League\Pipeline\PipelineBuilder;
class Pipeline class Pipeline
{ {
public function __construct( public function __construct(
private readonly UrlReferenceStage $referenceStage, private readonly UrlReferenceStage $referenceStage,
private readonly IncludeReferenceStage $includeStage,
) {} ) {}
public function parse(string $payload): string public function parse(string $payload): string
@ -23,6 +25,7 @@ class Pipeline
->add(new ReplaceBlocksStage('<pre><code class="hljs">', '</code></pre>', '```')) ->add(new ReplaceBlocksStage('<pre><code class="hljs">', '</code></pre>', '```'))
->add(new ReplaceBlocksStage('<code class="hljs">', '</code>', '``')) ->add(new ReplaceBlocksStage('<code class="hljs">', '</code>', '``'))
->add($this->referenceStage) ->add($this->referenceStage)
->add($this->includeStage)
->build() ->build()
; ;

View File

@ -0,0 +1,44 @@
<?php
namespace App\Service\SnipParser\Stages;
use App\Repository\SnipRepository;
use App\Security\Voter\SnipVoter;
use App\Service\SnipParser\Pipeline;
use App\Service\SnipServiceFactory;
use League\Pipeline\StageInterface;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
class IncludeReferenceStage implements StageInterface
{
public function __construct(
#[Autowire(lazy: true)] private readonly Security $security,
#[Autowire(lazy: true)] private readonly SnipRepository $snipRepository,
#[Autowire(lazy: true)] private readonly SnipServiceFactory $snipServiceFactory,
#[Autowire(lazy: true)] private readonly Pipeline $pipeline,
) {}
public function __invoke(mixed $payload): string
{
return $this->replaceReferences($payload);
}
private function replaceReferences(mixed $payload): string
{
// replaces all references (#n) to other snips with links
$pattern = '/\{\{(\d+)\}\}/';
return preg_replace_callback($pattern, function ($matches) {
$snip = $this->snipRepository->find($matches[1]);
if ($snip === null) {
return sprintf('<span title="not found">%s</span>', $matches[0]);
}
if (!$this->security->isGranted(SnipVoter::VIEW, $snip)) {
return sprintf('<span title="access denied">%s</span>', $matches[0]);
}
return $this->pipeline->parse($this->snipServiceFactory->create($snip)->get());
}, $payload);
}
}

View File

@ -6,14 +6,15 @@ use App\Repository\SnipRepository;
use App\Security\Voter\SnipVoter; use App\Security\Voter\SnipVoter;
use League\Pipeline\StageInterface; use League\Pipeline\StageInterface;
use Symfony\Bundle\SecurityBundle\Security; use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
class UrlReferenceStage implements StageInterface class UrlReferenceStage implements StageInterface
{ {
public function __construct( public function __construct(
private readonly UrlGeneratorInterface $router, #[Autowire(lazy: true)] private readonly UrlGeneratorInterface $router,
private readonly Security $security, #[Autowire(lazy: true)] private readonly Security $security,
private readonly SnipRepository $snipRepository, #[Autowire(lazy: true)] private readonly SnipRepository $snipRepository,
) {} ) {}
public function __invoke(mixed $payload): string public function __invoke(mixed $payload): string
@ -27,7 +28,6 @@ class UrlReferenceStage implements StageInterface
$pattern = '/#(\d+)/'; $pattern = '/#(\d+)/';
return preg_replace_callback($pattern, function ($matches) { return preg_replace_callback($pattern, function ($matches) {
dump($matches);
$snip = $this->snipRepository->find($matches[1]); $snip = $this->snipRepository->find($matches[1]);
if ($snip === null) { if ($snip === null) {
return sprintf('<span title="not found">%s</span>', $matches[0]); return sprintf('<span title="not found">%s</span>', $matches[0]);