Loading src/Element/ElementBase.php +7 −1 Original line number Diff line number Diff line Loading @@ -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']); } } /** Loading @@ -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' => [ Loading @@ -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']; Loading src/Plugin/Field/FieldWidget/ReferenceWidget.php +58 −11 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } /** Loading Loading @@ -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'] = [ [ Loading @@ -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. * Loading tests/src/Functional/ReferenceTest.php +1 −0 Original line number Diff line number Diff line Loading @@ -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); } Loading tests/src/Unit/ReferenceWidgetTest.php +16 −1 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ class ReferenceWidgetTest extends UnitTestBase { if ($tested_class_name === FALSE) { $methods[] = 'getAutoCreateBundle'; $methods[] = 'getCreateAccess'; } // Get the mockBuilder. Loading @@ -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); Loading Loading @@ -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'); Loading Loading
src/Element/ElementBase.php +7 −1 Original line number Diff line number Diff line Loading @@ -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']); } } /** Loading @@ -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' => [ Loading @@ -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']; Loading
src/Plugin/Field/FieldWidget/ReferenceWidget.php +58 −11 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } /** Loading Loading @@ -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'] = [ [ Loading @@ -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. * Loading
tests/src/Functional/ReferenceTest.php +1 −0 Original line number Diff line number Diff line Loading @@ -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); } Loading
tests/src/Unit/ReferenceWidgetTest.php +16 −1 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ class ReferenceWidgetTest extends UnitTestBase { if ($tested_class_name === FALSE) { $methods[] = 'getAutoCreateBundle'; $methods[] = 'getCreateAccess'; } // Get the mockBuilder. Loading @@ -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); Loading Loading @@ -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'); Loading