You are here

class ActivityFactory in Open Social 8

Same name and namespace in other branches
  1. 8.9 modules/custom/activity_creator/src/ActivityFactory.php \Drupal\activity_creator\ActivityFactory
  2. 8.2 modules/custom/activity_creator/src/ActivityFactory.php \Drupal\activity_creator\ActivityFactory
  3. 8.3 modules/custom/activity_creator/src/ActivityFactory.php \Drupal\activity_creator\ActivityFactory
  4. 8.4 modules/custom/activity_creator/src/ActivityFactory.php \Drupal\activity_creator\ActivityFactory
  5. 8.5 modules/custom/activity_creator/src/ActivityFactory.php \Drupal\activity_creator\ActivityFactory
  6. 8.6 modules/custom/activity_creator/src/ActivityFactory.php \Drupal\activity_creator\ActivityFactory
  7. 8.7 modules/custom/activity_creator/src/ActivityFactory.php \Drupal\activity_creator\ActivityFactory
  8. 8.8 modules/custom/activity_creator/src/ActivityFactory.php \Drupal\activity_creator\ActivityFactory
  9. 10.3.x modules/custom/activity_creator/src/ActivityFactory.php \Drupal\activity_creator\ActivityFactory
  10. 10.0.x modules/custom/activity_creator/src/ActivityFactory.php \Drupal\activity_creator\ActivityFactory
  11. 10.1.x modules/custom/activity_creator/src/ActivityFactory.php \Drupal\activity_creator\ActivityFactory
  12. 10.2.x modules/custom/activity_creator/src/ActivityFactory.php \Drupal\activity_creator\ActivityFactory

Class ActivityFactory to create Activity items based on ActivityLogs.

@package Drupal\activity_creator

Hierarchy

Expanded class hierarchy of ActivityFactory

5 files declare their use of ActivityFactory
ActivityWorkerActivities.php in modules/custom/activity_creator/src/Plugin/QueueWorker/ActivityWorkerActivities.php
ContentInMyGroupActivityContext.php in modules/custom/activity_basics/src/Plugin/ActivityContext/ContentInMyGroupActivityContext.php
FollowContentActivityContext.php in modules/social_features/social_follow_content/src/Plugin/ActivityContext/FollowContentActivityContext.php
OwnerActivityContext.php in modules/custom/activity_basics/src/Plugin/ActivityContext/OwnerActivityContext.php
ProfileActivityContext.php in modules/custom/activity_basics/src/Plugin/ActivityContext/ProfileActivityContext.php
1 string reference to 'ActivityFactory'
activity_creator.services.yml in modules/custom/activity_creator/activity_creator.services.yml
modules/custom/activity_creator/activity_creator.services.yml
1 service uses ActivityFactory
activity_creator.activity_factory in modules/custom/activity_creator/activity_creator.services.yml
Drupal\activity_creator\ActivityFactory

File

modules/custom/activity_creator/src/ActivityFactory.php, line 17

Namespace

Drupal\activity_creator
View source
class ActivityFactory extends ControllerBase {

  /**
   * Activity destination manager.
   *
   * @var \Drupal\activity_creator\Plugin\ActivityDestinationManager
   */
  protected $activityDestinationManager;

  /**
   * ActivityFactory constructor.
   *
   * @param \Drupal\activity_creator\Plugin\ActivityDestinationManager $activityDestinationManager
   *   The activity destination manager.
   */
  public function __construct(ActivityDestinationManager $activityDestinationManager) {
    $this->activityDestinationManager = $activityDestinationManager;
  }

  /**
   * Create the activities based on a data array.
   *
   * @param array $data
   *   An array of data to create activity from.
   *
   * @return array
   *   An array of created activities.
   */
  public function createActivities(array $data) {
    $activities = $this
      ->buildActivities($data);
    return $activities;
  }

