activity_stream-1.0.x-dev/activity_stream.module
activity_stream.module
<?php
/**
* @file
* Primary module hooks for Activity Stream module.
*/
use Drupal\Core\Render\Element;
use Drupal\user\UserInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\message\Entity\Message;
use Drupal\activity_stream\Plugin\ActivityActionInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityPublishedInterface;
use Drupal\Core\Entity\SynchronizableInterface;
use Drupal\node\NodeInterface;
use Drupal\activity_stream\Entity\Activity;
use Drupal\activity_stream\ActivityInterface;
use Drupal\activity_stream\Service\ActivityStreamBatchActivityDeletion;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\search_api\Task\TaskInterface;
/**
* Implements hook_theme().
*/
function activity_stream_theme(): array {
return [
'activity_stream_activity' => ['render element' => 'elements'],
];
}
/**
* Prepares variables for activity templates.
*
* Default template: activity-stream-activity.html.twig.
*
* @param array $variables
* An associative array containing:
* - elements: An associative array containing the activity information and any
* fields attached to the entity.
* - attributes: HTML attributes for the containing element.
*/
function template_preprocess_activity_stream_activity(array &$variables): void {
$variables['view_mode'] = $variables['elements']['#view_mode'];
foreach (Element::children($variables['elements']) as $key) {
$variables['content'][$key] = $variables['elements'][$key];
}
}
/**
* Implements hook_user_cancel().
*/
function activity_stream_user_cancel($edit, UserInterface $account, $method): void {
switch ($method) {
case 'user_cancel_block_unpublish':
// Unpublish activities.
$storage = \Drupal::entityTypeManager()->getStorage('activity_stream_activity');
$activity_stream_activity_ids = $storage->getQuery()
->condition('uid', $account->id())
->condition('status', 1)
->accessCheck(FALSE)
->execute();
foreach ($storage->loadMultiple($activity_stream_activity_ids) as $activity_stream_activity) {
$activity_stream_activity->set('status', FALSE)->save();
}
break;
case 'user_cancel_reassign':
// Anonymize activities.
$storage = \Drupal::entityTypeManager()->getStorage('activity_stream_activity');
$activity_stream_activity_ids = $storage->getQuery()
->condition('uid', $account->id())
->accessCheck(FALSE)
->execute();
foreach ($storage->loadMultiple($activity_stream_activity_ids) as $activity_stream_activity) {
$activity_stream_activity->setOwnerId(0)->save();
}
break;
}
}
/**
* Implements hook_ENTITY_TYPE_predelete() for user entities.
*/
function activity_stream_user_predelete(UserInterface $account): void {
// Delete activities that belong to this account.
$storage = \Drupal::entityTypeManager()->getStorage('activity_stream_activity');
$activity_stream_activity_ids = $storage->getQuery()
->condition('uid', $account->id())
->accessCheck(FALSE)
->execute();
$storage->delete(
$storage->loadMultiple($activity_stream_activity_ids)
);
// Delete old revisions.
$activity_stream_activity_ids = $storage->getQuery()
->allRevisions()
->condition('uid', $account->id())
->accessCheck(FALSE)
->execute();
foreach (array_keys($activity_stream_activity_ids) as $revision_id) {
$storage->deleteRevision($revision_id);
}
}
/**
* Implements hook_entity_insert().
*/
function activity_stream_entity_insert(EntityInterface $entity): void {
_activity_stream_entity_action($entity, 'create_entitiy_action');
// Check if the entity created with "published" status.
if ($entity instanceof EntityPublishedInterface) {
if ($entity->isPublished()) {
_activity_stream_entity_action($entity, 'publish_entity_action');
}
}
}
/**
* Implements hook_entity_update().
*/
function activity_stream_entity_update(EntityInterface $entity): void {
_activity_stream_entity_action($entity, 'update_entity_action');
}
/**
* Implements hook_entity_presave().
*/
function activity_stream_entity_presave(EntityInterface $entity): void {
// In case of an activity inserted
// Fill in bundle for DER.
if ($entity instanceof ActivityInterface) {
if ($entity->hasField('field_activity_entity') &&
isset($entity->field_activity_entity)
) {
if ($activity_entity = $entity->field_activity_entity->entity) {
// Get the bundle for this entity
$bundle = $activity_entity->bundle();
$entity->activity_entity_bundle = $bundle;
}
}
}
// Check if the entity become published.
if ($entity instanceof EntityPublishedInterface && !$entity->isNew()) {
// Check if entity change state from "unpublished" to "published".
// @phpstan-ignore-next-line
$original = $entity->original;
if (!$original->isPublished() && $entity->isPublished()) {
_activity_stream_entity_action($entity, 'publish_entity_action');
}
}
}
/**
* Create or modify some entity.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity.
* @param string $instance
* The instance.
*/
function _activity_stream_entity_action(EntityInterface $entity, $instance): void {
// During migration activities should not be created as this may flood stream.
if ($entity instanceof SynchronizableInterface && $entity->isSyncing()) {
return;
}
$plugin_manager = \Drupal::service('plugin.manager.activity_action.processor');
if ($plugin_manager->hasDefinition($instance)) {
$plugin = $plugin_manager->createInstance($instance);
assert($plugin instanceof ActivityActionInterface);
$plugin->create($entity);
}
}
/**
* Implements hook_entity_delete().
*
* Delete activity items when related entities are deleted.
*/
function activity_stream_entity_delete(EntityInterface $entity) {
_activity_stream_activity_for_entity_updater('delete', $entity);
}
/**
* Update and or delete activities for given entity.
*
* @param string $action
* A string containing the action. Can be delete or update.
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity object which is updated or deleted.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
* @throws \Drupal\Core\Entity\EntityStorageException
*/
function _activity_stream_activity_for_entity_updater($action, EntityInterface $entity) {
if ($entity !== NULL) {
// We never create activities for configuration entities but accessing
// entity queries during configuration changes may cause errors.
if ($entity instanceof ConfigEntityInterface) {
return;
}
// Ignore Task entity from search api module.
if (\Drupal::moduleHandler()->moduleExists('search_api') && $entity instanceof TaskInterface) {
return;
}
/** @var \Drupal\activity_stream\ActivityNotifications $activity_notification_service */
$activity_notification_service = \Drupal::service('activity_stream.activity_notifications');
$ids = $activity_notification_service->getActivityIdsByEntity($entity);
if (empty($ids)) {
return;
}
if ($action === 'update') {
$tags = [];
foreach ($ids as $id) {
$tags[] = 'activity:' . $id;
}
Cache::invalidateTags($tags);
}
elseif ($action === 'delete') {
// Delete all activities.
// For now we delelte activities not with batch,
// because the batch API does not work on decoupled environments.
ActivityStreamBatchActivityDeletion::deleteActivities($ids);
}
}
}
/**
* Implements hook_ENTITY_TYPE_insert().
*/
function activity_stream_activity_stream_activity_insert(ActivityInterface $activity) {
// We only care about status for activities when we're dealing with
// notifications.
if (in_array('notifications', $activity->getDestinations(), TRUE)) {
// Get recipients.
$recipients = $activity->getRecipient();
if (is_array($recipients)) {
$uids = [];
// Loop through the recipients and track the ID if the target is a user.
foreach ($recipients as $recipient) {
if ($recipient['target_type'] === 'user') {
$uids[] = $recipient['target_id'];
}
}
if (!empty($uids)) {
// If we have users, we insert a status for each user for the activity.
$connection = \Drupal::database();
$query = $connection->insert('activity_notification_status')->fields(['uid', 'aid']);
foreach ($uids as $uid) {
$query->values([
'uid' => $uid,
'aid' => $activity->id(),
]);
}
$query->execute();
}
}
}
}
