activitypub-1.0.x-dev/src/Services/Type/TypePluginBase.php

src/Services/Type/TypePluginBase.php
<?php

namespace Drupal\activitypub\Services\Type;

use Drupal\activitypub\Entity\ActivityPubActivity;
use Drupal\activitypub\Entity\ActivityPubActivityInterface;
use Drupal\activitypub\Entity\ActivityPubTypeInterface;
use Drupal\activitypub\Event\ActivityAudienceEvent;
use Drupal\activitypub\Services\ActivityPubProcessClientInterface;
use Drupal\activitypub\Services\ActivityPubUtilityInterface;
use Drupal\Component\Utility\NestedArray;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\File\FileUrlGeneratorInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\PluginBase;
use Drupal\Core\Render\RenderContext;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Url;
use Drupal\file\FileInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

/**
 * A base class for ActivityPub types that implements most of the boilerplate.
 */
abstract class TypePluginBase extends PluginBase implements TypePluginInterface, ContainerFactoryPluginInterface {

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

  /**
   * The renderer.
   *
   * @var \Drupal\Core\Render\RendererInterface
   */
  protected $renderer;

  /**
   * The date formatter.
   *
   * @var \Drupal\Core\DateTime\DateFormatInterface
   */
  protected $dateFormatter;

  /**
   * The ActivityPub process client.
   *
   * @var \Drupal\activitypub\Services\ActivityPubProcessClient
   */
  protected $activityPubProcessClient;

  /**
   * The ActivityPub utility service.
   *
   * @var \Drupal\activitypub\Services\ActivityPubUtilityInterface
   */
  protected $activityPubUtility;

  /**
   * The entity field manager.
   *
   * @var \Drupal\Core\Entity\EntityFieldManagerInterface
   */
  protected $entityFieldManager;

  /**
   * The config factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * A logger instance.
   *
   * @var \Psr\Log\LoggerInterface
   */
  protected $logger;

  /**
   * The file url generator.
   *
   * @var \Drupal\Core\File\FileUrlGeneratorInterface
   */
  protected $fileUrlGenerator;

