Repository URL to install this package:
|
Version:
2.0.2 ▾
|
<?php
namespace Drupal\custom_forms\Form;
use Drupal\Component\Plugin\Exception\PluginException;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Ajax\RedirectCommand;
use Drupal\Core\Entity\EntityMalformedException;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\EventSubscriber\AjaxResponseSubscriber;
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Language\LanguageManager;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Render\Element\StatusMessages;
use Drupal\Core\TempStore\TempStoreException;
use Drupal\Core\Url;
use Drupal\custom_forms\Ajax\CustomFormsErrorCommand;
use Drupal\custom_forms\Controller\SubmissionValidationController;
use Drupal\custom_forms\CustomFormItemFactory;
use Drupal\custom_forms\Entity\CustomForm as CustomFormEntity;
use Drupal\custom_forms\Entity\CustomFormSubmission;
use Drupal\custom_forms\Entity\CustomFormType;
use Drupal\dds\Service\SessionService;
use Drupal\node\Entity\Node;
use NumberFormatter;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Class CustomForm
*
* This is the form that is in charge for actually rendering the custom form.
* It makes sure all fields and groups are properly renderes as well as handle
* the submission events.
*
* @package Drupal\custom_forms\Form
*/
class CustomForm extends FormBase {
/**
* The event dispatcher.
*
* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
*/
protected $eventDispatcher;
/**
* The language the form is displayed in.
*
* @var \Drupal\Core\Language\LanguageInterface
*/
protected $language;
/**
* The logger channel to send log messages to.
*
* @var \Drupal\Core\Logger\LoggerChannelInterface
*/
protected $log;
/**
* The factory in charge of CRUD operations for custom form items.
*
* @var \Drupal\custom_forms\CustomFormItemFactory
*/
protected $itemFactory;
/**
* The validator used for validating submissions.
*
* @var \Drupal\custom_forms\Controller\SubmissionValidationController
*/
protected $validator;
protected $sessionService;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('event_dispatcher'),
$container->get('custom_forms.factory.item'),
$container->get('custom_forms.submission.validator'),
$container->get('language_manager'),
$container->get('dds.session')
);
}
/**
* {@inheritdoc}
*/
public function __construct(
EventDispatcherInterface $event_dispatcher,
CustomFormItemFactory $item_factory,
SubmissionValidationController $validator,
LanguageManager $language_manager,
SessionService $session_service
) {
$this->eventDispatcher = $event_dispatcher;
$this->language = $language_manager->getCurrentLanguage();
$this->log = $this->logger('Custom Forms');
$this->itemFactory = $item_factory;
$this->validator = $validator;
$this->sessionService = $session_service;
}
/**
* Returns a unique string identifying the form.
*
* The returned ID should be a unique string that can be a valid PHP function
* name, since it's used in hook implementation names such as
* hook_form_FORM_ID_alter().
*
* @return string
* The unique string identifying the form.
*/
public function getFormId() : string {
return 'custom_forms';
}
/**
* Form constructor.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*
* @return array
* The form structure.
*/
public function buildForm(array $form, FormStateInterface $form_state) : array {
$form_arguments = $form_state->getBuildInfo()['args'][0];
$request = $this->getRequest();
/** @var \Drupal\custom_forms\Entity\CustomForm $custom_form */
$custom_form = $form_arguments['custom_form'];
$custom_form_type = CustomFormType::load($custom_form->bundle());
// Get translated form if it exists.
if ($custom_form->hasTranslation($this->language->getId())) {
$custom_form = $custom_form->getTranslation($this->language->getId());
}
// Disable caching if it's been configured as such.
if (!$custom_form_type->isCachingEnabled()) {
$form['#cache']['max-age'] = 0;
}
// General styling.
$form['#attached']['library'][] = 'custom_forms/form-style';
// Add error handling javascript library.
$form['#attached']['library'][] = 'custom_forms/field-errors';
// Disable HTML5 validation as we have no control over it.
$form['#attributes']['novalidate'] = 'novalidate';
$form['#attributes']['data-custom-form-id'] = $custom_form->id();
$form['custom_form'] = [
'#type' => 'value',
'#value' => $custom_form,
];
if ((boolean) $custom_form->get('use_ajax')->value) {
$form['#attached']['library'][] = 'custom_forms/prevent-double-submit';
$form['_custom_form_detector'] = [
'#type' => 'hidden',
'#value' => 1,
];
}
// Add the receipt page id to the form so it's saved per submission.
if ($custom_form->hasField('receipt_page') && !$custom_form->get('receipt_page')->isEmpty()) {
$form['_receipt_page_id'] = [
'#type' => 'value',
'#value' => $custom_form->get('receipt_page')->target_id,
];
}
// Add the form URL if it's not been set yet.
if (empty($form_state->getValue('_form_url'))) {
$form['_form_url'] = [
'#type' => 'value',
'#value' => $this->generateFormUrl($request),
];
}
/** @var \Drupal\custom_forms\CustomFormItem[] $items */
$items = $this->itemFactory->getFormItemsAsTree($custom_form, TRUE, TRUE);
foreach ($items as $id => $item) {
$form += $item->buildForm($form, $form_state, $request);
}
return $form;
}
/**
* Form submission handler.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
public function submitForm(array &$form, FormStateInterface $form_state) : void {
$request = $this->getRequest();
if ($request->isXmlHttpRequest()) {
return;
}
/** @var \Drupal\custom_forms\Entity\CustomForm $custom_form */
$custom_form = $form_state->getValue('custom_form');
/** @var \Drupal\custom_forms\CustomFormItem[] $items */
$items = $this->itemFactory->getFormItems($custom_form, TRUE, TRUE);
$submission = $this->createSubmission($form_state);
$validation = $this->validateValues($submission, $items, $form_state);
if (!$validation) {
return;
}
$processed = $this->processValues($submission, $items, $form_state);
if (!$processed) {
return;
}
$initialized = $this->initializeSubmission($submission, $items, $form_state);
if (!$initialized) {
return;
}
}
/**
* Submits the form through ajax.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
* @param \Symfony\Component\HttpFoundation\Request $request
* The request that is calling this function.
*
* @return \Drupal\Core\Ajax\AjaxResponse
* Returns an AjaxResponse for usage within Drupal's ajax system.
*/
public function ajaxSubmitForm(array &$form, FormStateInterface $form_state, Request $request) : AjaxResponse {
$response = new AjaxResponse();
// If this isn't an ajax request, we simply return the empty ajax response.
if (!$request->isXmlHttpRequest()) {
return $response;
}
/** @var \Drupal\custom_forms\Entity\CustomForm $custom_form */
$custom_form = $form_state->getValue('custom_form');
/** @var \Drupal\custom_forms\CustomFormItem[] $items */
$items = $this->itemFactory->getFormItems($custom_form, TRUE, TRUE);
$submission = $this->createSubmission($form_state);
$validation = $this->validateValues($submission, $items, $form_state, $response);
// If validation failed we return the response.
if (!$validation) {
return $response;
}
$processed = $this->processValues($submission, $items, $form_state, $response);
if (!$processed) {
return $response;
}
$initialized = $this->initializeSubmission($submission, $items, $form_state, $response);
if (!$initialized) {
return $response;
}
return $response;
}
/**
* Create a submission from the form state.
*
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state used to populate the submission.
*
* @return \Drupal\custom_forms\Entity\CustomFormSubmission
* Returns the created Custom Form Submission.
*/
private function createSubmission(FormStateInterface $form_state) : CustomFormSubmission {
// Get the cleaned values from the form.
$values = $form_state->cleanValues()->getValues();
/** @var \Drupal\custom_forms\Entity\CustomForm $custom_form */
$custom_form = $form_state->getValue('custom_form');
/** @var \Drupal\custom_forms\Entity\CustomFormSubmission $submission */
$submission = CustomFormSubmission::create();
$submission->setFormId($custom_form->id());
// Unset the custom form and form detector as we do not want to serialize them.
unset($values['custom_form'], $values['_custom_form_detector']);
$submission->setDataArray($values);
return $submission;
}
/**
* Validate the submitted values.
*
* @param \Drupal\custom_forms\Entity\CustomFormSubmission $submission
* The submission that was created.
* @param \Drupal\custom_forms\CustomFormItem[] $items
* The items used for validation.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
* @param \Drupal\Core\Ajax\AjaxResponse|NULL $response
* (Optional) The response to return. Only used for ajax requests.
*
* @return bool
* Returns TRUE if the values successfully validate, otherwise FALSE.
*/
private function validateValues(CustomFormSubmission $submission, array $items, FormStateInterface $form_state, AjaxResponse $response = NULL): bool {
/** @var \Drupal\Core\Language\LanguageInterface $language */
$language = $submission->getForm()->language();
$number_formatter = new NumberFormatter($language->getId(), NumberFormatter::DECIMAL);
// Trigger the pre-transition
$submission->getState()->applyTransitionById('validate');
// Get any errors applied to the submission from the pre-transition.
$errors = $submission->getErrors();
// Catch any errors.
$status = $this->handleErrors($submission->getForm(), $errors, $items, $form_state, $response);
if (!$status) {
// We only return FALSE if the display error check returned false.
return FALSE;
}
// Run the validation.
$this->validator->validateItems($submission, $items, $number_formatter);
// Get any errors applied to the submission during validation.
$errors = $submission->getErrors();
// Catch any errors.
$status = $this->handleErrors($submission->getForm(), $errors, $items, $form_state, $response);
if (!$status) {
// We only return FALSE if the display error check returned false.
return FALSE;
}
// Only save the submission if validation was successful.
try {
// Clear any errors since validation was successful, to avoid confusion
// when troubleshooting.
$submission->setErrors([]);
// Save the submission.
$submission->save();
// Get any errors during post-transition.
$errors = $submission->getErrors();
// Catch any errors.
$status = $this->handleErrors($submission->getForm(), $errors, $items, $form_state, $response);
if (!$status) {
// We only return FALSE if the display error check returned false.
return FALSE;
}
// Return true as validation was successful and submission is now ready
// for processing.
return TRUE;
}
catch (EntityStorageException $e) {
if ($response instanceof AjaxResponse) {
$message = $this->t('An error occurred when saving the submission after validation, please try again.');
$response->addCommand(new InvokeCommand(
'form.custom-forms[data-custom-form-id="' . $submission->getForm()->id() . '"]',
'prepend',
[$this->renderCheck($message)]
));
}
$error_message = $this->t('An error occurred when saving the submission after validation. Message: @message', ['@message' => $e->getMessage()]);
$this->log->error($error_message);
return FALSE;
}
}
/**
* Process the submitted values by their item plugins.
*
* @param \Drupal\custom_forms\Entity\CustomFormSubmission $submission
* The submission that was created.
* @param \Drupal\custom_forms\CustomFormItem[] $items
* The items used for processing.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
* @param \Drupal\Core\Ajax\AjaxResponse|NULL $response
* (Optional) The response to return. Only used for ajax requests.
*
* @return bool
* Returns TRUE if processing succeeds, otherwise returns FALSE.
*/
private function processValues(CustomFormSubmission $submission, array $items, FormStateInterface $form_state, AjaxResponse $response = NULL): bool {
// Trigger the pre-transition
$submission->getState()->applyTransitionById('process');
$values = $submission->getData();
// Get any errors during pre-transition.
$errors = $submission->getErrors();
// Catch any errors.
$status = $this->handleErrors($submission->getForm(), $errors, $items, $form_state, $response);
if (!$status) {
// We only return FALSE if the display error check returned false.
return FALSE;
}
// Enable finalization step.
// This is primarily used so that other plugins can prevent the default
// finalization from happening if they want to do that themselves.
$values['_finalize'] = TRUE;
/** @var \Drupal\custom_forms\CustomFormItem $item */
foreach ($items as $item) {
try {
$item->getPlugin()->process($values, $form_state, $item);
$child_items = $item->getChildren();
foreach ($child_items as $child_item) {
$child_item->getPlugin()->process($values, $form_state, $item);
}
}
catch (PluginException $e) {
$error_message = t('PluginException during field processing. Message = %message', [
'%message' => $e->getMessage(),
]);
$this->log->error($error_message);
return FALSE;
}
}
// Only save the submission if processing was successful.
try {
// Clear any errors since processing was successful, to avoid confusion
// when troubleshooting.
$submission->setErrors([]);
// Set the processed values
$submission->setDataArray($values);
// Save the submission, this also triggers post-transition.
$submission->save();
// Get any errors during post-transition.
$errors = $submission->getErrors();
// Catch any errors.
$status = $this->handleErrors($submission->getForm(), $errors, $items, $form_state, $response);
if (!$status) {
// We only return FALSE if the display error check returned false.
return FALSE;
}
// Return true as processing was successful and submission is now ready
// for initialisation.
return TRUE;
}
catch (EntityStorageException $e) {
if ($response instanceof AjaxResponse) {
$message = $this->t('An error occurred when saving the submission after processing, please try again.');
$response->addCommand(new InvokeCommand(
'form.custom-forms[data-custom-form-id="' . $submission->getForm()->id() . '"]',
'prepend',
[$this->renderCheck($message)]
));
}
$error_message = $this->t('An error occurred when saving the submission after processing. Message: @message', ['@message' => $e->getMessage()]);
$this->log->error($error_message);
return FALSE;
}
}
/**
* Initialize the submission.
*
* @param \Drupal\custom_forms\Entity\CustomFormSubmission $submission
* @param \Drupal\custom_forms\CustomFormItem[] $items
* The items used for initialization.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
* @param \Drupal\Core\Ajax\AjaxResponse|NULL $response
* (Optional) The response to return. Only used for ajax requests.
*
* @return bool
*/
private function initializeSubmission(CustomFormSubmission $submission, array $items, FormStateInterface $form_state, AjaxResponse $response = NULL): bool {
// Trigger the pre-transition
$submission->getState()->applyTransitionById('initialize');
$values = $submission->getData();
$errors = $submission->getErrors();
// Catch any errors.
$status = $this->handleErrors($submission->getForm(), $errors, $items, $form_state, $response);
if (!$status) {
// We only return FALSE if the display error check returned false.
return FALSE;
}
// Store a unique value in the private temp store, so that we ensure that
// only the user who submitted the form can view the receipt.
try {
$unique_token = $this->generateToken(64);
/** @var \Drupal\Core\TempStore\PrivateTempStore $tempstore */
$tempstore = $this->sessionService->getTempStore('private', 'custom_form_submission_'.$submission->id());
if ($tempstore) {
$tempstore->set('submission_token', $unique_token);
$values['_submission_token'] = $unique_token;
}
} catch (\Throwable $t) {
$error_message = $this->t('An error occurred when handling submission token. Message: @message', ['@message' => $t->getMessage()]);
$this->log->error($error_message);
}
// Set redirect if it's enabled and a receipt page has been set.
if (!empty($values['_receipt_page_id'])) {
// Attempt to load the receipt page node.
$receipt_page = Node::load($values['_receipt_page_id']);
// Only proceed in setting the receipt redirect url if the node was
// properly loaded.
if ($receipt_page !== NULL) {
try {
$url = $receipt_page->toUrl('canonical', ['query' => ['S' => $submission->getUniqueId()]]);
$url->setAbsolute();
$values['_redirect_url'] = $url->toString();
$submission->setDataArray($values);
} catch (EntityMalformedException $e) {
if ($response instanceof AjaxResponse) {
$message = $this->t('An error occurred when saving the submission during initialization, please try again.');
$response->addCommand(new InvokeCommand(
'form.custom-forms[data-custom-form-id="' . $submission->getForm()->id() . '"]',
'prepend',
[$this->renderCheck($message)]
));
}
$error_message = $this->t('An error occurred when saving the submission during initialization. Message: @message', ['@message' => $e->getMessage()]);
$this->log->error($error_message);
}
}
}
// Only save the submission if initialization was successful.
try {
// Clear any errors since initialization was successful, to avoid confusion
// when troubleshooting.
$submission->setErrors([]);
// Save the submission, this also triggers post-transition.
$submission->save();
// Get any errors during post-transition.
$errors = $submission->getErrors();
// Catch any errors.
$status = $this->handleErrors($submission->getForm(), $errors, $items, $form_state, $response);
if (!$status) {
// We only return FALSE if the display error check returned false.
return FALSE;
}
}
catch (EntityStorageException $e) {
if ($response instanceof AjaxResponse) {
$message = $this->t('An error occurred when saving the submission after initialization, please try again.');
$response->addCommand(new InvokeCommand(
'form.custom-forms[data-custom-form-id="' . $submission->getForm()->id() . '"]',
'prepend',
[$this->renderCheck($message)]
));
}
$error_message = $this->t('An error occurred when saving the submission after initialization. Message: @message', ['@message' => $e->getMessage()]);
$this->log->error($error_message);
return FALSE;
}
// Get the updated values
$values = $submission->getData();
// If a redirect URL has been defined, use it.
if (!empty($values['_redirect_url'])) {
if ($response instanceof AjaxResponse) {
$response->addCommand(new RedirectCommand($values['_redirect_url']));
}
else {
$form_state->setRedirectUrl($values['_redirect_url']);
}
}
// We only want to trigger the finalize event if it has been enabled.
if ((bool) $values['_finalize']) {
// Trigger the pre-transition
$submission->getState()->applyTransitionById('finalize');
// Get any errors during pre-transition.
$errors = $submission->getErrors();
// Catch any errors.
$status = $this->handleErrors($submission->getForm(), $errors, $items, $form_state, $response);
if (!$status) {
// We only return FALSE if the display error check returned false.
return FALSE;
}
try {
// Clear any errors since finalization was successful, to avoid confusion
// when troubleshooting.
$submission->setErrors([]);
// Save the submission, this also triggers post-transition.
$submission->save();
// Get any errors during post-transition.
$errors = $submission->getErrors();
// Catch any errors.
$status = $this->handleErrors($submission->getForm(), $errors, $items, $form_state, $response);
if (!$status) {
// We only return FALSE if the display error check returned false.
return FALSE;
}
}
catch (EntityStorageException $e) {
$message = $this->t('An error occurred when saving the submission after finalization, please contact an administrator.');
$this->messenger()->addError($message);
$error_message = $this->t('An error occurred when saving the submission after finalization. Message: @message', ['@message' => $e->getMessage()]);
$this->log->error($error_message);
return FALSE;
}
}
return TRUE;
}
/**
* Handle any errors from the form.
*
* @param \Drupal\custom_forms\Entity\CustomForm $custom_form
* @param array $errors
* @param \Drupal\custom_forms\CustomFormItem[] $items
* @param \Drupal\Core\Form\FormStateInterface $form_state
* @param \Drupal\Core\Ajax\AjaxResponse $response
*
* @return bool
* Returns TRUE if no errors needed to be handled, otherwise FALSE.
*/
private function handleErrors(CustomFormEntity $custom_form, array $errors, array $items, FormStateInterface $form_state, AjaxResponse $response = NULL): bool {
if (!empty($errors)) {
// First check for log error, log them and remove them from the
// errors array.
if (!empty($errors['_log'])) {
foreach ($errors['_log'] as $type => $type_errors) {
foreach ($type_errors as $error_message) {
switch ($type) {
case 'error':
$this->log->error($error_message);
break;
case 'warning':
$this->log->warning($error_message);
break;
case 'critical':
$this->log->critical($error_message);
break;
case 'emergency':
$this->log->emergency($error_message);
break;
case 'alert':
$this->log->alert($error_message);
break;
case 'notice':
$this->log->notice($error_message);
break;
case 'debug':
$this->log->debug($error_message);
break;
case 'info':
default:
$this->log->info($error_message);
break;
}
}
}
}
unset($errors['_log']);
if ($response !== NULL) {
// Get all error messages so they don't get rendered, as we render
// them differently.
StatusMessages::renderMessages('error');
// Remove the current messages to avoid showing any messages double.
$response->addCommand(new InvokeCommand(
'form.custom-forms[data-custom-form-id="' . $custom_form->id() . '"] > [data-drupal-messages]',
'remove'
));
// Append the new message to the form.
$message = [
'#theme' => 'status_messages',
'#message_list' => [
'error' => [
$this->t('There were some errors with your submission, please check the form and try again.'),
],
],
'#status_headings' => [
'status' => t('Status message'),
'error' => t('Error message'),
'warning' => t('Warning message'),
],
];
$response->addCommand(new InvokeCommand(
'form.custom-forms[data-custom-form-id="' . $custom_form->id() . '"]',
'prepend',
[$this->renderCheck($message)]
));
}
// Display inline errors.
$this->generateInlineErrors($custom_form, $errors, $items, $form_state, $response);
return FALSE;
}
return TRUE;
}
/**
* Generate the inline errors for the items.
*
* @param \Drupal\custom_forms\Entity\CustomForm $custom_form
* @param array $errors
* @param array $items
* @param \Drupal\Core\Form\FormStateInterface $form_state
* @param \Drupal\Core\Ajax\AjaxResponse|NULL $response
*/
public function generateInlineErrors(CustomFormEntity $custom_form, array $errors, array $items, FormStateInterface $form_state, AjaxResponse $response = NULL): void {
/** @var \Drupal\custom_forms\CustomFormItem $item */
foreach ($items as $item) {
// Remove any existing error messages.
if ($response !== NULL) {
$response->addCommand(new CustomFormsErrorCommand('removeCustomFormsError', 'form.custom-forms[data-custom-form-id="' . $custom_form->id() . '"] [name="' . $item->getJquerySelector() . '"]'));
}
$children = $item->getChildren();
// If the item has no children and no errors, we skip it.
if (empty($children) && empty($errors[$item->getMachineName()])) {
continue;
}
$error_messages = [];
if (isset($errors[$item->getMachineName()])) {
/**
* @var string $error_type
* @var \Drupal\Core\StringTranslation\TranslatableMarkup $error_message
*/
foreach ($errors[$item->getMachineName()] as $error_type => $error_message) {
$error_messages[] = $error_message;
}
}
if (!empty($error_messages)) {
if (count($error_messages) > 1) {
$display_errors = [
'#theme' => 'item_list',
'#list_type' => 'ul',
'#items' => $error_messages,
];
}
else {
$display_errors = reset($error_messages);
}
if ($response !== NULL) {
$response->addCommand(new CustomFormsErrorCommand(
'addCustomFormsError',
'form.custom-forms[data-custom-form-id="' . $custom_form->id() . '"] [name="' . $item->getJquerySelector() . '"]',
$this->renderCheck($display_errors)
));
}
else {
$form_state->setErrorByName($item->getMachineName(), $display_errors);
}
}
// Also generate errors for children.
if ($item->getType() === 'group' && count($children) > 0) {
$this->generateInlineErrors($custom_form, $errors, $children, $form_state, $response);
}
}
}
/**
* Generates a unique token.
*
* @param int $length
* The maximum length of the token string.
*
* @return string
* Returns a unique token.
*
* @throws \Exception
* If it was not possible to gather sufficient entropy.
*/
private function generateToken($length) {
$token = '';
$codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
$codeAlphabet.= "0123456789";
$max = strlen($codeAlphabet); // edited
for ($i=0; $i < $length; $i++) {
$token .= $codeAlphabet[random_int(0, $max-1)];
}
return $token;
}
/**
* Generate the form url based on the request.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The request to generate the URL from.
*
* @return string
* Returns the form url as a string.
*/
private function generateFormUrl(Request $request) : string {
// Generate URL from quest.
$current_url = Url::createFromRequest($request);
// Set it to absolute so we get the full URL.
$current_url->setAbsolute(TRUE);
// Get the query parameters from the request so we can add them to the URL.
$query_parameters = $request->query->all();
$skipped_parameters = [
FormBuilderInterface::AJAX_FORM_REQUEST,
MainContentViewSubscriber::WRAPPER_FORMAT,
AjaxResponseSubscriber::AJAX_REQUEST_PARAMETER,
];
// Run through all query parameters and remove any ajax-related queries.
foreach ($query_parameters as $key => $value) {
if (!in_array($key, $skipped_parameters, FALSE)) {
$current_url->setRouteParameter($key, $value);
}
}
// return the form URL.
return $current_url->toString();
}
protected function renderCheck(&$element) {
if (!$element && $element !== 0) {
return NULL;
}
if (is_array($element)) {
// Early return if this element was pre-rendered (no need to re-render).
if (isset($element['#printed']) && $element['#printed'] == TRUE && isset($element['#markup']) && strlen($element['#markup']) > 0) {
return $element['#markup'];
}
show($element);
return \Drupal::service('renderer')->renderPlain($element);
}
else {
// Safe-guard for inappropriate use of render() on flat variables: return
// the variable as-is.
return $element;
}
}
}