contacts_events-8.x-1.x-dev/modules/teams/contacts_events_teams.module

modules/teams/contacts_events_teams.module
<?php

/**
 * @file
 * Contains contacts_events_teams.module.
 */

use Drupal\contacts_dbs\Entity\DBSWorkforce;
use Drupal\contacts_events\Controller\TicketsController;
use Drupal\contacts_events\Entity\EventInterface;
use Drupal\contacts_events\Entity\EventType;
use Drupal\contacts_events\Entity\Ticket;
use Drupal\contacts_events_teams\Controller\TeamApplicationController;
use Drupal\contacts_events_teams\Entity\Team;
use Drupal\contacts_events_teams\Entity\TeamApplication;
use Drupal\contacts_events_teams\Entity\TeamInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Database\Query\AlterableInterface;
use Drupal\Core\Database\Query\Select;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\PluralTranslatableMarkup;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\entity\BundleFieldDefinition;
use Drupal\user\UserInterface;

/**
 * Implements hook_theme().
 */
function contacts_events_teams_theme($existing, $type, $theme, $path) {
  return [
    'c_events_team_app' => [
      'render element' => 'elements',
      'file' => 'c_events_team_app.page.inc',
    ],
  ];
}

/**
 * Implements hook_entity_base_field_info().
 */
function contacts_events_teams_entity_base_field_info(EntityTypeInterface $entity_type) {
  $fields = [];

  if ($entity_type->id() == 'contacts_event') {
    // @todo Remove the has_teams after data has been migrated to settings.
    $fields['has_teams'] = BaseFieldDefinition::create('boolean')
      ->setName('has_teams')
      ->setTargetEntityTypeId($entity_type->id())
      ->setLabel(new TranslatableMarkup('This event has teams'))
      ->setDefaultValue(FALSE)
      ->setDisplayOptions('form', ['region' => 'hidden'])
      ->setDisplayOptions('view', ['region' => 'hidden'])
      ->setDisplayConfigurable('form', FALSE)
      ->setDisplayConfigurable('form', FALSE);
  }

  if ($entity_type->id() === 'c_events_team'&& \Drupal::moduleHandler()->moduleExists('contacts_dbs')) {
    $fields['dbs_workforce'] = BaseFieldDefinition::create('list_string')
      ->setName('dbs_workforce')
      ->setTargetEntityTypeId($entity_type->id())
      ->setLabel(new TranslatableMarkup('DBS Workforce'))
      ->setDefaultValue(NULL)
      // phpcs:ignore Drupal.Arrays.Array.LongLineDeclaration
      ->setSetting('allowed_values_function', [DBSWorkforce::class, 'getOptions'])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayOptions('form', [
        'type' => 'options_select',
        'weight' => 9,
      ])
      ->setDisplayConfigurable('view', TRUE)
      ->setDisplayOptions('view', [
        'region' => 'hidden',
      ]);
  }

  return $fields;
}

/**
 * Implements hook_entity_field_storage_info().
 */
