business_rules-8.x-1.0-beta1/src/Plugin/BusinessRulesAction/ChangeFieldInfo.php

src/Plugin/BusinessRulesAction/ChangeFieldInfo.php
<?php

namespace Drupal\business_rules\Plugin\BusinessRulesAction;

use Drupal\business_rules\ActionInterface;
use Drupal\business_rules\Entity\Action;
use Drupal\business_rules\Events\BusinessRulesEvent;
use Drupal\business_rules\ItemInterface;
use Drupal\business_rules\Plugin\BusinessRulesActionPlugin;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\RemoveCommand;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Symfony\Component\HttpFoundation\RedirectResponse;

/**
 * Class ChangeFieldInfo.
 *
 * Changes on multiple value fields can't be done via hooks yet.
 *
 * @see https://www.drupal.org/node/1592814
 *
 * @package Drupal\business_rules\Plugin\BusinessRulesAction
 *
 * @BusinessRulesAction(
 *   id = "change_field_info",
 *   label = @Translation("Change entity form field"),
 *   group = @Translation("Entity"),
 *   description = @Translation("Change a form field: Make required/optional/read-only/hidden/dependent/change field options values."),
 *   reactsOnIds = {"form_field_alter"},
 *   isContextDependent = TRUE,
 *   hasTargetEntity = TRUE,
 *   hasTargetBundle = TRUE,
 *   hasTargetField = FALSE,
 * )
 */
class ChangeFieldInfo extends BusinessRulesActionPlugin {

  const MAKE_REQUIRED  = 'make_required';
  const MAKE_OPTIONAL  = 'make_optional';
  const MAKE_READ_ONLY = 'make_read_only';
  const MAKE_HIDDEN    = 'make_hidden';

