Commit 03a51987 authored by André Matheus Pedrosa's avatar André Matheus Pedrosa Committed by Henrique Mendes
Browse files

Issue #3207231 by andregp, beatrizrodrigues, nyanmar, WagnerMelo,...

Issue #3207231 by andregp, beatrizrodrigues, nyanmar, WagnerMelo, aldairsoares, daften: "Other" option on taxonomy term field should only be available to users with permission
parent e2e43b0d
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -130,12 +130,16 @@ abstract class ElementBase extends FormElement {
      '#default_value' => $element['#default_value'],
      '#required' => $element['#required'],
      '#multiple' => $element['#multiple'],
      '#options' => static::addOtherOption($element['#original_options'] ?? $element['#options'], $element['#other_option']),
      '#options' => $element['#original_options'] ?? $element['#options'],
      '#attributes' => [
        'aria-label' => isset($element['#title']) ? $element['#title'] : $element['#name'],
      ],
      '#weight' => 10,
    ];

    if ($element['#other_allowed'] ?? TRUE) {
      $element['select']['#options'] = static::addOtherOption($element['select']['#options'], $element['#other_option']);
    }
  }

  /**
@@ -145,6 +149,7 @@ abstract class ElementBase extends FormElement {
   *   The select or other element.
   */
  protected static function addOtherField(array &$element) {
    if ($element['#other_allowed'] ?? TRUE) {
      $element['other'] = [
        '#type' => isset($element['#input_type']) ? $element['#input_type'] : 'textfield',
        '#attributes' => [
@@ -152,6 +157,7 @@ abstract class ElementBase extends FormElement {
        ],
        '#weight' => 20,
      ];
    }

    if (isset($element['#other_field_label']) && !empty($element['#other_field_label'])) {
      $element['other']['#title'] = $element['#other_field_label'];
+58 −11
Original line number Diff line number Diff line
@@ -9,9 +9,9 @@ use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\user\EntityOwnerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;

@@ -43,20 +43,37 @@ class ReferenceWidget extends WidgetBase implements ContainerFactoryPluginInterf
   */
  protected $bundleInfoService;

  /**
   * The account interface service.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $currentUser;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings'], $configuration['third_party_settings'], $container->get('entity_type.manager'), $container->get('entity_type.bundle.info'));
    return new static(
      $plugin_id,
      $plugin_definition,
      $configuration['field_definition'],
      $configuration['settings'],
      $configuration['third_party_settings'],
      $container->get('entity_type.manager'),
      $container->get('entity_type.bundle.info'),
      $container->get('current_user'),
    );
  }

  /**
   * Constructs a ReferenceWidget object.
   */
  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityTypeManagerInterface $entity_type = NULL, EntityTypeBundleInfoInterface $bundle_info_service = NULL) {
  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityTypeManagerInterface $entity_type = NULL, EntityTypeBundleInfoInterface $bundle_info_service = NULL, AccountInterface $current_user = NULL) {
    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
    $this->entityTypeManager = $entity_type;
    $this->bundleInfoService = $bundle_info_service;
    $this->currentUser = $current_user;
  }

  /**
@@ -148,21 +165,31 @@ class ReferenceWidget extends WidgetBase implements ContainerFactoryPluginInterf
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $element = parent::formElement($items, $delta, $element, $form, $form_state);
    $entity = $items->getEntity();

    $target_entity_type_id = $this->getFieldSetting('target_type');
    $element = $element + [
      '#target_type' => $this->getFieldSetting('target_type'),
      '#target_type' => $target_entity_type_id,
      '#selection_handler' => $this->getFieldSetting('handler'),
      '#selection_settings' => $this->getFieldSetting('handler_settings'),
      '#autocreate' => [
        'bundle' => $this->getAutocreateBundle(),
        'uid' => ($entity instanceof EntityOwnerInterface) ? $entity->getOwnerId() : \Drupal::currentUser()
          ->id(),
      ],
      '#validate_reference' => TRUE,
      '#tags' => $this->getFieldSetting('target_type') === 'taxonomy_term',
      '#tags' => $target_entity_type_id === 'taxonomy_term',
      '#merged_values' => TRUE,
    ];
    $autocreate_bundle = $this->getAutocreateBundle();
    $user = $this->currentUser;
    $access = $this->getCreateAccess($target_entity_type_id, $autocreate_bundle, $user);
    // Check whether access is allowed and if yes, fill out #autocreate.
    if ($access->isAllowed()) {
      $element['#autocreate'] = [
        'bundle' => $autocreate_bundle,
        'uid' => $user->id(),
      ];
    }
    else {
      // Otherwise do not autocreate and do not allow other.
      $element['#autocreate'] = NULL;
      $element['#other_allowed'] = FALSE;
    }

    $element['#element_validate'] = [
      [
@@ -174,6 +201,26 @@ class ReferenceWidget extends WidgetBase implements ContainerFactoryPluginInterf
    return $element;
  }

  /**
   * Returns the access result object.
   *
   * @param string $entity_type_id
   *   The entity type id.
   * @param string $bundle
   *   The bundle name.
   * @param \Drupal\Core\Session\AccountInterface $user
   *   The user account interface.
   *
   * @return \Drupal\Core\Access\AccessResultInterface|bool
   *   The access result. Returns a boolean if $return_as_object is FALSE (this
   *   is the default) and otherwise an AccessResultInterface object.
   */
  protected function getCreateAccess($entity_type_id, $bundle, AccountInterface $user) {
    return $this->entityTypeManager
      ->getAccessControlHandler($entity_type_id)
      ->createAccess($bundle, $user, [], TRUE);
  }

  /**
   * Returns the value of a setting for the entity reference selection handler.
   *
+1 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ class ReferenceTest extends TestBase {
    $widget = 'select_or_other_reference';
    $widgets = ['select_or_other_select', 'select_or_other_buttons'];
    $this->prepareTestFields('entity_reference', $field_settings, $widget, $widgets);
    $this->defaultPermissions[] = 'administer taxonomy';
    $user = $this->drupalCreateUser($this->defaultPermissions);
    $this->drupalLogin($user);
  }
+16 −1
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ class ReferenceWidgetTest extends UnitTestBase {

    if ($tested_class_name === FALSE) {
      $methods[] = 'getAutoCreateBundle';
      $methods[] = 'getCreateAccess';
    }

    // Get the mockBuilder.
@@ -51,7 +52,18 @@ class ReferenceWidgetTest extends UnitTestBase {
    $field_definition->expects($this->any())
      ->method('getFieldStorageDefinition')
      ->willReturn($this->getMockForAbstractClass('Drupal\Core\Field\FieldStorageDefinitionInterface'));
    $constructor_arguments = ['', '', $field_definition, [], []];
    $user = $this->getMockForAbstractClass('\Drupal\Core\Session\AccountInterface');
    $user->method('id')->willReturn('1');
    $constructor_arguments = [
      '',
      '',
      $field_definition,
      [],
      [],
      NULL,
      NULL,
      $user,
    ];

    $builder->setConstructorArgs($constructor_arguments)
      ->onlyMethods($methods);
@@ -135,8 +147,11 @@ class ReferenceWidgetTest extends UnitTestBase {
   */
  public function testFormElement() {
    foreach (['node', 'taxonomy_term'] as $target_type) {
      $access = $this->getMockForAbstractClass('\Drupal\Core\Access\AccessResultInterface');
      $access->method('isAllowed')->willReturn(TRUE);
      /** @var \Drupal\select_or_other\Plugin\Field\FieldWidget\ReferenceWidget $mock */
      $mock = $this->prepareFormElementMock($target_type);
      $mock->method('getCreateAccess')->willReturn($access);
      /** @var \Drupal\select_or_other\Plugin\Field\FieldWidget\WidgetBase $parent */
      $parent = $this->prepareFormElementMock($target_type, 'Drupal\select_or_other\Plugin\Field\FieldWidget\WidgetBase');