activitypub-1.0.x-dev/src/Services/ActivityPubFormAlter.php

src/Services/ActivityPubFormAlter.php
<?php

namespace Drupal\activitypub\Services;

use Drupal\Core\Cache\Cache;
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\user\EntityOwnerInterface;

class ActivityPubFormAlter implements ActivityPubFormAlterInterface {

  use StringTranslationTrait;
  use DependencySerializationTrait {
    __sleep as traitSleep;
  }

  /**
   * The ActivityPub Actor storage.
   *
   * @var \Drupal\activitypub\Entity\Storage\ActivityPubActorStorageInterface
   */
  protected $actorStorage;

  /**
   * The ActivityPub type storage.
   *
   * @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface
   */
  protected $typeStorage;

  /**
   * The ActivityPub Activity  storage.
   *
   * @var \Drupal\activitypub\Entity\Storage\ActivityPubActivityStorageInterface
   */
  protected $activityStorage;

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

  /**
   * The ActivityPub signature service.
   *
   * @var \Drupal\activitypub\Services\ActivityPubSignatureInterface
   */
  protected $activityPubSignature;

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $currentUser;

  /**
   * The messenger.
   *
   * @var \Drupal\Core\Messenger\MessengerInterface
   */
  protected $messenger;

  /**
   * The outbox service.
   *
   * @var \Drupal\activitypub\Services\ActivityPubOutboxInterface
   */
  protected $outbox;

  /**
   * ActivityPubFormAlter constructor
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\activitypub\Services\ActivityPubUtilityInterface $activitypub_utility
   *   The ActivityPub utility service.
   * @param \Drupal\Core\Session\AccountInterface $current_user
   *   The current user.
   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
   *   The messenger.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager, ActivityPubUtilityInterface $activitypub_utility, ActivityPubSignatureInterface $activitypub_signature, AccountInterface $current_user, MessengerInterface $messenger, ActivityPubOutboxInterface $outbox) {
    $this->actorStorage = $entity_type_manager->getStorage('activitypub_actor');
    $this->typeStorage = $entity_type_manager->getStorage('activitypub_type');
    $this->activityStorage = $entity_type_manager->getStorage('activitypub_activity');
    $this->activityPubUtility = $activitypub_utility;
    $this->activityPubSignature = $activitypub_signature;
    $this->currentUser = $current_user;
    $this->messenger = $messenger;
    $this->outbox = $outbox;
  }

  /**
   * {@inheritdoc}
   */
  public function addActivityPubSettingsFormElement(array &$form, FormStateInterface $form_state, EntityInterface $entity, $type) {

    if (!\Drupal::hasService('stream_wrapper.private')) {
      $this->messenger->addWarning($this->t('Warning: the private folder has not been configured.'));
    }

    /** @var \Drupal\activitypub\Entity\ActivityPubActorInterface $actor */
    $actor = $this->actorStorage->loadActorByEntityIdAndType($entity->id(), $type);

    $form['activitypub'] = [
      '#type' => 'container',
    ];

    $form['activitypub']['entity'] = [
      '#type' => 'value',
      '#value' => $entity,
    ];

    if ($actor) {
      $form['activitypub']['info'] = [
        '#markup' => '<p>' . $this->t('ActivityPub is enabled.') . '</p>',
      ];
      $form['activitypub']['name'] = [
        '#markup' => '<p>' . $this->t('Your Fediverse identifier for this site is @name. Try entering @name in Mastodon or Pixelfed search.', ['@name' => $this->activityPubUtility->getActivityPubName($actor)]) . '</p>',
      ];
      $form['activitypub']['activitypub_actor'] = [
        '#type' => 'value',
        '#value' => $actor->id(),
      ];
    }
    else {

      $form['activitypub']['activitypub_type'] = [
        '#type' => 'value',
        '#value' => $type,
      ];

      $form['activitypub']['activitypub_enable'] = [
        '#type' => 'checkbox',
        '#title' => $this->t('Enable ActivityPub'),
      ];

      $form['activitypub']['activitypub_name'] = [
        '#type' => 'textfield',
        '#title' => $this->t('Name'),
        '#description' => $this->t('It must only contain letters and numbers.'),
        '#states' => [
          'visible' => [':input[name="activitypub_enable"]' => ['checked' => TRUE]]
        ],
      ];

      $form['#validate'][] = [$this, 'validateSettingsForm'];
    }

    $form['activitypub']['activitypub_summary'] = [
      '#type' => 'textarea',
      '#title' => $this->t('Bio'),
      '#description' => $this->t('Add a summary for this profile.'),
    ];

    $form['activitypub']['activitypub_blocked_domains'] = [
      '#type' => 'textarea',
      '#title' => $this->t('Blocked domains'),
      '#description' => $this->t('Block domains from sending messages to your Inbox. Enter domains line per line. Wildcards are supported.'),
    ];

    if (!$actor) {
      $form['activitypub']['activitypub_summary']['#states'] = [
        'visible' => [':input[name="activitypub_enable"]' => ['checked' => TRUE]]
      ];
      $form['activitypub']['activitypub_blocked_domains']['#states'] = [
        'visible' => [':input[name="activitypub_enable"]' => ['checked' => TRUE]]
      ];
    }
    else {
      $form['activitypub']['activitypub_summary']['#default_value'] = $actor->getSummary();
      $form['activitypub']['activitypub_blocked_domains']['#default_value'] = $actor->getBlockedDomains();
    }

    $form['actions'] = [
      '#type' => 'actions',
    ];
    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#button_type' => 'primary',
      '#value' => $this->t('Save'),
    ];
    if ($actor) {
      $form['actions']['delete'] = [
        '#weight' => 20,
        '#markup' => Link::fromTextAndUrl($this->t('Delete'), Url::fromRoute('activitypub.actor.delete', ['user' => $actor->getOwnerId(), 'activitypub_actor' => $actor->getName()], ['attributes' => ['class' => ['button--danger', 'button']]]))->toString(),
      ];
    }

