editorjs-2.x-dev/src/EventSubscriber/EditorjsSubscriber.php
src/EventSubscriber/EditorjsSubscriber.php
<?php namespace Drupal\editorjs\EventSubscriber; use Drupal\Component\Serialization\Json; use Drupal\Component\Utility\DiffArray; use Drupal\Component\Utility\Html; use Drupal\Core\Entity\EntityRepositoryInterface; use Drupal\editorjs\Event\EditorJsEvents; use Drupal\editorjs\Event\MassageValuesEvent; use Drupal\editorjs\Event\LinkFetchEvent; use Drupal\file\FileUsage\FileUsageInterface; use GuzzleHttp\ClientInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Editorjs event subscriber. */ class EditorjsSubscriber implements EventSubscriberInterface { /** * The http client. * * @var \GuzzleHttp\ClientInterface */ protected $client; /** * The entity type manager. * * @var \Drupal\Core\Entity\EntityRepositoryInterface */ protected $entityRepository; /** * The file usage service. * * @var \Drupal\file\FileUsage\FileUsageInterface */ protected $fileUsage; /** * EditorjsSubscriber constructor. * * @param \GuzzleHttp\ClientInterface $client * The http client. * @param \Drupal\Core\Entity\EntityRepositoryInterface $entityRepository * The entity repository. * @param \Drupal\file\FileUsage\FileUsageInterface $fileUsage * The file usage service. */ public function __construct(ClientInterface $client, EntityRepositoryInterface $entityRepository, FileUsageInterface $fileUsage) { $this->client = $client; $this->entityRepository = $entityRepository; $this->fileUsage = $fileUsage; } /** * {@inheritdoc} */ public static function getSubscribedEvents() { return [ EditorJsEvents::LINK_FETCH => 'linkFetch', EditorJsEvents::MASSAGE_FORM_VALUES => 'processDifferenceValues', ]; } /** * Processing difference values. * * @param \Drupal\editorjs\Event\MassageValuesEvent $event * The event instance. */ public function processDifferenceValues(MassageValuesEvent $event) { foreach ($event->getNewValues() as $delta => $item) { $origin_delta = $item['_original_delta'] ?? $delta; $value = Json::decode($item['value']) ?? []; $origin_value = $event->getOriginValueByDelta($origin_delta); $origin_value = Json::decode($origin_value) ?? []; $diff = DiffArray::diffAssocRecursive($origin_value, $value); if (empty($diff)) { return; } foreach ($diff as $diff_item) { if (isset($diff_item['type']) && $diff_item['type'] === 'image') { $uuid = $diff_item['data']['file']['uuid'] ?? NULL; // Skip if file id not found. if (empty($uuid)) { return; } // Change status to temporary. /** @var \Drupal\file\Entity\File $file */ $file = $this->entityRepository->loadEntityByUuid('file', $uuid); if ($file && $file->isPermanent()) { $this->fileUsage->delete($file, 'editorjs'); $file->setTemporary(); $file->save(); } } } } } /** * Set meta data. * * @param \Drupal\editorjs\Event\LinkFetchEvent $event * The link fetch event. */ public function linkFetch(LinkFetchEvent $event): void { $responce = $this->client->request('GET', $event->url()); $dom = Html::load($responce->getBody()->getContents()); $metatags = $this->metatags($dom->getElementsByTagName('meta')); $desc = $metatags['og:description'] ?? $metatags['description'] ?? ''; $title = $metatags['og:title'] ?? ''; $img = $metatags['og:image'] ?? ''; if (empty($title)) { $title_tag = $dom->getElementsByTagName('title'); $title = $title_tag->count() ? $title_tag->item(0)->nodeValue : ''; } if (empty($img)) { $tag_imgs = $dom->getElementsByTagName('img'); $img = $tag_imgs->count() ? $tag_imgs->item(0)->getAttribute('src') : ''; if (empty(\parse_url($img, \PHP_URL_HOST))) { $img = \trim($event->url(), '/') . $img; } } $event->setMeta([ 'title' => $title, 'description' => $desc, 'image' => [ 'url' => $img, ], ]); } /** * Returns metatags array bu metatag NodeList. * * @param \DOMNodeList $list * The metatag NodeList. * * @return array * The metatags array. */ protected function metatags(\DOMNodeList $list): array { $metatags = []; foreach ($list as $item) { if ($item->hasAttribute('name')) { $metatags[$item->getAttribute('name')] = $item->getAttribute('content'); } if ($item->hasAttribute('property')) { $metatags[$item->getAttribute('property')] = $item->getAttribute('content'); } } return $metatags; } }