You are here

class ChangeFieldInfo in Business Rules 2.x

Same name and namespace in other branches
  1. 8 src/Plugin/BusinessRulesAction/ChangeFieldInfo.php \Drupal\business_rules\Plugin\BusinessRulesAction\ChangeFieldInfo

Class ChangeFieldInfo.

Changes on multiple value fields can't be done via hooks yet.

@package Drupal\business_rules\Plugin\BusinessRulesAction

Plugin annotation


@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,
)

Hierarchy

Expanded class hierarchy of ChangeFieldInfo

See also

https://www.drupal.org/node/1592814

File

src/Plugin/BusinessRulesAction/ChangeFieldInfo.php, line 37

Namespace

Drupal\business_rules\Plugin\BusinessRulesAction
View source
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;
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
BusinessRulesItemPluginBase::$processor protected property The business rules processor.
BusinessRulesItemPluginBase::$util protected property The business rules util.
BusinessRulesItemPluginBase::getDescription public function Provide a description of the item. Overrides BusinessRulesItemPluginInterface::getDescription
BusinessRulesItemPluginBase::getEditUrl public function Get the redirect url for the item edit-form route. Overrides BusinessRulesItemPluginInterface::getEditUrl
BusinessRulesItemPluginBase::getGroup public function Provide the group of the item. Overrides BusinessRulesItemPluginInterface::getGroup
BusinessRulesItemPluginBase::getRedirectUrl public function Get the redirect url for the item collection route. Overrides BusinessRulesItemPluginInterface::getRedirectUrl
BusinessRulesItemPluginBase::getVariables public function Return a variable set with all used variables on the item. Overrides BusinessRulesItemPluginInterface::getVariables 9
BusinessRulesItemPluginBase::pregMatch public function Extract the variables from the plugin settings. Overrides BusinessRulesItemPluginInterface::pregMatch
BusinessRulesItemPluginBase::processTokenArraySetting private function Helper function to process tokens if the setting is an array.
BusinessRulesItemPluginBase::processTokens public function Process the tokens on the settings property for the item. Overrides BusinessRulesItemPluginInterface::processTokens
BusinessRulesItemPluginBase::processVariables public function Process the item replacing the variables by it's values. Overrides BusinessRulesItemPluginInterface::processVariables 1
BusinessRulesItemPluginInterface::VARIABLE_REGEX constant
ChangeFieldInfo::$actionOptions protected property The available action options.
ChangeFieldInfo::addFieldSubmit public static function Add new field on action settings.
ChangeFieldInfo::buildForm public function Form constructor. Overrides BusinessRulesItemPluginBase::buildForm
ChangeFieldInfo::changeFieldInfo protected function Change info at the form array.
ChangeFieldInfo::execute public function Execute the action. Overrides BusinessRulesActionPlugin::execute
ChangeFieldInfo::getRows private function Get the current fields on the variable array.
ChangeFieldInfo::getSettingsForm public function Return the form array. Overrides BusinessRulesItemPluginBase::getSettingsForm
ChangeFieldInfo::MAKE_HIDDEN constant
ChangeFieldInfo::MAKE_OPTIONAL constant
ChangeFieldInfo::MAKE_READ_ONLY constant
ChangeFieldInfo::MAKE_REQUIRED constant
ChangeFieldInfo::processSettings public function Process the item settings before it's saved. Overrides BusinessRulesItemPluginBase::processSettings
ChangeFieldInfo::removeField public static function Remove one field from the action.
ChangeFieldInfo::validateAddFieldForm public static function Validate the add field operation.
ChangeFieldInfo::validateForm public function Plugin form validator. Overrides BusinessRulesItemPluginBase::validateForm
ChangeFieldInfo::__construct public function Constructs a \Drupal\Component\Plugin\PluginBase object. Overrides BusinessRulesItemPluginBase::__construct
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 2
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::isConfigurable public function Determines if the plugin is configurable.