access_policy-1.0.x-dev/modules/access_policy_ui/src/Form/AccessPolicyEditForm.php
modules/access_policy_ui/src/Form/AccessPolicyEditForm.php
<?php namespace Drupal\access_policy_ui\Form; use Drupal\access_policy\AccessPolicyHandlerManager; use Drupal\access_policy\AccessPolicyInformation; use Drupal\access_policy\AccessPolicySelectionInterface; use Drupal\access_policy\Http403ResponsePluginManager; use Drupal\access_policy_ui\HandlerTableUiBuilder; use Drupal\access_policy_ui\OperationsTableUiBuilder; use Drupal\Core\Entity\EntityForm; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Url; use Symfony\Component\DependencyInjection\ContainerInterface; /** * Class AccessPolicyEditForm. * * The AccessPolicy edit form. * * @package Drupal\access_policy\Form */ class AccessPolicyEditForm extends EntityForm { /** * The AccessPolicyHandlerManager service. * * @var \Drupal\access_policy\AccessPolicyHandlerManager */ protected $accessRulePluginManager; /** * The access denied behavior manager. * * @var \Drupal\access_policy\Http403ResponsePluginManager */ protected $http403ResponsePluginManager; /** * The access policy information service. * * @var \Drupal\access_policy\AccessPolicyInformation */ protected $accessPolicyInformation; /** * The access policy selection service. * * @var \Drupal\access_policy\AccessPolicySelectionInterface */ protected $accessPolicySelection; /** * The operations table ui builder. * * @var \Drupal\access_policy_ui\OperationsTableUiBuilder */ protected $operationsTableUiBuilder; /** * The handler table ui builder. * * @var \Drupal\access_policy_ui\HandlerTableUiBuilder */ protected $handlerTableUiBuilder; /** * Get the handler type. * * @var string */ protected $handlerType = 'access_rule'; /** * Constructs a AccessPolicyEdiForm object. * * @param \Drupal\access_policy\AccessPolicyHandlerManager $access_rule_manager * The access rule manager. * @param \Drupal\access_policy\Http403ResponsePluginManager $http_403_manager * The access denied behavior manager. * @param \Drupal\access_policy\AccessPolicyInformation $access_policy_information * The access policy information service. * @param \Drupal\access_policy\AccessPolicySelectionInterface $access_policy_selection * The access policy selection service. * @param \Drupal\access_policy_ui\OperationsTableUiBuilder $ui_builder * The operations table ui builder. * @param \Drupal\access_policy_ui\HandlerTableUiBuilder $handler_table_builder * The handler table ui builder. */ public function __construct(AccessPolicyHandlerManager $access_rule_manager, Http403ResponsePluginManager $http_403_manager, AccessPolicyInformation $access_policy_information, AccessPolicySelectionInterface $access_policy_selection, OperationsTableUiBuilder $ui_builder, HandlerTableUiBuilder $handler_table_builder) { $this->accessRulePluginManager = $access_rule_manager; $this->http403ResponsePluginManager = $http_403_manager; $this->accessPolicyInformation = $access_policy_information; $this->accessPolicySelection = $access_policy_selection; $this->operationsTableUiBuilder = $ui_builder; $this->handlerTableUiBuilder = $handler_table_builder; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { return new static( $container->get('plugin.manager.access_policy.access_rule'), $container->get('plugin.manager.http_403_response'), $container->get('access_policy.information'), $container->get('access_policy.selection'), $container->get('access_policy.operations_table_ui_builder'), $container->get('access_policy.handler_table_ui_builder') ); } /** * {@inheritdoc} */ public function form(array $form, FormStateInterface $form_state) { $form = parent::form($form, $form_state); $entity = $this->entity; $form['#title'] = $this->t('Configure %label access policy', ['%label' => $entity->label()]); $form['label'] = [ '#type' => 'textfield', '#title' => $this->t('Label'), '#maxlength' => 255, '#default_value' => $entity->label(), '#description' => $this->t("The human-readable name of this access policy. This name must be unique."), '#required' => TRUE, ]; $form['id'] = [ '#type' => 'machine_name', '#default_value' => $entity->id(), '#machine_name' => [ 'exists' => '\Drupal\access_policy\Entity\AccessPolicy::load', ], '#disabled' => !$entity->isNew(), ]; if ($this->accessPolicySelection->isSelectionPageEnabled($entity->getTargetEntityTypeId())) { $form['description'] = [ '#type' => 'textarea', '#title' => $this->t('Description'), '#default_value' => $entity->getDescription(), '#description' => $this->t('This text will be displayed on the Access page when this policy is chosen.'), ]; } $form['operations_container'] = [ '#type' => 'details', '#title' => $this->t('Operations'), '#open' => TRUE, ]; $form['operations_container']['role_table'] = $this->operationsTableUiBuilder->build($entity); if ($entity->getOperationsHandler()->supportsAccessRules()) { $form['access_rule_container'] = [ '#type' => 'details', '#title' => $this->t('Access Rules'), '#open' => TRUE, ]; $form['access_rule_container']['help'] = [ '#type' => 'markup', '#markup' => '<p>' . $this->t('Access rules allow you to define fine-grained access controls based on field and environmental values.') . '</p>', ]; $form['access_rule_container']['access_rules_table'] = $this->handlerTableUiBuilder->build($this->handlerType, $entity); $form['access_rule_container']['add_rule'] = [ '#type' => 'link', '#title' => $this->t('Add access rule'), '#url' => Url::fromRoute('access_policy_ui.access_policy_add_rule_form', [ 'access_policy' => $entity->id(), 'type' => 'access_rule', ]), '#attributes' => HandlerTableUiBuilder::getDialogOptions(), ]; $form['access_rule_container']['access_rule_operator'] = [ '#type' => 'select', '#title' => $this->t('Validation operator'), '#description' => $this->t('How many rules must be true before a user is granted access to a @entity_type?', [ '@entity_type' => $this->entity->getTargetEntityType()->getSingularLabel(), ]), '#default_value' => $entity->getAccessRuleOperator(), '#options' => [ 'AND' => 'All', 'OR' => 'Any', ], ]; } $form['query_settings'] = [ '#type' => 'details', '#title' => $this->t('Query settings'), '#open' => TRUE, ]; $form['query_settings']['query'] = [ '#type' => 'checkbox', '#default_value' => $entity->isQueryEnabled(), '#title' => $this->t('Apply access policy to queries'), '#description' => $this->t('This will hide @entity_type on listing pages and entity reference fields.', [ '@entity_type' => $this->entity->getTargetEntityType()->getPluralLabel(), ]), ]; $entity_type = $this->entity->getTargetEntityType(); if ($this->hasHtmlRouteProvider($entity_type)) { $form['403_behavior'] = [ '#type' => 'details', '#title' => $this->t('Error page'), '#tree' => TRUE, '#open' => TRUE, '#id' => '403-settings-wrapper', ]; $behavior = $this->getCurrentHttp403Behavior($form_state); $form['403_behavior']['plugin_id'] = [ '#type' => 'select', '#title' => $this->t('403 (access denied) response'), '#options' => $this->getHttp403Behaviors(), '#default_value' => $behavior ? $behavior->getPluginId() : '', '#empty_option' => $this->t('Default'), '#ajax' => [ 'callback' => [$this, 'get403BehaviorSettingsCallback'], 'event' => 'change', 'wrapper' => '403-settings-wrapper', ], ]; $form['403_behavior']['settings'] = [ '#type' => 'container', '#tree' => TRUE, ]; if ($behavior) { if ($behavior_form = $behavior->settingsForm([], $form_state)) { $form['403_behavior']['settings'] += $behavior_form; } } } return $form; } /** * Determine whether the entity type has an html route provider. * * Custom 403 behavior is only applicable to entities that have a html * route provider (e.g. nodes, media etc.). * * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type * The entity type. * * @return bool * TRUE if the entity has an html route provider; FALSE otherwise. */ protected function hasHtmlRouteProvider(EntityTypeInterface $entity_type) { $route_provider = $entity_type->getRouteProviderClasses(); if (isset($route_provider['html'])) { return TRUE; } return FALSE; } /** * Get the current 403 behavior plugin. * * @param \Drupal\Core\Form\FormStateInterface $form_state * The current form state. * * @return object|void * The Http403Response plugin if found. * * @throws \Drupal\Component\Plugin\Exception\PluginException */ protected function getCurrentHttp403Behavior(FormStateInterface $form_state) { $entity = $this->entity; // If the form is submitted load that plugin. $submitted_behavior = $form_state->getValue(['403_behavior', 'plugin_id']); if (isset($submitted_behavior)) { if (!empty($submitted_behavior)) { return $this->http403ResponsePluginManager->createInstance($submitted_behavior); } } else { return $entity->getHttp403Response(); } } /** * Callback for the 403 behavior settings. * * @param array $form * The form. * @param \Drupal\Core\Form\FormStateInterface $form_state * The form state. * * @return array * The response. */ public function get403BehaviorSettingsCallback(array &$form, FormStateInterface $form_state) { return $form['403_behavior']; } /** * Load all http 403 response plugins. * * @return array * Array of access denied behavior plugins. */ protected function getHttp403Behaviors() { $definitions = $this->http403ResponsePluginManager->getDefinitions(); $options = []; foreach ($definitions as $id => $definition) { $options[$id] = $definition['label']; } return $options; } /** * {@inheritdoc} */ public function save(array $form, FormStateInterface $form_state) { $entity = $this->entity; $values = $form_state->getValues(); $entity->resetHttp403Response(); $plugin_id = $values['403_behavior']['plugin_id'] ?? ''; if (!empty($plugin_id)) { $settings = $values['403_behavior']['settings'] ?? []; $entity->setHttp403Response($plugin_id, $settings); } $status = $entity->save(); switch ($status) { case SAVED_NEW: $this->messenger()->addMessage($this->t('Created the @label Access Policy.', [ '@label' => $entity->label(), ])); break; default: $this->messenger()->addMessage($this->t('Saved the @label Access Policy.', [ '@label' => $entity->label(), ])); } $form_state->setRedirectUrl($entity->toUrl('collection')); return $status; } /** * Provides the edit title. * * Note that this only affects the breadcrumb. The main title is set in the * form itself. * * @param \Drupal\Core\Routing\RouteMatchInterface $route_match * The route match. * * @return string|null * The title for the entity edit page, if an entity was found. */ public function getTitle(RouteMatchInterface $route_match) { $entity = $route_match->getParameter('access_policy'); return $this->t('%label', ['%label' => $entity->label()]); } }