/** * 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 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); }
/** * 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; }
/** * {@inheritdoc} */ public function buildConfigurationForm(array $form, FormStateInterface $form_state) { $form['keywords'] = array('#title' => t('Keywords'), '#type' => 'textarea', '#description' => t('The comment will be unpublished if it contains any of the phrases above. Use a case-sensitive, comma-separated list of phrases. Example: funny, bungee jumping, "Company, Inc."'), '#default_value' => Tags::implode($this->configuration['keywords'])); return $form; }
/** * 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->entity_type, $field->bundle, 'default')->setComponent($field->getName(), array('type' => 'taxonomy_autocomplete', 'settings' => array('placeholder' => 'Start typing here.')))->save(); $terms = array('term1' => $this->randomMachineName(), 'term2' => $this->randomMachineName(), 'term3' => $this->randomMachineName() . ', ' . $this->randomMachineName(), 'term4' => $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()] = 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 = taxonomy_get_tree($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]); } // 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()); // Get the node. $node = $this->drupalGetNodeByTitle($edit['title[0][value]']); $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()))); // Test autocomplete on term 3, which contains a comma. // The term will be quoted, and the " will be encoded in unicode (\u0022). $input = substr($term_objects['term3']->getName(), 0, 3); $json = $this->drupalGet('taxonomy/autocomplete/node/taxonomy_' . $this->vocabulary->id(), array('query' => array('q' => $input))); $this->assertEqual($json, '[{"value":"\\u0022' . $term_objects['term3']->getName() . '\\u0022","label":"' . $term_objects['term3']->getName() . '"}]', format_string('Autocomplete returns term %term_name after typing the first 3 letters.', array('%term_name' => $term_objects['term3']->getName()))); // Test autocomplete on term 4 - it is alphanumeric only, so no extra // quoting. $input = substr($term_objects['term4']->getName(), 0, 3); $this->drupalGet('taxonomy/autocomplete/node/taxonomy_' . $this->vocabulary->id(), array('query' => array('q' => $input))); $this->assertRaw('[{"value":"' . $term_objects['term4']->getName() . '","label":"' . $term_objects['term4']->getName() . '"}', format_string('Autocomplete returns term %term_name after typing the first 3 letters.', array('%term_name' => $term_objects['term4']->getName()))); // Test taxonomy autocomplete with a nonexistent field. $field_name = $this->randomMachineName(); $tag = $this->randomMachineName(); $message = t("Taxonomy field @field_name not found.", array('@field_name' => $field_name)); $this->assertFalse(FieldStorageConfig::loadByName('node', $field_name), format_string('Field %field_name does not exist.', array('%field_name' => $field_name))); $this->drupalGet('taxonomy/autocomplete/node/' . $field_name, array('query' => array('q' => $tag))); $this->assertRaw($message, 'Autocomplete returns correct error message when the taxonomy field does not exist.'); }
/** * 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()))); }