/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { // If the form is rebuilding. if ($form_state->isRebuilding()) { // If an encryption method change triggered the rebuild. if ($form_state->getTriggeringElement()['#name'] == 'encryption_method') { // Update the encryption method plugin. $this->updateEncryptionMethod($form_state); } } elseif ($this->operation == "edit") { // Only when the form is first built. /* @var $encryption_profile \Drupal\encrypt\Entity\EncryptionProfile */ $encryption_profile = $this->entity; $this->originalProfile = clone $encryption_profile; } return parent::buildForm($form, $form_state); }
/** * {@inheritdoc} */ protected function formMultipleElements(FieldItemListInterface $items, array &$form, FormStateInterface $form_state) { // We don't want to render empty items on field collection fields // unless a) the field collection is empty ; b) the form is rebuilding, // which means that the user clicked on "Add another item"; or // c) we are creating a new entity. if (count($items) > 0 && !$form_state->isRebuilding() && !$items->getEntity()->isNew()) { $field_name = $this->fieldDefinition->getName(); $cardinality = $this->fieldDefinition->getFieldStorageDefinition()->getCardinality(); $parents = $form['#parents']; if ($cardinality == FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED) { $field_state = static::getWidgetState($parents, $field_name, $form_state); $field_state['items_count']--; static::setWidgetState($parents, $field_name, $form_state, $field_state); } } // Adjust wrapper identifiers as they are shared between parents and // children in nested field collections. $form['#wrapper_id'] = Html::getUniqueID($items->getName()); $elements = parent::formMultipleElements($items, $form, $form_state); $elements['#prefix'] = '<div id="' . $form['#wrapper_id'] . '">'; $elements['#suffix'] = '</div>'; $elements['add_more']['#ajax']['wrapper'] = $form['#wrapper_id']; return $elements; }
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { if ($form_state->isRebuilding()) { $form_state->setUserInput(array()); } // Initialize $storage = $form_state->getStorage(); if (empty($storage)) { $user_input = $form_state->getUserInput(); if (empty($user_input)) { $_SESSION['constructions'] = 0; } // Put the initial thing into the storage $storage = ['thing' => ['title' => 'none', 'value' => '']]; $form_state->setStorage($storage); } // Count how often the form is constructed. $_SESSION['constructions']++; drupal_set_message("Form constructions: " . $_SESSION['constructions']); $form['title'] = array('#type' => 'textfield', '#title' => 'Title', '#default_value' => $storage['thing']['title'], '#required' => TRUE); $form['value'] = array('#type' => 'textfield', '#title' => 'Value', '#default_value' => $storage['thing']['value'], '#element_validate' => array('::elementValidateValueCached')); $form['continue_button'] = array('#type' => 'button', '#value' => 'Reset'); $form['continue_submit'] = array('#type' => 'submit', '#value' => 'Continue submit', '#submit' => array('::continueSubmitForm')); $form['submit'] = array('#type' => 'submit', '#value' => 'Save'); if (\Drupal::request()->get('cache')) { // Manually activate caching, so we can test that the storage keeps working // when it's enabled. $form_state->setCached(); } if ($this->getRequest()->get('immutable')) { $form_state->addBuildInfo('immutable', TRUE); } return $form; }
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { if ($form_state->isRebuilding()) { $form_state->setUserInput(array()); } // Initialize $storage = $form_state->getStorage(); if (empty($storage)) { $user_input = $form_state->getUserInput(); if (empty($user_input)) { $_SESSION['constructions'] = 0; } // Put the initial thing into the storage $storage = ['thing' => ['title' => 'none', 'value' => '']]; $form_state->setStorage($storage); } // Count how often the form is constructed. $_SESSION['constructions']++; drupal_set_message("Form constructions: " . $_SESSION['constructions']); $form['title'] = array('#type' => 'textfield', '#title' => 'Title', '#default_value' => $storage['thing']['title'], '#required' => TRUE); $form['value'] = array('#type' => 'textfield', '#title' => 'Value', '#default_value' => $storage['thing']['value'], '#element_validate' => array('::elementValidateValueCached')); $form['continue_button'] = array('#type' => 'button', '#value' => 'Reset'); $form['continue_submit'] = array('#type' => 'submit', '#value' => 'Continue submit', '#submit' => array('::continueSubmitForm')); $form['submit'] = array('#type' => 'submit', '#value' => 'Save'); // @todo Remove this in https://www.drupal.org/node/2524408, because form // cache immutability is no longer necessary, because we no longer cache // forms during safe HTTP methods. In the meantime, because // Drupal\system\Tests\Form still has test coverage for a poisoned form // cache following a GET request, trick $form_state into caching the form // to keep that test working until we either remove it or change it in // that issue. if ($this->getRequest()->get('immutable')) { $form_state->addBuildInfo('immutable', TRUE); if ($this->getRequest()->get('cache') && $this->getRequest()->isMethodSafe()) { $form_state->setRequestMethod('FAKE'); $form_state->setCached(); } } return $form; }
/** * {@inheritdoc} */ public function getForm(array &$original_form, FormStateInterface $form_state) { $form = []; // TODO - do we need better error handling for view and view_display (in case // either of those is nonexistent or display not of correct type)? $storage =& $form_state->getStorage(); if (empty($storage['selection_display_view']) || $form_state->isRebuilding()) { $storage['selection_display_view'] = $this->entityManager->getStorage('view')->load($this->configuration['view'])->getExecutable(); } // TODO - if there are entities that are selected multiple times this displays // them only once. Reason for that is how SQL and Views work and we probably // can't do much about it. if (!empty($this->selectedEntities)) { $ids = array_map(function (EntityInterface $item) { return $item->id(); }, $this->selectedEntities); $storage['selection_display_view']->setArguments([implode(',', $ids)]); } $form['view'] = $storage['selection_display_view']->executeDisplay($this->configuration['view_display']); $form['use_selected'] = array('#type' => 'submit', '#value' => t('Use selection'), '#name' => 'use_selected'); return $form; }
/** * Adds the #name and #value properties of an input element before rendering. */ protected function handleInputElement($form_id, &$element, FormStateInterface &$form_state) { if (!isset($element['#name'])) { $name = array_shift($element['#parents']); $element['#name'] = $name; if ($element['#type'] == 'file') { // To make it easier to handle files in file.inc, we place all // file fields in the 'files' array. Also, we do not support // nested file names. // @todo Remove this files prefix now? $element['#name'] = 'files[' . $element['#name'] . ']'; } elseif (count($element['#parents'])) { $element['#name'] .= '[' . implode('][', $element['#parents']) . ']'; } array_unshift($element['#parents'], $name); } // Setting #disabled to TRUE results in user input being ignored regardless // of how the element is themed or whether JavaScript is used to change the // control's attributes. However, it's good UI to let the user know that // input is not wanted for the control. HTML supports two attributes for: // this: http://www.w3.org/TR/html401/interact/forms.html#h-17.12. If a form // wants to start a control off with one of these attributes for UI // purposes, only, but still allow input to be processed if it's submitted, // it can set the desired attribute in #attributes directly rather than // using #disabled. However, developers should think carefully about the // accessibility implications of doing so: if the form expects input to be // enterable under some condition triggered by JavaScript, how would someone // who has JavaScript disabled trigger that condition? Instead, developers // should consider whether a multi-step form would be more appropriate // (#disabled can be changed from step to step). If one still decides to use // JavaScript to affect when a control is enabled, then it is best for // accessibility for the control to be enabled in the HTML, and disabled by // JavaScript on document ready. if (!empty($element['#disabled'])) { if (!empty($element['#allow_focus'])) { $element['#attributes']['readonly'] = 'readonly'; } else { $element['#attributes']['disabled'] = 'disabled'; } } // With JavaScript or other easy hacking, input can be submitted even for // elements with #access=FALSE or #disabled=TRUE. For security, these must // not be processed. Forms that set #disabled=TRUE on an element do not // expect input for the element, and even forms submitted with // self::submitForm() must not be able to get around this. Forms that set // #access=FALSE on an element usually allow access for some users, so forms // submitted with self::submitForm() may bypass access restriction and be // treated as high-privilege users instead. $process_input = empty($element['#disabled']) && ($form_state->isProgrammed() && $form_state->isBypassingProgrammedAccessChecks() || $form_state->isProcessingInput() && (!isset($element['#access']) || $element['#access'])); // Set the element's #value property. if (!isset($element['#value']) && !array_key_exists('#value', $element)) { // @todo Once all elements are converted to plugins in // https://www.drupal.org/node/2311393, rely on // $element['#value_callback'] directly. $value_callable = !empty($element['#value_callback']) ? $element['#value_callback'] : 'form_type_' . $element['#type'] . '_value'; if (!is_callable($value_callable)) { $value_callable = '\\Drupal\\Core\\Render\\Element\\FormElement::valueCallback'; } if ($process_input) { // Get the input for the current element. NULL values in the input need // to be explicitly distinguished from missing input. (see below) $input_exists = NULL; $input = NestedArray::getValue($form_state->getUserInput(), $element['#parents'], $input_exists); // For browser-submitted forms, the submitted values do not contain // values for certain elements (empty multiple select, unchecked // checkbox). During initial form processing, we add explicit NULL // values for such elements in FormState::$input. When rebuilding the // form, we can distinguish elements having NULL input from elements // that were not part of the initially submitted form and can therefore // use default values for the latter, if required. Programmatically // submitted forms can submit explicit NULL values when calling // self::submitForm() so we do not modify FormState::$input for them. if (!$input_exists && !$form_state->isRebuilding() && !$form_state->isProgrammed()) { // Add the necessary parent keys to FormState::$input and sets the // element's input value to NULL. NestedArray::setValue($form_state->getUserInput(), $element['#parents'], NULL); $input_exists = TRUE; } // If we have input for the current element, assign it to the #value // property, optionally filtered through $value_callback. if ($input_exists) { // Skip all value callbacks except safe ones like text if the CSRF // token was invalid. if (!$form_state->hasInvalidToken() || $this->valueCallableIsSafe($value_callable)) { $element['#value'] = call_user_func_array($value_callable, array(&$element, $input, &$form_state)); } else { $input = NULL; } if (!isset($element['#value']) && isset($input)) { $element['#value'] = $input; } } // Mark all posted values for validation. if (isset($element['#value']) || !empty($element['#required'])) { $element['#needs_validation'] = TRUE; } } // Load defaults. if (!isset($element['#value'])) { // Call #type_value without a second argument to request default_value // handling. $element['#value'] = call_user_func_array($value_callable, array(&$element, FALSE, &$form_state)); // Final catch. If we haven't set a value yet, use the explicit default // value. Avoid image buttons (which come with garbage value), so we // only get value for the button actually clicked. if (!isset($element['#value']) && empty($element['#has_garbage_value'])) { $element['#value'] = isset($element['#default_value']) ? $element['#default_value'] : ''; } } } // Determine which element (if any) triggered the submission of the form and // keep track of all the clickable buttons in the form for // \Drupal\Core\Form\FormState::cleanValues(). Enforce the same input // processing restrictions as above. if ($process_input) { // Detect if the element triggered the submission via Ajax. if ($this->elementTriggeredScriptedSubmission($element, $form_state)) { $form_state->setTriggeringElement($element); } // If the form was submitted by the browser rather than via Ajax, then it // can only have been triggered by a button, and we need to determine // which button within the constraints of how browsers provide this // information. if (!empty($element['#is_button'])) { // All buttons in the form need to be tracked for // \Drupal\Core\Form\FormState::cleanValues() and for the // self::doBuildForm() code that handles a form submission containing no // button information in \Drupal::request()->request. $buttons = $form_state->getButtons(); $buttons[] = $element; $form_state->setButtons($buttons); if ($this->buttonWasClicked($element, $form_state)) { $form_state->setTriggeringElement($element); } } } // Set the element's value in $form_state->getValues(), but only, if its key // does not exist yet (a #value_callback may have already populated it). if (!NestedArray::keyExists($form_state->getValues(), $element['#parents'])) { $form_state->setValueForElement($element, $element['#value']); } }
/** * {@inheritdoc} */ public function isRebuilding() { return $this->mainFormState->isRebuilding(); }
/** * Gets the current value of a #select element, from within a form constructor function. * * This function is intended for use in highly dynamic forms (in particular the * add view wizard) which are rebuilt in different ways depending on which * triggering element (AJAX or otherwise) was most recently fired. For example, * sometimes it is necessary to decide how to build one dynamic form element * based on the value of a different dynamic form element that may not have * even been present on the form the last time it was submitted. This function * takes care of resolving those conflicts and gives you the proper current * value of the requested #select element. * * By necessity, this function sometimes uses non-validated user input from * FormState::$input in making its determination. Although it performs some * minor validation of its own, it is not complete. The intention is that the * return value of this function should only be used to help decide how to * build the current form the next time it is reloaded, not to be saved as if * it had gone through the normal, final form validation process. Do NOT use * the results of this function for any other purpose besides deciding how to * build the next version of the form. * * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. * @param $parents * An array of parent keys that point to the part of the submitted form * values that are expected to contain the element's value (in the case where * this form element was actually submitted). In a simple case (assuming * #tree is TRUE throughout the form), if the select element is located in * $form['wrapper']['select'], so that the submitted form values would * normally be found in $form_state->getValue(array('wrapper', 'select')), * you would pass array('wrapper', 'select') for this parameter. * @param $default_value * The default value to return if the #select element does not currently have * a proper value set based on the submitted input. * @param $element * An array representing the current version of the #select element within * the form. * * @return * The current value of the #select element. A common use for this is to feed * it back into $element['#default_value'] so that the form will be rendered * with the correct value selected. */ public static function getSelected(FormStateInterface $form_state, $parents, $default_value, $element) { // For now, don't trust this to work on anything but a #select element. if (!isset($element['#type']) || $element['#type'] != 'select' || !isset($element['#options'])) { return $default_value; } // If there is a user-submitted value for this element that matches one of // the currently available options attached to it, use that. However, only // perform this check during the form rebuild. During the initial build // after #ajax is triggered, we need to rebuild the form as it was // initially. We need to check FormState::getUserInput() rather than // $form_state->getValues() here because the triggering element often has // the #limit_validation_errors property set to prevent unwanted errors // elsewhere on the form. This means that the $form_state->getValues() array // won't be complete. We could make it complete by adding each required part // of the form to the #limit_validation_errors property individually as the // form is being built, but this is difficult to do for a highly dynamic and // extensible form. This method is much simpler. $user_input = $form_state->isRebuilding() ? $form_state->getUserInput() : []; if (!empty($user_input)) { $key_exists = NULL; $submitted = NestedArray::getValue($user_input, $parents, $key_exists); // Check that the user-submitted value is one of the allowed options before // returning it. This is not a substitute for actual form validation; // rather it is necessary because, for example, the same select element // might have #options A, B, and C under one set of conditions but #options // D, E, F under a different set of conditions. So the form submission // might have occurred with option A selected, but when the form is rebuilt // option A is no longer one of the choices. In that case, we don't want to // use the value that was submitted anymore but rather fall back to the // default value. if ($key_exists && in_array($submitted, array_keys($element['#options']))) { return $submitted; } } // Fall back on returning the default value if nothing was returned above. return $default_value; }
/** * {@inheritdoc} */ public function getForm(array &$original_form, FormStateInterface $form_state, array $aditional_widget_parameters) { $form = []; // TODO - do we need better error handling for view and view_display (in case // either of those is nonexistent or display not of correct type)? /** @var \Drupal\views\ViewExecutable $view */ $form['#attached']['library'] = ['entity_browser/view']; $view = $this->entityManager->getStorage('view')->load($this->configuration['view'])->getExecutable(); // Add exposed filter values, if present foreach ($form_state->getUserInput() as $name => $value) { if (strpos($name, 'entity_browser_exposed_') === 0) { $name = str_replace('entity_browser_exposed_', '', $name); $view->exposed_data[$name] = $value; } } if (!empty($this->configuration['arguments'])) { if (!empty($aditional_widget_parameters['path_parts'])) { $arguments = []; // Map configuration arguments with original path parts. foreach ($this->configuration['arguments'] as $argument) { $arguments[] = isset($aditional_widget_parameters['path_parts'][$argument]) ? $aditional_widget_parameters['path_parts'][$argument] : ''; } $view->setArguments(array_values($arguments)); } } $form['view'] = $view->executeDisplay($this->configuration['view_display']); $ids = []; foreach ($view->result as $row_id => $row_result) { /** @var \Drupal\Core\Entity\EntityInterface $entity */ $entity = $row_result->_entity; $ids[$row_id] = ['id' => $entity->id(), 'type' => $entity->getEntityTypeId()]; } $form_state->set('view_widget_rows', $ids); if (empty($view->field['entity_browser_select'])) { $url = Url::fromRoute('entity.view.edit_form', ['view' => $this->configuration['view']])->toString(); if ($this->currentUser->hasPermission('administer views')) { return ['#markup' => t('Entity browser select form field not found on a view. <a href=":link">Go fix it</a>!', [':link' => $url])]; } else { return ['#markup' => t('Entity browser select form field not found on a view. Go fix it!')]; } } // When rebuilding makes no sense to keep checkboxes that were previously // selected. if (!empty($form['view']['entity_browser_select']) && $form_state->isRebuilding()) { foreach (Element::children($form['view']['entity_browser_select']) as $child) { $form['view']['entity_browser_select'][$child]['#process'][] = ['\\Drupal\\entity_browser\\Plugin\\EntityBrowser\\Widget\\View', 'processCheckbox']; $form['view']['entity_browser_select'][$child]['#process'][] = ['\\Drupal\\Core\\Render\\Element\\Checkbox', 'processAjaxForm']; $form['view']['entity_browser_select'][$child]['#process'][] = ['\\Drupal\\Core\\Render\\Element\\Checkbox', 'processGroup']; } } $form['view']['exposed_widgets']['filter'] = ['submit' => ['#type' => 'button', '#value' => t('Filter'), '#name' => 'filter']]; // Add exposed widgets from the view, if present. if (!empty($form['view']['view']['#view']->exposed_widgets)) { $form['view']['exposed_widgets'] += $form['view']['view']['#view']->exposed_widgets; $form['view']['exposed_widgets']['#weight'] = -1; unset($form['view']['view']['#view']->exposed_widgets); // Add exposed filter default values from the form state foreach ($form_state->getUserInput() as $name => $value) { if (strpos($name, 'entity_browser_exposed_') === 0) { $form['view']['exposed_widgets'][$name]['#value'] = $value; } } } else { // We are using this for pagers too so let's keep it in form. $form['view']['exposed_widgets']['filter']['submit']['#attributes']['class'][] = 'visually-hidden'; } $form['view']['view'] = ['#markup' => \Drupal::service('renderer')->render($form['view']['view'])]; return $form; }
/** * {@inheritdoc} */ public function save(array $form, FormStateInterface $form_state) { // Only save the server if the form doesn't need to be rebuilt. if (!$form_state->isRebuilding()) { try { $server = $this->getEntity(); $server->save(); drupal_set_message($this->t('The server was successfully saved.')); $form_state->setRedirect('entity.search_api_server.canonical', array('search_api_server' => $server->id())); } catch (SearchApiException $e) { $form_state->setRebuild(); watchdog_exception('search_api', $e); drupal_set_message($this->t('The server could not be saved.'), 'error'); } } }
/** * @covers ::isRebuilding * * @dataProvider providerSingleBooleanArgument * * @param bool $rebuild */ public function testIsRebuilding($rebuild) { $this->decoratedFormState->isRebuilding()->willReturn($rebuild)->shouldBeCalled(); $this->assertSame($rebuild, $this->formStateDecoratorBase->isRebuilding()); }
/** * {@inheritdoc} */ public function save(array $form, FormStateInterface $form_state) { // @todo Redirect to a confirm form if changing server or tracker, since // that isn't such a light operation (equaling a "clear", basically). // Only save the index if the form doesn't need to be rebuilt. if (!$form_state->isRebuilding()) { try { /** @var \Drupal\search_api\IndexInterface $index */ $index = $this->getEntity(); $index->save(); drupal_set_message($this->t('The index was successfully saved.')); $form_state->setRedirect('entity.search_api_index.canonical', array('search_api_index' => $index->id())); $index_task_manager = Utility::getIndexTaskManager(); if (!$index_task_manager->isTrackingComplete($index)) { $index_task_manager->addItemsBatch($index); } } catch (SearchApiException $ex) { $form_state->setRebuild(); watchdog_exception('search_api', $ex); drupal_set_message($this->t('The index could not be saved.'), 'error'); } } }
/** * {@inheritdoc} */ public function isRebuilding() { return $this->decoratedFormState->isRebuilding(); }
/** * Form API callback: Processes a group of file_generic field elements. * * Adds the weight field to each row so it can be ordered and adds a new Ajax * wrapper around the entire group so it can be replaced all at once. * * This method on is assigned as a #process callback in formMultipleElements() * method. */ public static function processMultiple($element, FormStateInterface $form_state, $form) { $element_children = Element::children($element, TRUE); $count = count($element_children); // Count the number of already uploaded files, in order to display new // items in \Drupal\file\Element\ManagedFile::uploadAjaxCallback(). if (!$form_state->isRebuilding()) { $count_items_before = 0; foreach ($element_children as $children) { if (!empty($element[$children]['#default_value']['fids'])) { $count_items_before++; } } $form_state->set('file_upload_delta_initial', $count_items_before); } foreach ($element_children as $delta => $key) { if ($key != $element['#file_upload_delta']) { $description = static::getDescriptionFromElement($element[$key]); $element[$key]['_weight'] = array('#type' => 'weight', '#title' => $description ? t('Weight for @title', array('@title' => $description)) : t('Weight for new file'), '#title_display' => 'invisible', '#delta' => $count, '#default_value' => $delta); } else { // The title needs to be assigned to the upload field so that validation // errors include the correct widget label. $element[$key]['#title'] = $element['#title']; $element[$key]['_weight'] = array('#type' => 'hidden', '#default_value' => $delta); } } // Add a new wrapper around all the elements for Ajax replacement. $element['#prefix'] = '<div id="' . $element['#id'] . '-ajax-wrapper">'; $element['#suffix'] = '</div>'; return $element; }
/** * {@inheritdoc} */ public function form(array $form, FormStateInterface $form_state) { // If the form is being rebuilt, rebuild the entity with the current form // values. if ($form_state->isRebuilding()) { $this->entity = $this->buildEntity($form, $form_state); } $form = parent::form($form, $form_state); // Set the page title according to whether we are creating or editing the // facet. if ($this->getEntity()->isNew()) { $form['#title'] = $this->t('Add facet'); } else { $form['#title'] = $this->t('Facet settings for %label facet', ['%label' => $this->getEntity()->label()]); } $this->buildEntityForm($form, $form_state, $this->getEntity()); $form['#attached']['library'][] = 'facets/drupal.facets.edit-facet'; return $form; }
/** * {@inheritdoc} */ public function save(array $form, FormStateInterface $form_state) { // @todo Redirect to a confirm form if changing server or tracker, since // that isn't such a light operation (equaling a "clear", basically). // Only save the index if the form doesn't need to be rebuilt. if (!$form_state->isRebuilding()) { try { $this->getEntity()->save(); drupal_set_message($this->t('The index was successfully saved.')); $form_state->setRedirect('entity.search_api_index.canonical', array('search_api_index' => $this->getEntity()->id())); } catch (SearchApiException $ex) { $form_state->setRebuild(); watchdog_exception('search_api', $ex); drupal_set_message($this->t('The index could not be saved.'), 'error'); } } }
/** * {@inheritdoc} */ public function getForm(array &$original_form, FormStateInterface $form_state, array $aditional_widget_parameters) { $form = []; // TODO - do we need better error handling for view and view_display (in case // either of those is nonexistent or display not of correct type)? $form['#attached']['library'] = ['entity_browser/view']; /** @var \Drupal\views\ViewExecutable $view */ $view = $this->entityManager->getStorage('view')->load($this->configuration['view'])->getExecutable(); // Check if the current user has access to this view. if (!$view->access($this->configuration['view_display'])) { return ['#markup' => t('You do not have access to this View.')]; } if (!empty($this->configuration['arguments'])) { if (!empty($aditional_widget_parameters['path_parts'])) { $arguments = []; // Map configuration arguments with original path parts. foreach ($this->configuration['arguments'] as $argument) { $arguments[] = isset($aditional_widget_parameters['path_parts'][$argument]) ? $aditional_widget_parameters['path_parts'][$argument] : ''; } $view->setArguments(array_values($arguments)); } } $form['view'] = $view->executeDisplay($this->configuration['view_display']); if (empty($view->field['entity_browser_select'])) { $url = Url::fromRoute('entity.view.edit_form', ['view' => $this->configuration['view']])->toString(); if ($this->currentUser->hasPermission('administer views')) { return ['#markup' => t('Entity browser select form field not found on a view. <a href=":link">Go fix it</a>!', [':link' => $url])]; } else { return ['#markup' => t('Entity browser select form field not found on a view. Go fix it!')]; } } // When rebuilding makes no sense to keep checkboxes that were previously // selected. if (!empty($form['view']['entity_browser_select']) && $form_state->isRebuilding()) { foreach (Element::children($form['view']['entity_browser_select']) as $child) { $form['view']['entity_browser_select'][$child]['#process'][] = ['\\Drupal\\entity_browser\\Plugin\\EntityBrowser\\Widget\\View', 'processCheckbox']; $form['view']['entity_browser_select'][$child]['#process'][] = ['\\Drupal\\Core\\Render\\Element\\Checkbox', 'processAjaxForm']; $form['view']['entity_browser_select'][$child]['#process'][] = ['\\Drupal\\Core\\Render\\Element\\Checkbox', 'processGroup']; } } $form['view']['view'] = ['#markup' => \Drupal::service('renderer')->render($form['view']['view'])]; return $form; }