function contacts_events_teams_entity_field_storage_info(EntityTypeInterface $entity_type) {
  $fields = [];

  if ($entity_type->id() === 'contacts_ticket') {
    $fields['is_team_ticket'] = BundleFieldDefinition::create('boolean')
      ->setName('is_team_ticket')
      ->setTargetEntityTypeId('contacts_ticket')
      ->setLabel(new TranslatableMarkup('Is this a team ticket?'));

    $fields['team'] = BundleFieldDefinition::create('entity_reference')
      ->setName('team')
      ->setTargetEntityTypeId('contacts_ticket')
      ->setSetting('target_type', 'c_events_team')
      ->setLabel(new TranslatableMarkup('Team'));

  }
  elseif ($entity_type->id() === 'c_events_team') {
    $fields['application_request_team_enabled'] = BundleFieldDefinition::create('boolean')
      ->setName('application_request_team_enabled')
      ->setTargetEntityTypeId('c_events_team')
      ->setLabel(new TranslatableMarkup('Enable application request (with team)?'));

    $fields['application_request_team_b_man'] = BundleFieldDefinition::create('boolean')
      ->setName('application_request_team_b_man')
      ->setTargetEntityTypeId('c_events_team')
      ->setLabel(new TranslatableMarkup('Do not send to the booking manager'));

    $fields['application_request_team_subject'] = BundleFieldDefinition::create('string')
      ->setName('application_request_team_subject')
      ->setTargetEntityTypeId('c_events_team')
      ->setLabel(new TranslatableMarkup('Application request subject (with team)'));

    $fields['application_request_team_body'] = BundleFieldDefinition::create('text_long')
      ->setName('application_request_team_body')
      ->setTargetEntityTypeId('c_events_team')
      ->setLabel(new TranslatableMarkup('Application request email (with team)'));

    $fields['application_accepted_enabled'] = BundleFieldDefinition::create('boolean')
      ->setName('application_accepted_enabled')
      ->setTargetEntityTypeId('c_events_team')
      ->setLabel(new TranslatableMarkup('Enable application accepted?'));

    $fields['application_accepted_subject'] = BundleFieldDefinition::create('string')
      ->setName('application_accepted_subject')
      ->setTargetEntityTypeId('c_events_team')
      ->setLabel(new TranslatableMarkup('Application accepted subject'));

    $fields['application_accepted_body'] = BundleFieldDefinition::create('text_long')
      ->setName('application_accepted_body')
      ->setTargetEntityTypeId('c_events_team')
      ->setLabel(new TranslatableMarkup('Application accepted email'));

    $fields['application_submitted_enabled'] = BundleFieldDefinition::create('boolean')
      ->setName('application_submitted_enabled')
      ->setTargetEntityTypeId('c_events_team')
      ->setLabel(new TranslatableMarkup('Enable application submitted?'));

    $fields['application_submitted_subject'] = BundleFieldDefinition::create('string')
      ->setName('application_submitted_subject')
      ->setTargetEntityTypeId('c_events_team')
      ->setLabel(new TranslatableMarkup('Application submitted subject'));

    $fields['application_submitted_body'] = BundleFieldDefinition::create('text_long')
      ->setName('application_submitted_body')
      ->setTargetEntityTypeId('c_events_team')
      ->setLabel(new TranslatableMarkup('Application submitted email'));
  }

  return $fields;
}

/**
 * Implements hook_entity_bundle_field_info().
 */
