You are here

public static function Registrants::processIdentityElement in RNG - Events and Registrations 3.x

Same name and namespace in other branches
  1. 8.2 src/Element/Registrants.php \Drupal\rng\Element\Registrants::processIdentityElement()
  2. 8 src/Element/Registrants.php \Drupal\rng\Element\Registrants::processIdentityElement()

Process the registrant element.

Parameters

array $element: An associative array containing the form structure of the element.

\Drupal\Core\Form\FormStateInterface $form_state: The current state of the form.

array $complete_form: An associative array containing the structure of the form.

Return value

array The new form structure for the element.

Throws

\Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException

\Drupal\Component\Plugin\Exception\PluginNotFoundException

\Drupal\Core\Entity\EntityMalformedException

File

src/Element/Registrants.php, line 93

Class

Registrants
Provides a form element for a registrant and person association.

Namespace

Drupal\rng\Element

Code

public static function processIdentityElement(array &$element, FormStateInterface $form_state, array &$complete_form) {
  if (!isset($element['#event'])) {
    throw new \InvalidArgumentException('Element is missing #event property.');
  }
  if (!$element['#event'] instanceof EntityInterface) {
    throw new \InvalidArgumentException('#event for element is not an entity.');
  }

  /** @var \Drupal\rng\Entity\RegistrationInterface $registration */
  $registration = $element['#registration'];
  $event_meta = $registration
    ->getEventMeta();
  $event_type = $event_meta
    ->getEventType();
  $allow_anon = $event_type
    ->getAllowAnonRegistrants();
  if (!$allow_anon && empty($element['#allow_creation']) && empty($element['#allow_reference'])) {
    throw new \InvalidArgumentException('Element cannot create or reference any entities.');
  }

  // Supporting services

  /** @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository */
  $entity_display_repository = \Drupal::service('entity_display.repository');

  /** @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface $bundle_info */
  $bundle_info = \Drupal::service('entity_type.bundle.info');

  /** @var \Drupal\Core\Entity\EntityFormBuilder $entity_form_builder */
  $entity_form_builder = \Drupal::service('entity.form_builder');
  $parents = $element['#parents'];
  $event = $element['#event'];
  $ajax_wrapper_id_root = 'ajax-wrapper-' . implode('-', $parents);
  $element['#tree'] = TRUE;
  $element['#identity_element_root'] = TRUE;
  $element['#prefix'] = '<div id="' . $ajax_wrapper_id_root . '">';
  $element['#suffix'] = '</div>';

  /** @var \Drupal\rng\Entity\RegistrantInterface[] $people */
  $people = $element['#value'];
  $ajax_wrapper_id_people = 'ajax-wrapper-people-' . implode('-', $parents);
  $element['people'] = [
    '#prefix' => '<div id="' . $ajax_wrapper_id_people . '">',
    '#suffix' => '</div>',
    '#tree' => TRUE,
  ];
  $counter = 0;
  foreach ($people as $reg_id => $registrant) {
    $counter++;
    $curr_parent = array_merge($parents, [
      $counter,
    ]);

    /** @var RegistrantFields $helper */
    $reg_form = [
      '#parents' => $curr_parent,
      '#reg_counter' => $counter,
      '#reg_id' => $reg_id,
    ];
    $helper = new RegistrantFields($reg_form, $form_state, $registrant);
    $reg_form = $helper
      ->getFields($reg_form, $form_state, $registrant);
    $row = [
      '#type' => 'fieldset',
      '#title' => 'Attendee ' . $counter . ' - ' . '<a href="/user">' . $registrant
        ->label() . '</a>',
      '#open' => TRUE,
      '#parents' => $curr_parent,
      'registrant' => $reg_form,
      '#wrapper_attributes' => [
        'class' => [
          'registrant-grid',
        ],
      ],
    ];
    $row['registrant']['#attributes']['class'][] = 'registrant-grid';
    $element['people'][] = $row;
  }
  if ($registration
    ->canAddRegistrants()) {
    $person_subform =& $element['entities']['person'];
    $person_subform['new_person'] = [
      '#type' => 'details',
      '#open' => TRUE,
      '#tree' => TRUE,
      '#title' => t('New @entity_type', [
        '@entity_type' => 'Registrant',
      ]),
      '#identity_element_create_container' => TRUE,
    ];
    if (count($people)) {

      // Add New button
      $person_subform['new_person']['load_create_form'] = [
        '#type' => 'submit',
        '#value' => t('Create new @label', [
          '@label' => $bundle_info['label'],
        ]),
        '#ajax' => [
          'callback' => [
            static::class,
            'ajaxElementRoot',
          ],
          'wrapper' => $ajax_wrapper_id_root,
        ],
        '#validate' => [
          [
            static::class,
            'decoyValidator',
          ],
        ],
        '#submit' => [
          [
            static::class,
            'submitToggleCreateEntity',
          ],
        ],
        '#toggle_create_entity' => TRUE,
        '#limit_validation_errors' => [],
      ];
    }
    else {

      // set form
      $person_subform['new_person']['newentityform'] = [
        '#tree' => TRUE,
        '#parents' => array_merge($parents, [
          'entities',
          'person',
          'new_person',
          'newentityform',
        ]),
      ];

      /** @var \Drupal\rng\RegistrantFactoryInterface $registrant_factory */
      $registrant_factory = \Drupal::service('rng.registrant_factory');
      $new_person = $registrant_factory
        ->createRegistrant([
        'event' => $event,
      ]);
      $new_person
        ->setRegistration($registration);
      $display = $entity_display_repository
        ->getFormDisplay('registrant', $new_person
        ->bundle());
      $display
        ->buildForm($new_person, $person_subform['new_person']['newentityform'], $form_state);
      $person_subform['new_person']['actions'] = [
        '#type' => 'actions',
        '#weight' => 10000,
      ];
      $person_subform['new_person']['actions']['create'] = [
        '#type' => 'submit',
        '#value' => t('Create and add to registration'),
        '#ajax' => [
          'callback' => [
            static::class,
            'ajaxElementRoot',
          ],
          'wrapper' => $ajax_wrapper_id_root,
        ],
        '#limit_validation_errors' => [
          array_merge($parents, [
            'entities',
            'person',
            'registrant',
          ]),
          array_merge($parents, [
            'entities',
            'person',
            'new_person',
          ]),
        ],
        '#validate' => [
          [
            static::class,
            'validateCreate',
          ],
        ],
        '#submit' => [
          [
            static::class,
            'submitCreate',
          ],
        ],
      ];
      $person_subform['new_person']['actions']['cancel'] = [
        '#type' => 'submit',
        '#value' => t('Cancel'),
        '#ajax' => [
          'callback' => [
            static::class,
            'ajaxElementRoot',
          ],
          'wrapper' => $ajax_wrapper_id_root,
        ],
        '#limit_validation_errors' => [],
        '#toggle_create_entity' => FALSE,
        '#validate' => [
          [
            static::class,
            'decoyValidator',
          ],
        ],
        '#submit' => [
          [
            static::class,
            'submitToggleCreateEntity',
          ],
        ],
      ];
    }
  }
  return $element;
  $values = NestedArray::getValue($form_state
    ->getUserInput(), $parents);
  $for_bundles = $utility
    ->peopleTypeOptions();
  if (isset($values['entities']['for_bundle'])) {
    $for_bundle = $values['entities']['for_bundle'];
  }
  else {

    // Set for bundle if there is only one person type.
    $for_bundle = count($for_bundles) == 1 ? key($for_bundles) : NULL;
  }
  $change_it = $utility
    ->getChangeIt();
  if (count($for_bundles) == 1) {

    // Show the form directly if it's single persond and only one bundle:
    $utility
      ->setShowCreateEntitySubform(TRUE);
  }
  $entity_create_form = $utility
    ->getShowCreateEntitySubform();
  if (!$change_it) {
    $element['for']['#tree'] = TRUE;
    if (count($people) > 0) {
      $people_labels = [];
      foreach ($people as $registrant) {
        $people_labels[] = (string) $registrant
          ->label();
      }
      $element['for']['fortext']['#markup'] = (string) t('This registration is for') . ' ' . implode(', ', $people_labels);
      $element['for']['change'] = [
        '#type' => 'submit',
        '#value' => t('Change'),
        '#ajax' => [
          'callback' => [
            static::class,
            'ajaxElementRoot',
          ],
          'wrapper' => $ajax_wrapper_id_root,
        ],
        '#limit_validation_errors' => [],
        '#validate' => [
          [
            static::class,
            'decoyValidator',
          ],
        ],
        '#submit' => [
          [
            static::class,
            'submitChangeDefault',
          ],
        ],
      ];
    }
    else {

      // There are zero registrants.
      $change_it = TRUE;
    }
  }
  $ajax_wrapper_id_people = 'ajax-wrapper-people-' . implode('-', $parents);

  // Drupals' radios element does not pass #executes_submit_callback and
  // #radios to its children radio like it does for #ajax. So we have to
  // create the children radios manually.
  $element['people'] = [
    '#prefix' => '<div id="' . $ajax_wrapper_id_people . '">',
    '#suffix' => '</div>',
  ];
  $element['people']['people_list'] = [
    '#type' => 'table',
    '#header' => [
      t('Person'),
      t('Operations'),
    ],
    '#access' => $change_it,
    '#empty' => t('There are no people yet, add people below.'),
  ];
  foreach ($people as $i => $registrant) {
    $row = [];
    $row[]['#markup'] = $registrant
      ->label();
    $row[] = [
      // Needs a name else the submission handlers think all buttons are the
      // last button.
      '#name' => 'ajax-submit-' . implode('-', $parents) . '-' . $i,
      '#type' => 'submit',
      '#value' => t('Remove'),
      '#ajax' => [
        'callback' => [
          static::class,
          'ajaxElementRoot',
        ],
        'wrapper' => $ajax_wrapper_id_root,
      ],
      '#limit_validation_errors' => [],
      '#validate' => [
        [
          static::class,
          'decoyValidator',
        ],
      ],
      '#submit' => [
        [
          static::class,
          'submitRemovePerson',
        ],
      ],
      '#identity_element_registrant_row' => $i,
    ];
    $display = $entity_display_repository
      ->getFormDisplay('registrant', $registrant
      ->bundle());
    $display
      ->buildForm($registrant, $row, $form_state);
    $row[] = $display;
    $element['people']['people_list'][] = $row;
  }
  $ajax_wrapper_id_entities = 'ajax-wrapper-entities-' . implode('-', $parents);
  $element['entities'] = [
    '#type' => 'details',
    '#access' => $change_it,
    '#prefix' => '<div id="' . $ajax_wrapper_id_entities . '">',
    '#suffix' => '</div>',
    '#open' => TRUE,
    '#tree' => TRUE,
    '#title' => t('Add another person'),
    '#attributes' => [
      'class' => [
        'entities',
      ],
    ],
  ];
  $element['entities']['controls'] = [
    '#type' => 'container',
    '#tree' => TRUE,
    '#attributes' => [
      'class' => [
        'person-controls',
      ],
    ],
  ];
  $element['entities']['controls']['for_bundle'] = [
    '#type' => 'radios',
    '#title' => t('Person type'),
    '#options' => $for_bundles,
    '#default_value' => $for_bundle,
    '#access' => $change_it && count($for_bundles) > 1,
    '#ajax' => [
      'callback' => [
        static::class,
        'ajaxElementRoot',
      ],
      'wrapper' => $ajax_wrapper_id_root,
      'progress' => [
        'type' => 'throbber',
        'message' => NULL,
      ],
    ],
    '#validate' => [
      [
        static::class,
        'decoyValidator',
      ],
    ],
    '#attributes' => [
      'class' => [
        'person-type',
      ],
    ],
    '#parents' => array_merge($parents, [
      'entities',
      'for_bundle',
    ]),
  ];
  $element['entities']['controls']['actions'] = [
    '#type' => 'actions',
    '#tree' => TRUE,
  ];

  // Display a close button if there are people and arity is multiple.
  if (count($people) > 0) {
    $element['entities']['controls']['actions']['done'] = [
      '#type' => 'submit',
      '#value' => t('Done'),
      '#ajax' => [
        'callback' => [
          static::class,
          'ajaxElementRoot',
        ],
        'wrapper' => $ajax_wrapper_id_root,
      ],
      '#limit_validation_errors' => [],
      '#validate' => [
        [
          static::class,
          'decoyValidator',
        ],
      ],
      '#submit' => [
        [
          static::class,
          'submitClose',
        ],
      ],
    ];
  }
  $element['entities']['person'] = [
    '#type' => 'container',
    '#tree' => TRUE,
    '#attributes' => [
      'class' => [
        'person-container',
      ],
    ],
  ];
  $person_subform =& $element['entities']['person'];
  if ($change_it && isset($for_bundle)) {
    [
      $person_entity_type_id,
      $person_bundle,
    ] = explode(':', $for_bundle);

    // Registrant.
    $person_subform['registrant'] = [
      '#tree' => TRUE,
      '#open' => TRUE,
      '#title' => t('Registrant metadata'),
      '#parents' => array_merge($parents, [
        'entities',
        'person',
        'registrant',
      ]),
    ];
    $display = \Drupal::service('entity_display.repository')
      ->getFormDisplay('registrant', $registrant
      ->bundle());
    $display
      ->buildForm($registrant, $person_subform['registrant'], $form_state);
    $form_state
      ->set('registrant__form_display', $display);
    $form_state
      ->set('registrant__entity', $registrant);
    if ($for_bundle === 'myself:') {
      $person_subform['myself']['actions'] = [
        '#type' => 'actions',
      ];
      $person_subform['myself']['actions']['add_myself'] = [
        '#type' => 'submit',
        '#value' => $arity_is_single ? t('Select my account') : t('Add my account'),
        '#ajax' => [
          'callback' => [
            static::class,
            'ajaxElementRoot',
          ],
          'wrapper' => $ajax_wrapper_id_root,
        ],
        '#limit_validation_errors' => [
          array_merge($element['#parents'], [
            'entities',
            'person',
            'registrant',
          ]),
          array_merge($element['#parents'], [
            'entities',
            'person',
            'myself',
          ]),
        ],
        '#validate' => [
          [
            static::class,
            'validateMyself',
          ],
        ],
        '#submit' => [
          [
            static::class,
            'submitMyself',
          ],
        ],
      ];
    }
    else {
      $entity_type = $entity_type_manager
        ->getDefinition($person_entity_type_id);
      $entity_bundle_info = $bundle_info
        ->getBundleInfo($person_entity_type_id);
      $bundle_info = $entity_bundle_info[$person_bundle];
      $allow_reference = isset($element['#allow_reference'][$person_entity_type_id]) && in_array($person_bundle, $element['#allow_reference'][$person_entity_type_id]);

      // Existing person.
      $person_subform['existing'] = [
        '#type' => 'details',
        '#open' => TRUE,
        '#title' => t('Existing @entity_type', [
          '@entity_type' => $entity_type
            ->getLabel(),
        ]),
        '#identity_element_existing_container' => TRUE,
        '#attributes' => [
          'class' => [
            'existing-container',
          ],
        ],
        '#access' => $allow_reference && $utility
          ->countReferenceableEntities($event, $person_entity_type_id) > 0,
      ];
      $person_subform['existing']['existing_autocomplete'] = [
        '#type' => 'entity_autocomplete',
        '#title' => t('Existing @entity_type', [
          '@entity_type' => $entity_type
            ->getLabel(),
        ]),
        '#target_type' => $person_entity_type_id,
        '#tags' => FALSE,
        '#selection_handler' => 'rng_register',
        '#selection_settings' => [
          'event_entity_type' => $event
            ->getEntityTypeId(),
          'event_entity_id' => $event
            ->id(),
        ],
        '#wrapper_attributes' => [
          'class' => [
            'existing-autocomplete-container',
          ],
        ],
      ];
      if ($entity_type
        ->getBundleEntityType() !== NULL) {

        // This entity type has bundles.
        $person_subform['existing']['existing_autocomplete']['#selection_settings']['target_bundles'] = [
          $person_bundle,
        ];
      }
      $person_subform['existing']['actions'] = [
        '#type' => 'actions',
      ];
      $person_subform['existing']['actions']['add_existing'] = [
        '#type' => 'submit',
        '#value' => t('Add person'),
        '#ajax' => [
          'callback' => [
            static::class,
            'ajaxElementRoot',
          ],
          'wrapper' => $ajax_wrapper_id_root,
        ],
        '#limit_validation_errors' => [
          array_merge($element['#parents'], [
            'entities',
            'person',
            'registrant',
          ]),
          array_merge($element['#parents'], [
            'entities',
            'person',
            'existing',
          ]),
        ],
        '#validate' => [
          [
            static::class,
            'validateExisting',
          ],
        ],
        '#submit' => [
          [
            static::class,
            'submitExisting',
          ],
        ],
      ];

      // New entity.
      $create = FALSE;
      if (isset($element['#allow_creation'][$person_entity_type_id])) {
        $create = RegistrantsElement::entityCreateAccess($person_entity_type_id, $person_bundle);
      }
      $person_subform['new_person'] = [
        '#type' => 'details',
        '#open' => TRUE,
        '#tree' => TRUE,
        '#title' => t('New @entity_type', [
          '@entity_type' => $entity_type
            ->getLabel(),
        ]),
        '#identity_element_create_container' => TRUE,
        '#access' => $create,
      ];
      if ($entity_create_form) {
        $person_subform['new_person']['newentityform'] = [
          '#access' => $entity_create_form,
          '#tree' => TRUE,
          '#parents' => array_merge($parents, [
            'entities',
            'person',
            'new_person',
            'newentityform',
          ]),
        ];
        $entity_storage = $entity_type_manager
          ->getStorage($person_entity_type_id);
        $new_person_options = [];
        if ($entity_type
          ->getBundleEntityType() !== NULL) {

          // This entity type has bundles.
          $new_person_options[$entity_type
            ->getKey('bundle')] = $person_bundle;
        }
        $new_person = $entity_storage
          ->create($new_person_options);
        $form_mode = 'default';
        if (isset($element['#form_modes'][$person_entity_type_id][$person_bundle])) {
          $form_mode = $element['#form_modes'][$person_entity_type_id][$person_bundle];
        }
        $display = \Drupal::service('entity_display.repository')
          ->getFormDisplay($person_entity_type_id, $person_bundle, $form_mode);
        $display
          ->buildForm($new_person, $person_subform['new_person']['newentityform'], $form_state);
        $form_state
          ->set('newentity__form_display', $display);
        $form_state
          ->set('newentity__entity', $new_person);
        $person_subform['new_person']['actions'] = [
          '#type' => 'actions',
          '#weight' => 10000,
        ];
        $person_subform['new_person']['actions']['create'] = [
          '#type' => 'submit',
          '#value' => t('Create and add to registration'),
          '#ajax' => [
            'callback' => [
              static::class,
              'ajaxElementRoot',
            ],
            'wrapper' => $ajax_wrapper_id_root,
          ],
          '#limit_validation_errors' => [
            array_merge($parents, [
              'entities',
              'person',
              'registrant',
            ]),
            array_merge($parents, [
              'entities',
              'person',
              'new_person',
            ]),
          ],
          '#validate' => [
            [
              static::class,
              'validateCreate',
            ],
          ],
          '#submit' => [
            [
              static::class,
              'submitCreate',
            ],
          ],
        ];
        $person_subform['new_person']['actions']['cancel'] = [
          '#type' => 'submit',
          '#value' => t('Cancel'),
          '#ajax' => [
            'callback' => [
              static::class,
              'ajaxElementRoot',
            ],
            'wrapper' => $ajax_wrapper_id_root,
          ],
          '#limit_validation_errors' => [],
          '#toggle_create_entity' => FALSE,
          '#validate' => [
            [
              static::class,
              'decoyValidator',
            ],
          ],
          '#submit' => [
            [
              static::class,
              'submitToggleCreateEntity',
            ],
          ],
        ];
      }
      else {
        $person_subform['new_person']['load_create_form'] = [
          '#type' => 'submit',
          '#value' => t('Create new @label', [
            '@label' => $bundle_info['label'],
          ]),
          '#ajax' => [
            'callback' => [
              static::class,
              'ajaxElementRoot',
            ],
            'wrapper' => $ajax_wrapper_id_root,
          ],
          '#validate' => [
            [
              static::class,
              'decoyValidator',
            ],
          ],
          '#submit' => [
            [
              static::class,
              'submitToggleCreateEntity',
            ],
          ],
          '#toggle_create_entity' => TRUE,
          '#limit_validation_errors' => [],
        ];
      }
    }
  }
  else {

    // There is no subform displayed to the side of "Person type" radios:
    $person_subform['#attributes']['class'][] = 'empty';
    $person_subform['select-person-type'] = [
      '#plain_text' => t('Select person type'),
      '#prefix' => '<div class="message">',
      '#suffix' => '</div>',
    ];
  }
  return $element;
}