  /**
   * The event dispatcher.
   *
   * @var \Symfony\Contracts\EventDispatcher\EventDispatcherInterface
   */
  protected $eventDispatcher;

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, RendererInterface $renderer, DateFormatterInterface $date_formatter, ActivityPubProcessClientInterface $activitypub_process_client, ActivityPubUtilityInterface $activitypub_utility, EntityFieldManagerInterface $entity_field_manager, ConfigFactoryInterface $config_factory, LoggerInterface $logger, FileUrlGeneratorInterface $file_url_generator, EventDispatcherInterface $event_dispatcher) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->setConfiguration($configuration);
    $this->entityTypeManager = $entity_type_manager;
    $this->renderer = $renderer;
    $this->dateFormatter = $date_formatter;
    $this->activityPubProcessClient = $activitypub_process_client;
    $this->activityPubUtility = $activitypub_utility;
    $this->entityFieldManager = $entity_field_manager;
    $this->configFactory = $config_factory;
    $this->logger = $logger;
    $this->fileUrlGenerator = $file_url_generator;
    $this->eventDispatcher = $event_dispatcher;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('entity_type.manager'),
      $container->get('renderer'),
      $container->get('date.formatter'),
      $container->get('activitypub.process.client'),
      $container->get('activitypub.utility'),
      $container->get('entity_field.manager'),
      $container->get('config.factory'),
      $container->get('logger.channel.activitypub'),
      $container->get('file_url_generator'),
      $container->get('event_dispatcher')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function isExposed() {
    return TRUE;
  }

  /**
   * {@inheritdoc}
   */
  public function build(ActivityPubActivityInterface $activity, EntityInterface $entity = NULL) {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function getActivities() {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function getObjects() {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function getProperties($object) {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function onActivityInboxPreSave(ActivityPubActivityInterface $activity, &$doSave) {}

  /**
   * {@inheritdoc}
   */
  public function onActivityOutboxPreSave(ActivityPubActivityInterface $activity, EntityInterface $entity, ActivityPubTypeInterface $activityPubType, &$doSave) {}

  /**
   * {@inheritdoc}
   */
  public function onActivityPostSave(ActivityPubActivityInterface $activity, $update = TRUE) {}

  /**
   * {@inheritdoc}
   */
  public function doInboxProcess(ActivityPubActivityInterface $activity, EntityInterface $entity = NULL) {}

  /**
   * {@inheritdoc}
   */
  public function onEntityDelete(ActivityPubActivityInterface $activity, EntityInterface $entity) {}

  /**
   * {@inheritdoc}
   */
  public function onActivityDelete(ActivityPubActivityInterface $activity) {}

  /**
   * Get value for a property.
   *
   * @param $property
   * @param $value
   * @param $field_type
   *
   * @return array|mixed|null
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  protected function getValue($property, $value, $field_type = NULL) {
    $return = NULL;

    switch ($property) {
      case 'published':
        $date_timestamp = $value[0]['value'];
        if (!is_numeric($date_timestamp)) {
          $date_timestamp = strtotime($value[0]['value']);
        }
        $return = $this->dateFormatter->format($date_timestamp, 'custom', 'Y-m-d\TH:i:s\Z');
        break;
      case 'name':
        $return = trim($value[0]['value']);
        break;
      case 'content':
      case 'summary':
        $return = trim(check_markup($value[0]['value'], $this->configFactory->get('activitypub.settings')->get('filter_format')));
        break;
      case 'object':
      case 'inReplyTo':
        // This can either be a link field or just a text field.
        if (!empty($value[0]['uri'])) {
          $return = $value[0]['uri'];
        }
        if (!empty($value[0]['value'])) {
          $return = $value[0]['value'];
        }
        break;
      case 'attachment':
        $return = [];
        foreach ($value as $v) {
          // Check if field_type is coming from media entity reference field
          // type.
          if ($field_type == 'entity_reference') {
            /** @var \Drupal\media\MediaInterface $media */
            $media = $this->entityTypeManager->getStorage('media')->load($v['target_id']);
            $fid = $media->getSource()->getSourceFieldValue($media);
            /** @var \Drupal\file\FileInterface $file */
            $file = $this->entityTypeManager->getStorage('file')->load($fid);
          }
          else {
            /** @var \Drupal\file\FileInterface $file */
            $file = $this->entityTypeManager->getStorage('file')->load($v['target_id']);
          }
          $type = $this->getMediaType($file);
          $return[] = (object) [
            'type' => $type,
            'mediaType' => $file->getMimeType(),
            'url' => $this->getFileUrl($file, $type),
          ];
        }
        break;
    }

    return $return;
  }

  /**
   * Get the media type.
   *
   * @param \Drupal\file\FileInterface $file
   *
   * @return string
   */
  protected function getMediaType(FileInterface $file) {
    $type = 'Document';

    switch ($file->getMimeType()) {
      case 'image/jpg':
      case 'image/jpeg':
      case 'image/webp':
      case 'image/png':
      case 'image/gif':
        $type = 'Image';
        break;
      case 'video/mpeg':
      case 'video/mp4':
      case 'video/quicktime':
      case 'video/ogg':
        $type = 'Video';
        break;
      case 'audio/ogg':
      case 'audio/mp3':
        $type = 'Audio';
        break;
    }

    return $type;
  }

  /**
   * Gets the file URL.
   *
   * @param \Drupal\file\FileInterface $file
   * @param string $type
   *
   * @return string
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  protected function getFileUrl(FileInterface $file, string $type) {
    $config = $this->configFactory->get('activitypub.settings');
    $attachment_content_style = $config->get('attachment_content_style');
    if (!empty($attachment_content_style) && $type == 'Image') {
      /** @var \Drupal\image\ImageStyleInterface $image_style */
      $storage = $this->entityTypeManager->getStorage('image_style');
      $image_style = $storage->load($attachment_content_style);
      return $image_style->buildUrl($file->getFileUri());
    }
    else {
      return $this->fileUrlGenerator->generateAbsoluteString($file->getFileUri());
    }
  }

  /**
   * Render a URL from an entity.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *
   * @return string
   */
  protected function renderEntityUrl(EntityInterface $entity) {
    return $this->renderer->executeInRenderContext(new RenderContext(), function () use ($entity) {
      return $entity->toUrl('canonical', ['absolute' => TRUE])->toString();
    });
  }

  /**
   * Render a Url.
   *
   * @param \Drupal\Core\Url $url
   *
   * @return string
   */
  protected function renderUrl(Url $url) {
    return $this->renderer->executeInRenderContext(new RenderContext(), function () use ($url) {
      return $url->toString();
    });
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'activity' => '',
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function setConfiguration(array $configuration) {
    $this->configuration = NestedArray::mergeDeep(
      $this->defaultConfiguration(),
      $configuration
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getConfiguration() {
    return $this->configuration;
  }

  /**
   * {@inheritdoc}
   */
  public function calculateDependencies() {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {

    $entity_type_id = $this->getConfiguration()['target_entity_type_id'];

    $entity_types = ['node' => $this->t('Content')];
    if (\Drupal::moduleHandler()->moduleExists('comment')) {
      $entity_types['comment'] = $this->t('Comment');
    }
    $form['target_entity_type_id'] = [
      '#type' => 'select',
      '#title' => $this->t('Entity type'),
      '#options' => $entity_types,
      '#default_value' => $entity_type_id,
      '#ajax' => [
        'trigger_as' => ['name' => 'type_configure'],
        'callback' => '::buildAjaxTypeForm',
        'wrapper' => 'type-config-form',
        'method' => 'replace',
        'effect' => 'fade',
      ],
    ];

    if ($entity_type_id == 'comment') {
      $bundle_options = activitypub_comment_get_names();
    }
    else {
      $bundle_options = node_type_get_names();
    }
    $form['target_bundle'] = [
      '#type' => 'select',
      '#title' => $this->t('Type'),
      '#options' => ['' => $this->t('- Select -')] + $bundle_options,
      '#default_value' => $this->getConfiguration()['target_bundle'],
      '#ajax' => [
        'trigger_as' => ['name' => 'type_configure'],
        'callback' => '::buildAjaxTypeForm',
        'wrapper' => 'type-config-form',
        'method' => 'replace',
        'effect' => 'fade',
      ],
    ];

    $activitypub_activity_options = ['' => $this->t('- Select -')];
    $activitypub_object_options = ['' => $this->t('- Select -')];

    foreach ($this->getActivities() as $a) {
      $activitypub_activity_options[$a] = $a;
    }
    foreach ($this->getObjects() as $o) {
      $option_id = $o;
      $activitypub_object_options[$option_id] = $o;
    }

    $form['activity'] = [
      '#type' => 'select',
      '#title' => $this->t('ActivityPub activity'),
      '#default_value' => $this->getConfiguration()['activity'],
      '#options' => $activitypub_activity_options,
    ];

    $form['object'] = [
      '#type' => 'select',
      '#title' => $this->t('ActivityPub object'),
      '#default_value' =>$this->getConfiguration()['object'],
      '#options' => $activitypub_object_options,
    ];

    return $form;
  }

  /**
   * Gets an entity from an url.
   *
   * @param $url string
   *   The string url to obtain an entity.
   *
   * @return \Drupal\Core\Entity\EntityInterface $entity|NULL
   *   Returns an entity or NULL.
   */
  public static function getEntityFromUrl(string $url) {
    $host = \Drupal::request()->getSchemeAndHttpHost();
    try {
      if (UrlHelper::externalIsLocal($url, $host)) {
        $path = str_replace($host . base_path(), '', $url);
        /** @var \Drupal\Core\Path\PathValidatorInterface $validator */
        $validator = \Drupal::service('path.validator');
        $url_object = $validator->getUrlIfValidWithoutAccessCheck($path);
        if ($url_object && in_array($url_object->getRouteName(), ["entity.node.canonical", "activitypub.user.self", "entity.comment.canonical"])) {
          $entity_type_id = $entity_id = NULL;
          switch ($url_object->getRouteName()) {
            case 'entity.node.canonical':
              $entity_type_id = 'node';
              $entity_id = $url_object->getRouteParameters()['node'];
              break;
            case 'entity.comment.canonical':
              $entity_type_id = 'comment';
              $entity_id = $url_object->getRouteParameters()['comment'];
              break;
            case 'activitypub.user.self':
              $entity_type_id = 'user';
              $entity_id = $url_object->getRouteParameters()['user'];
              break;
          }

          if ($entity_type_id && $entity_id) {
            $entity = \Drupal::entityTypeManager()->getStorage($entity_type_id)->load($entity_id);
            if ($entity) {
              return $entity;
            }
          }
        }
      }
    }
    catch (\Exception $ignored) {}

    return NULL;
  }

  /**
   * Build audience for an activity.
   *
   * @param $to
   * @param $cc
   * @param $mention
   * @param \Drupal\activitypub\Entity\ActivityPubActivityInterface $activity
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  protected function buildAudience(&$to, &$cc, &$mention, ActivityPubActivityInterface $activity) {
    if ($activity->isUnlisted()) {
      return;
    }

    $to = $activity->getTo();

    if ($activity->isPublic()) {
      array_unshift($to, ActivityPubActivityInterface::PUBLIC_URL);
    }

    if ($activity->isPublic() || $activity->isFollowers()) {
      /** @var \Drupal\activitypub\Entity\ActivityPubActorInterface $actor */
      $actor = $this->entityTypeManager->getStorage('activitypub_actor')->loadActorByEntityIdAndType($activity->getOwnerId(), 'person');
      $followers_url = $this->renderUrl(Url::fromRoute('activitypub.followers', ['user' => $actor->getOwnerId(), 'activitypub_actor' => $actor->getName()], ['absolute' => TRUE]));
      if ($activity->isPublic()) {
        $cc = [$followers_url];
      }
      else {
        $to = [$followers_url];
      }
    }

    if ($activity->isPrivate()) {
      if (!empty($to[0])) {
        $href = $to[0];
        $parsed = parse_url($href);
        if (!empty($parsed['host']) && !empty($parsed['path'])) {
          // A bit naive, but let's fix this later.
          $ex = explode('/', $parsed['path']);
          $username = array_pop($ex);
          $name = '@' . $username . '@' . $parsed['host'];
        }
        else {
          $name = $href;
        }
        $mention = [
          'type' => 'Mention',
          'href' => $href,
          'name' => $name,
        ];
      }
    }

    $audience = ['to' => $to, 'cc' => $cc, 'mention' => $mention];
    $event = new ActivityAudienceEvent($activity, $audience);
    $this->eventDispatcher->dispatch($event, ActivityAudienceEvent::ALTER_AUDIENCE);
    $audience = $event->getAudience();
    $to = $audience['to'];
    $cc = $audience['cc'];
    $mention = $audience['mention'];
  }

}

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

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