Я перелопатил код вей библиотеки
League\CommonMark но не нашел внятного примера. Очень запутанно.
Задача: есть тег типа |attach_photo_123_456| либо |attach_video_789_380|
где, к примеру, первое:
1) надо отобразить фото
2) прикрепленное к публикации с ID=123
3) у которого ID=456
У меня все получилось (скрипт ниже). Но получилось вставить только изображение. А мне надо изображение, обрамленное ссылкой. Чтоб по нему можно было кликнуть и открылось POP окно с увеличенным размером.
То же самое для VIDEO. Там будет скриншот, обрамленный DIV с определенным классом. При клике по DIV вместо скриншота JS потом вставит код видео-плеера.
Сейчас у меня получилось так:
Тут я подключаю и вызываю парсер:
<?php
declare(strict_types=1);
namespace App\Commonmark\Extensions\Blog;
use League\CommonMark\Environment\EnvironmentBuilderInterface;
use League\CommonMark\Extension\ExtensionInterface;
use League\CommonMark\Parser\InlineParserContext;
final class AttachMediaExtension implements ExtensionInterface
{
public function register(EnvironmentBuilderInterface $environment): void
{
$environment->addInlineParser(new AttachMediaParser());
}
}
и парсер строки для вставки медиафайла:
<?php
declare(strict_types=1);
namespace App\Commonmark\Extensions\Blog;
use App\Models\Blog\Posts\BlogPost;
use Str;
use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\CommonMark\Node\Inline\Image;
use League\CommonMark\Parser\Inline\InlineParserInterface;
use League\CommonMark\Parser\Inline\InlineParserMatch;
use League\CommonMark\Parser\InlineParserContext;
use League\CommonMark\Renderer\NodeRendererInterface;
class AttachMediaParser implements InlineParserInterface
{
private const REGEX = '\|attach\-(photo|video|gif|audio)\-(\d+)\-(\d+)\|';
public function getMatchDefinition(): InlineParserMatch
{
return InlineParserMatch::regex(self::REGEX);
}
public function parse(InlineParserContext $inlineContext): bool
{
$match = $inlineContext->getFullMatch();
$matches = $inlineContext->getMatches();
$type = $matches[1] ?? null; // тип медиафайла
$postId = $matches[2] ?? null; // ID поста
$mediaId = $matches[3] ?? null; // ID файла
if (!empty($type) && !empty($postId) && !empty($mediaId)) {
$post = BlogPost::find($postId);
if (!empty($post)) {
switch($type)
{
case 'photo':
$photo = $post->photos->keyBy('id')->get($mediaId, null);
if (!empty($photo)) {
$url = $photo->prev()->url();
$image = new Image($url);
$image->data->set('attributes/class', 'w-100');
$inlineContext->getCursor()->advanceBy($inlineContext->getFullMatchLength());
$inlineContext->getContainer()->appendChild($image);
}
break;
case 'video':
break;
case 'gif':
break;
case 'audio':
break;
}
}
}
return true;
}
}
Работает изумительно и быстро, если вставлять просто картинку.
Но как вложить тег изображения в тег ссылки?
Теоретически, надо создать рендер, помещенный внутрь парсера, как это написано в документации? Но там же написано, что это медленнее, т.к. после этого обработка будет производиться снова. И чем больше вложенностей, тем медленнее.