function contacts_events_teams_entity_bundle_field_info(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) {
  $fields = [];

  if ($entity_type->id() === 'contacts_ticket') {
    $fields['is_team_ticket'] = BundleFieldDefinition::create('boolean')
      ->setName('is_team_ticket')
      ->setTargetEntityTypeId('contacts_ticket')
      ->setLabel(new TranslatableMarkup('Is this a team ticket?'))
      ->setDisplayOptions('form', [
        'type' => 'boolean_checkbox',
        'weight' => 9,
      ]);

    $fields['team'] = BundleFieldDefinition::create('entity_reference')
      ->setName('team')
      ->setTargetEntityTypeId('contacts_ticket')
      ->setLabel(new TranslatableMarkup('Team'))
      ->setDescription(new TranslatableMarkup('The team, if any, that this ticket holder is applying for. (Please enter the applicants own unique email address in the email address field above).'))
      ->setSetting('target_type', 'c_events_team')
      ->setSetting('handler', 'active_teams:c_events_team')
      ->setDisplayOptions('form', [
        'type' => 'options_select',
        'weight' => 10,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);
  }

  return $fields;
}

/**
 * Implements hook_entity_field_access().
 */
function contacts_events_teams_entity_field_access($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
  // Don't allow modifying team status for cancelled tickets.
  if ($field_definition->getTargetEntityTypeId() == 'contacts_ticket') {
    if (in_array($field_definition->getName(), ['is_team_ticket', 'team'])) {
      /** @var \Drupal\contacts_events\Entity\TicketInterface|null $ticket */
      $ticket = $items ? $items->getEntity() : NULL;
      if ($ticket) {
        if ($ticket->getStatus() == 'cancelled') {
          return AccessResult::forbidden();
        }

        if ($event = $ticket->getEvent()) {
          $team_enabled_state = $event->getSetting('teams.enabled', TeamInterface::STATUS_CLOSED);
          // Check event has teams enabled.
          if ($team_enabled_state == TeamInterface::STATUS_CLOSED) {
            return AccessResult::forbidden();
          }
          // Don't display teams if they're private and user isn't staff.
          elseif ($team_enabled_state == TeamInterface::STATUS_PRIVATE && !$account->hasPermission('can manage bookings for contacts_events')) {
            return AccessResult::forbidden();
          }
        }
      }
    }
  }

  return AccessResult::neutral();
}

/**
 * Implements hook_entity_access().
 */
function contacts_events_teams_entity_access(EntityInterface $entity, $operation, AccountInterface $account) {
  // Don't allow team tickets to be transferred between orders.
  if ($entity->getEntityTypeId() == 'contacts_ticket' && $operation == 'transfer') {
    return AccessResult::forbiddenIf($entity->get('is_team_ticket')->value, 'Ticket transfer does not support team tickets');
  }
  return AccessResult::neutral();
}

/**
 * Implements hook_workflows_alter().
 */
function contacts_events_teams_workflows_alter(array &$workflows) {
  // Remove the reference steps if the module is not installed.
  if (isset($workflows['contacts_events_teams_application_process']) && !\Drupal::moduleHandler()->moduleExists('contacts_references')) {
    $states = ['references_received', 'references_reviewed'];
    $workflow = &$workflows['contacts_events_teams_application_process'];

    // Remove the reference states.
    foreach ($states as $state) {
      unset($workflow['states'][$state]);
    }

    // Update the transitions.
    foreach ($workflow['transitions'] as $transition_id => &$transition) {
      // Remove any transition to a removed state.
      if (in_array($transition_id, $states)) {
        unset($workflow['transitions'][$transition_id]);
        continue;
      }

      // Remove our state from the from states.
      $transition['from'] = array_diff($transition['from'], $states);

      // Remove any states with no from.
      if (empty($transition['from'])) {
        unset($workflow['transitions'][$transition_id]);
      }
    }
  }

  // Add additional team statuses to the order item workflow.
  if (isset($workflows['contacts_events_order_item_process'])) {
    $workflow = &$workflows['contacts_events_order_item_process'];

    $workflow['states'] += [
      'team_app_in_progress' => ['label' => 'Team Application In Progress'],
    ];

    $workflow['transitions'] += [
      // Ticket moves from confirmed to team app in progress.
      'team_app_in_progress' => [
        'label' => 'Team Application In Progress',
        'from' => ['pending'],
        'to' => 'team_app_in_progress',
      ],
      'team_app_back_to_pending' => [
        'label' => 'Team Application back to Pending',
        'from' => ['team_app_in_progress', 'paid_in_full'],
        'to' => 'pending',
      ],
      'team_payment_undone' => [
        'label' => 'Team payment undone',
        'from' => ['paid_in_full'],
        'to' => 'team_app_in_progress',
      ],
    ];

    // Allow moving from team app in progress to paid in full.
    $workflow['transitions']['paid_in_full']['from'][] = 'team_app_in_progress';
    $workflow['transitions']['cancel']['from'][] = 'team_app_in_progress';
  }
}

/**
 * Implements hook_contacts_events_ticket_form_alter().
 */
function contacts_events_teams_contacts_events_ticket_form_alter(array &$form, FormStateInterface $form_state, Ticket $ticket, string $display_mode) {
  \Drupal::service('contacts_events_teams.form_alter.ticket')->alter($form, $form_state, $ticket, $display_mode);
}

/**
 * Implements hook_form_FORM_ID_alter() for state_machine_transition_form.
 */
function contacts_events_teams_form_state_machine_transition_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  // For team application state transitions, some are only available for staff
  // others for staff and team leaders, some are automated and not available for
  // any users to invoke.
  /** @var \Drupal\state_machine\Form\StateTransitionForm $form_object */
  $form_object = $form_state->getFormObject();
  $entity = $form_object->getEntity();
  if ($entity instanceof TeamApplication) {
    $allowed_transitions = $entity->getManuallyAllowedTransitions(\Drupal::currentUser());
    foreach (Element::children($form['actions']) as $delta) {
      if (!in_array($delta, $allowed_transitions)) {
        unset($form['actions'][$delta]);
      }
    }
  }
}

