Commit d38a69e1 authored by webchick's avatar webchick

Issue #2211553 by andypost, Berdir: Allow usage of entity_reference field...

Issue #2211553 by andypost, Berdir: Allow usage of entity_reference field widget and formatter for base fields.
parent 99b9a6a5
......@@ -9,7 +9,9 @@
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 @@ public function __construct(EntityManagerInterface $entity_manager, SelectionPlu
* 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 @@ public function __construct(EntityManagerInterface $entity_manager, SelectionPlu
*
* @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 @@ public function getMatches($field, $instance, $entity_type, $entity_id = '', $pr
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 @@ public static function create(ContainerInterface $container) {
* 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 @@ public function handleAutocomplete(Request $request, $type, $field_name, $entity
$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 @@ function testEntityReferenceAutocompletion() {
// 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 @@ function testEntityReferenceAutocompletion() {
$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 @@ function testEntityReferenceAutocompletion() {
// 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 @@ function testEntityReferenceAutocompletion() {
$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 @@ protected function getAutocompleteResult($type, $input) {
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.');
}
}
}
<?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);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment