diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceAutocomplete.php b/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceAutocomplete.php index c1d6114..ccc1116 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceAutocomplete.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceAutocomplete.php @@ -9,6 +9,7 @@ use Drupal\Component\Utility\Tags; use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\entity_reference\Plugin\Type\SelectionPluginManager; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; @@ -50,10 +51,8 @@ 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 $entity_id @@ -72,7 +71,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, $entity_id = '', $prefix = '', $string = '') { $matches = array(); $entity = NULL; @@ -82,11 +81,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 = $field_definition->getDisplayOptions('form'); $match_operator = !empty($widget['settings']['match_operator']) ? $widget['settings']['match_operator'] : 'CONTAINS'; $entity_labels = $handler->getReferenceableEntities($string, $match_operator, 10); diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceController.php b/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceController.php index 2dfda5d..ec707c0 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceController.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceController.php @@ -70,12 +70,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(); } @@ -91,7 +94,7 @@ public function handleAutocomplete(Request $request, $type, $field_name, $entity $prefix = count($items_typed) ? drupal_implode_tags($items_typed) . ', ' : ''; } - $matches = $this->entityReferenceAutocomplete->getMatches($instance->getField(), $instance, $entity_type, $entity_id, $prefix, $last_item); + $matches = $this->entityReferenceAutocomplete->getMatches($field_definition, $entity_type, $entity_id, $prefix, $last_item); return new JsonResponse($matches); } diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAutocompleteTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAutocompleteTest.php index 84e48f8..60f97e6 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAutocompleteTest.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAutocompleteTest.php @@ -7,6 +7,8 @@ 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; @@ -44,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( @@ -80,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. @@ -89,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.'); @@ -97,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'; @@ -107,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.'); } @@ -130,6 +132,32 @@ protected function getAutocompleteResult($type, $input) { $entity_reference_controller = EntityReferenceController::create($this->container); $result = $entity_reference_controller->handleAutocomplete($request, $type, $this->fieldName, $this->entityType, $this->bundle, 'NULL')->getContent(); - return drupal_json_decode($result); + return Json::decode($result); } + + /** + * Tests autocomplete for entity base fields. + */ + public function testBaseField() { + entity_test_create_bundle('test_bundle', 'Test bundle', 'entity_test_base_field_display'); + + // Add an entity with a slash in its name. + $entity_1 = entity_create($this->entityType, array('name' => '10/16/2011', $this->fieldName => NULL)); + $entity_1->save(); + + // Add another entity that differs after the slash character. + $entity_2 = entity_create($this->entityType, array('name' => '10/17/2011', $this->fieldName => NULL)); + $entity_2->save(); + + $request = Request::create('entity_reference/autocomplete/single/er/entity_test_base_field_display/test_bundle/NULL'); + $request->query->set('q', '10'); + + $entity_reference_controller = EntityReferenceController::create($this->container); + $result = $entity_reference_controller->handleAutocomplete($request, 'single', 'er', 'entity_test_base_field_display', 'test_bundle', 'NULL')->getContent(); + + $data = Json::decode($result); + $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'); + } + } diff --git a/core/modules/entity_reference/tests/modules/entity_reference_test/entity_reference_test.module b/core/modules/entity_reference/tests/modules/entity_reference_test/entity_reference_test.module index 37dc050..6e76326 100644 --- a/core/modules/entity_reference/tests/modules/entity_reference_test/entity_reference_test.module +++ b/core/modules/entity_reference/tests/modules/entity_reference_test/entity_reference_test.module @@ -4,3 +4,25 @@ * @file * Helper module for the Entity Reference tests. */ + + +/** + * Implements hook_entity_base_field_info(). + */ +function entity_reference_test_entity_base_field_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type) { + if ($entity_type->id() === 'entity_test_base_field_display') { + $fields['er'] = \Drupal\Core\Field\FieldDefinition::create('entity_reference') + ->setLabel(t('The entity reference')) + ->setSettings(array( + 'target_type' => 'entity_test', + 'handler' => 'default', + )) + ->setDisplayOptions('form', array( + 'type' => 'entity_reference_autocomplete', + 'weight' => 0, + )) + ->setDisplayConfigurable('form', TRUE); + + return $fields; + } +}