bynder-4.0.0-beta1/modules/bynder_usage/src/EventSubscriber/UsageEventSubscriber.php

modules/bynder_usage/src/EventSubscriber/UsageEventSubscriber.php
<?php

namespace Drupal\bynder_usage\EventSubscriber;

use Drupal\bynder\BynderApiInterface;
use Drupal\bynder\Plugin\media\Source\Bynder;
use Drupal\bynder_usage\Exception\UnableToAddUsageException;
use Drupal\bynder_usage\Exception\UnableToDeleteUsageException;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Url;
use Drupal\Core\Utility\Error;
use Drupal\entity_usage\Events\EntityUsageEvent;
use Drupal\entity_usage\Events\Events;
use Drupal\media\MediaInterface;
use Drupal\paragraphs\ParagraphInterface;
use GuzzleHttp\Exception\RequestException;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * Listens for the usage events from Entity Usage module.
 */
class UsageEventSubscriber implements EventSubscriberInterface {

  /**
   * Bynder api service.
   *
   * @var \Drupal\bynder\BynderApiInterface
   *   Bynder api service.
   */
  protected $bynderApi;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The request stack.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected $requestStack;

  /**
   * UsageEventSubscriber constructor.
   *
   * @param \Drupal\bynder\BynderApiInterface $bynder_api_service
   *   Bynder api service.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The request stack.
   */
  public function __construct(BynderApiInterface $bynder_api_service, EntityTypeManagerInterface $entity_type_manager, RequestStack $request_stack) {
    $this->bynderApi = $bynder_api_service;
    $this->entityTypeManager = $entity_type_manager;
    $this->requestStack = $request_stack;
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    $events[Events::USAGE_REGISTER][] = ['onUsageRegister'];
    $events[Events::DELETE_BY_SOURCE_ENTITY][] = ['onDeleteBySourceEntity'];
    $events[Events::DELETE_BY_TARGET_ENTITY][] = ['onDeleteByTargetEntity'];
    return $events;
  }

  /**
   * Returns the remote media ID.
   *
   * @param \Drupal\media\MediaInterface $media
   *   The media to get the remote ID for.
   *
   * @return mixed|null
   *   The remote media ID or NULL if not found.
   */
  protected function getRemoteMediaId(MediaInterface $media) {
    $source_plugin = $media->getSource();
    if (!$source_plugin instanceof Bynder) {
      return NULL;
    }

    return $source_plugin->getSourceFieldValue($media);
  }

  /**
   * Returns the canonical URL for the given entity.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The source entity.
   *
   * @return \Drupal\Core\Url|null
   *   The absolute URL of the given entity.
   */
  protected function getEntityUrl(EntityInterface $entity) {
    // If the entity is a paragraph, attempt to recursively load the parent.
    while ($entity && $entity instanceof ParagraphInterface) {
      $entity = $entity->getParentEntity();
    }

    // If the entity exists and has a canonical link template, get the URI.
    return $entity && $entity->hasLinkTemplate('canonical') ? $entity->toUrl('canonical')
      ->setOption('path_processing', FALSE)
      ->setAbsolute() : NULL;
  }

  /**
   * Auxiliary function to get media information for asset usage operations.
   *
   * @param \Drupal\entity_usage\Events\EntityUsageEvent $event
   *
   * @return array|null
   */
  private function getUsageEventMediainformation(EntityUsageEvent $event) {
    if ($event->getTargetEntityType() !== 'media') {
      return NULL;
    }

    /** @var \Drupal\media\MediaInterface $media */
    $media = $this->entityTypeManager->getStorage('media')
      ->load($event->getTargetEntityId());
    if (!isset($media)) {
      return NULL;
    }

    $source_plugin = $media->getSource();
    if (!$source_plugin instanceof Bynder) {
      return NULL;
    }

    $url = NULL;
    if ($source_id = $event->getSourceEntityId()) {
      if ($entity = $this->entityTypeManager->getStorage($event->getSourceEntityType())->load($source_id)) {
        $url = $this->getEntityUrl($entity);
      }
    }

    if ($url) {
      return [
        'mediaId' => $source_plugin->getSourceFieldValue($media),
        'url' => $url,
      ];
    }
  }