  /**
   * Build the activities based on a data array.
   *
   * @param array $data
   *   An array of data to create activity from.
   *
   * @return array
   *   An array of created activities.
   */
  protected function buildActivities(array $data) {
    $activities = [];
    $message = Message::load($data['mid']);

    // Initialize fields for new activity entity.
    $activity_fields = [
      'created' => $this
        ->getCreated($message),
      'field_activity_destinations' => $this
        ->getFieldDestinations($data),
      'field_activity_entity' => $this
        ->getFieldEntity($data),
      'field_activity_message' => $this
        ->getFieldMessage($data),
      'field_activity_output_text' => $this
        ->getFieldOutputText($message),
      'field_activity_recipient_group' => $this
        ->getFieldRecipientGroup($data),
      'field_activity_recipient_user' => $this
        ->getFieldRecipientUser($data),
      // Default activity status.
      'field_activity_status' => ACTIVITY_STATUS_RECEIVED,
      'user_id' => $this
        ->getActor($data),
    ];

    // Check if aggregation is enabled for this message type.
    // @TODO: Consider if we should put aggregation to separate service.
    if ($this
      ->getAggregationSettings($message)) {
      $activities = $this
        ->buildAggregatedActivites($data, $activity_fields);
    }
    else {
      $activity = Activity::create($activity_fields);
      $activity
        ->save();
      $activities[] = $activity;
    }
    return $activities;
  }

  /**
   * Get field value for 'destination' field from data array.
   */
  protected function getFieldDestinations(array $data, $allowed_destinations = []) {
    $value = NULL;
    if (isset($data['destination'])) {
      $value = $data['destination'];
      if (!empty($allowed_destinations)) {
        foreach ($value as $key => $destination) {
          if (!in_array($destination['value'], $allowed_destinations)) {
            unset($value[$key]);
          }
        }
      }
    }
    return $value;
  }

  /**
   * Get field value for 'entity' field from data array.
   */
  protected function getFieldEntity($data) {
    $value = NULL;
    if (isset($data['related_object'])) {
      $value = $data['related_object'];
    }
    return $value;
  }

  /**
   * Get field value for 'message' field from data array.
   */
  protected function getFieldMessage($data) {
    $value = NULL;
    if (isset($data['mid'])) {
      $value = [];
      $value[] = [
        'target_id' => $data['mid'],
      ];
    }
    return $value;
  }

  /**
   * Get field value for 'output_text' field from data array.
   */
  protected function getFieldOutputText(Message $message, $arguments = []) {
    $value = NULL;
    if (isset($message)) {
      $value = $this
        ->getMessageText($message);

      // Text for aggregated activities.
      if (!empty($value[1]) && !empty($arguments)) {
        $text = str_replace('@count', $arguments['@count'], $value[1]);
      }
      else {
        $text = $value[0];
      }

      // Add format.
      $value = [
        '0' => [
          'value' => $text,
          'format' => 'basic_html',
        ],
      ];
    }
    return $value;
  }

  /**
   * Get field value for 'created' field from data array.
   */
  protected function getCreated(Message $message) {
    $value = NULL;
    if (isset($message)) {
      $value = $message
        ->getCreatedTime();
    }
    return $value;
  }

  /**
   * Get aggregation settings from message template.
   */
  protected function getAggregationSettings(Message $message) {
    $message_template = $message
      ->getTemplate();
    return $message_template
      ->getThirdPartySetting('activity_logger', 'activity_aggregate', NULL);
  }

  /**
   * Build the aggregated activities based on a data array.
   */
  protected function buildAggregatedActivites($data, $activity_fields) {
    $activities = [];
    $common_destinations = $this->activityDestinationManager
      ->getListByProperties('isCommon', TRUE);
    $personal_destinations = $this->activityDestinationManager
      ->getListByProperties('isCommon', FALSE);

    // Get related activities.
    $related_activities = $this
      ->getAggregationRelatedActivities($data);
    if (!empty($related_activities)) {

      // Update related activities.
      foreach ($related_activities as $related_activity) {
        $destination = $related_activity->field_activity_destinations->value;

        // If user already have related activity we remove it and create new.
        // And we also remove related activities from common streams.
        if ($related_activity
          ->getOwnerId() == $this
          ->getActor($data) || in_array($destination, $common_destinations)) {

          // @TODO: Consider if need to delete or unpublish old activites.
          $related_activity
            ->delete();
        }
        else {

          // For other users we leave activity only on their profile stream.
          $related_activity
            ->set('field_activity_destinations', [
            'stream_profile',
          ]);
          $related_activity
            ->save();
        }
      }

      // Clone activity fields for separate profile stream activity.
      $profile_activity_fields = $activity_fields;

      // Update output text for activity on not user related streams.
      $arguments = [];
      $message = Message::load($data['mid']);
      $count = $this
        ->getAggregationAuthorsCount($data);
      if (is_numeric($count) && $count > 1) {
        $arguments = [
          '@count' => $count - 1,
        ];
      }
      $activity_fields['field_activity_output_text'] = $this
        ->getFieldOutputText($message, $arguments);
      $activity_fields['field_activity_destinations'] = $this
        ->getFieldDestinations($data, $common_destinations);

      // Create separate activity for activity on user related streams.
      $profile_activity_fields['field_activity_destinations'] = $this
        ->getFieldDestinations($data, $personal_destinations);
      $activity = Activity::create($profile_activity_fields);
      $activity
        ->save();
      $activities[] = $activity;
    }
    $activity = Activity::create($activity_fields);
    $activity
      ->save();
    $activities[] = $activity;
    return $activities;
  }