/**
 * Implements hook_mail().
 */
function contacts_events_teams_mail($key, &$message, $params) {
  $message['subject'] = $params['subject'];

  $build = [
    '#type' => 'processed_text',
    '#text' => $params['body'],
    '#format' => $params['body_format'],
    '#filter_types_to_skip' => [],
    '#langcode' => $message['langcode'],
  ];
  $message['body'][] = \Drupal::service('renderer')->render($build);

  if ($params['from']) {
    $message['headers']['From'] = $params['from'];
  }
}

/**
 * Implements hook_query_TAG_alter().
 *
 * For contacts_events_teams_tickets_without_apps.
 */
function contacts_events_teams_query_contacts_events_teams_tickets_without_apps_alter(AlterableInterface $query) {
  if (!$query instanceof Select) {
    throw new \Exception('Tag contacts_events_teams_tickets_without_apps only supported for Select queries.');
  }

  // Check the metadata for an explicit table, otherwise assume the base table.
  if ($ticket_alias = $query->getMetaData('contacts_events_teams_tickets_without_apps_ticket_table')) {
    // Just in-case anyone puts user input into the query metadata, let's escape
    // the table. There isn't an escapeTable method, but escapeField should do.
    $ticket_alias = $query->escapeField($ticket_alias);
  }
  else {
    $ticket_alias = array_keys($query->getTables())[0];
  }

  $app_alias = $query->leftJoin('c_events_team_app', 'app',
    "%alias.ticket = {$ticket_alias}.id AND %alias.state != :archived", [
      ':archived' => 'archived',
    ]);
  $query->isNull("{$app_alias}.id");
}

/**
 * Implements hook_contacts_user_dashboard_user_summary_blocks_alter().
 */
function contacts_events_teams_contacts_user_dashboard_user_summary_blocks_alter(&$content, UserInterface $user) {
  $team_app_controller = \Drupal::service('class_resolver')->getInstanceFromDefinition(TeamApplicationController::class);
  $team_data = $team_app_controller->myActiveTeams($user);

  if (!empty($team_data['table']['#rows'])) {
    $content['team_applications'] = [
      '#type' => 'user_dashboard_summary',
      '#buttons' => [],
      '#title' => 'Your active team applications',
      '#content' => $team_data,
    ];
  }
}

/**
 * Implements hook_entity_extra_field_info().
 */
function contacts_events_teams_entity_extra_field_info() {
  $extra = [];

  foreach (EventType::loadMultiple() as $bundle) {
    $extra['contacts_event'][$bundle->id()]['form']['team_settings'] = [
      'label' => new TranslatableMarkup('Team settings'),
      'visible' => FALSE,
    ];
  }

  return $extra;
}

/**
 * Implements hook_form_BASE_FORM_ID_alter().
 */