  /**
   * Returns whether the given remote ID and URI have a remote usage.
   *
   * @param string $remote_id
   *   The remote ID.
   * @param string $uri
   *   The URI this asset was used on.
   *
   * @return bool
   *   TRUE if there is a remote usage for the ID and URI. Otherwise, FALSE.
   */
  protected function hasRemoteUsageByUri($remote_id, $uri) {
    $usages = $this->bynderApi->getAssetUsages($remote_id);
    // No remote usages.
    if (empty($usages)) {
      return FALSE;
    }

    foreach ($usages as $usage) {
      // There is a remote usage on the given URI.
      if ($usage['uri'] === $uri) {
        return TRUE;
      }
    }

    return FALSE;
  }

  /**
   * Triggers when a usage is registered (create or update) for a Bynder asset.
   *
   * @param \Drupal\entity_usage\Events\EntityUsageEvent $event
   *   The event to process.
   */
  public function onUsageRegister(EntityUsageEvent $event) {
    $mediaInfo = $this->getUsageEventMediainformation($event);
    if (isset($mediaInfo)) {
      try {
        // Add a usage only once if the count is positive and there are no
        // usages registered on this URI.
        if ($event->getCount() > 0) {
          $usage_url = $mediaInfo['url'];
          if (!$this->hasRemoteUsageByUri($mediaInfo['mediaId'], $usage_url->toString())) {
            $this->bynderApi->addAssetUsage(
              $mediaInfo['mediaId'],
              $usage_url,
              date(DATE_ATOM, \Drupal::time()->getRequestTime()), 'Added asset by user ' . \Drupal::currentUser()->getAccountName() . '.'
            );
          }
        }
        // If the count is zero, the item was removed.
        else {
          $this->bynderApi->removeAssetUsage($mediaInfo['mediaId'], $mediaInfo['url']->toString());
        }
      }
      catch (RequestException $e) {
        Error::logException(\Drupal::logger('bynder'), $e);
        (new UnableToAddUsageException($e->getMessage()))->logException()->displayMessage();
      }
    }
  }

  /**
   * Triggers when the source entity is deleted.
   *
   * @param \Drupal\entity_usage\Events\EntityUsageEvent $event
   *   The event to process.
   */
  public function onDeleteBySourceEntity(EntityUsageEvent $event) {
    // Skip if a non-default revision or translation is deleted.
    if ($event->getSourceEntityRevisionId() || $event->getSourceEntityLangcode()) {
      return;
    }

    $storage = $this->entityTypeManager->getStorage($event->getSourceEntityType());
    $entity = $storage->load($event->getSourceEntityId());
    if (!$entity) {
      return;
    }

    $usage_url = $this->getEntityUrl($entity);
    if (!$usage_url) {
      return;
    }

    // At this point, the entity usages are already deleted so we can't query
    // the entity usage table to find the relevant media usages. Instead, loop
    // over the references of the source entity and delete all usages of the
    // Bynder media assets on this URI.
    foreach ($entity->referencedEntities() as $referenced_entity) {
      if ($referenced_entity instanceof MediaInterface && ($remote_id = $this->getRemoteMediaId($referenced_entity))) {
        try {
          $this->bynderApi->removeAssetUsage($remote_id, $usage_url->toString());
        }
        catch (RequestException $e) {
          Error::logException(\Drupal::logger('bynder'), $e);
          (new UnableToDeleteUsageException($e->getMessage()))->logException()->displayMessage();
        }
      }
    }
  }

  /**
   * Triggers if the target (media) entity is deleted. Remove all Bynder usages.
   *
   * @param \Drupal\entity_usage\Events\EntityUsageEvent $event
   *   The entity usage event.
   */
  public function onDeleteByTargetEntity(EntityUsageEvent $event) {
    if ($event->getTargetEntityType() === 'media') {
      /** @var \Drupal\media\MediaInterface $media */
      $media = $this->entityTypeManager->getStorage('media')->load($event->getTargetEntityId());
      if ($media) {
        $remote_id = $this->getRemoteMediaId($media);
        if ($remote_id) {
          try {
            // The Bynder media entity is deleted from the system. Delete all
            // remote usages for this asset.
            $usages = $this->bynderApi->getAssetUsages($remote_id);
            $base_url = Url::fromUri('base:/')->setAbsolute()->toString();
            foreach ($usages as $usage) {
              // If the usage appears to be on this site remove all the usages.
              if (strpos($usage['uri'], $base_url) === 0) {
                $this->bynderApi->removeAssetUsage($remote_id, $usage['uri']);
              }
            }
          }
          catch (RequestException $e) {
            Error::logException(\Drupal::logger('bynder'), $e);
            (new UnableToDeleteUsageException($e->getMessage()))->logException()->displayMessage();
          }
        }
      }
    }
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc