Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
novicell/custom_forms / modules / states / src / Form / CustomFormItemStatesForm.php
Size: Mime:
<?php

namespace Drupal\custom_forms_states\Form;

use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\CloseDialogCommand;
use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element\StatusMessages;
use Drupal\custom_forms\CustomFormItem;
use Drupal\custom_forms\CustomFormItemFactory;
use Drupal\custom_forms\Form\CustomFormFieldListForm;
use Drupal\custom_forms\Form\CustomFormItemFormBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * Class CustomFormItemStatesForm
 *
 * @package Drupal\custom_forms_states\Form
 */
class CustomFormItemStatesForm extends CustomFormItemFormBase {

  /**
   * The factory in charge of CRUD operations for custom form items.
   *
   * @var \Drupal\custom_forms\CustomFormItemFactory
   */
  protected $itemFactory;

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'custom_form_item_states_form';
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('custom_forms.factory.item')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function __construct(CustomFormItemFactory $item_factory) {
    $this->itemFactory = $item_factory;
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form = parent::buildForm($form, $form_state);
    $request      = \Drupal::request();
    $attributes   = $request->attributes;
    $customForm   = $attributes->get('custom_form');
    $formItem     = $this->itemFactory->loadItem($attributes->get('item'));

    $form['description'] = [
      '#type' => 'container',
      'text' => ['#markup' => $this->t('Use the form below to manage the conditional states.')],
      '#attributes' => [
        'class' => [
          'custom-form-item-states--description'
        ]
      ]
    ];
    $form['#attached']['library'][] = 'custom_forms_states/states-ui';

    $selectors = [];
    /** @var CustomFormItem $item */
    foreach ($this->itemFactory->getFormItems($customForm) as $item) {
      if ($item->id() === $formItem->id()) {
        continue;
      }
      if ($item->getPluginId() === 'checkboxes') {
        $option_lines = preg_split("/\r\n|\n|\r/", $item->getSetting('options'));
        foreach ($option_lines as $line) {
          $split = explode('|', $line);
          $selectors[$item->getMachineName() . '[' . (string)$split[0] . ']'] = $item->getSetting('label') . ' (' . $split[1] . ')';
        }
      } else {
        $selectors[$item->getJquerySelector()] = $item->getSetting('label');
      }
    }

    $form['states'] = [
      '#type' => 'state_element',
      '#selector_options' => $selectors,
      '#default_value' => $formItem->getStates()
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $trigger = $form_state->getTriggeringElement();
    $request = \Drupal::request();
    if ($trigger['#op'] === 'cancel' || $request->isXmlHttpRequest()) {
      return;
    }

    $values = $form_state->cleanValues()->getValues();
    $attributes   = $request->attributes;
    $custom_form  = $attributes->get('custom_form');
    $item         = $this->itemFactory->loadItem($attributes->get('item'));

    // Create a new custom form revision since we are modifying it by removing a field.
    $revision_saved = FALSE;
    $custom_form->setNewRevision(TRUE);
    $custom_form->setRevisionTranslationAffected(TRUE); // for some reason required for log messages to show up?
    $custom_form->setRevisionLogMessage(
      $this->t('Updated states for @field-label', [
        '@field-label' => $item->getSetting('label')
      ]));
    $custom_form->setRevisionCreationTime(\Drupal::time()->getRequestTime());
    $custom_form->setRevisionUserId(\Drupal::currentUser()->id());
    try {
      $custom_form->save();
      $revision_saved = TRUE;
    } catch (EntityStorageException $e) {
      $error_message = $this->t('Failed during creation of new revision. Message = %message', [
        '%message' => $e->getMessage()
      ]);
      \Drupal::logger('Custom Forms States')->error($error_message);
      $this->messenger()->addError($this->t('Failed during creation of new revision, please try again. If it continues please contact an administrator.'));
    }

    if ($revision_saved) {
      $states = $this->cleanStates($values['states']['states']);
      $item->setStates($states);

      try {
        // We save it without creating a new revision, as that has already been done at this point.
        $item->save(FALSE);

        $form_state->setRedirect('entity.custom_form.fields_form', ['custom_form' => $custom_form->id()]);
        $this->messenger()->addMessage($this->t('%item-label states were successfully saved.', ['%item-label' => $item->getSetting('label')]));
      } catch (\Exception $e) {
        $error_message = $this->t('Field states saving failed. Message = %message', [
          '%message' => $e->getMessage()
        ]);
        \Drupal::logger('Custom Forms States')->error($error_message);
        $this->messenger()->addError($this->t('Failed during saving of field states, please try again. If this continues please contact an administrator.'));
      }
    }
  }

  /**
   * Submit 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) {
    $response         = new AjaxResponse();
    $values           = $form_state->cleanValues()->getValues();
    $settings_config  = \Drupal::config('custom_forms.settings');
    $attributes       = $request->attributes;

    /** @var \Drupal\custom_forms\Entity\CustomForm $custom_form */
    $custom_form = $attributes->get('custom_form');
    /** @var CustomFormItem $item */
    $item = $this->itemFactory->loadItem($attributes->get('item'));

    // Create a new custom form revision since we are modifying it by removing a field.
    $revision_saved = FALSE;
    $custom_form->setNewRevision(TRUE);
    $custom_form->setRevisionTranslationAffected(TRUE); // for some reason required for log messages to show up?
    $custom_form->setRevisionLogMessage(
      $this->t('Updated states for @field-label', [
        '@field-label' => $item->getSetting('label')
      ]));
    $custom_form->setRevisionCreationTime(\Drupal::time()->getRequestTime());
    $custom_form->setRevisionUserId(\Drupal::currentUser()->id());
    try {
      $custom_form->save();
      $revision_saved = TRUE;
    } catch (EntityStorageException $e) {
      $error_message = $this->t('Failed during creation of new revision. Message = %message. Trace = @trace', [
        '%message' => $e->getMessage(),
        '@trace' => $e->getTraceAsString()
      ]);
      \Drupal::logger('Custom Forms States')->error($error_message);
      $this->messenger()->addError($this->t('Failed during creation of new revision, please try again. If it continues please contact an administrator.'));
    }

    if ($revision_saved) {
      $new_item = $this->itemFactory->loadItem($item->id(), NULL, $custom_form->getLoadedRevisionId(), $custom_form->language()->getId());

      // We unset the states sub array to avoid duplicates.
      unset($values['states']['states']);
      $states = $this->cleanStates($values['states']);
      $new_item->setStates($states);

      try {
        // We save it without creating a new revision, as that has already been done at this point.
        $new_item->save(FALSE);
        $response->addCommand(new CloseDialogCommand('#drupal-off-canvas'));
        $this->messenger()->addMessage($this->t('%item-label states were successfully saved.', ['%item-label' => $new_item->getSetting('label')]));

        switch ($settings_config->get('off_screen_field_settings')) {
          case 'rebuild':
            $form = \Drupal::formBuilder()->getForm(CustomFormFieldListForm::class);
            $response->addCommand(new ReplaceCommand('#custom-form__field-list', $form));

            // Get the messages for display
            $messages = StatusMessages::renderMessages();
            // Remove the current messages to avoid showing any sticky messages double.
            $response->addCommand(new InvokeCommand('div.region.region-highlighted div.messages', 'remove'));
            // Append the new messages to the highlighted region.
            $response->addCommand(new InvokeCommand('div.region.region-highlighted', 'append', [\Drupal::service('renderer')->render($messages)]));
            break;
          case 'reload':
          default:
            $response->addCommand(new InvokeCommand('form.custom-forms-fields input.form-submit[type="submit"][name="op"]', 'click', []));
            break;
        }

      } catch (\Exception $e) {
        $error_message = $this->t('Field states saving failed. Message = %message. Trace = @trace', [
          '%message' => $e->getMessage(),
          '@trace' => $e->getTraceAsString()
        ]);
        \Drupal::logger('Custom Forms States')->error($error_message);
        $this->messenger()->addError($this->t('Failed during saving of field states, please try again. If this continues please contact an administrator.'));
      }
    }

    return $response;
  }

  /**
   * Clean the states array to make is easier to use.
   *
   * @param array $states
   *
   * @return array
   */
  private function cleanStates($states): array {
    // State cleanup
    $real_states = [];
    $state_index = 0;
    foreach ($states as $state) {
      if (!empty($state['state'])) {
        $real_states[$state_index] = [
          'state' => $state['state'],
          'value' => $state['value'],
          'operator' => $state['operator'],
          'condition' => [],
        ];
        $condition_index = 0;
        foreach ($state['condition'] as $condition) {
          if (!empty($condition['selector']) && !empty($condition['trigger'])) {
            $real_states[$state_index]['condition'][$condition_index] = [
              'selector' => $condition['selector'],
              'trigger' => $condition['trigger'],
              'value' => $condition['value'],
            ];
            $condition_index++;
          }
        }
        $state_index++;
      }
    }
    return $real_states;
  }
}