eca-1.0.x-dev/modules/form/src/Plugin/Action/FormFieldActionBase.php
modules/form/src/Plugin/Action/FormFieldActionBase.php
<?php
namespace Drupal\eca_form\Plugin\Action;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\eca\Plugin\FormFieldPluginTrait;
/**
* Base class for form field actions.
*/
abstract class FormFieldActionBase extends FormActionBase {
use FormFieldPluginTrait;
/**
* Whether this action supports multiple form fields to operate with.
*
* @var bool
*/
protected bool $supportsMultiple = TRUE;
/**
* {@inheritdoc}
*/
public function access($object, ?AccountInterface $account = NULL, $return_as_object = FALSE) {
$result = parent::access($object, $account, TRUE);
$original_field_name = $this->configuration['field_name'];
$missing_form_fields = [];
foreach ($this->extractFormFieldNames($original_field_name) as $field_name) {
$this->configuration['field_name'] = $field_name;
if (is_null($this->getTargetElement())) {
$missing_form_fields[] = $field_name;
}
}
if ($missing_form_fields) {
$form_field_result = AccessResult::forbidden(sprintf("The following form fields were not found: %s", implode(', ', $missing_form_fields)));
}
else {
$form_field_result = AccessResult::allowed();
}
$result = $result->andIf($form_field_result);
// Restoring the original config entry.
$this->configuration['field_name'] = $original_field_name;
return $return_as_object ? $result : $result->isAllowed();
}
/**
* {@inheritdoc}
*
* Optionally allows execution on multiple field names, calling ::doExecute()
* for each single field name.
*/
public function execute(): void {
$original_field_name = $this->configuration['field_name'];
$field_names = $this->extractFormFieldNames($original_field_name);
if (!$this->supportsMultiple && count($field_names) > 1) {
throw new \InvalidArgumentException("This action does not support multiple fields.");
}
foreach ($field_names as $field_name) {
$this->configuration['field_name'] = $field_name;
$this->doExecute();
}
// Restoring the original config entry.
$this->configuration['field_name'] = $original_field_name;
}
/**
* Actually performs action execution.
*
* This is only relevant when not overriding ::execute() and instead making
* use of the implementation resided in
* \Drupal\eca_form\Plugin\Action\FormFieldActionBase::execute().
*/
protected function doExecute(): void {}
/**
* {@inheritdoc}
*/
public function defaultConfiguration(): array {
return $this->defaultFormFieldConfiguration() + parent::defaultConfiguration();
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state): array {
$form = $this->buildFormFieldConfigurationForm($form, $form_state);
return parent::buildConfigurationForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function validateConfigurationForm(array &$form, FormStateInterface $form_state): void {
$this->validateFormFieldConfigurationForm($form, $form_state);
parent::validateConfigurationForm($form, $form_state);
if (mb_strpos($form_state->getValue('field_name', ''), ',') !== FALSE) {
$form_state->setError($form['field_name'], $this->t('This action does not support multiple fields.'));
}
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void {
$this->submitFormFieldConfigurationForm($form, $form_state);
parent::submitConfigurationForm($form, $form_state);
}
/**
* Extracts form field names from the given user input.
*
* Runs through token replacement, and the input will be transformed into
* an array of field names, ready for being evaluated.
*
* @param string $user_input
* The user input containing configured form field names.
*
* @return array
* The extracted form field names, ready for evaluation.
*/
protected function extractFormFieldNames(string $user_input): array {
return array_map('trim', explode(',', (string) $this->tokenService->replace($user_input)));
}
}
