class ViewsFormBase
Same name in other branches
- 9 core/modules/views_ui/src/Form/Ajax/ViewsFormBase.php \Drupal\views_ui\Form\Ajax\ViewsFormBase
- 8.9.x core/modules/views_ui/src/Form/Ajax/ViewsFormBase.php \Drupal\views_ui\Form\Ajax\ViewsFormBase
- 11.x core/modules/views_ui/src/Form/Ajax/ViewsFormBase.php \Drupal\views_ui\Form\Ajax\ViewsFormBase
Provides a base class for Views UI AJAX forms.
Hierarchy
- class \Drupal\Core\Form\FormBase implements \Drupal\Core\Form\FormInterface, \Drupal\Core\DependencyInjection\ContainerInjectionInterface uses \Drupal\Core\DependencyInjection\DependencySerializationTrait, \Drupal\Core\Logger\LoggerChannelTrait, \Drupal\Core\Messenger\MessengerTrait, \Drupal\Core\Routing\RedirectDestinationTrait, \Drupal\Core\StringTranslation\StringTranslationTrait
- class \Drupal\views_ui\Form\Ajax\ViewsFormBase extends \Drupal\Core\Form\FormBase implements \Drupal\views_ui\Form\Ajax\ViewsFormInterface
Expanded class hierarchy of ViewsFormBase
File
-
core/
modules/ views_ui/ src/ Form/ Ajax/ ViewsFormBase.php, line 26
Namespace
Drupal\views_ui\Form\AjaxView source
abstract class ViewsFormBase extends FormBase implements ViewsFormInterface {
/**
* The ID of the item this form is manipulating.
*
* @var string
*/
protected $id;
/**
* The type of item this form is manipulating.
*
* @var string
*/
protected $type;
/**
* Sets the ID for this form.
*
* @param string $id
* The ID of the item this form is manipulating.
*/
protected function setID($id) {
if ($id) {
$this->id = $id;
}
}
/**
* Sets the type for this form.
*
* @param string $type
* The type of the item this form is manipulating.
*/
protected function setType($type) {
if ($type) {
$this->type = $type;
}
}
/**
* {@inheritdoc}
*/
public function getFormState(ViewEntityInterface $view, $display_id, $js) {
// $js may already have been converted to a Boolean.
$ajax = is_string($js) ? $js === 'ajax' : $js;
return (new FormState())->set('form_id', $this->getFormId())
->set('form_key', $this->getFormKey())
->set('ajax', $ajax)
->set('display_id', $display_id)
->set('view', $view)
->set('type', $this->type)
->set('id', $this->id)
->disableRedirect()
->addBuildInfo('callback_object', $this);
}
/**
* {@inheritdoc}
*/
public function getForm(ViewEntityInterface $view, $display_id, $js) {
/** @var \Drupal\Core\Form\FormStateInterface $form_state */
$form_state = $this->getFormState($view, $display_id, $js);
$view = $form_state->get('view');
$form_key = $form_state->get('form_key');
// @todo Remove the need for this.
\Drupal::moduleHandler()->loadInclude('views_ui', 'inc', 'admin');
// Reset the cache of IDs. Drupal rather aggressively prevents ID
// duplication but this causes it to remember IDs that are no longer even
// being used.
Html::resetSeenIds();
// Check to see if this is the top form of the stack. If it is, pop
// it off; if it isn't, the user clicked somewhere else and the stack is
// now irrelevant.
if (!empty($view->stack)) {
$identifier = implode('-', array_filter([
$form_key,
$view->id(),
$display_id,
$form_state->get('type'),
$form_state->get('id'),
]));
// Retrieve the first form from the stack without changing the integer keys,
// as they're being used for the "2 of 3" progress indicator.
reset($view->stack);
$stack_key = key($view->stack);
$top = current($view->stack);
next($view->stack);
unset($view->stack[$stack_key]);
if (array_shift($top) != $identifier) {
$view->stack = [];
}
}
// Automatically remove the form cache if it is set and the key does
// not match. This way navigating away from the form without hitting
// update will work.
if (isset($view->form_cache) && $view->form_cache['key'] !== $form_key) {
unset($view->form_cache);
}
$form_class = get_class($form_state->getFormObject());
$response = $this->ajaxFormWrapper($form_class, $form_state);
// If the form has not been submitted, or was not set for rerendering, stop.
if (!$form_state->isSubmitted() || $form_state->get('rerender')) {
return $response;
}
// Sometimes we need to re-generate the form for multi-step type operations.
if (!empty($view->stack)) {
$stack = $view->stack;
$top = array_shift($stack);
// Build the new form state for the next form in the stack.
$reflection = new \ReflectionClass($view::$forms[$top[1]]);
$form_state = $reflection->newInstanceArgs(array_slice($top, 3, 2))
->getFormState($view, $top[2], $form_state->get('ajax'));
$form_class = get_class($form_state->getFormObject());
$form_state->setUserInput([]);
$form_url = views_ui_build_form_url($form_state);
if (!$form_state->get('ajax')) {
return new RedirectResponse($form_url->setAbsolute()
->toString());
}
$form_state->set('url', $form_url);
$response = $this->ajaxFormWrapper($form_class, $form_state);
}
elseif (!$form_state->get('ajax')) {
// If nothing on the stack, non-js forms just go back to the main view editor.
$display_id = $form_state->get('display_id');
return new RedirectResponse(Url::fromRoute('entity.view.edit_display_form', [
'view' => $view->id(),
'display_id' => $display_id,
], [
'absolute' => TRUE,
])
->toString());
}
else {
$response = new AjaxResponse();
$response->addCommand(new CloseModalDialogCommand());
$response->addCommand(new ShowButtonsCommand(!empty($view->changed)));
$response->addCommand(new TriggerPreviewCommand());
if ($page_title = $form_state->get('page_title')) {
$response->addCommand(new ReplaceTitleCommand($page_title));
}
}
// If this form was for view-wide changes, there's no need to regenerate
// the display section of the form.
if ($display_id !== '') {
\Drupal::entityTypeManager()->getFormObject('view', 'edit')
->rebuildCurrentTab($view, $response, $display_id);
}
return $response;
}
/**
* Wrapper for handling AJAX forms.
*
* Wrapper around \Drupal\Core\Form\FormBuilderInterface::buildForm() to
* handle some AJAX stuff automatically.
* This makes some assumptions about the client.
*
* @param \Drupal\Core\Form\FormInterface|string $form_class
* The value must be one of the following:
* - The name of a class that implements \Drupal\Core\Form\FormInterface.
* - An instance of a class that implements \Drupal\Core\Form\FormInterface.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*
* @return \Drupal\Core\Ajax\AjaxResponse|string|array
* Returns one of three possible values:
* - A \Drupal\Core\Ajax\AjaxResponse object.
* - The rendered form, as a string.
* - A render array with the title in #title and the rendered form in the
* #markup array.
*/
protected function ajaxFormWrapper($form_class, FormStateInterface &$form_state) {
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = \Drupal::service('renderer');
// This won't override settings already in.
if (!$form_state->has('rerender')) {
$form_state->set('rerender', FALSE);
}
$ajax = $form_state->get('ajax');
// Do not overwrite if the redirect has been disabled.
if (!$form_state->isRedirectDisabled()) {
$form_state->disableRedirect($ajax);
}
$form_state->disableCache();
// Builds the form in a render context in order to ensure that cacheable
// metadata is bubbled up.
$render_context = new RenderContext();
$callable = function () use ($form_class, &$form_state) {
return \Drupal::formBuilder()->buildForm($form_class, $form_state);
};
$form = $renderer->executeInRenderContext($render_context, $callable);
if (!$render_context->isEmpty()) {
BubbleableMetadata::createFromRenderArray($form)->merge($render_context->pop())
->applyTo($form);
}
$output = $renderer->renderRoot($form);
// These forms have the title built in, so set the title here:
$title = $form_state->get('title') ?: '';
if ($ajax && (!$form_state->isExecuted() || $form_state->get('rerender'))) {
// If the form didn't execute and we're using ajax, build up an
// Ajax command list to execute.
$response = new AjaxResponse();
// Attach the library necessary for using the OpenModalDialogCommand and
// set the attachments for this Ajax response.
$form['#attached']['library'][] = 'core/drupal.dialog.ajax';
$response->setAttachments($form['#attached']);
$display = '';
$status_messages = [
'#type' => 'status_messages',
];
if ($messages = $renderer->renderRoot($status_messages)) {
$display = '<div class="views-messages">' . $messages . '</div>';
}
$display .= $output;
$options = [
'classes' => [
'ui-dialog' => 'views-ui-dialog js-views-ui-dialog',
],
'width' => '75%',
];
$response->addCommand(new OpenModalDialogCommand($title, $display, $options));
// Views provides its own custom handling of AJAX form submissions.
// Usually this happens at the same path, but custom paths may be
// specified in $form_state.
$form_url = $form_state->has('url') ? $form_state->get('url')
->toString() : Url::fromRoute('<current>')->toString();
$response->addCommand(new SetFormCommand($form_url));
if ($section = $form_state->get('#section')) {
$response->addCommand(new HighlightCommand('.' . Html::cleanCssIdentifier($section)));
}
return $response;
}
return $title ? [
'#title' => $title,
'#markup' => $output,
] : $output;
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
}
}
Members
Title Sort descending | Modifiers | Object type | Summary | Overriden Title | Overrides |
---|---|---|---|---|---|
DependencySerializationTrait::$_entityStorages | protected | property | |||
DependencySerializationTrait::$_serviceIds | protected | property | |||
DependencySerializationTrait::__sleep | public | function | 1 | ||
DependencySerializationTrait::__wakeup | public | function | 2 | ||
FormBase::$configFactory | protected | property | The config factory. | 3 | |
FormBase::$requestStack | protected | property | The request stack. | 1 | |
FormBase::$routeMatch | protected | property | The route match. | ||
FormBase::config | protected | function | Retrieves a configuration object. | ||
FormBase::configFactory | protected | function | Gets the config factory for this form. | 3 | |
FormBase::container | private | function | Returns the service container. | ||
FormBase::create | public static | function | Instantiates a new instance of this class. | Overrides ContainerInjectionInterface::create | 111 |
FormBase::currentUser | protected | function | Gets the current user. | 2 | |
FormBase::getRequest | protected | function | Gets the request object. | ||
FormBase::getRouteMatch | protected | function | Gets the route match. | ||
FormBase::logger | protected | function | Gets the logger for a specific channel. | ||
FormBase::redirect | protected | function | Returns a redirect response object for the specified route. | ||
FormBase::resetConfigFactory | public | function | Resets the configuration factory. | ||
FormBase::setConfigFactory | public | function | Sets the config factory for this form. | ||
FormBase::setRequestStack | public | function | Sets the request stack object to use. | ||
FormInterface::buildForm | public | function | Form constructor. | 203 | |
FormInterface::getFormId | public | function | Returns a unique string identifying the form. | 284 | |
LoggerChannelTrait::$loggerFactory | protected | property | The logger channel factory service. | ||
LoggerChannelTrait::getLogger | protected | function | Gets the logger for a specific channel. | ||
LoggerChannelTrait::setLoggerFactory | public | function | Injects the logger channel factory. | ||
MessengerTrait::$messenger | protected | property | The messenger. | 16 | |
MessengerTrait::messenger | public | function | Gets the messenger. | 16 | |
MessengerTrait::setMessenger | public | function | Sets the messenger. | ||
RedirectDestinationTrait::$redirectDestination | protected | property | The redirect destination service. | 2 | |
RedirectDestinationTrait::getDestinationArray | protected | function | Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url. | ||
RedirectDestinationTrait::getRedirectDestination | protected | function | Returns the redirect destination service. | ||
RedirectDestinationTrait::setRedirectDestination | public | function | Sets the redirect destination service. | ||
StringTranslationTrait::$stringTranslation | protected | property | The string translation service. | 3 | |
StringTranslationTrait::formatPlural | protected | function | Formats a string containing a count of items. | ||
StringTranslationTrait::getNumberOfPlurals | protected | function | Returns the number of plurals supported by a given language. | ||
StringTranslationTrait::getStringTranslation | protected | function | Gets the string translation service. | ||
StringTranslationTrait::setStringTranslation | public | function | Sets the string translation service to use. | 2 | |
StringTranslationTrait::t | protected | function | Translates a string to the current language or to a given language. | ||
ViewsFormBase::$id | protected | property | The ID of the item this form is manipulating. | ||
ViewsFormBase::$type | protected | property | The type of item this form is manipulating. | ||
ViewsFormBase::ajaxFormWrapper | protected | function | Wrapper for handling AJAX forms. | ||
ViewsFormBase::getForm | public | function | Creates a new instance of this form. | Overrides ViewsFormInterface::getForm | 6 |
ViewsFormBase::getFormState | public | function | Gets the form state for this form. | Overrides ViewsFormInterface::getFormState | 1 |
ViewsFormBase::setID | protected | function | Sets the ID for this form. | ||
ViewsFormBase::setType | protected | function | Sets the type for this form. | ||
ViewsFormBase::submitForm | public | function | Form submission handler. | Overrides FormInterface::submitForm | 9 |
ViewsFormBase::validateForm | public | function | Form validation handler. | Overrides FormBase::validateForm | 3 |
ViewsFormInterface::getFormKey | public | function | Returns the key that represents this form. | 10 |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.