  /**
   * The available action options.
   *
   * @var array
   */
  protected $actionOptions = [];

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration = [], $plugin_id = 'change_field_info', $plugin_definition = []) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);

    $this->actionOptions = [
      ''                   => t('-Select-'),
      self::MAKE_REQUIRED  => t('Make field required'),
      self::MAKE_OPTIONAL  => t('Make field optional'),
      self::MAKE_READ_ONLY => t('Make field read only'),
      self::MAKE_HIDDEN    => t('Make field hidden'),
    ];

  }

  /**
   * Add new field on action settings.
   *
   * @param array $form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form_state.
   */
  public static function addFieldSubmit(array $form, FormStateInterface $form_state) {
    /** @var \Drupal\business_rules\Entity\Action $action */
    $action   = $form_state->get('action');
    $field    = $form_state->getValue('fields')['new.field'];
    $id       = $field['field'] . '__' . $field['action'];
    $settings = $action->getSettings();

    $availableFields = \Drupal::getContainer()
      ->get('business_rules.util')
      ->getBundleEditableFields($action->getTargetEntityType(), $action->getTargetBundle());

    $settings['fields'][$id] = [
      'id'     => $id,
      'field'  => $field['field'],
      'action' => $field['action'],
    ];

    uasort($settings['fields'], function ($a, $b) use ($availableFields) {
      return ($availableFields[$a['field']] > $availableFields[$b['field']]) ? 1 : -1;
    });

    $action->setSetting('fields', $settings['fields']);
    $action->save();

    $form_state->setRedirect('entity.business_rules_action.edit_form', ['business_rules_action' => $action->id()], ['fragment' => 'field-' . $id]);
  }

  /**
   * Remove one field from the action.
   *
   * @param string $action
   *   The action id.
   * @param string $field
   *   The field id.
   * @param string $method
   *   The method: ajax|nojs.
   *
   * @return \Drupal\Core\Ajax\AjaxResponse|\Symfony\Component\HttpFoundation\RedirectResponse
   *   The response.
   */
  public static function removeField($action, $field, $method) {
    $action = Action::load($action);
    $fields = $action->getSettings('fields');
    unset($fields[$field]);
    $action->setSetting('fields', $fields);
    $action->save();

    if ($method == 'ajax') {
      $response = new AjaxResponse();
      $response->addCommand(new RemoveCommand('#field-' . $field));

      return $response;
    }
    else {
      $url = new Url('entity.business_rules_action.edit_form', ['business_rules_action' => $action->id()]);

      return new RedirectResponse($url->toString());
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getSettingsForm(array &$form, FormStateInterface $form_state, ItemInterface $item) {

    if ($item->isNew()) {
      return [];
    }

    $form_state->set('action', $item);

    $settings['fields'] = [
      '#type'       => 'table',
      '#header'     => [
        'field'      => t('Filed'),
        'action'     => t('Action'),
        'operations' => t('Operations'),
      ],
      '#attributes' => ['id' => 'array_variable_fields_table'],
    ];

    $settings['info'] = [
      '#type'   => 'markup',
      '#markup' => t('Multiple value fields cannot be changed to be Required or Optional by this module. Create a new rule as "Entity form validation" to achieve this purpose see this issue on https://www.drupal.org/node/1592814. 
      <br>Hidden fields are removed from the form array, and not rendered. So be careful if you hide a required field because some field widgets can validate it anyway.'),
    ];

    $this->getRows($item, $settings['fields']);

    return $settings;
  }

  /**
   * Get the current fields on the variable array.
   *
   * @param \Drupal\business_rules\ItemInterface $item
   *   The variable.
   * @param array $settings
   *   The current setting to add rows.
   */
  private function getRows(ItemInterface $item, array &$settings) {

    $fields          = $item->getSettings('fields');
    $availableFields = $this->util->getBundleEditableFields($item->getTargetEntityType(), $item->getTargetBundle());

    if (count($fields)) {
      foreach ($fields as $key => $field) {

        $links['remove'] = [
          'title'  => t('Remove'),
          'url'    => Url::fromRoute('business_rules.plugins.action.change_field_info.remove_field', [
            'action' => $item->id(),
            'field'  => $field['id'],
            'method' => 'nojs',
          ],
            [
              'attributes' => [
                'class' => ['use-ajax'],
              ],
            ]
          ),
          'weight' => 1,
        ];

        $settings[$key] = [
          'field'       => [
            '#type'   => 'markup',
            '#markup' => $availableFields[$field['field']],
          ],
          'action'      => [
            '#type'   => 'markup',
            '#markup' => $this->actionOptions[$field['action']],
          ],
          'operations'  => [
            '#type'  => 'operations',
            '#links' => $links,
          ],
          '#attributes' => ['id' => 'field-' . $field['id']],
        ];
      }
    }

    $settings['new.field'] = [
      'field'      => [
        '#type'     => 'select',
        '#required' => FALSE,
        '#options'  => array_merge(['' => t('-Select-')], $availableFields),
      ],
      'action'     => [
        '#type'     => 'select',
        '#required' => FALSE,
        '#options'  => $this->actionOptions,
      ],
      'operations' => [
        '#type'     => 'submit',
        '#value'    => t('Add'),
        '#validate' => [get_class($this) . '::validateAddFieldForm'],
        '#submit'   => [get_class($this) . '::addFieldSubmit'],
      ],
    ];

  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array &$form, FormStateInterface $form_state) {
    unset($form['variables']);
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    self::validateAddFieldForm($form, $form_state);
  }

  /**
   * Validate the add field operation.
   *
   * @param array $form
   *   The form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The form_state.
   */
  public static function validateAddFieldForm(array &$form, FormStateInterface $form_state) {
    $field        = $form_state->getValue('fields');
    $field_field  = $field['new.field']['field'];
    $field_action = $field['new.field']['action'];

    if ((empty($field_action) && !empty($field_field)) || (!empty($field_action) && empty($field_field))) {
      $form_state->setErrorByName('fields', t("Please, fill all field data or none of them."));
    }

    // The title field can't be optional.
    if ($field['new.field']['field'] == 'title' && $field['new.field']['action'] == self::MAKE_OPTIONAL) {
      $form_state->setErrorByName('fields', t('The title field cannot be optional.'));
    }
  }

  /**
   * {@inheritdoc}
   */
  public function processSettings(array $settings, ItemInterface $item) {

    if ($item->isNew()) {
      return [];
    }

    if (count($item->getSettings('fields'))) {
      $settings['fields'] += $item->getSettings('fields');
    }

    if ($settings['fields']['new.field']['field'] && $settings['fields']['new.field']['action']) {
      $availableFields               = $this->util->getBundleEditableFields($item->getTargetEntityType(), $item->getTargetBundle());
      $id                            = $settings['fields']['new.field']['field'] . '__' . $settings['fields']['new.field']['action'];
      $settings['fields'][$id]       = $settings['fields']['new.field'];
      $settings['fields'][$id]['id'] = $id;

      uasort($settings['fields'], function ($a, $b) use ($availableFields) {
        return ($availableFields[$a['field']] > $availableFields[$b['field']]) ? 1 : -1;
      });
    }

    unset($settings['fields']['new.field']);

    return $settings;
  }

  /**
   * {@inheritdoc}
   */
  public function execute(ActionInterface $action, BusinessRulesEvent $event) {
    $fields = $action->getSettings('fields');

    if (!count($fields)) {
      // Nothing to do.
      $result = [
        '#type'   => 'markup',
        '#markup' => t('Nothing to do.'),
      ];

      return $result;
    }

    $element = $event->getArgument('element');
    $context = $event->getArgument('context');
    /** @var \Drupal\Core\Field\FieldItemList $items */
    $items        = $context['items'];
    $element_name = $items->getName();

    // Change the field properties.
    foreach ($fields as $field) {
      if ($field['field'] == $element_name) {
        $this->changeFieldInfo($element, $field);
      }
    }

    $event->setArgument('element', $element);

    foreach ($fields as $field) {
      $debug_message = t('<br>%method: %field', [
        '%field'  => $field['field'],
        '%method' => $this->actionOptions[$field['action']],
      ]);

      $result[] = [
        '#type'   => 'markup',
        '#markup' => $debug_message,
      ];
    }

    return $result;
  }

  /**
   * Change info at the form array.
   */
  protected function changeFieldInfo(array &$element, $action_field) {
    switch ($action_field['action']) {
      case self::MAKE_REQUIRED:
        $element['#required'] = TRUE;
        if (isset($element[0])) {
          $element[0]['#required'] = TRUE;
        }
        if (isset($element['target_id'])) {
          $element['target_id']['#required'] = TRUE;
        }
        break;

      case self::MAKE_OPTIONAL:
        $element['#required'] = FALSE;
        if (isset($element[0])) {
          $element[0]['#required'] = FALSE;
        }
        if (isset($element['target_id'])) {
          $element['target_id']['#required'] = FALSE;
        }
        break;

      case self::MAKE_READ_ONLY:
        $element['#disabled'] = TRUE;
        break;

      case self::MAKE_HIDDEN:
        $element = [];
        break;

    }
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc