social_event_managers.module in Open Social 8.9
Same filename and directory in other branches
- 8 modules/social_features/social_event/modules/social_event_managers/social_event_managers.module
- 8.2 modules/social_features/social_event/modules/social_event_managers/social_event_managers.module
- 8.3 modules/social_features/social_event/modules/social_event_managers/social_event_managers.module
- 8.4 modules/social_features/social_event/modules/social_event_managers/social_event_managers.module
- 8.5 modules/social_features/social_event/modules/social_event_managers/social_event_managers.module
- 8.6 modules/social_features/social_event/modules/social_event_managers/social_event_managers.module
- 8.7 modules/social_features/social_event/modules/social_event_managers/social_event_managers.module
- 8.8 modules/social_features/social_event/modules/social_event_managers/social_event_managers.module
- 10.3.x modules/social_features/social_event/modules/social_event_managers/social_event_managers.module
- 10.0.x modules/social_features/social_event/modules/social_event_managers/social_event_managers.module
- 10.1.x modules/social_features/social_event/modules/social_event_managers/social_event_managers.module
- 10.2.x modules/social_features/social_event/modules/social_event_managers/social_event_managers.module
Contains social_event_managers.module.
File
modules/social_features/social_event/modules/social_event_managers/social_event_managers.moduleView source
<?php
/**
* @file
* Contains social_event_managers.module.
*/
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Access\AccessResultAllowed;
use Drupal\Core\Access\AccessResultForbidden;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\block\Entity\Block;
use Drupal\node\Entity\Node;
use Drupal\node\NodeInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\social_event\EventEnrollmentInterface;
use Drupal\social_event_managers\SocialEventManagersAccessHelper;
use Drupal\user\Entity\User;
use Drupal\views\ViewExecutable;
use Drupal\social_event\Entity\EventEnrollment;
use Drupal\views_bulk_operations\ViewsBulkOperationsBatch;
/**
* Implements hook_preprocess_block().
*/
function social_event_managers_preprocess_block(&$variables) {
/** @var \Drupal\node\Entity\Node $node */
$node = \Drupal::routeMatch()
->getParameter('node');
// Add variables to sidebar blocks.
switch ($variables['elements']['#derivative_plugin_id']) {
case 'managers-event_managers':
// Show "All" button only when there are more than 10 organisers.
if ($node->field_event_managers
->count() > 10) {
$variables['view_all_path'] = Url::fromUserInput('/node/' . $node
->id() . '/organisers');
$variables['button_text'] = t('All @label', [
'@label' => $variables['label']['#markup'],
]);
}
break;
}
}
/**
* Implements hook_views_data_alter().
*/
function social_event_managers_views_data_alter(array &$data) {
// Create our own views VBO field for enrollments.
$data['views']['social_views_bulk_operations_bulk_form_enrollments'] = [
'title' => t('Social Views bulk operations for Enrollments'),
'help' => t("Process enrollments returned by the view with Views Bulk Operations' actions."),
'field' => [
'id' => 'social_views_bulk_operations_bulk_form_enrollments',
],
];
}
/**
* Implement hook_activity_send_email_notifications_alter().
*/
function social_event_managers_activity_send_email_notifications_alter(array &$items, array $email_message_templates) {
// If a member_added_by_event_organiser template is enabled then we add it in
// the "Message to Me" section.
if (isset($email_message_templates['member_added_by_event_organiser'])) {
$items['message_to_me']['templates'][] = 'member_added_by_event_organiser';
}
}
/**
* Implements hook_block_access().
*/
function social_event_managers_block_access(Block $block, $operation, AccountInterface $account) {
if ($operation == 'view' && $block
->getPluginId() == 'views_block:managers-event_managers') {
// Exclude block form edit node page.
$route_name = \Drupal::routeMatch()
->getRouteName();
if ($route_name == 'entity.node.edit_form') {
return AccessResult::forbidden();
}
}
$route_name = \Drupal::routeMatch()
->getRouteName();
$excluded_routes = [
'social_event_managers.vbo.confirm',
'social_event_managers.vbo.execute_configurable',
];
if (in_array($route_name, $excluded_routes)) {
if ($operation === 'view' && ($block
->getPluginId() === 'social_page_title_block' || $block
->getPluginId() === 'views_block:event_enrollments-event_enrollments')) {
return AccessResult::forbidden();
}
}
// No opinion for other situations really.
return AccessResult::neutral();
}
/**
* Implements hook_link_alter().
*/
function social_event_managers_link_alter(&$variables) {
/** @var \Drupal\Core\Url $url */
$url = $variables['url'];
// Let's make sure we reroute the view more link.
if ($url instanceof Url && !$url
->isExternal() && $url
->isRouted() && $url
->getRouteName() === 'view.event_enrollments.view_enrollments' && stripos(strtolower($variables['text']), 'all enrollments') !== FALSE) {
$params = $url
->getRouteParameters();
$variables['url'] = Url::fromRoute('view.event_manage_enrollments.page_manage_enrollments', $params);
}
}
/**
* Implements hook_entity_access().
*/
function social_event_managers_entity_access(EntityInterface $entity, $operation, AccountInterface $account) {
// Event Manager & Organizers can view/delete/edit enrollments for events
// they are organizing.
if ($entity instanceof EventEnrollmentInterface) {
if (social_event_manager_or_organizer()) {
return AccessResult::allowedIf($entity instanceof EventEnrollmentInterface);
}
}
}
/**
* Implements hook_form_alter().
*/
function social_event_managers_form_alter(&$form, FormStateInterface $form_state, $form_id) {
// Make sure we pass along the ccorrect view id, display id and node
// parameter to our custom views bulk forms and redirects.
if (isset($form['views_bulk_operations_bulk_form']) && isset($form['output'][0]['#view'])) {
$view =& $form['output'][0]['#view'];
if ($view instanceof ViewExecutable) {
$view_id = $view
->id();
$display_id = $view->current_display;
}
}
elseif (strpos($form_id, 'views_form_event_manage_enrollments_page_manage_enrollments') !== FALSE && isset($form['output'][0]['#view'])) {
$view =& $form['output'][0]['#view'];
if ($view instanceof ViewExecutable) {
$view_id = $view
->id();
$display_id = $view->current_display;
}
}
elseif (isset($form['social_views_bulk_operations_bulk_form_enrollments_1']) && isset($form['output'][0]['#view'])) {
$view =& $form['output'][0]['#view'];
if ($view instanceof ViewExecutable) {
$view_id = $view
->id();
$display_id = $view->current_display;
}
}
elseif ($form_id === 'views_bulk_operations_configure_action') {
$data = $form_state
->get('views_bulk_operations');
$view_id = $data['view_id'];
$display_id = $data['display_id'];
}
if (isset($view_id) && $view_id === 'event_manage_enrollments' && $display_id === 'page_manage_enrollments') {
$form_state
->set('node', \Drupal::routeMatch()
->getRawParameter('node'));
if ($form_id === 'views_bulk_operations_configure_action') {
$callbacks =& $form['actions']['submit']['#submit'];
}
else {
$callbacks =& $form['#submit'];
}
$callbacks[] = '_social_event_managers_views_bulk_operations_bulk_form_submit';
}
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function social_event_managers_form_node_event_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) {
// On event event edit node form we check if users can alter author.
$node = \Drupal::routeMatch()
->getParameter('node');
// Not on newly created nodes so we check if there is a route match for a node
// object.
if ($node) {
// Get the current user.
$user = \Drupal::currentUser();
// Remove authoring information for everybody on node event edit form.
$form['author']['#access'] = FALSE;
// Check for permission. Otherwise you can't change the author.
// Unless you are the author / have the right permissions.
if ($user
->hasPermission('administer nodes') || $user
->id() == $node
->getOwnerId()) {
$form['author']['#access'] = TRUE;
}
}
}
/**
* Implements hook_node_access_records().
*/
function social_event_managers_node_access_records(NodeInterface $node) {
$grants = [];
// Only for events.
if ($node
->getType() === 'event' && ($event_managers_ids = array_column($node
->get('field_event_managers')
->getValue(), 'target_id'))) {
// Event organizers should be granted access.
// Load the event managers accounts.
$users = User::loadMultiple($event_managers_ids);
foreach ($users as $event_manager) {
// Event organizers must have access
// to view the record in the first place.
if ($node
->access('view', $event_manager)) {
// Add grant.
$grants[] = [
'realm' => 'social_event_managers:' . $node
->id(),
'gid' => $event_manager
->id(),
'grant_view' => 1,
'grant_update' => 1,
'grant_delete' => 0,
];
}
}
}
return $grants;
}
/**
* Implements hook_node_grants().
*/
function social_event_managers_node_grants(AccountInterface $account, $op) {
$grants = [];
// TODO:
// Fetch all nodes this user has access to and add a grant for each of those!
$query = \Drupal::database()
->select('node__field_event_managers', 'em');
$query
->fields('em', [
'entity_id',
]);
$query
->condition('em.field_event_managers_target_id', $account
->id());
// Add grants.
foreach ($query
->execute()
->fetchAllAssoc('entity_id') as $nid) {
$grants['social_event_managers:' . $nid->entity_id][] = $account
->id();
}
// Tell Drupal about users grants.
return $grants;
}
/**
* Implements hook_module_implements_alter().
*/
function social_event_managers_module_implements_alter(&$implementations, $hook) {
if ($hook == 'node_access') {
// Remove the gnode implementation, we have a fallback in our hook.
if (isset($implementations['gnode']) && function_exists('gnode_node_access')) {
unset($implementations['gnode']);
}
}
}
/**
* Implements hook_node_access().
*
* Remember: if any module returns forbidden and denies access to certain node
* and operation it will not allow the user to do the operation on the node.
*
* We need this implementation because we also want to give edit access to event
* manager regardless these scenarios thought of in gnode_node_access:
* - is a member in the group and:
* - has edit own or edit any permission in the group
*
* The gnode module specifically returns allowed if any of the above scenarios
* are met, but forbidden in all the other scenarios. Our code ensures that if
* we are in operation update and if gnode already returns forbidden we are able
* to return an allowed if user is an event manager.
*/
function social_event_managers_node_access(NodeInterface $node, $op, AccountInterface $account) {
// Only continue if the gnode module is enabled.
if (function_exists('gnode_node_access')) {
$gnode_access = gnode_node_access($node, $op, $account);
if ($op === 'update') {
if ($gnode_access instanceof AccessResultForbidden) {
$social_event_managers_access = SocialEventManagersAccessHelper::getEntityAccessResult($node, $op, $account);
// Only return the result of SocialEventManagersAccessHelper
// if it is allowed.
if ($social_event_managers_access instanceof AccessResultAllowed) {
return $social_event_managers_access;
}
}
return $gnode_access;
}
return $gnode_access;
}
return SocialEventManagersAccessHelper::getEntityAccessResult($node, $op, $account);
}
/**
* Implements hook_menu_local_tasks_alter().
*/
function social_event_managers_menu_local_tasks_alter(&$data, $route_name) {
$can_show_managers_link = FALSE;
$routes_to_check = [
'view.event_enrollments.view_enrollments',
'entity.node.canonical',
'view.managers.view_managers',
'view.manage_enrollments.page',
'view.event_manage_enrollments.page_manage_enrollments',
];
if (in_array($route_name, $routes_to_check)) {
$node = \Drupal::service('current_route_match')
->getParameter('node');
if (!is_null($node) && !$node instanceof Node) {
$node = Node::load($node);
}
if ($node instanceof Node && $node
->getType() === 'event') {
$can_show_managers_link = TRUE;
// Should we minimise the amount of tabs? If so we remove enrollees as we
// show it in the management tab.
if (!empty($data['tabs'][0]['views_view:view.event_enrollments.view_enrollments'])) {
unset($data['tabs'][0]['views_view:view.event_enrollments.view_enrollments']);
}
// For Guest Enrollments alone we hide them as well and place them in the
// manage tab.
if (!empty($data['tabs'][0]['views_view:view.manage_enrollments.page'])) {
unset($data['tabs'][0]['views_view:view.manage_enrollments.page']);
}
if (!social_event_manager_or_organizer()) {
$data['tabs'][0]['views_view:view.event_manage_enrollments.page_manage_enrollments']['#link']['title'] = t('Enrollments');
}
}
}
// PLace this here, since hiding it should happen
// always and not only on the mentioned routes.
if (!$can_show_managers_link) {
unset($data['tabs'][0]['views_view:view.managers.view_managers']);
unset($data['tabs'][0]['views_view:view.event_manage_enrollments.page_manage_enrollments']);
}
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function social_event_managers_form_node_event_form_alter(&$form, FormStateInterface $form_state, $form_id) {
// Set author of event as event organiser automatically.
$config = \Drupal::configFactory()
->getEditable('social_event_managers.settings');
if ($config
->get('author_as_manager')) {
if ($form_state
->getTriggeringElement() === NULL) {
$account = \Drupal::currentUser();
$user = \Drupal::entityTypeManager()
->getStorage('user')
->load($account
->id());
$last_key = $form['field_event_managers']['widget']['#max_delta'];
$form['field_event_managers']['widget'][$last_key]['target_id']['#default_value'] = $user;
}
}
}
/**
* Implements hook_activity_recipient_organizer_alter().
*/
function social_event_managers_activity_recipient_organizer_alter(array &$recipients, Node $event, $data) {
$receiver = '';
$organizers = $event
->get('field_event_managers')
->getValue();
if ($data['target_type'] === 'event_enrollment' && !empty($data['target_id'])) {
$enrollment = EventEnrollment::load($data['target_id']);
$receiver = $enrollment
->getAccount();
}
// If there are more organizers we want them to receive a notification too
// so we add them to the array of recipients.
if (!empty($organizers)) {
foreach ($organizers as $organizer) {
// We don't want Organizers to receive activity_on_events_im_organizing.
// It will already receive it as part of a different context.
if (!empty($receiver) && $organizer['target_id'] === $receiver) {
continue;
}
// Make sure we don't add the people twice.
if (!in_array($organizer['target_id'], array_column($recipients, 'target_id'))) {
$recipients[] = [
'target_type' => 'user',
'target_id' => $organizer['target_id'],
];
}
}
}
}
/**
* Implements hook_batch_alter().
*/
function social_event_managers_batch_alter(&$batch) {
if (!isset($batch['source_url'])) {
return;
}
$actions = [
'social_event_enrolments_export_enrollments_action',
'social_event_managers_send_email_action',
'social_event_managers_delete_event_enrollment_action',
'social_event_an_enroll_enrolments_export_action',
'social_event_an_enroll_send_email_action',
];
/** @var \Drupal\Core\Url $url */
$url =& $batch['source_url'];
if ($url
->getRouteName() === 'social_event_managers.vbo.confirm' || $url
->getRouteName() === 'views_bulk_operations.confirm' || $url
->getRouteName() === 'views_bulk_operations.execute_batch') {
// Get the action ID.
$action_id = _social_event_managers_get_action_id($batch);
$batch['sets'][0]['results']['action'] = $action_id;
if (in_array($action_id, $actions, TRUE)) {
$batch['sets'][0]['finished'] = '_social_event_managers_action_batch_finish';
}
}
}
/**
* Action batch finished callback.
*
* @param bool $success
* Was the process successfull?
* @param array $results
* Batch process results array.
* @param array $operations
* Performed operations array.
*/
function _social_event_managers_action_batch_finish($success, array $results, array $operations) {
// When we do a bulk action on all the items in a view, across multiple pages,
// the saveList function needs to be called. So after pre-populating the list
// the actual action is performed on the entities.
if (!empty($results['view_id']) && !empty($results['display_id'])) {
ViewsBulkOperationsBatch::saveList(TRUE, $results, $operations);
return;
}
$operations = array_count_values($results['operations']);
$results_count = 0;
foreach ($operations as $count) {
$results_count += $count;
}
$hook = 'social_event_managers_action_' . $results['action'] . '_finish';
foreach (\Drupal::moduleHandler()
->getImplementations($hook) as $module) {
$function = $module . '_' . $hook;
$messages = $function($success);
if (is_array($messages)) {
$fields = 0;
foreach ($messages as $type => $message) {
if (($type === 'singular' || $type === 'plural') && !empty($message) && is_string($message)) {
$fields++;
}
}
if ($fields === 2) {
// @todo: source strings will never be translatable when we use
// variables. This should be refactored.
$message = \Drupal::translation()
->formatPlural($results_count, $messages['singular'], $messages['plural']);
$type = $success ? MessengerInterface::TYPE_STATUS : MessengerInterface::TYPE_WARNING;
\Drupal::messenger()
->addMessage($message, $type);
}
}
}
}
/**
* Function to get the action id of a batch.
*
* @param array $batch
* The batch array.
*
* @return string
* Returns the batch action id.
*/
function _social_event_managers_get_action_id(array &$batch) {
/** @var \Drupal\Core\Form\FormStateInterface $form_state */
$form_state =& $batch['form_state'];
$action_id = '';
if ($form_state instanceof FormStateInterface) {
$data = $form_state
->get('views_bulk_operations');
$action_id = $data['action_id'];
}
else {
foreach ($batch['sets'][0]['operations'] as $operations) {
if (empty($operations) || !is_array($operations)) {
break;
}
foreach ($operations as $operation) {
if (empty($operation) || !is_array($operation)) {
break;
}
foreach ($operation as $items) {
if (empty($items) || !is_array($items)) {
break;
}
if (!empty($items['action_id'])) {
$action_id = $items['action_id'];
break;
}
}
}
}
}
return $action_id;
}
/**
* Implements hook_social_event_action_ACTION_ID_finish().
*/
function social_event_managers_social_event_managers_action_social_event_managers_send_email_action_finish($success) {
if ($success) {
// When the queue storage module is enabled the email is send in the
// background.
if (\Drupal::moduleHandler()
->moduleExists('social_queue_storage')) {
return [
'singular' => 'Your email will be send to 1 selected enrollee',
'plural' => 'Your email will be send to @count selected enrollees',
];
}
return [
'singular' => 'Your email has been sent to 1 selected enrollee successfully',
'plural' => 'Your email has been sent to @count selected enrollees successfully',
];
}
return [
'singular' => 'Your email has not been sent to 1 selected enrollee successfully',
'plural' => 'Your email has not been sent to @count selected enrollees successfully',
];
}
/**
* Implements hook_social_event_action_ACTION_ID_finish().
*/
function social_event_managers_social_event_managers_action_social_event_managers_delete_event_enrollment_action_finish($success) {
if ($success) {
return [
'singular' => '1 selected enrollee has been removed from the event successfully',
'plural' => '@count selected enrollees have been removed from the event successfully',
];
}
return [
'singular' => '1 selected enrollee has not been removed from the event successfully',
'plural' => '@count selected enrollees have not been removed from the event successfully',
];
}
/**
* Add node ID to the route of action confirmation step.
*/
function _social_event_managers_views_bulk_operations_bulk_form_submit($form, FormStateInterface $form_state) {
/** @var \Drupal\Core\Url $url */
$url = $form_state
->getRedirect();
$node = '';
if ($form_state
->get('node')) {
$node = $form_state
->get('node');
}
if (empty($node)) {
$route = \Drupal::routeMatch()
->getParameter('node');
$node = $route
->id();
}
$route_parameters = [
'node' => $node,
];
if (!empty($node)) {
if ($url
->getRouteName() === 'views_bulk_operations.execute_configurable') {
$url = Url::fromRoute('social_event_managers.vbo.execute_configurable', $route_parameters);
}
if ($url
->getRouteName() === 'social_event_managers.vbo.confirm') {
$url = Url::fromRoute('social_event_managers.vbo.confirm', $route_parameters);
}
}
$form_state
->setRedirectUrl($url);
}
/**
* Implements hook_preprocess_HOOK().
*/
function social_event_managers_preprocess_views_view(&$variables) {
if (!\Drupal::moduleHandler()
->moduleExists('social_event_invite')) {
/** @var \Drupal\views\ViewExecutable $view */
$view =& $variables['view'];
// Remove header & VBO actions from the Enrollment Management tab if the
// user is not a manager or organiser.
if ($view
->id() === 'event_manage_enrollments') {
if (!social_event_manager_or_organizer()) {
unset($variables['rows']['social_views_bulk_operations_bulk_form_enrollments_1']);
unset($variables['rows']['header']);
unset($variables['rows']['actions']);
}
$block = \Drupal::entityTypeManager()
->getStorage('block')
->load('socialblue_local_actions');
$variables['header']['actions'] = \Drupal::entityTypeManager()
->getViewBuilder('block')
->view($block);
}
}
}
/**
* Implements hook_views_pre_view().
*/
function social_event_managers_views_pre_view(ViewExecutable $view, $display_id, array &$args) {
// Remove fields from the Enrollment Management tab if the user is not a
// manager or organiser.
if ($view
->id() === 'event_manage_enrollments') {
if (!social_event_manager_or_organizer()) {
$fields = $view->display_handler
->getOption('fields');
$fields['operations_1']['exclude'] = TRUE;
$fields['social_views_bulk_operations_bulk_form_enrollments_1']['exclude'] = TRUE;
$view->display_handler
->overrideOption('fields', $fields);
}
}
}