You are here

social_activity.module in Open Social 10.3.x

The Social activity module.

File

modules/social_features/social_activity/social_activity.module
View source
<?php

/**
 * @file
 * The Social activity module.
 */
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Template\Attribute;
use Drupal\Core\Url;
use Drupal\node\NodeInterface;
use Drupal\views\ViewExecutable;

/**
 * Implements hook_views_plugins_display_alter().
 */
function social_activity_views_plugins_display_alter(array &$plugins) {
  $plugins['block']['class'] = 'Drupal\\social_activity\\Plugin\\views\\display\\ModeBlock';
}

/**
 * Implements hook_social_user_account_header_items().
 *
 * Adds the Notification Center to the account header block.
 */
function social_activity_social_user_account_header_items(array $context) {

  // We require a valid user to load the notifications for.
  if (empty($context['user'])) {
    return [];
  }

  // Get the total amount of notifications for the user.
  $num_notifications = social_activity_social_account_notifications_counter($context['user']);
  return [
    'notifications' => [
      '#type' => 'account_header_element',
      '#wrapper_attributes' => [
        'class' => [
          'desktop',
          'notification-bell',
        ],
      ],
      '#title' => new TranslatableMarkup('Notification Centre'),
      '#icon' => $num_notifications > 0 ? 'notifications' : 'notifications_none',
      '#label' => new TranslatableMarkup('Notifications'),
      '#url' => Url::fromRoute('view.activity_stream_notifications.page_1'),
      '#notification_count' => $num_notifications,
      '#weight' => 800,
      'header' => [
        '#wrapper_attributes' => [
          'class' => 'dropdown-header',
        ],
        '#markup' => new TranslatableMarkup('Notification Centre'),
      ],
      'header-divider' => [
        '#wrapper_attributes' => [
          'class' => 'divider',
        ],
        '#markup' => '',
      ],
      // Element to contain the link for ajaxified view for notifications.
      'load_link' => [
        '#title' => '',
        '#type' => 'link',
        '#url' => Url::fromRoute('activity_creator.stream.notifications'),
        '#attributes' => [
          'class' => 'use-ajax',
        ],
      ],
      'notifications' => [
        '#wrapper_attributes' => [
          'class' => 'js-notification-center-wrapper',
        ],
        // @todo Change ajax throbber to opensocial spinner.
        // @see: https://www.drupal.org/project/social/issues/3074740
        '#markup' => '<div className="spinner">
      <div className="bounce1"></div>
      <div className="bounce2"></div>
      <div className="bounce3"></div>
    </div>',
        '#attached' => [
          'library' => [
            'core/drupal.ajax',
            'activity_creator/activity_creator.notifications',
          ],
        ],
        '#cache' => [
          'max-age' => 0,
        ],
      ],
      'footer-divider' => [
        '#wrapper_attributes' => [
          'class' => 'divider',
        ],
        '#markup' => '',
      ],
      'footer' => [
        '#wrapper_attributes' => [
          'class' => 'dropdown-header',
        ],
        '#type' => 'link',
        '#title' => [
          '#type' => 'inline_template',
          '#template' => "{% trans %}All notifications{% endtrans %} <svg class='btn-icon icon-black pull-right'><use xlink:href='#icon-navigate_next'></use></svg>",
          '#allowed_tags' => [
            'use',
            'svg',
          ],
        ],
        '#url' => Url::fromRoute('view.activity_stream_notifications.page_1'),
        '#attributes' => [
          'title' => new TranslatableMarkup('View all notifications'),
          'class' => [
            'block',
            'clearfix',
          ],
        ],
        // The link is wrapped in a container to avoid .dropdown-menu > li > a
        // styling.
        '#prefix' => '<div>',
        '#suffix' => '</div>',
      ],
    ],
  ];
}

/**
 * Implements hook_social_user_account_header_account_links().
 *
 * Adds the mobile indicator for activity notifications under the profile icon
 * menu.
 */
function social_activity_social_user_account_header_account_links(array $context) {

  // We require a logged in user for this indicator.
  if (empty($context['user']) || !$context['user']
    ->isAuthenticated()) {
    return [];
  }

  // Get the total amount of notifications for the user.
  $num_notifications = social_activity_social_account_notifications_counter($context['user']);

  // Depending on the amount of notifications, set a class for the indicator.
  $label_classes = 'hidden';
  if ($num_notifications > 0) {
    $label_classes = 'badge badge-accent badge--pill';

    // When there are more than 99 notifications, display this and not
    // the exact amount.
    if ($num_notifications > 99) {
      $num_notifications = '99+';
    }
  }
  return [
    'notification_mobile' => [
      '#wrapper_attributes' => [
        'class' => [
          'mobile notification-bell',
        ],
      ],
      '#weight' => 300,
      '#type' => 'link',
      '#attributes' => [
        'title' => new TranslatableMarkup('Notification Centre'),
      ],
      '#title' => [
        '#type' => 'inline_template',
        '#template' => '<span>{% trans %}Notification Centre{% endtrans %}</span><span{{ attributes }}>{{ icon }}</span>',
        '#context' => [
          'attributes' => new Attribute([
            'class' => $label_classes,
          ]),
          'icon' => (string) $num_notifications,
        ],
      ],
    ] + Url::fromRoute('view.activity_stream_notifications.page_1')
      ->toRenderArray(),
  ];
}

