/** * Autocomplete the label of an entity. * * @param \Symfony\Component\HttpFoundation\Request $request * The request object that contains the typed tags. * @param string $target_type * The ID of the target entity type. * @param string $selection_handler * The plugin ID of the entity reference selection handler. * @param string $selection_settings_key * The hashed key of the key/value entry that holds the selection handler * settings. * * @return \Symfony\Component\HttpFoundation\JsonResponse * The matched entity labels as a JSON response. * * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException * Thrown if the selection settings key is not found in the key/value store * or if it does not match the stored data. */ public function handleAutocomplete(Request $request, $target_type, $selection_handler, $selection_settings_key) { $matches = array(); // Get the typed string from the URL, if it exists. if ($input = $request->query->get('q')) { $typed_string = Tags::explode($input); $typed_string = Unicode::strtolower(array_pop($typed_string)); // Selection settings are passed in as a hashed key of a serialized array // stored in the key/value store. $selection_settings = $this->keyValue->get($selection_settings_key, FALSE); if ($selection_settings !== FALSE) { $selection_settings_hash = Crypt::hmacBase64(serialize($selection_settings) . $target_type . $selection_handler, Settings::getHashSalt()); if ($selection_settings_hash !== $selection_settings_key) { // Disallow access when the selection settings hash does not match the // passed-in key. throw new AccessDeniedHttpException('Invalid selection settings key.'); } } else { // Disallow access when the selection settings key is not found in the // key/value store. throw new AccessDeniedHttpException(); } $matches = $this->matcher->getMatches($target_type, $selection_handler, $selection_settings, $typed_string); } return new JsonResponse($matches); }
/** * Implodes a series of tags. */ public function testImplodeTags() { $tags = array_values($this->validTags); // Let's explode and implode to our heart's content. for ($i = 0; $i < 10; $i++) { $string = Tags::implode($tags); $tags = Tags::explode($string); } $this->assertTags($tags); }
/** * Autocomplete the label of an entity. * * @param \Symfony\Component\HttpFoundation\Request $request * The request object that contains the typed tags. * @param string $target_type * The ID of the target entity type. * @param string $selection_handler * The plugin ID of the entity reference selection handler. * @param string $selection_settings * The settings that will be passed to the selection handler. * * @return \Symfony\Component\HttpFoundation\JsonResponse * The matched entity labels as a JSON response. */ public function handleAutocomplete(Request $request, $target_type, $selection_handler, $selection_settings = '') { $matches = array(); // Get the typed string from the URL, if it exists. if ($input = $request->query->get('q')) { $typed_string = Tags::explode($input); $typed_string = Unicode::strtolower(array_pop($typed_string)); // Selection settings are passed in as an encoded serialized array. $selection_settings = $selection_settings ? unserialize(base64_decode($selection_settings)) : array(); $matches = $this->matcher->getMatches($target_type, $selection_handler, $selection_settings, $typed_string); } return new JsonResponse($matches); }
/** * Returns autocompletion content for file name textfield. * * @param \Symfony\Component\HttpFoundation\Request $request * The request of the page. * * @return \Symfony\Component\HttpFoundation\JsonResponse * A JSON response. */ public function autocompleteFilename(Request $request) { $matches = array(); // Get the typed string from the URL, if it exists. if ($input = $request->query->get('q')) { $typed_string = Tags::explode($input); $typed_string = Unicode::strtolower(array_pop($typed_string)); $filenames = db_select('uc_files', 'f')->fields('f', ['filename'])->condition('filename', '%' . db_like($typed_string) . '%', 'LIKE')->execute(); while ($name = $filenames->fetchField()) { $matches[] = array('value' => $name); } } return new JsonResponse($matches); }
/** * Tests autocompletion edge cases with slashes in the names. */ function testEntityReferenceAutocompletion() { // Add an entity with a slash in its name. $entity_1 = $this->container->get('entity_type.manager')->getStorage($this->entityType)->create(array('name' => '10/16/2011')); $entity_1->save(); // Add another entity that differs after the slash character. $entity_2 = $this->container->get('entity_type.manager')->getStorage($this->entityType)->create(array('name' => '10/17/2011')); $entity_2->save(); // Add another entity that has both a comma, a slash and markup. $entity_3 = $this->container->get('entity_type.manager')->getStorage($this->entityType)->create(array('name' => 'label with, and / test')); $entity_3->save(); // Try to autocomplete a entity label that matches both entities. // We should get both entities in a JSON encoded string. $input = '10/'; $data = $this->getAutocompleteResult($input); $this->assertIdentical($data[0]['label'], Html::escape($entity_1->name->value), 'Autocomplete returned the first matching entity'); $this->assertIdentical($data[1]['label'], Html::escape($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. $input = '10/16'; $data = $this->getAutocompleteResult($input); $target = array('value' => $entity_1->name->value . ' (1)', 'label' => Html::escape($entity_1->name->value)); $this->assertIdentical(reset($data), $target, 'Autocomplete returns only the expected matching entity.'); // Try to autocomplete a entity label that matches the second entity, and // the first entity is already typed in the autocomplete (tags) widget. $input = $entity_1->name->value . ' (1), 10/17'; $data = $this->getAutocompleteResult($input); $this->assertIdentical($data[0]['label'], Html::escape($entity_2->name->value), 'Autocomplete returned the second matching entity'); // Try to autocomplete a entity label with both a comma, a slash and markup. $input = '"label with, and /"'; $data = $this->getAutocompleteResult($input); $n = $entity_3->name->value . ' (3)'; // Entity labels containing commas or quotes must be wrapped in quotes. $n = Tags::encode($n); $target = array('value' => $n, 'label' => Html::escape($entity_3->name->value)); $this->assertIdentical(reset($data), $target, 'Autocomplete returns an entity label containing a comma and a slash.'); }
/** * Autocomplete the label of an entity. * * @param Request $request * The request object that contains the typed tags. * @param string $type * The widget type (i.e. 'single' or 'tags'). * @param string $field_name * The name of the entity reference field. * @param string $entity_type * The entity type. * @param string $bundle_name * The bundle name. * @param string $entity_id * (optional) The entity ID the entity reference field is attached to. * Defaults to ''. * * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException * Throws access denied when either the field or field instance does not * exists or the user does not have access to edit the field. * * @return \Symfony\Component\HttpFoundation\JsonResponse * The matched labels as json. */ public function handleAutocomplete(Request $request, $type, $field_name, $entity_type, $bundle_name, $entity_id) { $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 ($field_definition->getType() != 'entity_reference' || !$access_controller->fieldAccess('edit', $field_definition)) { throw new AccessDeniedHttpException(); } // Get the typed string, if exists from the URL. $items_typed = $request->query->get('q'); $items_typed = Tags::explode($items_typed); $last_item = drupal_strtolower(array_pop($items_typed)); $prefix = ''; // The user entered a comma-separated list of entity labels, so we generate // a prefix. if ($type == 'tags' && !empty($last_item)) { $prefix = count($items_typed) ? Tags::implode($items_typed) . ', ' : ''; } $matches = $this->entityReferenceAutocomplete->getMatches($field_definition, $entity_type, $bundle_name, $entity_id, $prefix, $last_item); return new JsonResponse($matches); }
/** * {@inheritdoc} */ public function elementValidate($element, &$form_state, $form) { $value = array(); // If a value was entered into the autocomplete. $handler = \Drupal::service('plugin.manager.entity_reference.selection')->getSelectionHandler($this->fieldDefinition); $bundles = entity_get_bundles($this->getFieldSetting('target_type')); $auto_create = $this->getSelectionHandlerSetting('auto_create'); if (!empty($element['#value'])) { $value = array(); foreach (Tags::explode($element['#value']) as $input) { $match = FALSE; // Take "label (entity id)', match the ID from parenthesis when it's a // number. if (preg_match("/.+\\((\\d+)\\)/", $input, $matches)) { $match = $matches[1]; } elseif (preg_match("/.+\\(([\\w.]+)\\)/", $input, $matches)) { $match = $matches[1]; } else { // Try to get a match from the input string when the user didn't use // the autocomplete but filled in a value manually. $match = $handler->validateAutocompleteInput($input, $element, $form_state, $form, !$auto_create); } if ($match) { $value[] = array('target_id' => $match); } elseif ($auto_create && (count($this->getSelectionHandlerSetting('target_bundles')) == 1 || count($bundles) == 1)) { // Auto-create item. See // \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem::presave(). $value[] = array('target_id' => NULL, 'entity' => $this->createNewEntity($input, $element['#autocreate_uid'])); } } } // Change the element['#parents'], so in form_set_value() we // populate the correct key. array_pop($element['#parents']); form_set_value($element, $value, $form_state); }
public function validateExposed(&$form, &$form_state) { if (empty($this->options['exposed'])) { return; } if (empty($this->options['expose']['identifier'])) { return; } $identifier = $this->options['expose']['identifier']; $input = $form_state['values'][$identifier]; if ($this->options['is_grouped'] && isset($this->options['group_info']['group_items'][$input])) { $this->operator = $this->options['group_info']['group_items'][$input]['operator']; $input = $this->options['group_info']['group_items'][$input]['value']; } $values = Tags::explode($input); if (!$this->options['is_grouped'] || $this->options['is_grouped'] && $input != 'All') { $uids = $this->validate_user_strings($form[$identifier], $form_state, $values); } else { $uids = FALSE; } if ($uids) { $this->validated_exposed_input = $uids; } }
/** * Returns matched labels based on a given search string. * * @param string $target_type * The ID of the target entity type. * @param string $selection_handler * The plugin ID of the entity reference selection handler. * @param array $selection_settings * An array of settings that will be passed to the selection handler. * @param string $string * (optional) The label of the entity to query by. * * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException * Thrown when the current user doesn't have access to the specifies entity. * * @return array * An array of matched entity labels, in the format required by the AJAX * autocomplete API (e.g. array('value' => $value, 'label' => $label)). * * @see \Drupal\system\Controller\EntityAutocompleteController */ public function getMatches($target_type, $selection_handler, $selection_settings, $string = '') { $matches = array(); $options = array('target_type' => $target_type, 'handler' => $selection_handler, 'handler_settings' => $selection_settings); $handler = $this->selectionManager->getInstance($options); if (isset($string)) { // Get an array of matching entities. $match_operator = !empty($selection_settings['match_operator']) ? $selection_settings['match_operator'] : 'CONTAINS'; $entity_labels = $handler->getReferenceableEntities($string, $match_operator, 10); // Loop through the entities and convert them into autocomplete output. foreach ($entity_labels as $values) { foreach ($values as $entity_id => $label) { $key = "{$label} ({$entity_id})"; // Strip things like starting/trailing white spaces, line breaks and // tags. $key = preg_replace('/\\s\\s+/', ' ', str_replace("\n", '', trim(String::decodeEntities(strip_tags($key))))); // Names containing commas or quotes must be wrapped in quotes. $key = Tags::encode($key); $matches[] = array('value' => $key, 'label' => $label); } } } return $matches; }
/** * Gets terms which matches some typed terms. * * @param string $tags_typed * The full typed tags string. * @param array $vids * An array of vocabulary IDs which * @param $tag_last * The lasted typed tag. * * @return array * Returns an array of matching terms. */ protected function getMatchingTerms($tags_typed, array $vids, $tag_last) { $matches = array(); $this->termEntityQuery->addTag('term_access'); // Do not select already entered terms. if (!empty($tags_typed)) { $this->termEntityQuery->condition('name', $tags_typed, 'NOT IN'); } // Select rows that match by term name. $tids = $this->termEntityQuery->condition('vid', $vids, 'IN')->condition('name', $tag_last, 'CONTAINS')->range(0, 10)->execute(); $prefix = count($tags_typed) ? Tags::implode($tags_typed) . ', ' : ''; if (!empty($tids)) { $terms = $this->entityManager->getStorage('taxonomy_term')->loadMultiple(array_keys($tids)); foreach ($terms as $term) { // Term names containing commas or quotes must be wrapped in quotes. $name = Tags::encode($term->getName()); $matches[] = array('value' => $prefix . $name, 'label' => String::checkPlain($term->getName())); } return $matches; } return $matches; }
/** * Provide a full array of possible theme functions to try for a given hook. * * @param string $hook * The hook to use. This is the base theme/template name. * * @return array * An array of theme hook suggestions. */ public function buildThemeFunctions($hook) { $themes = array(); $display = isset($this->display_handler) ? $this->display_handler->display : NULL; $id = $this->storage->id(); if ($display) { $themes[] = $hook . '__' . $id . '__' . $display['id']; $themes[] = $hook . '__' . $display['id']; // Add theme suggestions for each single tag. foreach (Tags::explode($this->storage->get('tag')) as $tag) { $themes[] = $hook . '__' . preg_replace('/[^a-z0-9]/', '_', strtolower($tag)); } if ($display['id'] != $display['display_plugin']) { $themes[] = $hook . '__' . $id . '__' . $display['display_plugin']; $themes[] = $hook . '__' . $display['display_plugin']; } } $themes[] = $hook . '__' . $id; $themes[] = $hook; return $themes; }
public function validateExposed(&$form, &$form_state) { if (empty($this->options['exposed'])) { return; } $identifier = $this->options['expose']['identifier']; // We only validate if they've chosen the text field style. if ($this->options['type'] != 'textfield') { if ($form_state['values'][$identifier] != 'All') { $this->validated_exposed_input = (array) $form_state['values'][$identifier]; } return; } if (empty($this->options['expose']['identifier'])) { return; } $values = Tags::explode($form_state['values'][$identifier]); $tids = $this->validate_term_strings($form[$identifier], $values); if ($tids) { $this->validated_exposed_input = $tids; } }
/** * {@inheritdoc} */ public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { $this->configuration['keywords'] = Tags::explode($form_state->getValue('keywords')); }
/** * Converts an array of entity objects into a string of entity labels. * * This method is also responsible for checking the 'view label' access on the * passed-in entities. * * @param \Drupal\Core\Entity\EntityInterface[] $entities * An array of entity objects. * * @return string * A string of entity labels separated by commas. */ public static function getEntityLabels(array $entities) { $entity_labels = array(); foreach ($entities as $entity) { // Use the special view label, since some entities allow the label to be // viewed, even if the entity is not allowed to be viewed. $label = $entity->access('view label') ? $entity->label() : t('- Restricted access -'); // Take into account "autocreated" entities. if (!$entity->isNew()) { $label .= ' (' . $entity->id() . ')'; } // Labels containing commas or quotes must be wrapped in quotes. $entity_labels[] = Tags::encode($label); } return implode(', ', $entity_labels); }
/** * Tests term autocompletion edge cases with slashes in the names. */ function testTermAutocompletion() { // Add a term with a slash in the name. $first_term = $this->createTerm($this->vocabulary); $first_term->setName('10/16/2011'); $first_term->save(); // Add another term that differs after the slash character. $second_term = $this->createTerm($this->vocabulary); $second_term->setName('10/17/2011'); $second_term->save(); // Add another term that has both a comma and a slash character. $third_term = $this->createTerm($this->vocabulary); $third_term->setName('term with, a comma and / a slash'); $third_term->save(); // Try to autocomplete a term name that matches both terms. // We should get both terms in a json encoded string. $input = '10/'; $path = 'taxonomy/autocomplete/node/taxonomy_' . $this->vocabulary->id(); // The result order is not guaranteed, so check each term separately. $result = $this->drupalGet($path, array('query' => array('q' => $input))); // Pull the label properties from the array of arrays. $data = Json::decode($result); $data = array_map(function ($item) { return $item['label']; }, $data); $this->assertTrue(in_array(String::checkPlain($first_term->getName()), $data), 'Autocomplete returned the first matching term'); $this->assertTrue(in_array(String::checkPlain($second_term->getName()), $data), 'Autocomplete returned the second matching term'); // Try to autocomplete a term name that matches first term. // We should only get the first term in a json encoded string. $input = '10/16'; $path = 'taxonomy/autocomplete/node/taxonomy_' . $this->vocabulary->id(); $this->drupalGet($path, array('query' => array('q' => $input))); $target = array(array('value' => String::checkPlain($first_term->getName()), 'label' => $first_term->getName())); $this->assertRaw(Json::encode($target), 'Autocomplete returns only the expected matching term.'); // Try to autocomplete a term name with both a comma and a slash. $input = '"term with, comma and / a'; $path = 'taxonomy/autocomplete/node/taxonomy_' . $this->vocabulary->id(); $this->drupalGet($path, array('query' => array('q' => $input))); // Term names containing commas or quotes must be wrapped in quotes. $n = Tags::encode($third_term->getName()); $target = array(array('value' => $n, 'label' => String::checkPlain($third_term->getName()))); $this->assertRaw(Json::encode($target), 'Autocomplete returns a term containing a comma and a slash.'); }
/** * Test term creation with a free-tagging vocabulary from the node form. */ function testNodeTermCreationAndDeletion() { // Enable tags in the vocabulary. $field = $this->field; entity_get_form_display($field->getTargetEntityTypeId(), $field->getTargetBundle(), 'default')->setComponent($field->getName(), array('type' => 'entity_reference_autocomplete_tags', 'settings' => array('placeholder' => 'Start typing here.')))->save(); // Prefix the terms with a letter to ensure there is no clash in the first // three letters. // @see https://www.drupal.org/node/2397691 $terms = array('term1' => 'a' . $this->randomMachineName(), 'term2' => 'b' . $this->randomMachineName(), 'term3' => 'c' . $this->randomMachineName() . ', ' . $this->randomMachineName(), 'term4' => 'd' . $this->randomMachineName()); $edit = array(); $edit['title[0][value]'] = $this->randomMachineName(); $edit['body[0][value]'] = $this->randomMachineName(); // Insert the terms in a comma separated list. Vocabulary 1 is a // free-tagging field created by the default profile. $edit[$field->getName() . '[target_id]'] = Tags::implode($terms); // Verify the placeholder is there. $this->drupalGet('node/add/article'); $this->assertRaw('placeholder="Start typing here."', 'Placeholder is present.'); // Preview and verify the terms appear but are not created. $this->drupalPostForm(NULL, $edit, t('Preview')); foreach ($terms as $term) { $this->assertText($term, 'The term appears on the node preview.'); } $tree = $this->container->get('entity.manager')->getStorage('taxonomy_term')->loadTree($this->vocabulary->id()); $this->assertTrue(empty($tree), 'The terms are not created on preview.'); // taxonomy.module does not maintain its static caches. taxonomy_terms_static_reset(); // Save, creating the terms. $this->drupalPostForm('node/add/article', $edit, t('Save')); $this->assertRaw(t('@type %title has been created.', array('@type' => t('Article'), '%title' => $edit['title[0][value]'])), 'The node was created successfully.'); foreach ($terms as $term) { $this->assertText($term, 'The term was saved and appears on the node page.'); } // Get the created terms. $term_objects = array(); foreach ($terms as $key => $term) { $term_objects[$key] = taxonomy_term_load_multiple_by_name($term); $term_objects[$key] = reset($term_objects[$key]); } // Get the node. $node = $this->drupalGetNodeByTitle($edit['title[0][value]']); // Test editing the node. $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save')); foreach ($terms as $term) { $this->assertText($term, 'The term was retained after edit and still appears on the node page.'); } // Delete term 1 from the term edit page. $this->drupalGet('taxonomy/term/' . $term_objects['term1']->id() . '/edit'); $this->clickLink(t('Delete')); $this->drupalPostForm(NULL, NULL, t('Delete')); // Delete term 2 from the term delete page. $this->drupalGet('taxonomy/term/' . $term_objects['term2']->id() . '/delete'); $this->drupalPostForm(NULL, array(), t('Delete')); $term_names = array($term_objects['term3']->getName(), $term_objects['term4']->getName()); $this->drupalGet('node/' . $node->id()); foreach ($term_names as $term_name) { $this->assertText($term_name, format_string('The term %name appears on the node page after two terms, %deleted1 and %deleted2, were deleted.', array('%name' => $term_name, '%deleted1' => $term_objects['term1']->getName(), '%deleted2' => $term_objects['term2']->getName()))); } $this->assertNoText($term_objects['term1']->getName(), format_string('The deleted term %name does not appear on the node page.', array('%name' => $term_objects['term1']->getName()))); $this->assertNoText($term_objects['term2']->getName(), format_string('The deleted term %name does not appear on the node page.', array('%name' => $term_objects['term2']->getName()))); }
public function rowAttributes() { $variables = array(); $active_row_regions = array(); $config_settings = \Drupal::config($this->theme_name . '.settings')->get('settings'); // If rows are empty return early. if (empty($this->layout_config['rows'])) { return; } // Build array of rows with region values. foreach ($this->layout_config['rows'] as $row_name => $row_data) { // Set a bool for active regions, assume false. $variables[$row_name . '__regions']['active'] = FALSE; $i = 1; foreach ($row_data['regions'] as $region_key => $region_name) { $region_source_order[$row_name][$region_key] = $i++; // Set an increment value for each region for the .hr class (has-regions) $row_regions[$row_name][] = $region_key; // Build array to intersect and use for the .arc class (active region count). } // Pass on row wrapper attributes only for rows with active regions $active_row_regions[$row_name]['attributes'] = $row_data['attributes']; // Remove inactive regions. $active_row_regions[$row_name]['regions'] = array_intersect($row_regions[$row_name], $this->active_regions); // Unset inactive rows. if (empty($active_row_regions[$row_name]['regions'])) { unset($active_row_regions[$row_name]); } } // Set additional attributes for rows. foreach ($active_row_regions as $row_key => $row_values) { //if (!empty($row_values['regions'])) {} // If active regions set to true to print the row, basically a catch all condition. $variables[$row_key . '__regions']['active'] = TRUE; // Wrapper attributes. $variables[$row_key . '__wrapper_attributes'] = new Attribute; $variables[$row_key . '__wrapper_attributes']['class'] = array('l-pr', 'page__row', 'pr-' . $row_key); foreach ($row_values['attributes'] as $attribute_type => $attribute_values) { if (is_array($attribute_values)) { $variables[$row_key . '__wrapper_attributes'][$attribute_type] = array(implode(' ', $attribute_values)); } else { $variables[$row_key . '__wrapper_attributes'][$attribute_type] = array($attribute_values); } } // Container attributes. $variables[$row_key . '__container_attributes'] = new Attribute; $variables[$row_key . '__container_attributes']['class'] = array('l-rw', 'regions', 'container', 'pr-'. str_replace('_', '-', $row_key) . '__rw'); // Active Regions: "arc" is "active region count", this is number of active regions in this row on this page. $count = count($row_values['regions']); $variables[$row_key . '__container_attributes']['class'][] = 'arc--'. $count; // Match each active region with its'corrosponding source order increment. foreach ($row_values['regions'] as $region) { if (isset($region_source_order[$row_key][$region])) { $row_has_regions[$row_key][] = $region_source_order[$row_key][$region]; } } // Has Regions: the "hr" class tells us which regions are active by source order (as per the layout markup yml), // this allows us to push layout dependant on exactly which regions are active. if (isset($row_has_regions[$row_key])) { $variables[$row_key . '__container_attributes']['class'][] = 'hr--' . implode('-', $row_has_regions[$row_key]); } // Shortcode classes. if (isset($config_settings['enable_extensions']) && $config_settings['enable_extensions'] === 1) { if (isset($config_settings['enable_shortcodes']) && $config_settings['enable_shortcodes'] === 1) { // Wrapper codes if (!empty($config_settings['page_classes_row_wrapper_' . $row_key])) { $shortcodes = Tags::explode($config_settings['page_classes_row_wrapper_' . $row_key]); foreach ($shortcodes as $class) { $variables[$row_key . '__wrapper_attributes']['class'][] = Html::cleanCssIdentifier($class); } } // Container codes if (!empty($config_settings['page_classes_row_container_' . $row_key])) { $shortcodes = Tags::explode($config_settings['page_classes_row_container_' . $row_key]); foreach ($shortcodes as $class) { $variables[$row_key . '__container_attributes']['class'][] = Html::cleanCssIdentifier($class); } } } } } return $variables; }
/** * Returns matched labels based on a given field, instance and search string. * * This function can be used by other modules that wish to pass a mocked * definition of the field on instance. * * @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 ''. * @param string $prefix * (optional) A prefix for all the keys returned by this function. * @param string $string * (optional) The label of the entity to query by. * * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException * Thrown when the current user doesn't have access to the specifies entity. * * @return array * A list of matched entity labels. * * @see \Drupal\entity_reference\EntityReferenceController */ public function getMatches(FieldDefinitionInterface $field_definition, $entity_type, $bundle, $entity_id = '', $prefix = '', $string = '') { $matches = array(); $entity = NULL; if ($entity_id !== 'NULL') { $entity = $this->entityManager->getStorage($entity_type)->load($entity_id); if (!$entity || !$entity->access('view')) { throw new AccessDeniedHttpException(); } } $handler = $this->selectionHandlerManager->getSelectionHandler($field_definition, $entity); if (isset($string)) { // Get an array of matching entities. $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); // Loop through the entities and convert them into autocomplete output. foreach ($entity_labels as $values) { foreach ($values as $entity_id => $label) { $key = "{$label} ({$entity_id})"; // Strip things like starting/trailing white spaces, line breaks and // tags. $key = preg_replace('/\\s\\s+/', ' ', str_replace("\n", '', trim(decode_entities(strip_tags($key))))); // Names containing commas or quotes must be wrapped in quotes. $key = Tags::encode($key); $matches[] = array('value' => $prefix . $key, 'label' => $label); } } } return $matches; }
/** * Converts an array of entity objects into a string of entity labels. * * This method is also responsible for checking the 'view' access on the * passed-in entities. * * @param \Drupal\Core\Entity\EntityInterface[] $entities * An array of entity objects. * * @return string * A string of entity labels separated by commas. */ public static function getEntityLabels(array $entities) { $entity_labels = array(); foreach ($entities as $entity) { $label = $entity->access('view') ? $entity->label() : t('- Restricted access -'); // Take into account "autocreated" entities. if (!$entity->isNew()) { $label .= ' (' . $entity->id() . ')'; } // Labels containing commas or quotes must be wrapped in quotes. $entity_labels[] = Tags::encode($label); } return implode(', ', $entity_labels); }
/** * {@inheritdoc} */ public function submitConfigurationForm(array &$form, array &$form_state) { $this->configuration['keywords'] = Tags::explode($form_state['values']['keywords']); }
/** * {@inheritdoc} */ public function validateExposed(&$form, FormStateInterface $form_state) { if (empty($this->options['exposed']) || empty($this->options['expose']['identifier'])) { return; } $identifier = $this->options['expose']['identifier']; $input = $form_state->getValues()[$identifier]; if ($this->options['is_grouped'] && isset($this->options['group_info']['group_items'][$input])) { $this->operator = $this->options['group_info']['group_items'][$input]['operator']; $input = $this->options['group_info']['group_items'][$input]['value']; } $values = $this->isMultiValued() ? Tags::explode($input) : array($input); if (!$this->options['is_grouped'] || ($this->options['is_grouped'] && ($input != 'All'))) { $this->validatedExposedInput = $this->validateEntityStrings($form[$identifier], $values, $form_state); } else { $this->validatedExposedInput = FALSE; } }
/** * Gets the entity labels. */ protected function getLabels(FieldItemListInterface $items, $delta) { if ($items->isEmpty()) { return array(); } $entity_labels = array(); // Load those entities and loop through them to extract their labels. $entities = entity_load_multiple($this->getFieldSetting('target_type'), $this->getEntityIds($items, $delta)); foreach ($entities as $entity_id => $entity_item) { $label = $entity_item->label(); $key = "{$label} ({$entity_id})"; // Labels containing commas or quotes must be wrapped in quotes. $key = Tags::encode($key); $entity_labels[] = $key; } return $entity_labels; }