  /**
   * Get related activities for activity aggregation.
   */
  protected function getAggregationRelatedActivities($data) {
    $activities = [];
    $related_object = $data['related_object'][0];
    if (!empty($related_object['target_id']) && !empty($related_object['target_type'])) {
      if ($related_object['target_type'] === 'comment') {

        // Get commented entity.
        $comment_storage = \Drupal::entityTypeManager()
          ->getStorage('comment');
        $comment = $comment_storage
          ->load($related_object['target_id']);
        $commented_entity = $comment
          ->getCommentedEntity();

        // Get all comments of commented entity.
        $comment_query = \Drupal::entityQuery('comment');
        $comment_query
          ->condition('entity_id', $commented_entity
          ->id(), '=');
        $comment_query
          ->condition('entity_type', $commented_entity
          ->getEntityTypeId(), '=');
        $comment_ids = $comment_query
          ->execute();

        // Get all activities provided by comments of commented entity.
        if (!empty($comment_ids)) {
          $activity_query = \Drupal::entityQuery('activity');
          $activity_query
            ->condition('field_activity_entity.target_id', $comment_ids, 'IN');
          $activity_query
            ->condition('field_activity_entity.target_type', $related_object['target_type'], '=');

          // We exclude activities with email, platform_email and notifications
          // destinations from aggregation.
          $aggregatable_destinations = $this->activityDestinationManager
            ->getListByProperties('isAggregatable', TRUE);
          $activity_query
            ->condition('field_activity_destinations.value', $aggregatable_destinations, 'IN');
          $activity_ids = $activity_query
            ->execute();
          if (!empty($activity_ids)) {
            $activities = Activity::loadMultiple($activity_ids);
          }
        }
      }
    }
    return $activities;
  }

  /**
   * Get related entity for activity aggregation.
   */
  public static function getActivityRelatedEntity($data) {
    $related_object = $data['related_object'][0];

    // We return parent comment as related object as comment
    // for create_comment_reply messages.
    if ($data['message_template'] === 'create_comment_reply') {
      $comment_storage = \Drupal::entityTypeManager()
        ->getStorage('comment');

      // @TODO: Check if comment published?
      $comment = $comment_storage
        ->load($related_object['target_id']);
      $parent_comment = $comment
        ->getParentComment();
      if (!empty($parent_comment)) {
        $related_object = [
          'target_type' => $parent_comment
            ->getEntityTypeId(),
          'target_id' => $parent_comment
            ->id(),
        ];
      }
    }
    elseif (isset($related_object['target_type']) && $related_object['target_type'] === 'comment') {
      $comment_storage = \Drupal::entityTypeManager()
        ->getStorage('comment');

      // @todo: Check if comment published?
      $comment = $comment_storage
        ->load($related_object['target_id']);
      if ($comment) {
        $commented_entity = $comment
          ->getCommentedEntity();
        if (!empty($commented_entity)) {
          $related_object = [
            'target_type' => $commented_entity
              ->getEntityTypeId(),
            'target_id' => $commented_entity
              ->id(),
          ];
        }
      }
    }
    return $related_object;
  }

  /**
   * Get unique authors number for activity aggregation.
   */
  protected function getAggregationAuthorsCount(array $data) {
    $count = 0;
    $related_object = $data['related_object'][0];
    if (isset($related_object['target_type']) && $related_object['target_type'] === 'comment') {

      // Get related entity.
      $related_entity = $this
        ->getActivityRelatedEntity($data);
      if (!empty($related_entity['target_id']) && !empty($related_entity['target_type'])) {
        $query = \Drupal::database()
          ->select('comment_field_data', 'cfd');
        $query
          ->addExpression('COUNT(DISTINCT cfd.uid)');
        $query
          ->condition('cfd.status', 1);
        $query
          ->condition('cfd.entity_type', $related_entity['target_type']);
        $query
          ->condition('cfd.entity_id', $related_entity['target_id']);
        $count = $query
          ->execute()
          ->fetchField();
      }
    }
    return $count;
  }

  /**
   * Get field value for 'recipient_group' field from data array.
   */
  protected function getFieldRecipientGroup($data) {
    $value = NULL;
    if (isset($data['recipient'])) {
      if ($data['recipient']['target_type'] === 'group') {

        // Should be in an array for the field.
        $value = [
          $data['recipient'],
        ];
      }
    }
    return $value;
  }

  /**
   * Get field value for 'recipient_user' field from data array.
   */
  protected function getFieldRecipientUser($data) {
    $value = NULL;
    if (isset($data['recipient']) && is_array($data['recipient'])) {
      if ($data['recipient']['target_type'] === 'user') {

        // Should be in an array for the field.
        $value = [
          $data['recipient'],
        ];
      }
    }
    return $value;
  }

  /**
   * Return the actor uid.
   *
   * @param array $data
   *   Array of data.
   *
   * @return int
   *   Value uid integer.
   */
  protected function getActor(array $data) {
    $value = 0;
    if (isset($data['actor'])) {
      $value = $data['actor'];
    }
    return $value;
  }

  /**
   * Get message text.
   *
   * @param \Drupal\message\Entity\Message $message
   *   Message object we get the text for.
   * @param string $langcode
   *   The language code we try to get the translation for.
   *
   * @return array
   *   Message text array.
   */
  public function getMessageText(Message $message, $langcode = '') {

    /** @var \Drupal\message\Entity\MessageTemplate $message_template */
    $message_template = $message
      ->getTemplate();
    $message_arguments = $message
      ->getArguments();
    $message_template_text = $message_template
      ->get('text');

    // If we have a language code here we can try to get a translated text.
    if (!empty($langcode)) {
      $language_manager = \Drupal::languageManager();
      if ($language_manager instanceof ConfigurableLanguageManagerInterface) {

        // Load the language override for the message template.
        $config_translation = $language_manager
          ->getLanguageConfigOverride($langcode, 'message.template.' . $message_template
          ->id());
        $translated_text = $config_translation
          ->get('text');

        // Replace the text *only* if we have an translation available.
        if ($translated_text) {
          $message_template_text = $translated_text;
        }
      }
    }
    $output = $this
      ->processArguments($message_arguments, $message_template_text, $message);
    $token_options = $message_template
      ->getSetting('token options', []);
    if (!empty($token_options['token replace'])) {

      // Token should be processed.
      $output = $this
        ->processTokens($output, !empty($token_options['clear']), $message);
    }
    return $output;
  }

  /**
   * Process the message given the arguments saved with it.
   *
   * @param array $arguments
   *   Array with the arguments.
   * @param array $output
   *   Array with the templated text saved in the message template.
   * @param \Drupal\message\Entity\Message $message
   *   Message object.
   *
   * @return array
   *   The templated text, with the placeholders replaced with the actual value,
   *   if there are indeed arguments.
   */
  protected function processArguments(array $arguments, array $output, Message $message) {

    // Check if we have arguments saved along with the message.
    if (empty($arguments)) {
      return $output;
    }
    foreach ($arguments as $key => $value) {
      if (is_array($value) && !empty($value['callback']) && is_callable($value['callback'])) {

        // A replacement via callback function.
        $value += [
          'pass message' => FALSE,
        ];
        if ($value['pass message']) {

          // Pass the message object as-well.
          $value['arguments']['message'] = $message;
        }
        $arguments[$key] = call_user_func_array($value['callback'], $value['arguments']);
      }
    }
    foreach ($output as $key => $value) {
      $output[$key] = new FormattableMarkup($value, $arguments);
    }
    return $output;
  }

  /**
   * Replace placeholders with tokens.
   *
   * @param array $output
   *   The templated text to be replaced.
   * @param bool $clear
   *   Determine if unused token should be cleared.
   * @param \Drupal\message\Entity\Message $message
   *   Message object.
   *
   * @return array
   *   The output with placeholders replaced with the token value,
   *   if there are indeed tokens.
   */
  protected function processTokens(array $output, $clear, Message $message) {
    $options = [
      'clear' => $clear,
    ];
    foreach ($output as $key => $value) {
      if (is_string($value)) {
        $output[$key] = \Drupal::token()
          ->replace($value, [
          'message' => $message,
        ], $options);
      }
      else {
        if (isset($value['value'])) {
          $output[$key] = \Drupal::token()
            ->replace($value['value'], [
            'message' => $message,
          ], $options);
        }
      }
    }
    return $output;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
ActivityFactory::$activityDestinationManager protected property Activity destination manager.
ActivityFactory::buildActivities protected function Build the activities based on a data array.
ActivityFactory::buildAggregatedActivites protected function Build the aggregated activities based on a data array.
ActivityFactory::createActivities public function Create the activities based on a data array.
ActivityFactory::getActivityRelatedEntity public static function Get related entity for activity aggregation.
ActivityFactory::getActor protected function Return the actor uid.
ActivityFactory::getAggregationAuthorsCount protected function Get unique authors number for activity aggregation.
ActivityFactory::getAggregationRelatedActivities protected function Get related activities for activity aggregation.
ActivityFactory::getAggregationSettings protected function Get aggregation settings from message template.
ActivityFactory::getCreated protected function Get field value for 'created' field from data array.
ActivityFactory::getFieldDestinations protected function Get field value for 'destination' field from data array.
ActivityFactory::getFieldEntity protected function Get field value for 'entity' field from data array.
ActivityFactory::getFieldMessage protected function Get field value for 'message' field from data array.
ActivityFactory::getFieldOutputText protected function Get field value for 'output_text' field from data array.
ActivityFactory::getFieldRecipientGroup protected function Get field value for 'recipient_group' field from data array.
ActivityFactory::getFieldRecipientUser protected function Get field value for 'recipient_user' field from data array.
ActivityFactory::getMessageText public function Get message text.
ActivityFactory::processArguments protected function Process the message given the arguments saved with it.
ActivityFactory::processTokens protected function Replace placeholders with tokens.
ActivityFactory::__construct public function ActivityFactory constructor.
ControllerBase::$configFactory protected property The configuration factory.
ControllerBase::$currentUser protected property The current user service. 1
ControllerBase::$entityFormBuilder protected property The entity form builder.
ControllerBase::$entityManager protected property The entity manager.
ControllerBase::$entityTypeManager protected property The entity type manager.
ControllerBase::$formBuilder protected property The form builder. 2
ControllerBase::$keyValue protected property The key-value storage. 1
ControllerBase::$languageManager protected property The language manager. 1
ControllerBase::$moduleHandler protected property The module handler. 2
ControllerBase::$stateService protected property The state service.
ControllerBase::cache protected function Returns the requested cache bin.
ControllerBase::config protected function Retrieves a configuration object.
ControllerBase::container private function Returns the service container.
ControllerBase::create public static function Instantiates a new instance of this class. Overrides ContainerInjectionInterface::create 40
ControllerBase::currentUser protected function Returns the current user. 1
ControllerBase::entityFormBuilder protected function Retrieves the entity form builder.
ControllerBase::entityManager Deprecated protected function Retrieves the entity manager service.
ControllerBase::entityTypeManager protected function Retrieves the entity type manager.
ControllerBase::formBuilder protected function Returns the form builder service. 2
ControllerBase::keyValue protected function Returns a key/value storage collection. 1
ControllerBase::languageManager protected function Returns the language manager service. 1
ControllerBase::moduleHandler protected function Returns the module handler. 2
ControllerBase::redirect protected function Returns a redirect response object for the specified route. Overrides UrlGeneratorTrait::redirect
ControllerBase::state protected function Returns the state storage service.
LinkGeneratorTrait::$linkGenerator protected property The link generator. 1
LinkGeneratorTrait::getLinkGenerator Deprecated protected function Returns the link generator.
LinkGeneratorTrait::l Deprecated protected function Renders a link to a route given a route name and its parameters.
LinkGeneratorTrait::setLinkGenerator Deprecated public function Sets the link generator service.
LoggerChannelTrait::$loggerFactory protected property The logger channel factory service.
LoggerChannelTrait::getLogger protected function Gets the logger for a specific channel.
LoggerChannelTrait::setLoggerFactory public function Injects the logger channel factory.
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
RedirectDestinationTrait::$redirectDestination protected property The redirect destination service. 1
RedirectDestinationTrait::getDestinationArray protected function Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url.
RedirectDestinationTrait::getRedirectDestination protected function Returns the redirect destination service.
RedirectDestinationTrait::setRedirectDestination public function Sets the redirect destination service.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
UrlGeneratorTrait::$urlGenerator protected property The url generator.
UrlGeneratorTrait::getUrlGenerator Deprecated protected function Returns the URL generator service.
UrlGeneratorTrait::setUrlGenerator Deprecated public function Sets the URL generator service.
UrlGeneratorTrait::url Deprecated protected function Generates a URL or path for a specific route based on the given parameters.