function contacts_events_teams_form_contacts_event_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $event = $form_state->getFormObject()->getEntity();
  $settings = $event->getSetting('teams', []);
  $form['team_settings'] = [
    '#type' => 'fieldset',
    '#title' => new TranslatableMarkup('Team settings'),
    '#parents' => array_merge($form['#parents'] ?? [], ['settings', 'teams']),
    '#tree' => TRUE,
  ];

  $form['team_settings']['enabled'] = [
    '#type' => 'radios',
    '#title' => new TranslatableMarkup('Does this event have volunteer teams?'),
    '#description' => new TranslatableMarkup('Public and invite only teams can be created on the Teams tab once the event is saved.'),
    '#options' => [
      TeamInterface::STATUS_OPEN => new TranslatableMarkup('Published'),
      TeamInterface::STATUS_PRIVATE => new TranslatableMarkup('Private'),
      TeamInterface::STATUS_CLOSED => new TranslatableMarkup('No teams'),
    ],
    '#default_value' => $settings['enabled'] ?? TeamInterface::STATUS_CLOSED,
  ];

  $form['team_settings']['min_age'] = [
    '#type' => 'number',
    '#title' => new TranslatableMarkup('Minimum age'),
    '#description' => new TranslatableMarkup('The minimum age allowed for team applications. Individual teams may set higher minimum ages.'),
    '#default_value' => $settings['min_age'] ?? NULL,
    '#min' => 0,
  ];

  // If the teams checkbox is shown, hide the settings if unchecked.
  if (isset($form['team_settings']['enabled']) && ($form['team_settings']['enabled']['#access'] ?? TRUE)) {
    $form['team_settings']['min_age']['#states']['invisible'][] = [
      ':input[name="settings[teams][enabled]"]' => ['value' => TeamInterface::STATUS_CLOSED],
    ];
  }
}

/**
 * Implements hook_inline_entity_form_table_fields_alter().
 */
function contacts_events_teams_inline_entity_form_table_fields_alter(&$fields, $context) {
  if ($context['entity_type'] == 'commerce_order_item' && $context['allowed_bundles'] == ['contacts_ticket']) {
    if (\Drupal::currentUser()->hasPermission('can manage bookings for contacts_events')) {
      $fields['team'] = [
        'type' => 'callback',
        'label' => new TranslatableMarkup('Team'),
        'weight' => 5.1,
        'callback' => [Team::class, 'getTeamNameFromOrderItem'],
      ];
    }
  }
}

/**
 * Implements hook_field_group_build_build_alter().
 */
function contacts_events_teams_field_group_form_process_build_alter(&$element) {
  // Hide the email configuration if override is disabled.
  if (isset($element['group_emails_wrapper'])) {
    $element['group_emails_wrapper']['#states'] = [
      'invisible' => [
        ':input[name="team_email_override[value]"]' => ['checked' => FALSE],
      ],
    ];
    // Also hide the fieldset label. The fieldset is only added because #states
    // do not work with the tabs formatter.
    $element['group_emails_wrapper']['#title'] = '';
  }
}

/**
 * Implements hook_contacts_events_ticket_summary_alter().
 */
function contacts_events_teams_contacts_events_ticket_summary_alter(array &$build, EventInterface $event) {
  $build['paid_in_full']['#description'] = new TranslatableMarkup('Including approved team tickets.');
  $build['paid_in_full']['#description_display'] = 'after';

  $build['teams']['#cache']['tags'] = ['contacts_ticket_list'];
  $build['teams']['divider'] = ['#markup' => '<hr/>'];

  // Build our query, grouped by is team ticket.
  $query = TicketsController::getBaseStatsQuery($event);
  $query->condition('state', ['pending', 'cancelled'], 'NOT IN');
  $query->groupBy('purchased_entity.entity:contacts_ticket.is_team_ticket');

  // Build our result array.
  $team_counts = [
    'delegates' => 0,
    'team' => 0,
  ];
  foreach ($query->execute() as $row) {
    $key = $row['is_team_ticket_value'] ? 'team' : 'delegates';
    $team_counts[$key] += $row['order_item_id_count'];
  }

  $build['teams']['delegates'] = [
    '#type' => 'item',
    '#title' => new TranslatableMarkup('Confirmed delegates'),
    '#markup' => new PluralTranslatableMarkup($team_counts['delegates'],
      '@number ticket',
      '@number tickets',
      ['@number' => number_format($team_counts['delegates'], 0)]
    ),
  ];

  $build['teams']['team'] = [
    '#type' => 'item',
    '#title' => new TranslatableMarkup('Confirmed team'),
    '#markup' => new PluralTranslatableMarkup($team_counts['team'],
      '@number ticket',
      '@number tickets',
      ['@number' => number_format($team_counts['team'], 0)]),
  ];
}

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

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