updated core to 8.6.3

This commit is contained in:
2018-11-21 12:49:46 +01:00
parent 8ca34853a3
commit c92c348eee
521 changed files with 12199 additions and 4578 deletions
@@ -0,0 +1,135 @@
<?php
namespace Drupal\Tests\taxonomy\Functional;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\views\Views;
/**
* Ensure that data added as terms appears in RSS feeds if "RSS Category" format
* is selected.
*
* @group taxonomy
*/
class RssTest extends TaxonomyTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['node', 'field_ui', 'views'];
/**
* Vocabulary for testing.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
/**
* Name of the taxonomy term reference field.
*
* @var string
*/
protected $fieldName;
protected function setUp() {
parent::setUp();
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy', 'bypass node access', 'administer content types', 'administer node display']));
$this->vocabulary = $this->createVocabulary();
$this->fieldName = 'taxonomy_' . $this->vocabulary->id();
$handler_settings = [
'target_bundles' => [
$this->vocabulary->id() => $this->vocabulary->id(),
],
'auto_create' => TRUE,
];
$this->createEntityReferenceField('node', 'article', $this->fieldName, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
entity_get_form_display('node', 'article', 'default')
->setComponent($this->fieldName, [
'type' => 'options_select',
])
->save();
entity_get_display('node', 'article', 'default')
->setComponent($this->fieldName, [
'type' => 'entity_reference_label',
])
->save();
}
/**
* Tests that terms added to nodes are displayed in core RSS feed.
*
* Create a node and assert that taxonomy terms appear in rss.xml.
*/
public function testTaxonomyRss() {
// Create two taxonomy terms.
$term1 = $this->createTerm($this->vocabulary);
// RSS display must be added manually.
$this->drupalGet("admin/structure/types/manage/article/display");
$edit = [
"display_modes_custom[rss]" => '1',
];
$this->drupalPostForm(NULL, $edit, t('Save'));
// Change the format to 'RSS category'.
$this->drupalGet("admin/structure/types/manage/article/display/rss");
$edit = [
"fields[taxonomy_" . $this->vocabulary->id() . "][type]" => 'entity_reference_rss_category',
"fields[taxonomy_" . $this->vocabulary->id() . "][region]" => 'content',
];
$this->drupalPostForm(NULL, $edit, t('Save'));
// Post an article.
$edit = [];
$edit['title[0][value]'] = $this->randomMachineName();
$edit[$this->fieldName . '[]'] = $term1->id();
$this->drupalPostForm('node/add/article', $edit, t('Save'));
// Check that the term is displayed when the RSS feed is viewed.
$this->drupalGet('rss.xml');
$test_element = sprintf(
'<category %s>%s</category>',
'domain="' . $term1->url('canonical', ['absolute' => TRUE]) . '"',
$term1->getName()
);
$this->assertRaw($test_element, 'Term is displayed when viewing the rss feed.');
// Test that the feed icon exists for the term.
$this->drupalGet("taxonomy/term/{$term1->id()}");
$this->assertLinkByHref("taxonomy/term/{$term1->id()}/feed");
// Test that the feed page exists for the term.
$this->drupalGet("taxonomy/term/{$term1->id()}/feed");
$assert = $this->assertSession();
$assert->responseHeaderContains('Content-Type', 'application/rss+xml');
// Ensure the RSS version is 2.0.
$rss_array = $this->getSession()->getDriver()->find('rss');
$this->assertEquals('2.0', reset($rss_array)->getAttribute('version'));
// Check that the "Exception value" is disabled by default.
$this->drupalGet('taxonomy/term/all/feed');
$this->assertResponse(404);
// Set the exception value to 'all'.
$view = Views::getView('taxonomy_term');
$arguments = $view->getDisplay()->getOption('arguments');
$arguments['tid']['exception']['value'] = 'all';
$view->getDisplay()->overrideOption('arguments', $arguments);
$view->storage->save();
// Check the article is shown in the feed.
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
$raw_xml = '<title>' . $node->label() . '</title>';
$this->drupalGet('taxonomy/term/all/feed');
$this->assertRaw($raw_xml, "Raw text '$raw_xml' is found.");
// Unpublish the article and check that it is not shown in the feed.
$node->setUnpublished()->save();
$this->drupalGet('taxonomy/term/all/feed');
$this->assertNoRaw($raw_xml);
}
}
@@ -0,0 +1,95 @@
<?php
namespace Drupal\Tests\taxonomy\Functional;
/**
* Ensure that the term indentation works properly.
*
* @group taxonomy
*/
class TaxonomyTermIndentationTest extends TaxonomyTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['taxonomy'];
/**
* Vocabulary for testing.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
protected function setUp() {
parent::setUp();
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy', 'bypass node access']));
$this->vocabulary = $this->createVocabulary();
}
/**
* Tests term indentation.
*/
public function testTermIndentation() {
$assert = $this->assertSession();
// Create three taxonomy terms.
$term1 = $this->createTerm($this->vocabulary);
$term2 = $this->createTerm($this->vocabulary);
$term3 = $this->createTerm($this->vocabulary);
// Get the taxonomy storage.
$taxonomy_storage = $this->container->get('entity.manager')->getStorage('taxonomy_term');
// Indent the second term under the first one.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->get('vid') . '/overview');
$hidden_edit = [
'terms[tid:' . $term2->id() . ':0][term][tid]' => 2,
'terms[tid:' . $term2->id() . ':0][term][parent]' => 1,
'terms[tid:' . $term2->id() . ':0][term][depth]' => 1,
];
// Because we can't post hidden form elements, we have to change them in
// code here, and then submit.
foreach ($hidden_edit as $field => $value) {
$node = $assert->hiddenFieldExists($field);
$node->setValue($value);
}
$edit = [
'terms[tid:' . $term2->id() . ':0][weight]' => 1,
];
// Submit the edited form and check for HTML indentation element presence.
$this->drupalPostForm(NULL, $edit, t('Save'));
$this->assertPattern('|<div class="js-indentation indentation">&nbsp;</div>|');
// Check explicitly that term 2's parent is term 1.
$parents = $taxonomy_storage->loadParents($term2->id());
$this->assertEqual(key($parents), 1, 'Term 1 is the term 2\'s parent');
// Move the second term back out to the root level.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->get('vid') . '/overview');
$hidden_edit = [
'terms[tid:' . $term2->id() . ':0][term][tid]' => 2,
'terms[tid:' . $term2->id() . ':0][term][parent]' => 0,
'terms[tid:' . $term2->id() . ':0][term][depth]' => 0,
];
// Because we can't post hidden form elements, we have to change them in
// code here, and then submit.
foreach ($hidden_edit as $field => $value) {
$node = $assert->hiddenFieldExists($field);
$node->setValue($value);
}
$edit = [
'terms[tid:' . $term2->id() . ':0][weight]' => 1,
];
$this->drupalPostForm(NULL, $edit, t('Save'));
// All terms back at the root level, no indentation should be present.
$this->assertSession()->responseNotMatches('|<div class="js-indentation indentation">&nbsp;</div>|');
// Check explicitly that term 2 has no parents.
\Drupal::entityManager()->getStorage('taxonomy_term')->resetCache();
$parents = $taxonomy_storage->loadParents($term2->id());
$this->assertTrue(empty($parents), 'Term 2 has no parents now');
}
}
@@ -2,8 +2,8 @@
namespace Drupal\Tests\taxonomy\Functional;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\Tests\BrowserTestBase;
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
/**
* Provides common helper methods for Taxonomy module tests.
@@ -3,9 +3,9 @@
namespace Drupal\Tests\taxonomy\Functional;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
/**
* Provides common testing base for translated taxonomy terms.
@@ -0,0 +1,229 @@
<?php
namespace Drupal\Tests\taxonomy\Functional;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Entity\Entity\EntityViewDisplay;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
/**
* Tests the autocomplete implementation of the taxonomy class.
*
* @group taxonomy
*/
class TermAutocompleteTest extends TaxonomyTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['node'];
/**
* The vocabulary.
*
* @var \Drupal\taxonomy\Entity\Vocabulary
*/
protected $vocabulary;
/**
* The field to add to the content type for the taxonomy terms.
*
* @var string
*/
protected $fieldName;
/**
* The admin user.
*
* @var \Drupal\user\Entity\User
*/
protected $adminUser;
/**
* The autocomplete URL to call.
*
* @var string
*/
protected $autocompleteUrl;
/**
* The term IDs indexed by term names.
*
* @var array
*/
protected $termIds;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Create a vocabulary.
$this->vocabulary = $this->createVocabulary();
// Create 11 terms, which have some sub-string in common, in a
// non-alphabetical order, so that we will have more than 10 matches later
// when we test the correct number of results is returned, and we can test
// the order of the results. The location of the sub-string to match varies
// also, since it should not be necessary to start with the sub-string to
// match it. Save term IDs to reuse later.
$termNames = [
'aaa 20 bbb',
'aaa 70 bbb',
'aaa 10 bbb',
'aaa 12 bbb',
'aaa 40 bbb',
'aaa 11 bbb',
'aaa 30 bbb',
'aaa 50 bbb',
'aaa 80',
'aaa 90',
'bbb 60 aaa',
];
foreach ($termNames as $termName) {
$term = $this->createTerm($this->vocabulary, ['name' => $termName]);
$this->termIds[$termName] = $term->id();
}
// Create a taxonomy_term_reference field on the article Content Type that
// uses a taxonomy_autocomplete widget.
$this->fieldName = mb_strtolower($this->randomMachineName());
FieldStorageConfig::create([
'field_name' => $this->fieldName,
'entity_type' => 'node',
'type' => 'entity_reference',
'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
'settings' => [
'target_type' => 'taxonomy_term',
],
])->save();
FieldConfig::create([
'field_name' => $this->fieldName,
'bundle' => 'article',
'entity_type' => 'node',
'settings' => [
'handler' => 'default',
'handler_settings' => [
// Restrict selection of terms to a single vocabulary.
'target_bundles' => [
$this->vocabulary->id() => $this->vocabulary->id(),
],
],
],
])->save();
EntityFormDisplay::load('node.article.default')
->setComponent($this->fieldName, [
'type' => 'entity_reference_autocomplete',
])
->save();
EntityViewDisplay::load('node.article.default')
->setComponent($this->fieldName, [
'type' => 'entity_reference_label',
])
->save();
// Create a user and then login.
$this->adminUser = $this->drupalCreateUser(['create article content']);
$this->drupalLogin($this->adminUser);
// Retrieve the autocomplete url.
$this->drupalGet('node/add/article');
$result = $this->xpath('//input[@name="' . $this->fieldName . '[0][target_id]"]');
$this->autocompleteUrl = $this->getAbsoluteUrl($result[0]->getAttribute('data-autocomplete-path'));
}
/**
* Helper function for JSON formatted requests.
*
* @param string|\Drupal\Core\Url $path
* Drupal path or URL to load into Mink controlled browser.
* @param array $options
* (optional) Options to be forwarded to the url generator.
* @param string[] $headers
* (optional) An array containing additional HTTP request headers.
*
* @return string[]
* Array representing decoded JSON response.
*/
protected function drupalGetJson($path, array $options = [], array $headers = []) {
$options = array_merge_recursive(['query' => ['_format' => 'json']], $options);
return Json::decode($this->drupalGet($path, $options, $headers));
}
/**
* Tests that the autocomplete method returns the good number of results.
*
* @see \Drupal\taxonomy\Controller\TermAutocompleteController::autocomplete()
*/
public function testAutocompleteCountResults() {
// Test that no matching term found.
$data = $this->drupalGetJson(
$this->autocompleteUrl,
['query' => ['q' => 'zzz']]
);
$this->assertTrue(empty($data), 'Autocomplete returned no results');
// Test that only one matching term found, when only one matches.
$data = $this->drupalGetJson(
$this->autocompleteUrl,
['query' => ['q' => 'aaa 10']]
);
$this->assertEqual(1, count($data), 'Autocomplete returned 1 result');
// Test the correct number of matches when multiple are partial matches.
$data = $this->drupalGetJson(
$this->autocompleteUrl,
['query' => ['q' => 'aaa 1']]
);
$this->assertEqual(3, count($data), 'Autocomplete returned 3 results');
// Tests that only 10 results are returned, even if there are more than 10
// matches.
$data = $this->drupalGetJson(
$this->autocompleteUrl,
['query' => ['q' => 'aaa']]
);
$this->assertEqual(10, count($data), 'Autocomplete returned only 10 results (for over 10 matches)');
}
/**
* Tests that the autocomplete method returns properly ordered results.
*
* @see \Drupal\taxonomy\Controller\TermAutocompleteController::autocomplete()
*/
public function testAutocompleteOrderedResults() {
$expectedResults = [
'aaa 10 bbb',
'aaa 11 bbb',
'aaa 12 bbb',
'aaa 20 bbb',
'aaa 30 bbb',
'aaa 40 bbb',
'aaa 50 bbb',
'aaa 70 bbb',
'bbb 60 aaa',
];
// Build $expected to match the autocomplete results.
$expected = [];
foreach ($expectedResults as $termName) {
$expected[] = [
'value' => $termName . ' (' . $this->termIds[$termName] . ')',
'label' => $termName,
];
}
$data = $this->drupalGetJson(
$this->autocompleteUrl,
['query' => ['q' => 'bbb']]
);
$this->assertIdentical($expected, $data);
}
}
@@ -0,0 +1,606 @@
<?php
namespace Drupal\Tests\taxonomy\Functional;
use Drupal\Component\Utility\Tags;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\taxonomy\Entity\Term;
use Drupal\taxonomy\Entity\Vocabulary;
/**
* Tests load, save and delete for taxonomy terms.
*
* @group taxonomy
*/
class TermTest extends TaxonomyTestBase {
/**
* Vocabulary for testing.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
/**
* Taxonomy term reference field for testing.
*
* @var \Drupal\field\FieldConfigInterface
*/
protected $field;
/**
* Modules to enable.
*
* @var string[]
*/
public static $modules = ['block'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->drupalPlaceBlock('local_actions_block');
$this->drupalPlaceBlock('local_tasks_block');
$this->drupalPlaceBlock('page_title_block');
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy', 'bypass node access']));
$this->vocabulary = $this->createVocabulary();
$field_name = 'taxonomy_' . $this->vocabulary->id();
$handler_settings = [
'target_bundles' => [
$this->vocabulary->id() => $this->vocabulary->id(),
],
'auto_create' => TRUE,
];
$this->createEntityReferenceField('node', 'article', $field_name, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
$this->field = FieldConfig::loadByName('node', 'article', $field_name);
entity_get_form_display('node', 'article', 'default')
->setComponent($field_name, [
'type' => 'options_select',
])
->save();
entity_get_display('node', 'article', 'default')
->setComponent($field_name, [
'type' => 'entity_reference_label',
])
->save();
}
/**
* The "parent" field must restrict references to the same vocabulary.
*/
public function testParentHandlerSettings() {
$vocabulary_fields = \Drupal::service('entity_field.manager')->getFieldDefinitions('taxonomy_term', $this->vocabulary->id());
$parent_target_bundles = $vocabulary_fields['parent']->getSetting('handler_settings')['target_bundles'];
$this->assertIdentical([$this->vocabulary->id() => $this->vocabulary->id()], $parent_target_bundles);
}
/**
* Test terms in a single and multiple hierarchy.
*/
public function testTaxonomyTermHierarchy() {
// Create two taxonomy terms.
$term1 = $this->createTerm($this->vocabulary);
$term2 = $this->createTerm($this->vocabulary);
// Get the taxonomy storage.
$taxonomy_storage = $this->container->get('entity.manager')->getStorage('taxonomy_term');
// Check that hierarchy is flat.
$vocabulary = Vocabulary::load($this->vocabulary->id());
$this->assertEqual(0, $vocabulary->getHierarchy(), 'Vocabulary is flat.');
// Edit $term2, setting $term1 as parent.
$edit = [];
$edit['parent[]'] = [$term1->id()];
$this->drupalPostForm('taxonomy/term/' . $term2->id() . '/edit', $edit, t('Save'));
// Check the hierarchy.
$children = $taxonomy_storage->loadChildren($term1->id());
$parents = $taxonomy_storage->loadParents($term2->id());
$this->assertTrue(isset($children[$term2->id()]), 'Child found correctly.');
$this->assertTrue(isset($parents[$term1->id()]), 'Parent found correctly.');
// Load and save a term, confirming that parents are still set.
$term = Term::load($term2->id());
$term->save();
$parents = $taxonomy_storage->loadParents($term2->id());
$this->assertTrue(isset($parents[$term1->id()]), 'Parent found correctly.');
// Create a third term and save this as a parent of term2.
$term3 = $this->createTerm($this->vocabulary);
$term2->parent = [$term1->id(), $term3->id()];
$term2->save();
$parents = $taxonomy_storage->loadParents($term2->id());
$this->assertTrue(isset($parents[$term1->id()]) && isset($parents[$term3->id()]), 'Both parents found successfully.');
}
/**
* Tests that many terms with parents show on each page
*/
public function testTaxonomyTermChildTerms() {
// Set limit to 10 terms per page. Set variable to 9 so 10 terms appear.
$this->config('taxonomy.settings')->set('terms_per_page_admin', '9')->save();
$term1 = $this->createTerm($this->vocabulary);
$terms_array = [];
$taxonomy_storage = $this->container->get('entity.manager')->getStorage('taxonomy_term');
// Create 40 terms. Terms 1-12 get parent of $term1. All others are
// individual terms.
for ($x = 1; $x <= 40; $x++) {
$edit = [];
// Set terms in order so we know which terms will be on which pages.
$edit['weight'] = $x;
// Set terms 1-20 to be children of first term created.
if ($x <= 12) {
$edit['parent'] = $term1->id();
}
$term = $this->createTerm($this->vocabulary, $edit);
$children = $taxonomy_storage->loadChildren($term1->id());
$parents = $taxonomy_storage->loadParents($term->id());
$terms_array[$x] = Term::load($term->id());
}
// Get Page 1.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview');
$this->assertText($term1->getName(), 'Parent Term is displayed on Page 1');
for ($x = 1; $x <= 13; $x++) {
$this->assertText($terms_array[$x]->getName(), $terms_array[$x]->getName() . ' found on Page 1');
}
// Get Page 2.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview', ['query' => ['page' => 1]]);
$this->assertText($term1->getName(), 'Parent Term is displayed on Page 2');
for ($x = 1; $x <= 18; $x++) {
$this->assertText($terms_array[$x]->getName(), $terms_array[$x]->getName() . ' found on Page 2');
}
// Get Page 3.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview', ['query' => ['page' => 2]]);
$this->assertNoText($term1->getName(), 'Parent Term is not displayed on Page 3');
for ($x = 1; $x <= 17; $x++) {
$this->assertNoText($terms_array[$x]->getName(), $terms_array[$x]->getName() . ' not found on Page 3');
}
for ($x = 18; $x <= 25; $x++) {
$this->assertText($terms_array[$x]->getName(), $terms_array[$x]->getName() . ' found on Page 3');
}
}
/**
* Test that hook_node_$op implementations work correctly.
*
* Save & edit a node and assert that taxonomy terms are saved/loaded properly.
*/
public function testTaxonomyNode() {
// Create two taxonomy terms.
$term1 = $this->createTerm($this->vocabulary);
$term2 = $this->createTerm($this->vocabulary);
// Post an article.
$edit = [];
$edit['title[0][value]'] = $this->randomMachineName();
$edit['body[0][value]'] = $this->randomMachineName();
$edit[$this->field->getName() . '[]'] = $term1->id();
$this->drupalPostForm('node/add/article', $edit, t('Save'));
// Check that the term is displayed when the node is viewed.
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
$this->drupalGet('node/' . $node->id());
$this->assertText($term1->getName(), 'Term is displayed when viewing the node.');
$this->clickLink(t('Edit'));
$this->assertText($term1->getName(), 'Term is displayed when editing the node.');
$this->drupalPostForm(NULL, [], t('Save'));
$this->assertText($term1->getName(), 'Term is displayed after saving the node with no changes.');
// Edit the node with a different term.
$edit[$this->field->getName() . '[]'] = $term2->id();
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
$this->drupalGet('node/' . $node->id());
$this->assertText($term2->getName(), 'Term is displayed when viewing the node.');
// Preview the node.
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Preview'));
$this->assertUniqueText($term2->getName(), 'Term is displayed when previewing the node.');
$this->drupalPostForm('node/' . $node->id() . '/edit', NULL, t('Preview'));
$this->assertUniqueText($term2->getName(), 'Term is displayed when previewing the node again.');
}
/**
* Test term creation with a free-tagging vocabulary from the node form.
*/
public function testNodeTermCreationAndDeletion() {
// Enable tags in the vocabulary.
$field = $this->field;
entity_get_form_display($field->getTargetEntityTypeId(), $field->getTargetBundle(), 'default')
->setComponent($field->getName(), [
'type' => 'entity_reference_autocomplete_tags',
'settings' => [
'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 = [
'term1' => 'a' . $this->randomMachineName(),
'term2' => 'b' . $this->randomMachineName(),
'term3' => 'c' . $this->randomMachineName() . ', ' . $this->randomMachineName(),
'term4' => 'd' . $this->randomMachineName(),
];
$edit = [];
$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->assertText(t('@type @title has been created.', ['@type' => t('Article'), '@title' => $edit['title[0][value]']]), 'The node was created successfully.');
// Verify that the creation message contains a link to a node.
$view_link = $this->xpath('//div[@class="messages"]//a[contains(@href, :href)]', [':href' => 'node/']);
$this->assert(isset($view_link), 'The message area contains a link to a node');
foreach ($terms as $term) {
$this->assertText($term, 'The term was saved and appears on the node page.');
}
// Get the created terms.
$term_objects = [];
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, [], t('Delete'));
$term_names = [$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.', ['%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.', ['%name' => $term_objects['term1']->getName()]));
$this->assertNoText($term_objects['term2']->getName(), format_string('The deleted term %name does not appear on the node page.', ['%name' => $term_objects['term2']->getName()]));
}
/**
* Save, edit and delete a term using the user interface.
*/
public function testTermInterface() {
\Drupal::service('module_installer')->install(['views']);
$edit = [
'name[0][value]' => $this->randomMachineName(12),
'description[0][value]' => $this->randomMachineName(100),
];
// Explicitly set the parents field to 'root', to ensure that
// TermForm::save() handles the invalid term ID correctly.
$edit['parent[]'] = [0];
// Create the term to edit.
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add', $edit, t('Save'));
$terms = taxonomy_term_load_multiple_by_name($edit['name[0][value]']);
$term = reset($terms);
$this->assertNotNull($term, 'Term found in database.');
// Submitting a term takes us to the add page; we need the List page.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview');
$this->clickLink(t('Edit'));
$this->assertRaw($edit['name[0][value]'], 'The randomly generated term name is present.');
$this->assertText($edit['description[0][value]'], 'The randomly generated term description is present.');
$edit = [
'name[0][value]' => $this->randomMachineName(14),
'description[0][value]' => $this->randomMachineName(102),
];
// Edit the term.
$this->drupalPostForm('taxonomy/term/' . $term->id() . '/edit', $edit, t('Save'));
// Check that the term is still present at admin UI after edit.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview');
$this->assertText($edit['name[0][value]'], 'The randomly generated term name is present.');
$this->assertLink(t('Edit'));
// Check the term link can be clicked through to the term page.
$this->clickLink($edit['name[0][value]']);
$this->assertResponse(200, 'Term page can be accessed via the listing link.');
// View the term and check that it is correct.
$this->drupalGet('taxonomy/term/' . $term->id());
$this->assertText($edit['name[0][value]'], 'The randomly generated term name is present.');
$this->assertText($edit['description[0][value]'], 'The randomly generated term description is present.');
// Did this page request display a 'term-listing-heading'?
$this->assertTrue($this->xpath('//div[contains(@class, "field--name-description")]'), 'Term page displayed the term description element.');
// Check that it does NOT show a description when description is blank.
$term->setDescription(NULL);
$term->save();
$this->drupalGet('taxonomy/term/' . $term->id());
$this->assertFalse($this->xpath('//div[contains(@class, "field--entity-taxonomy-term--description")]'), 'Term page did not display the term description when description was blank.');
// Check that the description value is processed.
$value = $this->randomMachineName();
$term->setDescription($value);
$term->save();
$this->assertEqual($term->description->processed, "<p>$value</p>\n");
// Check that the term feed page is working.
$this->drupalGet('taxonomy/term/' . $term->id() . '/feed');
// Delete the term.
$this->drupalGet('taxonomy/term/' . $term->id() . '/edit');
$this->clickLink(t('Delete'));
$this->drupalPostForm(NULL, NULL, t('Delete'));
// Assert that the term no longer exists.
$this->drupalGet('taxonomy/term/' . $term->id());
$this->assertResponse(404, 'The taxonomy term page was not found.');
}
/**
* Save, edit and delete a term using the user interface.
*/
public function testTermReorder() {
$assert = $this->assertSession();
$this->createTerm($this->vocabulary);
$this->createTerm($this->vocabulary);
$this->createTerm($this->vocabulary);
$taxonomy_storage = $this->container->get('entity.manager')->getStorage('taxonomy_term');
// Fetch the created terms in the default alphabetical order, i.e. term1
// precedes term2 alphabetically, and term2 precedes term3.
$taxonomy_storage->resetCache();
list($term1, $term2, $term3) = $taxonomy_storage->loadTree($this->vocabulary->id(), 0, NULL, TRUE);
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview');
// Each term has four hidden fields, "tid:1:0[tid]", "tid:1:0[parent]",
// "tid:1:0[depth]", and "tid:1:0[weight]". Change the order to term2,
// term3, term1 by setting weight property, make term3 a child of term2 by
// setting the parent and depth properties, and update all hidden fields.
$hidden_edit = [
'terms[tid:' . $term2->id() . ':0][term][tid]' => $term2->id(),
'terms[tid:' . $term2->id() . ':0][term][parent]' => 0,
'terms[tid:' . $term2->id() . ':0][term][depth]' => 0,
'terms[tid:' . $term3->id() . ':0][term][tid]' => $term3->id(),
'terms[tid:' . $term3->id() . ':0][term][parent]' => $term2->id(),
'terms[tid:' . $term3->id() . ':0][term][depth]' => 1,
'terms[tid:' . $term1->id() . ':0][term][tid]' => $term1->id(),
'terms[tid:' . $term1->id() . ':0][term][parent]' => 0,
'terms[tid:' . $term1->id() . ':0][term][depth]' => 0,
];
// Because we can't post hidden form elements, we have to change them in
// code here, and then submit.
foreach ($hidden_edit as $field => $value) {
$node = $assert->hiddenFieldExists($field);
$node->setValue($value);
}
// Edit non-hidden elements within drupalPostForm().
$edit = [
'terms[tid:' . $term2->id() . ':0][weight]' => 0,
'terms[tid:' . $term3->id() . ':0][weight]' => 1,
'terms[tid:' . $term1->id() . ':0][weight]' => 2,
];
$this->drupalPostForm(NULL, $edit, 'Save');
$taxonomy_storage->resetCache();
$terms = $taxonomy_storage->loadTree($this->vocabulary->id());
$this->assertEqual($terms[0]->tid, $term2->id(), 'Term 2 was moved above term 1.');
$this->assertEqual($terms[1]->parents, [$term2->id()], 'Term 3 was made a child of term 2.');
$this->assertEqual($terms[2]->tid, $term1->id(), 'Term 1 was moved below term 2.');
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview', [], t('Reset to alphabetical'));
// Submit confirmation form.
$this->drupalPostForm(NULL, [], t('Reset to alphabetical'));
// Ensure form redirected back to overview.
$this->assertUrl('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview');
$taxonomy_storage->resetCache();
$terms = $taxonomy_storage->loadTree($this->vocabulary->id(), 0, NULL, TRUE);
$this->assertEqual($terms[0]->id(), $term1->id(), 'Term 1 was moved to back above term 2.');
$this->assertEqual($terms[1]->id(), $term2->id(), 'Term 2 was moved to back below term 1.');
$this->assertEqual($terms[2]->id(), $term3->id(), 'Term 3 is still below term 2.');
$this->assertEqual($terms[2]->parents, [$term2->id()], 'Term 3 is still a child of term 2.');
}
/**
* Test saving a term with multiple parents through the UI.
*/
public function testTermMultipleParentsInterface() {
// Add a new term to the vocabulary so that we can have multiple parents.
$parent = $this->createTerm($this->vocabulary);
// Add a new term with multiple parents.
$edit = [
'name[0][value]' => $this->randomMachineName(12),
'description[0][value]' => $this->randomMachineName(100),
'parent[]' => [0, $parent->id()],
];
// Save the new term.
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add', $edit, t('Save'));
// Check that the term was successfully created.
$terms = taxonomy_term_load_multiple_by_name($edit['name[0][value]']);
$term = reset($terms);
$this->assertNotNull($term, 'Term found in database.');
$this->assertEqual($edit['name[0][value]'], $term->getName(), 'Term name was successfully saved.');
$this->assertEqual($edit['description[0][value]'], $term->getDescription(), 'Term description was successfully saved.');
// Check that the parent tid is still there. The other parent (<root>) is
// not added by \Drupal\taxonomy\TermStorageInterface::loadParents().
$parents = $this->container->get('entity.manager')->getStorage('taxonomy_term')->loadParents($term->id());
$parent = reset($parents);
$this->assertEqual($edit['parent[]'][1], $parent->id(), 'Term parents were successfully saved.');
}
/**
* Test taxonomy_term_load_multiple_by_name().
*/
public function testTaxonomyGetTermByName() {
$term = $this->createTerm($this->vocabulary);
// Load the term with the exact name.
$terms = taxonomy_term_load_multiple_by_name($term->getName());
$this->assertTrue(isset($terms[$term->id()]), 'Term loaded using exact name.');
// Load the term with space concatenated.
$terms = taxonomy_term_load_multiple_by_name(' ' . $term->getName() . ' ');
$this->assertTrue(isset($terms[$term->id()]), 'Term loaded with extra whitespace.');
// Load the term with name uppercased.
$terms = taxonomy_term_load_multiple_by_name(strtoupper($term->getName()));
$this->assertTrue(isset($terms[$term->id()]), 'Term loaded with uppercased name.');
// Load the term with name lowercased.
$terms = taxonomy_term_load_multiple_by_name(strtolower($term->getName()));
$this->assertTrue(isset($terms[$term->id()]), 'Term loaded with lowercased name.');
// Try to load an invalid term name.
$terms = taxonomy_term_load_multiple_by_name('Banana');
$this->assertFalse($terms, 'No term loaded with an invalid name.');
// Try to load the term using a substring of the name.
$terms = taxonomy_term_load_multiple_by_name(mb_substr($term->getName(), 2), 'No term loaded with a substring of the name.');
$this->assertFalse($terms);
// Create a new term in a different vocabulary with the same name.
$new_vocabulary = $this->createVocabulary();
$new_term = Term::create([
'name' => $term->getName(),
'vid' => $new_vocabulary->id(),
]);
$new_term->save();
// Load multiple terms with the same name.
$terms = taxonomy_term_load_multiple_by_name($term->getName());
$this->assertEqual(count($terms), 2, 'Two terms loaded with the same name.');
// Load single term when restricted to one vocabulary.
$terms = taxonomy_term_load_multiple_by_name($term->getName(), $this->vocabulary->id());
$this->assertEqual(count($terms), 1, 'One term loaded when restricted by vocabulary.');
$this->assertTrue(isset($terms[$term->id()]), 'Term loaded using exact name and vocabulary machine name.');
// Create a new term with another name.
$term2 = $this->createTerm($this->vocabulary);
// Try to load a term by name that doesn't exist in this vocabulary but
// exists in another vocabulary.
$terms = taxonomy_term_load_multiple_by_name($term2->getName(), $new_vocabulary->id());
$this->assertFalse($terms, 'Invalid term name restricted by vocabulary machine name not loaded.');
// Try to load terms filtering by a non-existing vocabulary.
$terms = taxonomy_term_load_multiple_by_name($term2->getName(), 'non_existing_vocabulary');
$this->assertEqual(count($terms), 0, 'No terms loaded when restricted by a non-existing vocabulary.');
}
/**
* Tests that editing and saving a node with no changes works correctly.
*/
public function testReSavingTags() {
// Enable tags in the vocabulary.
$field = $this->field;
entity_get_form_display($field->getTargetEntityTypeId(), $field->getTargetBundle(), 'default')
->setComponent($field->getName(), [
'type' => 'entity_reference_autocomplete_tags',
])
->save();
// Create a term and a node using it.
$term = $this->createTerm($this->vocabulary);
$edit = [];
$edit['title[0][value]'] = $this->randomMachineName(8);
$edit['body[0][value]'] = $this->randomMachineName(16);
$edit[$this->field->getName() . '[target_id]'] = $term->getName();
$this->drupalPostForm('node/add/article', $edit, t('Save'));
// Check that the term is displayed when editing and saving the node with no
// changes.
$this->clickLink(t('Edit'));
$this->assertRaw($term->getName(), 'Term is displayed when editing the node.');
$this->drupalPostForm(NULL, [], t('Save'));
$this->assertRaw($term->getName(), 'Term is displayed after saving the node with no changes.');
}
/**
* Check the breadcrumb on edit and delete a term page.
*/
public function testTermBreadcrumbs() {
$edit = [
'name[0][value]' => $this->randomMachineName(14),
'description[0][value]' => $this->randomMachineName(100),
'parent[]' => [0],
];
// Create the term.
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add', $edit, 'Save');
$terms = taxonomy_term_load_multiple_by_name($edit['name[0][value]']);
$term = reset($terms);
$this->assertNotNull($term, 'Term found in database.');
// Check the breadcrumb on the term edit page.
$this->drupalGet('taxonomy/term/' . $term->id() . '/edit');
$breadcrumbs = $this->getSession()->getPage()->findAll('css', 'nav.breadcrumb ol li a');
$this->assertIdentical(count($breadcrumbs), 2, 'The breadcrumbs are present on the page.');
$this->assertIdentical($breadcrumbs[0]->getText(), 'Home', 'First breadcrumb text is Home');
$this->assertIdentical($breadcrumbs[1]->getText(), $term->label(), 'Second breadcrumb text is term name on term edit page.');
$this->assertEscaped($breadcrumbs[1]->getText(), 'breadcrumbs displayed and escaped.');
// Check the breadcrumb on the term delete page.
$this->drupalGet('taxonomy/term/' . $term->id() . '/delete');
$breadcrumbs = $this->getSession()->getPage()->findAll('css', 'nav.breadcrumb ol li a');
$this->assertIdentical(count($breadcrumbs), 2, 'The breadcrumbs are present on the page.');
$this->assertIdentical($breadcrumbs[0]->getText(), 'Home', 'First breadcrumb text is Home');
$this->assertIdentical($breadcrumbs[1]->getText(), $term->label(), 'Second breadcrumb text is term name on term delete page.');
$this->assertEscaped($breadcrumbs[1]->getText(), 'breadcrumbs displayed and escaped.');
}
}
@@ -0,0 +1,149 @@
<?php
namespace Drupal\Tests\taxonomy\Functional;
use Drupal\Core\Url;
use Drupal\Tests\system\Functional\Menu\AssertBreadcrumbTrait;
/**
* Tests for proper breadcrumb translation.
*
* @group taxonomy
*/
class TermTranslationTest extends TaxonomyTestBase {
use AssertBreadcrumbTrait;
use TaxonomyTranslationTestTrait;
/**
* Term to translated term mapping.
*
* @var array
*/
protected $termTranslationMap = [
'one' => 'translatedOne',
'two' => 'translatedTwo',
'three' => 'translatedThree',
];
/**
* Created terms.
*
* @var \Drupal\taxonomy\Entity\Term[]
*/
protected $terms = [];
/**
* {@inheritdoc}
*/
public static $modules = ['taxonomy', 'language', 'content_translation'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->setupLanguages();
$this->vocabulary = $this->createVocabulary();
$this->enableTranslation();
$this->setUpTerms();
$this->setUpTermReferenceField();
}
/**
* Test translated breadcrumbs.
*/
public function testTranslatedBreadcrumbs() {
// Ensure non-translated breadcrumb is correct.
$breadcrumb = [Url::fromRoute('<front>')->toString() => 'Home'];
foreach ($this->terms as $term) {
$breadcrumb[$term->url()] = $term->label();
}
// The last item will not be in the breadcrumb.
array_pop($breadcrumb);
// Check the breadcrumb on the leaf term page.
$term = $this->getLeafTerm();
$this->assertBreadcrumb($term->urlInfo(), $breadcrumb, $term->label());
$languages = \Drupal::languageManager()->getLanguages();
// Construct the expected translated breadcrumb.
$breadcrumb = [Url::fromRoute('<front>', [], ['language' => $languages[$this->translateToLangcode]])->toString() => 'Home'];
foreach ($this->terms as $term) {
$translated = $term->getTranslation($this->translateToLangcode);
$url = $translated->url('canonical', ['language' => $languages[$this->translateToLangcode]]);
$breadcrumb[$url] = $translated->label();
}
array_pop($breadcrumb);
// Check for the translated breadcrumb on the translated leaf term page.
$term = $this->getLeafTerm();
$translated = $term->getTranslation($this->translateToLangcode);
$this->assertBreadcrumb($translated->urlInfo('canonical', ['language' => $languages[$this->translateToLangcode]]), $breadcrumb, $translated->label());
}
/**
* Test translation of terms are showed in the node.
*/
public function testTermsTranslation() {
// Set the display of the term reference field on the article content type
// to "Check boxes/radio buttons".
entity_get_form_display('node', 'article', 'default')
->setComponent($this->termFieldName, [
'type' => 'options_buttons',
])
->save();
$this->drupalLogin($this->drupalCreateUser(['create article content']));
// Test terms are listed.
$this->drupalget('node/add/article');
$this->assertText('one');
$this->assertText('two');
$this->assertText('three');
// Test terms translated are listed.
$this->drupalget('hu/node/add/article');
$this->assertText('translatedOne');
$this->assertText('translatedTwo');
$this->assertText('translatedThree');
}
/**
* Setup translated terms in a hierarchy.
*/
protected function setUpTerms() {
$parent_vid = 0;
foreach ($this->termTranslationMap as $name => $translation) {
$term = $this->createTerm($this->vocabulary, [
'name' => $name,
'langcode' => $this->baseLangcode,
'parent' => $parent_vid,
]);
$term->addTranslation($this->translateToLangcode, [
'name' => $translation,
]);
$term->save();
// Each term is nested under the last.
$parent_vid = $term->id();
$this->terms[] = $term;
}
}
/**
* Get the final (leaf) term in the hierarchy.
*
* @return \Drupal\taxonomy\Entity\Term
* The final term in the hierarchy.
*/
protected function getLeafTerm() {
return $this->terms[count($this->termTranslationMap) - 1];
}
}
@@ -2,7 +2,7 @@
namespace Drupal\Tests\taxonomy\Functional\Views;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
use Drupal\taxonomy\Entity\Term;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\Tests\views_ui\Functional\UITestBase;
@@ -4,7 +4,7 @@ namespace Drupal\Tests\taxonomy\Functional\Views;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
use Drupal\Tests\views\Functional\ViewTestBase;
use Drupal\views\Tests\ViewTestData;
use Drupal\taxonomy\Entity\Vocabulary;
@@ -39,19 +39,21 @@ class MigrateVocabularyFieldInstanceTest extends MigrateDrupal6TestBase {
public function testVocabularyFieldInstance() {
$this->executeMigration('d6_vocabulary_field_instance');
// Test that the field exists.
// Test that the field exists. Tags has a multilingual option of 'None'.
$field_id = 'node.article.field_tags';
$field = FieldConfig::load($field_id);
$this->assertSame($field_id, $field->id(), 'Field instance exists on article bundle.');
$this->assertSame('Tags', $field->label());
$this->assertTrue($field->isRequired(), 'Field is required');
$this->assertFalse($field->isTranslatable());
// Test the page bundle as well.
// Test the page bundle as well. Tags has a multilingual option of 'None'.
$field_id = 'node.page.field_tags';
$field = FieldConfig::load($field_id);
$this->assertSame($field_id, $field->id(), 'Field instance exists on page bundle.');
$this->assertSame('Tags', $field->label());
$this->assertTrue($field->isRequired(), 'Field is required');
$this->assertFalse($field->isTranslatable());
$settings = $field->getSettings();
$this->assertSame('default:taxonomy_term', $settings['handler'], 'The handler plugin ID is correct.');
@@ -60,15 +62,32 @@ class MigrateVocabularyFieldInstanceTest extends MigrateDrupal6TestBase {
$this->assertSame(['node', 'article', 'field_tags'], $this->getMigration('d6_vocabulary_field_instance')->getIdMap()->lookupDestinationId([4, 'article']));
// Test the the field vocabulary_1_i_0_.
// Test the the field vocabulary_1_i_0_ with multilingual option,
// 'per language terms'.
$field_id = 'node.story.field_vocabulary_1_i_0_';
$field = FieldConfig::load($field_id);
$this->assertFalse($field->isRequired(), 'Field is not required');
$this->assertTrue($field->isTranslatable());
// Test the the field vocabulary_2_i_0_ with multilingual option,
// 'Set language to vocabulary'.
$field_id = 'node.story.field_vocabulary_2_i_1_';
$field = FieldConfig::load($field_id);
$this->assertFalse($field->isRequired(), 'Field is not required');
$this->assertFalse($field->isTranslatable());
// Test the the field vocabulary_3_i_0_ with multilingual option,
// 'Localize terms'.
$field_id = 'node.story.field_vocabulary_3_i_2_';
$field = FieldConfig::load($field_id);
$this->assertFalse($field->isRequired(), 'Field is not required');
$this->assertFalse($field->isTranslatable());
// Tests that a vocabulary named like a D8 base field will be migrated and
// prefixed with 'field_' to avoid conflicts.
$field_type = FieldConfig::load('node.sponsor.field_type');
$this->assertInstanceOf(FieldConfig::class, $field_type);
$this->assertFalse($field->isTranslatable());
}
/**
@@ -15,11 +15,15 @@ class MigrateTaxonomyTermTest extends MigrateDrupal7TestBase {
public static $modules = [
'comment',
'content_translation',
'datetime',
'forum',
'image',
'language',
'link',
'menu_ui',
// Required for translation migrations.
'migrate_drupal_multilingual',
'node',
'taxonomy',
'telephone',
@@ -38,16 +42,23 @@ class MigrateTaxonomyTermTest extends MigrateDrupal7TestBase {
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('comment');
$this->installEntitySchema('node');
$this->installEntitySchema('taxonomy_term');
$this->installConfig(static::$modules);
$this->executeMigrations([
'language',
'd7_user_role',
'd7_user',
'd7_node_type',
'd7_comment_type',
'd7_field',
'd7_taxonomy_vocabulary',
'd7_field_instance',
'd7_taxonomy_term',
'd7_entity_translation_settings',
'd7_taxonomy_term_entity_translation',
]);
}
@@ -110,7 +121,7 @@ class MigrateTaxonomyTermTest extends MigrateDrupal7TestBase {
$this->assertEntity(2, 'Term1 (This is a real field!)', 'test_vocabulary', 'The first term. (This is a real field!)', 'filtered_html', 0, [], NULL, 3);
$this->assertEntity(3, 'Term2', 'test_vocabulary', 'The second term.', 'filtered_html');
$this->assertEntity(4, 'Term3', 'test_vocabulary', 'The third term.', 'full_html', 0, [3], 6);
$this->assertEntity(4, 'Term3 in plain old English', 'test_vocabulary', 'The third term in plain old English.', 'full_html', 0, [3], 6);
$this->assertEntity(5, 'Custom Forum', 'forums', 'Where the cool kids are.', NULL, 3);
$this->assertEntity(6, 'Games', 'forums', '', NULL, 4, [], NULL, NULL, 1);
$this->assertEntity(7, 'Minecraft', 'forums', '', NULL, 1, [6]);
@@ -142,7 +153,7 @@ class MigrateTaxonomyTermTest extends MigrateDrupal7TestBase {
* Assert that a term is present in the tree storage, with the right parents.
*
* @param string $vid
* Vocabular ID.
* Vocabulary ID.
* @param int $tid
* ID of the term to check.
* @param array $parent_ids
@@ -162,4 +173,56 @@ class MigrateTaxonomyTermTest extends MigrateDrupal7TestBase {
$this->assertEquals($parent_ids, array_filter($term->parents), "Term $tid has correct parents in taxonomy tree");
}
/**
* Tests the migration of taxonomy term entity translations.
*/
public function testTaxonomyTermEntityTranslations() {
$manager = $this->container->get('content_translation.manager');
// Get the term and its translations.
$term = Term::load(4);
$term_fr = $term->getTranslation('fr');
$term_is = $term->getTranslation('is');
// Test that fields translated with Entity Translation are migrated.
$this->assertSame('Term3 in plain old English', $term->getName());
$this->assertSame('Term3 en français s\'il vous plaît', $term_fr->getName());
$this->assertSame('Term3 á íslensku', $term_is->getName());
$this->assertSame('The third term in plain old English.', $term->getDescription());
$this->assertSame('The third term en français s\'il vous plaît.', $term_fr->getDescription());
$this->assertSame('The third term á íslensku.', $term_is->getDescription());
$this->assertSame('full_html', $term->getFormat());
$this->assertSame('filtered_html', $term_fr->getFormat());
$this->assertSame('plain_text', $term_is->getFormat());
$this->assertSame('6', $term->field_integer->value);
$this->assertSame('5', $term_fr->field_integer->value);
$this->assertSame('4', $term_is->field_integer->value);
// Test that the French translation metadata is correctly migrated.
$metadata_fr = $manager->getTranslationMetadata($term_fr);
$this->assertTrue($metadata_fr->isPublished());
$this->assertSame('en', $metadata_fr->getSource());
$this->assertSame('2', $metadata_fr->getAuthor()->uid->value);
$this->assertSame('1531922267', $metadata_fr->getCreatedTime());
$this->assertSame('1531922268', $metadata_fr->getChangedTime());
$this->assertTrue($metadata_fr->isOutdated());
// Test that the Icelandic translation metadata is correctly migrated.
$metadata_is = $manager->getTranslationMetadata($term_is);
$this->assertFalse($metadata_is->isPublished());
$this->assertSame('en', $metadata_is->getSource());
$this->assertSame('1', $metadata_is->getAuthor()->uid->value);
$this->assertSame('1531922278', $metadata_is->getCreatedTime());
$this->assertSame('1531922279', $metadata_is->getChangedTime());
$this->assertFalse($metadata_is->isOutdated());
// Test that untranslatable properties are the same as the source language.
$this->assertSame($term->bundle(), $term_fr->bundle());
$this->assertSame($term->bundle(), $term_is->bundle());
$this->assertSame($term->getWeight(), $term_fr->getWeight());
$this->assertSame($term->getWeight(), $term_is->getWeight());
$this->assertSame($term->parent->terget_id, $term_fr->parent->terget_id);
$this->assertSame($term->parent->terget_id, $term_is->parent->terget_id);
}
}
@@ -0,0 +1,334 @@
<?php
namespace Drupal\Tests\taxonomy\Kernel\Plugin\migrate\source\d7;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests taxonomy term entity translation source plugin.
*
* @covers \Drupal\taxonomy\Plugin\migrate\source\d7\TermEntityTranslation
* @group taxonomy
*/
class TermEntityTranslationTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['taxonomy', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [];
// The source data.
$tests[0]['source_data']['entity_translation'] = [
[
'entity_type' => 'taxonomy_term',
'entity_id' => 1,
'revision_id' => 1,
'language' => 'en',
'source' => '',
'uid' => 1,
'status' => 1,
'translate' => 0,
'created' => 1531343498,
'changed' => 1531343498,
],
[
'entity_type' => 'taxonomy_term',
'entity_id' => 1,
'revision_id' => 1,
'language' => 'fr',
'source' => 'en',
'uid' => 2,
'status' => 1,
'translate' => 1,
'created' => 1531343508,
'changed' => 1531343508,
],
[
'entity_type' => 'taxonomy_term',
'entity_id' => 1,
'revision_id' => 1,
'language' => 'es',
'source' => 'en',
'uid' => 1,
'status' => 0,
'translate' => 0,
'created' => 1531343528,
'changed' => 1531343528,
],
];
$tests[0]['source_data']['field_config'] = [
[
'id' => 1,
'field_name' => 'field_test',
'type' => 'text',
'module' => 'text',
'active' => 1,
'storage_type' => 'field_sql_storage',
'storage_module' => 'field_sql_storage',
'storage_active' => 1,
'locked' => 1,
'data' => 'a:0:{}',
'cardinality' => 1,
'translatable' => 1,
'deleted' => 0,
],
[
'id' => 2,
'field_name' => 'name_field',
'type' => 'text',
'module' => 'text',
'active' => 1,
'storage_type' => 'field_sql_storage',
'storage_module' => 'field_sql_storage',
'storage_active' => 1,
'locked' => 1,
'data' => 'a:0:{}',
'cardinality' => 1,
'translatable' => 1,
'deleted' => 0,
],
[
'id' => 3,
'field_name' => 'description_field',
'type' => 'text',
'module' => 'text',
'active' => 1,
'storage_type' => 'field_sql_storage',
'storage_module' => 'field_sql_storage',
'storage_active' => 1,
'locked' => 1,
'data' => 'a:0:{}',
'cardinality' => 1,
'translatable' => 1,
'deleted' => 0,
],
];
$tests[0]['source_data']['field_config_instance'] = [
[
'id' => '1',
'field_id' => 1,
'field_name' => 'field_test',
'entity_type' => 'taxonomy_term',
'bundle' => 'tags',
'data' => 'a:0:{}',
'deleted' => 0,
],
[
'id' => 2,
'field_id' => 2,
'field_name' => 'name_field',
'entity_type' => 'taxonomy_term',
'bundle' => 'tags',
'data' => 'a:0:{}',
'deleted' => 0,
],
[
'id' => 3,
'field_id' => 3,
'field_name' => 'description_field',
'entity_type' => 'taxonomy_term',
'bundle' => 'tags',
'data' => 'a:0:{}',
'deleted' => 0,
],
];
$tests[0]['source_data']['field_data_field_test'] = [
[
'entity_type' => 'taxonomy_term',
'bundle' => 'tags',
'deleted' => 0,
'entity_id' => 1,
'revision_id' => 1,
'language' => 'en',
'delta' => 0,
'field_test_value' => 'English field',
'field_test_format' => 'filtered_html',
],
[
'entity_type' => 'taxonomy_term',
'bundle' => 'tags',
'deleted' => 0,
'entity_id' => 1,
'revision_id' => 1,
'language' => 'fr',
'delta' => 0,
'field_test_value' => 'French field',
'field_test_format' => 'filtered_html',
],
[
'entity_type' => 'taxonomy_term',
'bundle' => 'tags',
'deleted' => 0,
'entity_id' => 1,
'revision_id' => 1,
'language' => 'es',
'delta' => 0,
'field_test_value' => 'Spanish field',
'field_test_format' => 'filtered_html',
],
];
$tests[0]['source_data']['field_data_name_field'] = [
[
'entity_type' => 'taxonomy_term',
'bundle' => 'tags',
'deleted' => '0',
'entity_id' => '1',
'revision_id' => '1',
'language' => 'en',
'delta' => '0',
'name_field_value' => 'Term Name EN',
'name_field_format' => NULL,
],
[
'entity_type' => 'taxonomy_term',
'bundle' => 'tags',
'deleted' => '0',
'entity_id' => '1',
'revision_id' => '1',
'language' => 'fr',
'delta' => '0',
'name_field_value' => 'Term Name FR',
'name_field_format' => NULL,
],
[
'entity_type' => 'taxonomy_term',
'bundle' => 'tags',
'deleted' => '0',
'entity_id' => '1',
'revision_id' => '1',
'language' => 'es',
'delta' => '0',
'name_field_value' => 'Term Name ES',
'name_field_format' => NULL,
],
];
$tests[0]['source_data']['field_data_description_field'] = [
[
'entity_type' => 'taxonomy_term',
'bundle' => 'tags',
'deleted' => '0',
'entity_id' => '1',
'revision_id' => '1',
'language' => 'en',
'delta' => '0',
'description_field_value' => 'Term Description EN',
'description_field_format' => 'full_html',
],
[
'entity_type' => 'taxonomy_term',
'bundle' => 'tags',
'deleted' => '0',
'entity_id' => '1',
'revision_id' => '1',
'language' => 'fr',
'delta' => '0',
'description_field_value' => 'Term Description FR',
'description_field_format' => 'full_html',
],
[
'entity_type' => 'taxonomy_term',
'bundle' => 'tags',
'deleted' => '0',
'entity_id' => '1',
'revision_id' => '1',
'language' => 'es',
'delta' => '0',
'description_field_value' => 'Term Description ES',
'description_field_format' => 'full_html',
],
];
$tests[0]['source_data']['system'] = [
[
'name' => 'title',
'type' => 'module',
'status' => 1,
],
];
$tests[0]['source_data']['taxonomy_term_data'] = [
[
'tid' => 1,
'vid' => 1,
'name' => 'Term Name',
'description' => 'Term Description',
'format' => 'filtered_html',
'weight' => 0,
],
];
$tests[0]['source_data']['taxonomy_term_hierarchy'] = [
[
'tid' => 1,
'parent' => 0,
],
];
$tests[0]['source_data']['taxonomy_vocabulary'] = [
[
'vid' => 1,
'name' => 'Tags',
'machine_name' => 'tags',
'description' => '',
'hierarchy' => 0,
'module' => 'taxonomy',
'weight' => 0,
],
];
// The expected results.
$tests[0]['expected_data'] = [
[
'entity_type' => 'taxonomy_term',
'entity_id' => 1,
'revision_id' => 1,
'language' => 'fr',
'source' => 'en',
'uid' => 2,
'status' => 1,
'translate' => 1,
'created' => 1531343508,
'changed' => 1531343508,
'name' => 'Term Name FR',
'description' => 'Term Description FR',
'format' => 'full_html',
'machine_name' => 'tags',
'is_container' => FALSE,
'field_test' => [
[
'value' => 'French field',
'format' => 'filtered_html',
],
],
],
[
'entity_type' => 'taxonomy_term',
'entity_id' => 1,
'revision_id' => 1,
'language' => 'es',
'source' => 'en',
'uid' => 1,
'status' => 0,
'translate' => 0,
'created' => 1531343528,
'changed' => 1531343528,
'name' => 'Term Name ES',
'description' => 'Term Description ES',
'format' => 'full_html',
'machine_name' => 'tags',
'is_container' => FALSE,
'field_test' => [
[
'value' => 'Spanish field',
'format' => 'filtered_html',
],
],
],
];
return $tests;
}
}
@@ -254,6 +254,10 @@ class TermTest extends MigrateSqlSourceTestBase {
'name' => 'forum_containers',
'value' => 'a:3:{i:0;s:1:"5";i:1;s:1:"6";i:2;s:1:"7";}',
],
[
'name' => 'language_default',
'value' => 'O:8:"stdClass":1:{s:8:"language";s:2:"en";}',
],
];
// The expected results.
@@ -265,6 +269,7 @@ class TermTest extends MigrateSqlSourceTestBase {
'description' => 'description value 1 (description_field)',
'weight' => 0,
'parent' => [0],
'language' => 'en',
],
[
'tid' => 2,
@@ -273,6 +278,7 @@ class TermTest extends MigrateSqlSourceTestBase {
'description' => 'description value 2',
'weight' => 0,
'parent' => [0],
'language' => 'en',
],
[
'tid' => 3,
@@ -281,6 +287,7 @@ class TermTest extends MigrateSqlSourceTestBase {
'description' => 'description value 3',
'weight' => 0,
'parent' => [0],
'language' => 'en',
],
[
'tid' => 4,
@@ -289,6 +296,7 @@ class TermTest extends MigrateSqlSourceTestBase {
'description' => 'description value 4 (description_field)',
'weight' => 1,
'parent' => [1],
'language' => 'en',
],
[
'tid' => 5,
@@ -297,6 +305,7 @@ class TermTest extends MigrateSqlSourceTestBase {
'description' => 'description value 5',
'weight' => 1,
'parent' => [2],
'language' => 'en',
],
[
'tid' => 6,
@@ -305,6 +314,7 @@ class TermTest extends MigrateSqlSourceTestBase {
'description' => 'description value 6',
'weight' => 0,
'parent' => [3, 2],
'language' => 'en',
],
[
'tid' => 7,
@@ -313,6 +323,7 @@ class TermTest extends MigrateSqlSourceTestBase {
'description' => 'description value 7',
'weight' => 0,
'parent' => [0],
'language' => 'en',
],
];
@@ -330,6 +341,7 @@ class TermTest extends MigrateSqlSourceTestBase {
'description' => 'description value 1 (description_field)',
'weight' => 0,
'parent' => [0],
'language' => 'en',
],
[
'tid' => 4,
@@ -338,6 +350,7 @@ class TermTest extends MigrateSqlSourceTestBase {
'description' => 'description value 4 (description_field)',
'weight' => 1,
'parent' => [1],
'language' => 'en',
],
];
$tests[1]['expected_count'] = NULL;
@@ -4,7 +4,7 @@ namespace Drupal\Tests\taxonomy\Kernel\Views;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
use Drupal\Tests\node\Traits\NodeCreationTrait;
use Drupal\Tests\views\Kernel\ViewsKernelTestBase;