    $form['#submit'][] = [$this, 'submitSettingsForm'];
  }

  /**
   * Validate callback for the ActivityPub settings form element.
   *
   * @param $form
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   */
  public function validateSettingsForm($form, FormStateInterface $form_state) {
    if ($form_state->getValue('activitypub_enable')) {
      $name = trim($form_state->getValue('activitypub_name'));
      if (empty($name)) {
        $form_state->setErrorByName('activitypub_name', $this->t('Please enter your ActivityPub username.'));
      }
      elseif (!ctype_alnum($name)) {
        $form_state->setErrorByName('activitypub_name', $this->t('The username can only contain letters and numbers.'));
      }
      elseif ($this->actorStorage->nameExists($name)) {
        $form_state->setErrorByName('activitypub_name', $this->t('This username is already taken.'));
      }
    }
  }

  /**
   * Submit callback for the ActivityPub settings form element.
   *
   * @param $form
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *
   * @throws \Drupal\Core\Entity\EntityStorageException
   */
  public function submitSettingsForm($form, FormStateInterface $form_state) {
    $entity = $form_state->getValue('entity');

    if ($form_state->getValue('activitypub_enable')) {

      $values = [
        'entity_id' => $entity->id(),
        'type' => $form_state->getValue('activitypub_type'),
        'name' => trim($form_state->getValue('activitypub_name')),
      ];

      if (!empty($form_state->getValue('activitypub_blocked_domains'))) {
        $values['blocked_domains'] = $form_state->getValue('activitypub_blocked_domains');
      }
      if (!empty($form_state->getValue('activitypub_summary'))) {
        $values['summary'] = $form_state->getValue('activitypub_summary');
      }

      if ($entity instanceof EntityOwnerInterface) {
        $values['uid'] = $entity->getOwnerId();
      }

      /** @var \Drupal\activitypub\Entity\ActivityPubActorInterface $actor */
      $actor = $this->actorStorage->create($values);
      if ($this->activityPubSignature->generateKeys($actor->getName())) {
        $actor->save();
      }
      else {
        $this->messenger->addError($this->t('Error while creating keys: This may be caused by a problem with file or directory permissions. Check the logs or ask an administrator.'));
      }
    }
    elseif ($form_state->getValue('activitypub_actor')) {
      /** @var \Drupal\activitypub\Entity\ActivityPubActorInterface $actor */
      $actor = $this->actorStorage->load($form_state->getValue('activitypub_actor'));
      $actor->set('blocked_domains', $form_state->getValue('activitypub_blocked_domains'));
      $actor->set('summary', $form_state->getValue('activitypub_summary'));
      $actor->save();
      $this->messenger->addMessage($this->t('Settings saved'));
    }

    Cache::invalidateTags([$entity->getEntityTypeId() . ':' . $entity->id()]);
  }

  /**
   * {@inheritdoc}
   */
  public function addActivityPubOutboxFormElement(array &$form, FormStateInterface $form_state, EntityInterface $entity) {

    $config = \Drupal::configFactory()->getEditable('activitypub.settings');

    $actor = $this->actorStorage->loadActorByEntityIdAndType($this->currentUser->id(), 'person');

    // Check if a site-wide actor is configured and the current user has the permission to publish.
    if (!$actor) {
      $site_wide_uid = $config->get('site_wide_uid');
      if ($site_wide_uid && $this->currentUser->hasPermission('publish to site-wide actor')) {
        $actor = $this->actorStorage->loadActorByEntityIdAndType($site_wide_uid, 'person');
      }
    }

    if (!$actor) {
      return;
    }

    $create_options = $update_options = [];
    $outbox_selected = [];
    /** @var \Drupal\activitypub\Entity\ActivityPubActivityInterface[] $outboxEntities */
    if ($entity->id()) {
      $outboxEntities = $this->activityStorage->loadByProperties(['entity_type_id' => $entity->getEntityTypeId(), 'entity_id' => $entity->id(), 'collection' => 'outbox']);
      foreach ($outboxEntities as $outboxEntity) {
        $outbox_selected[$outboxEntity->getConfigID()] = $outboxEntity->id();
      }
    }

    /** @var \Drupal\activitypub\Entity\ActivityPubTypeInterface[] $typeEntities */
    $typeEntities = $this->typeStorage->loadByProperties(['status' => TRUE, 'plugin.configuration.target_entity_type_id' => $entity->getEntityTypeId(), 'plugin.configuration.target_bundle' => $entity->bundle()]);
    if (!$typeEntities) {
      return;
    }

    foreach ($typeEntities as $typeEntity) {
      if (!isset($outbox_selected[$typeEntity->id()])) {
        $create_options[$typeEntity->id()] = $typeEntity->label();
      }
      elseif ($typeEntity->getPlugin()['id'] == 'activitypub_dynamic_types' && $typeEntity->getPlugin()['configuration']['activity'] == 'Create' && in_array($typeEntity->getPlugin()['configuration']['object'], ['Note', 'Article'])) {
        $update_options[$outbox_selected[$typeEntity->id()]] = $typeEntity->label();
      }
    }

    $form['activitypub_actor'] = [
      '#type' => 'value',
      '#value' => $actor,
    ];

    $form['activitypub_wrapper'] = [
      '#type' => 'details',
      '#title' => $this->t('ActivityPub outbox'),
      '#group' => 'advanced',
    ];

    if ($create_options || $update_options) {
      $form['activitypub_wrapper']['activitypub_create'] = [
        '#type' => 'select',
        '#title' => $this->t('Create'),
        '#options' => ['' => $this->t('- Select -')] + $create_options,
        '#access' => !empty($create_options),
      ];

      $form['activitypub_wrapper']['activitypub_update'] = [
        '#type' => 'select',
        '#title' => $this->t('Update'),
        '#options' => ['' => $this->t('- Select -')] + $update_options,
        '#access' => !$entity->isNew() && !empty($update_options),
      ];

      $form['activitypub_wrapper']['activitypub_visibility'] = [
        '#type' => 'select',
        '#title' => $this->t('Post privacy'),
        '#options' => $this->activityPubUtility->getVisibilityOptions(),
        '#access' => !empty($create_options),
        '#states' => [
          'visible' => [
            ':input[name="activitypub_create"]' => ['!value' => ''],
          ]
        ],
      ];

      $form['activitypub_wrapper']['activitypub_to'] = [
        '#type' => 'textarea',
        '#title' => $this->t('Send to'),
        '#description' => $this->t('Add URL\'s of (remote) users line per line. Only add those who do not follow you.'),
        '#default_value' => !empty($_GET['to']) ? $_GET['to'] : '',
        '#access' => !empty($create_options),
        '#states' => [
          'visible' => [
            ':input[name="activitypub_create"]' => ['!value' => ''],
          ]
        ],
      ];

      foreach (array_keys($form['actions']) as $action) {
        if ($action === 'submit' && isset($form['actions'][$action]['#type']) && $form['actions'][$action]['#type'] === 'submit') {
          $form['actions'][$action]['#submit'][] = [$this, 'submitOutboxForm'];
        }
      }
    }
    else {
      $form['activitypub_wrapper']['activitypub_sent'] = [
        '#markup' => $this->t('This post has been sent to the outbox.'),
      ];
    }
  }

  /**
   * Submit outbox form.
   *
   * @param $form
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *
   * @throws \Drupal\Core\Entity\EntityStorageException
   */
  public function submitOutboxForm($form, FormStateInterface $form_state) {
    /** @var \Drupal\Core\Entity\EntityInterface $entity */
    $entity = $form_state->getFormObject()->getEntity();
    if ($type = $form_state->getValue('activitypub_create')) {
      $this->outbox->createActivity($type, $entity, $form_state->getValue('activitypub_actor'), $form_state->getValue('activitypub_visibility'), $form_state->getValue('activitypub_to'));
    }

    if ($update = $form_state->getValue('activitypub_update')) {
      /** @var \Drupal\activitypub\Entity\ActivityPubActivityInterface $activity */
      $activity = $this->activityStorage->load($update);
      $this->outbox->updateActivity($activity);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function alterCommentForm(array &$form, FormStateInterface $form_state, EntityInterface $entity) {
    /** @var \Drupal\comment\CommentInterface $entity */
    if (isset($form['activitypub_activity'])) {
      $actor = $this->actorStorage->loadActorByEntityIdAndType($this->currentUser->id(), 'person');
      if (!$actor) {
        $form['activitypub_activity']['#access'] = $this->currentUser->hasPermission('administer comments');
      }
      else {
        $form['activitypub_activity']['#access'] = $this->currentUser->hasPermission('administer comments') || ($actor->getOwnerId() == $this->currentUser->id() && $actor->getOwnerId() == $entity->getCommentedEntity()->getOwnerId());
      }
    }
  }

}

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

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