Issue #2211553 by andypost, Berdir: Allow usage of entity_reference field widget and formatter for base fields.
parent
99b9a6a579
commit
d38a69e113
|
@ -9,7 +9,9 @@ namespace Drupal\entity_reference;
|
|||
|
||||
use Drupal\Component\Utility\Tags;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\entity_reference\Plugin\Type\SelectionPluginManager;
|
||||
use Drupal\field\FieldInstanceConfigInterface;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
|
||||
/**
|
||||
|
@ -50,12 +52,12 @@ class EntityReferenceAutocomplete {
|
|||
* This function can be used by other modules that wish to pass a mocked
|
||||
* definition of the field on instance.
|
||||
*
|
||||
* @param array $field
|
||||
* The field array definition.
|
||||
* @param array $instance
|
||||
* The instance array definition.
|
||||
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
|
||||
* The field definition.
|
||||
* @param string $entity_type
|
||||
* The entity type.
|
||||
* @param string $bundle
|
||||
* The entity bundle.
|
||||
* @param string $entity_id
|
||||
* (optional) The entity ID the entity reference field is attached to.
|
||||
* Defaults to ''.
|
||||
|
@ -72,7 +74,7 @@ class EntityReferenceAutocomplete {
|
|||
*
|
||||
* @see \Drupal\entity_reference\EntityReferenceController
|
||||
*/
|
||||
public function getMatches($field, $instance, $entity_type, $entity_id = '', $prefix = '', $string = '') {
|
||||
public function getMatches(FieldDefinitionInterface $field_definition, $entity_type, $bundle, $entity_id = '', $prefix = '', $string = '') {
|
||||
$matches = array();
|
||||
$entity = NULL;
|
||||
|
||||
|
@ -82,11 +84,11 @@ class EntityReferenceAutocomplete {
|
|||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
}
|
||||
$handler = $this->selectionHandlerManager->getSelectionHandler($instance, $entity);
|
||||
$handler = $this->selectionHandlerManager->getSelectionHandler($field_definition, $entity);
|
||||
|
||||
if (isset($string)) {
|
||||
// Get an array of matching entities.
|
||||
$widget = entity_get_form_display($instance->entity_type, $instance->bundle, 'default')->getComponent($instance->getName());
|
||||
$widget = entity_get_form_display($entity_type, $bundle, 'default')->getComponent($field_definition->getName());
|
||||
$match_operator = !empty($widget['settings']['match_operator']) ? $widget['settings']['match_operator'] : 'CONTAINS';
|
||||
$entity_labels = $handler->getReferenceableEntities($string, $match_operator, 10);
|
||||
|
||||
|
|
|
@ -71,12 +71,15 @@ class EntityReferenceController extends ControllerBase {
|
|||
* The matched labels as json.
|
||||
*/
|
||||
public function handleAutocomplete(Request $request, $type, $field_name, $entity_type, $bundle_name, $entity_id) {
|
||||
if (!$instance = field_info_instance($entity_type, $field_name, $bundle_name)) {
|
||||
$definitions = $this->entityManager()->getFieldDefinitions($entity_type, $bundle_name);
|
||||
|
||||
if (!isset($definitions[$field_name])) {
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
|
||||
$field_definition = $definitions[$field_name];
|
||||
$access_controller = $this->entityManager()->getAccessController($entity_type);
|
||||
if ($instance->getType() != 'entity_reference' || !$access_controller->fieldAccess('edit', $instance)) {
|
||||
if ($field_definition->getType() != 'entity_reference' || !$access_controller->fieldAccess('edit', $field_definition)) {
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
|
||||
|
@ -92,7 +95,7 @@ class EntityReferenceController extends ControllerBase {
|
|||
$prefix = count($items_typed) ? Tags::implode($items_typed) . ', ' : '';
|
||||
}
|
||||
|
||||
$matches = $this->entityReferenceAutocomplete->getMatches($instance->getField(), $instance, $entity_type, $entity_id, $prefix, $last_item);
|
||||
$matches = $this->entityReferenceAutocomplete->getMatches($field_definition, $entity_type, $bundle_name, $entity_id, $prefix, $last_item);
|
||||
|
||||
return new JsonResponse($matches);
|
||||
}
|
||||
|
|
|
@ -8,11 +8,12 @@
|
|||
namespace Drupal\entity_reference\Tests;
|
||||
|
||||
use Drupal\Component\Utility\Json;
|
||||
use Drupal\Component\Utility\String;
|
||||
use Drupal\Component\Utility\Tags;
|
||||
use Drupal\entity_reference\EntityReferenceController;
|
||||
use Drupal\system\Tests\Entity\EntityUnitTestBase;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
|
||||
/**
|
||||
* Tests the autocomplete functionality of Entity Reference.
|
||||
|
@ -45,7 +46,7 @@ class EntityReferenceAutocompleteTest extends EntityUnitTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('entity_reference');
|
||||
public static $modules = array('entity_reference', 'entity_reference_test');
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
|
@ -81,8 +82,8 @@ class EntityReferenceAutocompleteTest extends EntityUnitTestBase {
|
|||
// We should get both entities in a JSON encoded string.
|
||||
$input = '10/';
|
||||
$data = $this->getAutocompleteResult('single', $input);
|
||||
$this->assertIdentical($data[0]['label'], check_plain($entity_1->name->value), 'Autocomplete returned the first matching entity');
|
||||
$this->assertIdentical($data[1]['label'], check_plain($entity_2->name->value), 'Autocomplete returned the second matching entity');
|
||||
$this->assertIdentical($data[0]['label'], String::checkPlain($entity_1->name->value), 'Autocomplete returned the first matching entity');
|
||||
$this->assertIdentical($data[1]['label'], String::checkPlain($entity_2->name->value), 'Autocomplete returned the second matching entity');
|
||||
|
||||
// Try to autocomplete a entity label that matches the first entity.
|
||||
// We should only get the first entity in a JSON encoded string.
|
||||
|
@ -90,7 +91,7 @@ class EntityReferenceAutocompleteTest extends EntityUnitTestBase {
|
|||
$data = $this->getAutocompleteResult('single', $input);
|
||||
$target = array(
|
||||
'value' => $entity_1->name->value . ' (1)',
|
||||
'label' => check_plain($entity_1->name->value),
|
||||
'label' => String::checkPlain($entity_1->name->value),
|
||||
);
|
||||
$this->assertIdentical(reset($data), $target, 'Autocomplete returns only the expected matching entity.');
|
||||
|
||||
|
@ -98,7 +99,7 @@ class EntityReferenceAutocompleteTest extends EntityUnitTestBase {
|
|||
// the first entity is already typed in the autocomplete (tags) widget.
|
||||
$input = $entity_1->name->value . ' (1), 10/17';
|
||||
$data = $this->getAutocompleteResult('tags', $input);
|
||||
$this->assertIdentical($data[0]['label'], check_plain($entity_2->name->value), 'Autocomplete returned the second matching entity');
|
||||
$this->assertIdentical($data[0]['label'], String::checkPlain($entity_2->name->value), 'Autocomplete returned the second matching entity');
|
||||
|
||||
// Try to autocomplete a entity label with both a comma and a slash.
|
||||
$input = '"label with, and / t';
|
||||
|
@ -108,7 +109,7 @@ class EntityReferenceAutocompleteTest extends EntityUnitTestBase {
|
|||
$n = Tags::encode($n);
|
||||
$target = array(
|
||||
'value' => $n,
|
||||
'label' => check_plain($entity_3->name->value),
|
||||
'label' => String::checkPlain($entity_3->name->value),
|
||||
);
|
||||
$this->assertIdentical(reset($data), $target, 'Autocomplete returns an entity label containing a comma and a slash.');
|
||||
}
|
||||
|
@ -133,4 +134,35 @@ class EntityReferenceAutocompleteTest extends EntityUnitTestBase {
|
|||
|
||||
return Json::decode($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests autocomplete for entity base fields.
|
||||
*/
|
||||
public function testBaseField() {
|
||||
// Add two users.
|
||||
$user_1 = entity_create('user', array('name' => 'auto1'));
|
||||
$user_1->save();
|
||||
$user_2 = entity_create('user', array('name' => 'auto2'));
|
||||
$user_2->save();
|
||||
|
||||
$request = Request::create('entity_reference/autocomplete/single/user_id/entity_test/entity_test/NULL');
|
||||
$request->query->set('q', 'auto');
|
||||
|
||||
$entity_reference_controller = EntityReferenceController::create($this->container);
|
||||
$result = $entity_reference_controller->handleAutocomplete($request, 'single', 'user_id', 'entity_test', 'entity_test', 'NULL')->getContent();
|
||||
|
||||
$data = Json::decode($result);
|
||||
$this->assertIdentical($data[0]['label'], String::checkPlain($user_1->getUsername()), 'Autocomplete returned the first matching entity');
|
||||
$this->assertIdentical($data[1]['label'], String::checkPlain($user_2->getUsername()), 'Autocomplete returned the second matching entity');
|
||||
|
||||
// Checks that exception thrown for unknown field.
|
||||
try {
|
||||
$entity_reference_controller->handleAutocomplete($request, 'single', 'unknown_field', 'entity_test', 'entity_test', 'NULL')->getContent();
|
||||
$this->fail('Autocomplete throws exception for unknown field.');
|
||||
}
|
||||
catch (AccessDeniedHttpException $e) {
|
||||
$this->pass('Autocomplete throws exception for unknown field.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Helper module for the Entity Reference tests.
|
||||
*/
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
|
||||
/**
|
||||
* Implements hook_entity_base_field_info_alter().
|
||||
*/
|
||||
function entity_reference_test_entity_base_field_info_alter(&$fields, EntityTypeInterface $entity_type) {
|
||||
if ($entity_type->id() === 'entity_test') {
|
||||
// Allow user_id field to use configurable widget.
|
||||
$fields['user_id']
|
||||
->setSetting('handler', 'default')
|
||||
->setDisplayOptions('form', array(
|
||||
'type' => 'entity_reference_autocomplete',
|
||||
'weight' => 0,
|
||||
))
|
||||
->setDisplayConfigurable('form', TRUE);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue