You are here

private function WebformCivicrmPostProcess::validateParticipants in Webform CiviCRM Integration 8.5

Validate event participants and add line items

1 call to WebformCivicrmPostProcess::validateParticipants()
WebformCivicrmPostProcess::validate in src/WebformCivicrmPostProcess.php
Called after a webform is submitted Or, for a multipage form, called after each page

File

src/WebformCivicrmPostProcess.php, line 446
Front-end form validation and post-processing.

Class

WebformCivicrmPostProcess

Namespace

Drupal\webform_civicrm

Code

private function validateParticipants() {

  // If we have no valid contacts on the form, don't bother continuing
  if (!$this->existing_contacts) {
    return;
  }
  $count = $this->data['participant_reg_type'] == 'all' ? count($this->existing_contacts) : 1;
  $utils = \Drupal::service('webform_civicrm.utils');

  // Collect selected events
  foreach ($this->data['participant'] as $c => $par) {
    if ($this->data['participant_reg_type'] == 'all') {
      $contacts = $this->existing_contacts;
    }
    elseif (isset($this->existing_contacts[$c])) {
      $contacts = [
        $this->existing_contacts[$c],
      ];
    }
    else {
      continue;
    }
    $participants = current(wf_crm_aval($this->data['contact'], "{$c}:contact", []));
    $participantName = ($participants['first_name'] ?? '') . ' ' . ($participants['last_name'] ?? '');
    if (!trim($participantName)) {
      $participantName = $participants['webform_label'] ?? NULL;
      if (!empty($this->existing_contacts[$c])) {
        $participantName = $utils
          ->wf_crm_apivalues('contact', 'get', $this->existing_contacts[$c], 'display_name')[0];
      }
    }

    // @todo this duplicates a lot in \wf_crm_webform_preprocess::populateEvents
    foreach (wf_crm_aval($par, 'participant', []) as $n => $p) {
      foreach (array_filter(wf_crm_aval($p, 'event_id', [])) as $id_and_type) {
        list($eid) = explode('-', $id_and_type);
        if (is_numeric($eid)) {
          $this->events[$eid]['ended'] = TRUE;
          $this->events[$eid]['title'] = t('this event');
          $this->events[$eid]['count'] = wf_crm_aval($this->events, "{$eid}:count", 0) + $count;
          $this->line_items[] = [
            'qty' => $count,
            'entity_table' => 'civicrm_participant',
            'event_id' => $eid,
            'contact_ids' => $contacts,
            'unit_price' => $p['fee_amount'] ?? 0,
            'element' => "civicrm_{$c}_participant_{$n}_participant_{$id_and_type}",
            'contact_label' => $participantName,
          ];
        }
      }
    }
  }

  // Subtract events already registered for - this only works with known contacts
  $cids = array_filter($this->existing_contacts);
  if ($this->events && $cids) {
    $status_types = $utils
      ->wf_crm_apivalues('participant_status_type', 'get', [
      'is_counted' => 1,
      'return' => 'id',
    ]);
    $existing = $utils
      ->wf_crm_apivalues('Participant', 'get', [
      'return' => [
        'event_id',
        'contact_id',
      ],
      'event_id' => [
        'IN' => array_keys($this->events),
      ],
      'status_id' => [
        'IN' => array_keys($status_types),
      ],
      'contact_id' => [
        'IN' => $cids,
      ],
      'is_test' => 0,
    ]);
    foreach ($existing as $participant) {
      if (isset($this->events[$participant['event_id']])) {
        if (!--$this->events[$participant['event_id']]['count']) {
          unset($this->events[$participant['event_id']]);
        }
      }
      foreach ($this->line_items as $k => &$item) {
        if ($participant['event_id'] == $item['event_id'] && in_array($participant['contact_id'], $item['contact_ids'])) {
          unset($this->line_items[$k]['contact_ids'][array_search($participant['contact_id'], $item['contact_ids'])]);
          if (!--$item['qty']) {
            unset($this->line_items[$k]);
          }
        }
      }
    }
  }
  $this
    ->loadEvents();

  // Add event info to line items
  $format = wf_crm_aval($this->data['reg_options'], 'title_display', 'title');
  foreach ($this->line_items as &$item) {
    $label = empty($item['contact_label']) ? '' : "{$item['contact_label']} - ";
    $item['label'] = $label . $utils
      ->wf_crm_format_event($this->events[$item['event_id']], $format);
    $item['financial_type_id'] = wf_crm_aval($this->events[$item['event_id']], 'financial_type_id', 'Event Fee');
  }

  // Form Validation
  if (!empty($this->data['reg_options']['validate'])) {
    foreach ($this->events as $eid => $event) {
      if ($event['ended']) {
        $this->form_state
          ->setErrorByName($eid, t('Sorry, you can no longer register for %event.', [
          '%event' => $event['title'],
        ]));
      }
      elseif (!empty($event['max_participants']) && $event['count'] > $event['available_places']) {
        if (!empty($event['is_full'])) {
          $this->form_state
            ->setErrorByName($eid, t('%event : @text', [
            '%event' => $event['title'],
            '@text' => $event['event_full_text'],
          ]));
        }
        else {
          $this->form_state
            ->setErrorByName($eid, format_plural($event['available_places'], 'Sorry, you tried to register !count people for %event but there is only 1 space remaining.', 'Sorry, you tried to register !count people for %event but there are only @count spaces remaining.', [
            '%event' => $event['title'],
            '@count' => $event['count'],
          ]));
        }
      }
    }
  }
}