/**
 * Implements hook_social_user_account_header_items().
 *
 * Adds an indicator to the user account menu on mobile.
 */
function social_activity_social_user_account_header_items_alter(array &$menu_links, array $context) {

  // We require a logged in user for this indicator.
  if (empty($context['user']) || !$context['user']
    ->isAuthenticated()) {
    return;
  }

  // If the account_box link was removed we have nothing to do.
  if (!isset($menu_links['account_box'])) {
    return;
  }

  // Get the total amount of notifications for the user.
  $num_notifications = social_activity_social_account_notifications_counter($context['user']);
  if ($num_notifications > 0) {
    $menu_links['account_box']['#wrapper_attributes']['class'][] = 'has-alert';
  }
}

/**
 * Implements hook_theme().
 */
function social_activity_theme($existing, $type, $theme, $path) {
  return [
    'message_post_teaser' => [
      'variables' => [
        'link' => '',
        'name' => '',
        'date' => '',
        'summary' => '',
      ],
    ],
    'message_node_teaser' => [
      'variables' => [
        'link' => '',
        'type' => '',
      ],
    ],
  ];
}

/**
 * Wrapper method to get the number of unread notifications.
 *
 * @param \Drupal\Core\Session\AccountInterface $account
 *   Account object to get notifications for.
 * @param array $status
 *   Filter by status.
 *
 * @return int|void
 *   Returns the amount of notifications.
 *
 * @see \Drupal\activity_creator\ActivityNotifications
 */
function social_activity_social_account_notifications_counter(AccountInterface $account, array $status = [
  ACTIVITY_STATUS_RECEIVED,
]) {
  $account_notifications = \Drupal::service('activity_creator.activity_notifications');
  return count($account_notifications
    ->getNotifications($account, $status)) ?? 0;
}

/**
 * Implements hook_views_post_build().
 */
function social_activity_views_post_build(ViewExecutable $view) {
  $override_displays = [
    'block_stream_explore',
    'block_stream_homepage',
    'block_stream_homepage_without_post',
  ];
  if ($view
    ->id() == "activity_stream" && in_array($view->current_display, $override_displays)) {
    if (isset($view->filter_type) && $view->filter_type === 'dashboard') {

      // Override default view mode for activity stream views block if it was
      // added via layout builder.
      $view->rowPlugin->options['view_mode'] = 'featured';

      // Attach and use featured styles for activity stream on dashboard.
      $view->element['#attached']['library'][] = 'social_featured_content/paragraph.featured';
    }
  }
}

/**
 * Implements hook_preprocess_HOOK().
 */
function social_activity_preprocess_block(&$variables) {
  $route_match = \Drupal::routeMatch();
  $allowed_routes = [
    'entity.node.canonical',
    'layout_builder.overrides.node.view',
  ];
  $allowed_bundles = [
    'dashboard',
    'landing_page',
  ];
  $allowed_content_names = [
    'activity_stream',
    'community_activities',
    'activity_stream_profile',
    'activity_stream_group',
  ];
  if (($node = $route_match
    ->getParameter('node')) && $node instanceof NodeInterface) {

    // Use lazy builder for stream blocks only if:
    // 1. It on the node or landing builder page.
    // 2. Node is a Dashboard or a Landing page
    // 3. This block is from views.
    // 4. View one of the stream views.
    if (in_array($route_match
      ->getRouteName(), $allowed_routes) && in_array($node
      ->bundle(), $allowed_bundles) && $variables['base_plugin_id'] === 'views_block' && isset($variables['content']['#name']) && in_array($variables['content']['#name'], $allowed_content_names)) {
      if ($node
        ->bundle() === 'dashboard') {
        $variables['attributes']['class'][] = 'block-dashboard-activity-stream card';
      }

      /** @var \Drupal\views\ViewExecutable $view */
      $view = $variables['content']['#view'];
      $variables['content'] = [
        '#create_placeholder' => TRUE,
        '#lazy_builder' => [
          'social_activity.lazy_builder:viewsLazyBuild',
          [
            $variables['content']['#name'],
            $variables['content']['#display_id'],
            $node
              ->bundle(),
            $view
              ->getItemsPerPage(),
          ],
        ],
      ];

      // Set vocabulary ID from views filter.
      if (isset($view->filter_vocabulary)) {
        $variables['content']['#lazy_builder'][1] = array_merge($variables['content']['#lazy_builder'][1], [
          $view->filter_vocabulary,
        ]);
      }

      // Set taxonomy IDs from views filter.
      if (isset($view->filter_tags) && is_array($view->filter_tags)) {
        $variables['content']['#lazy_builder'][1] = array_merge($variables['content']['#lazy_builder'][1], array_keys($view->filter_tags));
      }
    }
  }
}