updated core and modules

This commit is contained in:
Bachir Soussi Chiadmi
2017-09-09 16:27:51 +02:00
parent 027aa99b32
commit 41863f872c
7810 changed files with 318922 additions and 83631 deletions
@@ -182,7 +182,7 @@ display:
group_type: group
admin_label: ''
operator: '='
value: true
value: '1'
group: 1
exposed: false
expose:
@@ -3,11 +3,13 @@ label: Taxonomy terms
migration_tags:
- Drupal 6
source:
plugin: taxonomy_term
plugin: d6_taxonomy_term
process:
# If you are using this file to build a custom migration consider removing
# the tid field to allow incremental migrations.
tid: tid
vid:
plugin: migration
plugin: migration_lookup
migration: d6_taxonomy_vocabulary
source: vid
name: name
@@ -20,7 +22,7 @@ process:
method: process
source: parent
-
plugin: migration
plugin: migration_lookup
migration: d6_taxonomy_term
parent:
plugin: default_value
@@ -0,0 +1,39 @@
id: d6_taxonomy_term_translation
label: Taxonomy terms
migration_tags:
- Drupal 6
source:
plugin: d6_taxonomy_term
translations: true
process:
# If you are using this file to build a custom migration consider removing
# the tid field to allow incremental migrations.
tid: tid
langcode: language
vid:
plugin: migration
migration: d6_taxonomy_vocabulary
source: vid
name: name
description: description
weight: weight
# Only attempt to stub real (non-zero) parents.
parent_id:
-
plugin: skip_on_empty
method: process
source: parent
-
plugin: migration
migration: d6_taxonomy_term
parent:
plugin: default_value
default_value: 0
source: '@parent_id'
changed: timestamp
destination:
plugin: entity:taxonomy_term
migration_dependencies:
required:
- d6_taxonomy_vocabulary
- d6_taxonomy_term
@@ -10,10 +10,11 @@ process:
plugin: machine_name
source: name
-
plugin: dedupe_entity
plugin: make_unique_entity_field
entity_type: taxonomy_vocabulary
field: vid
length: 32
migrated: true
label: name
name: name
description: description
@@ -0,0 +1,27 @@
id: d6_taxonomy_vocabulary_translation
label: Taxonomy vocabularies
migration_tags:
- Drupal 6
source:
plugin: d6_taxonomy_vocabulary_translation
process:
vid:
-
plugin: machine_name
source: name
-
plugin: substr
length: 32
langcode: language
property:
plugin: static_map
source: property
map:
name: name
description: description
translation: translation
destination:
plugin: entity:taxonomy_vocabulary
migration_dependencies:
required:
- d6_taxonomy_vocabulary
@@ -8,7 +8,7 @@ source:
process:
nid:
-
plugin: migration
plugin: migration_lookup
migration: d6_node
source: nid
-
@@ -8,7 +8,7 @@ source:
process:
vid:
-
plugin: migration
plugin: migration_lookup
migration: d6_node
source: vid
-
@@ -15,9 +15,16 @@ process:
entity_type: 'constants/entity_type'
view_mode: 'constants/view_mode'
options: 'constants/options'
bundle: type
bundle:
-
plugin: migration_lookup
migration: d6_node_type
source: type
-
plugin: skip_on_empty
method: row
field_name:
plugin: migration
plugin: migration_lookup
migration: d6_taxonomy_vocabulary
source: vid
destination:
@@ -19,9 +19,16 @@ process:
0: options_select
1: entity_reference_autocomplete_tags
options/weight: 'constants/options/weight'
bundle: type
bundle:
-
plugin: migration_lookup
migration: d6_node_type
source: type
-
plugin: skip_on_empty
method: row
field_name:
plugin: migration
plugin: migration_lookup
migration: d6_taxonomy_vocabulary
source: vid
destination:
@@ -13,7 +13,7 @@ process:
type: 'constants/type'
field_name:
-
plugin: migration
plugin: migration_lookup
migration: d6_taxonomy_vocabulary
source: vid
-
@@ -22,7 +22,10 @@ process:
'settings/target_type': 'constants/target_entity_type'
cardinality: cardinality
destination:
plugin: md_entity:field_storage_config
plugin: entity:field_storage_config
dependencies:
module:
- entity_reference
migration_dependencies:
required:
- d6_taxonomy_vocabulary
@@ -10,10 +10,17 @@ source:
selection_handler: 'default:taxonomy_term'
process:
entity_type: 'constants/entity_type'
bundle: type
bundle:
-
plugin: migration_lookup
migration: d6_node_type
source: type
-
plugin: skip_on_empty
method: row
field_name:
-
plugin: migration
plugin: migration_lookup
migration: d6_taxonomy_vocabulary
source: vid
-
@@ -2,12 +2,15 @@ id: d7_taxonomy_term
label: Taxonomy terms
migration_tags:
- Drupal 7
deriver: Drupal\taxonomy\Plugin\migrate\D7TaxonomyTermDeriver
source:
plugin: taxonomy_term
plugin: d7_taxonomy_term
process:
# If you are using this file to build a custom migration consider removing
# the tid field to allow incremental migrations.
tid: tid
vid:
plugin: migration
plugin: migration_lookup
migration: d7_taxonomy_vocabulary
source: vid
name: name
@@ -21,7 +24,7 @@ process:
method: process
source: parent
-
plugin: migration
plugin: migration_lookup
migration: d7_taxonomy_term
parent:
plugin: default_value
@@ -33,3 +36,5 @@ destination:
migration_dependencies:
required:
- d7_taxonomy_vocabulary
optional:
- d7_field_instance
@@ -5,7 +5,16 @@ migration_tags:
source:
plugin: d7_taxonomy_vocabulary
process:
vid: machine_name
vid:
-
plugin: machine_name
source: name
-
plugin: make_unique_entity_field
entity_type: taxonomy_vocabulary
field: vid
length: 32
migrated: true
label: name
name: name
description: description
@@ -22,7 +22,7 @@ class TaxonomyController extends ControllerBase {
* The taxonomy term add form.
*/
public function addForm(VocabularyInterface $taxonomy_vocabulary) {
$term = $this->entityManager()->getStorage('taxonomy_term')->create(array('vid' => $taxonomy_vocabulary->id()));
$term = $this->entityManager()->getStorage('taxonomy_term')->create(['vid' => $taxonomy_vocabulary->id()]);
return $this->entityFormBuilder()->getForm($term);
}
+34 -38
View File
@@ -61,14 +61,14 @@ class Term extends ContentEntityBase implements TermInterface {
parent::postDelete($storage, $entities);
// See if any of the term's children are about to be become orphans.
$orphans = array();
$orphans = [];
foreach (array_keys($entities) as $tid) {
if ($children = $storage->loadChildren($tid)) {
foreach ($children as $child) {
// If the term has multiple parents, we don't delete it.
$parents = $storage->loadParents($child->id());
if (empty($parents)) {
$orphans[] = $child->id();
$orphans[] = $child;
}
}
}
@@ -79,7 +79,7 @@ class Term extends ContentEntityBase implements TermInterface {
$storage->deleteTermHierarchy(array_keys($entities));
if (!empty($orphans)) {
entity_delete_multiple('taxonomy_term', $orphans);
$storage->delete($orphans);
}
}
@@ -92,7 +92,7 @@ class Term extends ContentEntityBase implements TermInterface {
// Only change the parents if a value is set, keep the existing values if
// not.
if (isset($this->parent->target_id)) {
$storage->deleteTermHierarchy(array($this->id()));
$storage->deleteTermHierarchy([$this->id()]);
$storage->updateTermHierarchy($this);
}
}
@@ -101,65 +101,48 @@ class Term extends ContentEntityBase implements TermInterface {
* {@inheritdoc}
*/
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields['tid'] = BaseFieldDefinition::create('integer')
->setLabel(t('Term ID'))
->setDescription(t('The term ID.'))
->setReadOnly(TRUE)
->setSetting('unsigned', TRUE);
/** @var \Drupal\Core\Field\BaseFieldDefinition[] $fields */
$fields = parent::baseFieldDefinitions($entity_type);
$fields['uuid'] = BaseFieldDefinition::create('uuid')
->setLabel(t('UUID'))
->setDescription(t('The term UUID.'))
->setReadOnly(TRUE);
$fields['tid']->setLabel(t('Term ID'))
->setDescription(t('The term ID.'));
$fields['vid'] = BaseFieldDefinition::create('entity_reference')
->setLabel(t('Vocabulary'))
->setDescription(t('The vocabulary to which the term is assigned.'))
->setSetting('target_type', 'taxonomy_vocabulary');
$fields['uuid']->setDescription(t('The term UUID.'));
$fields['langcode'] = BaseFieldDefinition::create('language')
->setLabel(t('Language'))
->setDescription(t('The term language code.'))
->setTranslatable(TRUE)
->setDisplayOptions('view', array(
'type' => 'hidden',
))
->setDisplayOptions('form', array(
'type' => 'language_select',
'weight' => 2,
));
$fields['vid']->setLabel(t('Vocabulary'))
->setDescription(t('The vocabulary to which the term is assigned.'));
$fields['langcode']->setDescription(t('The term language code.'));
$fields['name'] = BaseFieldDefinition::create('string')
->setLabel(t('Name'))
->setDescription(t('The term name.'))
->setTranslatable(TRUE)
->setRequired(TRUE)
->setSetting('max_length', 255)
->setDisplayOptions('view', array(
->setDisplayOptions('view', [
'label' => 'hidden',
'type' => 'string',
'weight' => -5,
))
->setDisplayOptions('form', array(
])
->setDisplayOptions('form', [
'type' => 'string_textfield',
'weight' => -5,
))
])
->setDisplayConfigurable('form', TRUE);
$fields['description'] = BaseFieldDefinition::create('text_long')
->setLabel(t('Description'))
->setDescription(t('A description of the term.'))
->setTranslatable(TRUE)
->setDisplayOptions('view', array(
->setDisplayOptions('view', [
'label' => 'hidden',
'type' => 'text_default',
'weight' => 0,
))
])
->setDisplayConfigurable('view', TRUE)
->setDisplayOptions('form', array(
->setDisplayOptions('form', [
'type' => 'text_textfield',
'weight' => 0,
))
])
->setDisplayConfigurable('form', TRUE);
$fields['weight'] = BaseFieldDefinition::create('integer')
@@ -249,4 +232,17 @@ class Term extends ContentEntityBase implements TermInterface {
return $this->get('vid')->target_id;
}
/**
* {@inheritdoc}
*/
protected function getFieldsToSkipFromTranslationChangesCheck() {
// @todo the current implementation of the parent field makes it impossible
// for ::hasTranslationChanges() to correctly check the field for changes,
// so it is currently skipped from the comparision and has to be fixed by
// https://www.drupal.org/node/2843060.
$fields = parent::getFieldsToSkipFromTranslationChangesCheck();
$fields[] = 'parent';
return $fields;
}
}
@@ -73,13 +73,13 @@ class Vocabulary extends ConfigEntityBundleBase implements VocabularyInterface {
* The type of hierarchy allowed within the vocabulary.
*
* Possible values:
* - TAXONOMY_HIERARCHY_DISABLED: No parents.
* - TAXONOMY_HIERARCHY_SINGLE: Single parent.
* - TAXONOMY_HIERARCHY_MULTIPLE: Multiple parents.
* - VocabularyInterface::HIERARCHY_DISABLED: No parents.
* - VocabularyInterface::HIERARCHY_SINGLE: Single parent.
* - VocabularyInterface::HIERARCHY_MULTIPL: Multiple parents.
*
* @var int
*/
protected $hierarchy = TAXONOMY_HIERARCHY_DISABLED;
protected $hierarchy = VocabularyInterface::HIERARCHY_DISABLED;
/**
* The weight of this vocabulary in relation to other vocabularies.
@@ -140,13 +140,13 @@ class Vocabulary extends ConfigEntityBundleBase implements VocabularyInterface {
return;
}
$vocabularies = array();
$vocabularies = [];
foreach ($entities as $vocabulary) {
$vocabularies[$vocabulary->id()] = $vocabulary->id();
}
// Load all Taxonomy module fields and delete those which use only this
// vocabulary.
$field_storages = entity_load_multiple_by_properties('field_storage_config', array('module' => 'taxonomy'));
$field_storages = entity_load_multiple_by_properties('field_storage_config', ['module' => 'taxonomy']);
foreach ($field_storages as $field_storage) {
$modified_storage = FALSE;
// Term reference fields may reference terms from more than one
@@ -21,6 +21,13 @@ class OverviewTerms extends FormBase {
*/
protected $moduleHandler;
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
protected $entityManager;
/**
* The term storage handler.
*
@@ -38,6 +45,7 @@ class OverviewTerms extends FormBase {
*/
public function __construct(ModuleHandlerInterface $module_handler, EntityManagerInterface $entity_manager) {
$this->moduleHandler = $module_handler;
$this->entityManager = $entity_manager;
$this->storageController = $entity_manager->getStorage('taxonomy_term');
}
@@ -101,10 +109,10 @@ class OverviewTerms extends FormBase {
$forward_step = 0;
// An array of the terms to be displayed on this page.
$current_page = array();
$current_page = [];
$delta = 0;
$term_deltas = array();
$term_deltas = [];
$tree = $this->storageController->loadTree($taxonomy_vocabulary->id(), 0, NULL, TRUE);
$tree_index = 0;
do {
@@ -199,93 +207,94 @@ class OverviewTerms extends FormBase {
$destination = $this->getDestinationArray();
$row_position = 0;
// Build the actual form.
$form['terms'] = array(
$form['terms'] = [
'#type' => 'table',
'#header' => array($this->t('Name'), $this->t('Weight'), $this->t('Operations')),
'#empty' => $this->t('No terms available. <a href=":link">Add term</a>.', array(':link' => $this->url('entity.taxonomy_term.add_form', array('taxonomy_vocabulary' => $taxonomy_vocabulary->id())))),
'#attributes' => array(
'#header' => [$this->t('Name'), $this->t('Weight'), $this->t('Operations')],
'#empty' => $this->t('No terms available. <a href=":link">Add term</a>.', [':link' => $this->url('entity.taxonomy_term.add_form', ['taxonomy_vocabulary' => $taxonomy_vocabulary->id()])]),
'#attributes' => [
'id' => 'taxonomy',
),
);
],
];
foreach ($current_page as $key => $term) {
/** @var $term \Drupal\Core\Entity\EntityInterface */
$term = $this->entityManager->getTranslationFromContext($term);
$form['terms'][$key]['#term'] = $term;
$indentation = array();
$indentation = [];
if (isset($term->depth) && $term->depth > 0) {
$indentation = array(
$indentation = [
'#theme' => 'indentation',
'#size' => $term->depth,
);
];
}
$form['terms'][$key]['term'] = array(
$form['terms'][$key]['term'] = [
'#prefix' => !empty($indentation) ? drupal_render($indentation) : '',
'#type' => 'link',
'#title' => $term->getName(),
'#url' => $term->urlInfo(),
);
if ($taxonomy_vocabulary->getHierarchy() != TAXONOMY_HIERARCHY_MULTIPLE && count($tree) > 1) {
];
if ($taxonomy_vocabulary->getHierarchy() != VocabularyInterface::HIERARCHY_MULTIPLE && count($tree) > 1) {
$parent_fields = TRUE;
$form['terms'][$key]['term']['tid'] = array(
$form['terms'][$key]['term']['tid'] = [
'#type' => 'hidden',
'#value' => $term->id(),
'#attributes' => array(
'class' => array('term-id'),
),
);
$form['terms'][$key]['term']['parent'] = array(
'#attributes' => [
'class' => ['term-id'],
],
];
$form['terms'][$key]['term']['parent'] = [
'#type' => 'hidden',
// Yes, default_value on a hidden. It needs to be changeable by the
// javascript.
'#default_value' => $term->parents[0],
'#attributes' => array(
'class' => array('term-parent'),
),
);
$form['terms'][$key]['term']['depth'] = array(
'#attributes' => [
'class' => ['term-parent'],
],
];
$form['terms'][$key]['term']['depth'] = [
'#type' => 'hidden',
// Same as above, the depth is modified by javascript, so it's a
// default_value.
'#default_value' => $term->depth,
'#attributes' => array(
'class' => array('term-depth'),
),
);
'#attributes' => [
'class' => ['term-depth'],
],
];
}
$form['terms'][$key]['weight'] = array(
$form['terms'][$key]['weight'] = [
'#type' => 'weight',
'#delta' => $delta,
'#title' => $this->t('Weight for added term'),
'#title_display' => 'invisible',
'#default_value' => $term->getWeight(),
'#attributes' => array(
'class' => array('term-weight'),
),
);
$operations = array(
'edit' => array(
'#attributes' => [
'class' => ['term-weight'],
],
];
$operations = [
'edit' => [
'title' => $this->t('Edit'),
'query' => $destination,
'url' => $term->urlInfo('edit-form'),
),
'delete' => array(
],
'delete' => [
'title' => $this->t('Delete'),
'query' => $destination,
'url' => $term->urlInfo('delete-form'),
),
);
],
];
if ($this->moduleHandler->moduleExists('content_translation') && content_translation_translate_access($term)->isAllowed()) {
$operations['translate'] = array(
$operations['translate'] = [
'title' => $this->t('Translate'),
'query' => $destination,
'url' => $term->urlInfo('drupal:content-translation-overview'),
);
];
}
$form['terms'][$key]['operations'] = array(
$form['terms'][$key]['operations'] = [
'#type' => 'operations',
'#links' => $operations,
);
];
$form['terms'][$key]['#attributes']['class'] = array();
$form['terms'][$key]['#attributes']['class'] = [];
if ($parent_fields) {
$form['terms'][$key]['#attributes']['class'][] = 'draggable';
}
@@ -314,44 +323,44 @@ class OverviewTerms extends FormBase {
}
if ($parent_fields) {
$form['terms']['#tabledrag'][] = array(
$form['terms']['#tabledrag'][] = [
'action' => 'match',
'relationship' => 'parent',
'group' => 'term-parent',
'subgroup' => 'term-parent',
'source' => 'term-id',
'hidden' => FALSE,
);
$form['terms']['#tabledrag'][] = array(
];
$form['terms']['#tabledrag'][] = [
'action' => 'depth',
'relationship' => 'group',
'group' => 'term-depth',
'hidden' => FALSE,
);
];
$form['terms']['#attached']['library'][] = 'taxonomy/drupal.taxonomy';
$form['terms']['#attached']['drupalSettings']['taxonomy'] = [
'backStep' => $back_step,
'forwardStep' => $forward_step,
];
}
$form['terms']['#tabledrag'][] = array(
$form['terms']['#tabledrag'][] = [
'action' => 'order',
'relationship' => 'sibling',
'group' => 'term-weight',
);
];
if ($taxonomy_vocabulary->getHierarchy() != TAXONOMY_HIERARCHY_MULTIPLE && count($tree) > 1) {
$form['actions'] = array('#type' => 'actions', '#tree' => FALSE);
$form['actions']['submit'] = array(
if ($taxonomy_vocabulary->getHierarchy() != VocabularyInterface::HIERARCHY_MULTIPLE && count($tree) > 1) {
$form['actions'] = ['#type' => 'actions', '#tree' => FALSE];
$form['actions']['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Save'),
'#button_type' => 'primary',
);
$form['actions']['reset_alphabetical'] = array(
];
$form['actions']['reset_alphabetical'] = [
'#type' => 'submit',
'#submit' => array('::submitReset'),
'#submit' => ['::submitReset'],
'#value' => $this->t('Reset to alphabetical'),
);
];
}
$form['pager_pager'] = ['#type' => 'pager'];
@@ -378,13 +387,13 @@ class OverviewTerms extends FormBase {
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
// Sort term order based on weight.
uasort($form_state->getValue('terms'), array('Drupal\Component\Utility\SortArray', 'sortByWeightElement'));
uasort($form_state->getValue('terms'), ['Drupal\Component\Utility\SortArray', 'sortByWeightElement']);
$vocabulary = $form_state->get(['taxonomy', 'vocabulary']);
// Update the current hierarchy type as we go.
$hierarchy = TAXONOMY_HIERARCHY_DISABLED;
$hierarchy = VocabularyInterface::HIERARCHY_DISABLED;
$changed_terms = array();
$changed_terms = [];
$tree = $this->storageController->loadTree($vocabulary->id(), 0, NULL, TRUE);
if (empty($tree)) {
@@ -400,12 +409,12 @@ class OverviewTerms extends FormBase {
$changed_terms[$term->id()] = $term;
}
$weight++;
$hierarchy = $term->parents[0] != 0 ? TAXONOMY_HIERARCHY_SINGLE : $hierarchy;
$hierarchy = $term->parents[0] != 0 ? VocabularyInterface::HIERARCHY_SINGLE : $hierarchy;
$term = $tree[$weight];
}
// Renumber the current page weights and assign any new parents.
$level_weights = array();
$level_weights = [];
foreach ($form_state->getValue('terms') as $tid => $values) {
if (isset($form['terms'][$tid]['#term'])) {
$term = $form['terms'][$tid]['#term'];
@@ -427,7 +436,7 @@ class OverviewTerms extends FormBase {
$term->parent->target_id = $values['term']['parent'];
$changed_terms[$term->id()] = $term;
}
$hierarchy = $term->parents[0] != 0 ? TAXONOMY_HIERARCHY_SINGLE : $hierarchy;
$hierarchy = $term->parents[0] != 0 ? VocabularyInterface::HIERARCHY_SINGLE : $hierarchy;
$weight++;
}
}
@@ -440,7 +449,7 @@ class OverviewTerms extends FormBase {
$term->setWeight($weight);
$changed_terms[$term->id()] = $term;
}
$hierarchy = $term->parents[0] != 0 ? TAXONOMY_HIERARCHY_SINGLE : $hierarchy;
$hierarchy = $term->parents[0] != 0 ? VocabularyInterface::HIERARCHY_SINGLE : $hierarchy;
}
// Save all updated terms.
@@ -38,7 +38,7 @@ class TermDeleteForm extends ContentEntityDeleteForm {
* {@inheritdoc}
*/
protected function getDeletionMessage() {
return $this->t('Deleted term %name.', array('%name' => $this->entity->label()));
return $this->t('Deleted term %name.', ['%name' => $this->entity->label()]);
}
/**
@@ -54,7 +54,7 @@ class TermDeleteForm extends ContentEntityDeleteForm {
$vocabulary = $storage->load($this->entity->bundle());
// @todo Move to storage http://drupal.org/node/1988712
taxonomy_check_vocabulary_hierarchy($vocabulary, array('tid' => $term->id()));
taxonomy_check_vocabulary_hierarchy($vocabulary, ['tid' => $term->id()]);
}
}
@@ -20,7 +20,7 @@ class VocabularyDeleteForm extends EntityDeleteForm {
* {@inheritdoc}
*/
public function getQuestion() {
return $this->t('Are you sure you want to delete the vocabulary %title?', array('%title' => $this->entity->label()));
return $this->t('Are you sure you want to delete the vocabulary %title?', ['%title' => $this->entity->label()]);
}
/**
@@ -34,7 +34,7 @@ class VocabularyDeleteForm extends EntityDeleteForm {
* {@inheritdoc}
*/
protected function getDeletionMessage() {
return $this->t('Deleted vocabulary %name.', array('%name' => $this->entity->label()));
return $this->t('Deleted vocabulary %name.', ['%name' => $this->entity->label()]);
}
}
@@ -49,7 +49,7 @@ class VocabularyResetForm extends EntityConfirmFormBase {
* {@inheritdoc}
*/
public function getQuestion() {
return $this->t('Are you sure you want to reset the vocabulary %title to alphabetical order?', array('%title' => $this->entity->label()));
return $this->t('Are you sure you want to reset the vocabulary %title to alphabetical order?', ['%title' => $this->entity->label()]);
}
/**
@@ -80,8 +80,8 @@ class VocabularyResetForm extends EntityConfirmFormBase {
parent::submitForm($form, $form_state);
$this->termStorage->resetWeights($this->entity->id());
drupal_set_message($this->t('Reset vocabulary %name to alphabetical order.', array('%name' => $this->entity->label())));
$this->logger('taxonomy')->notice('Reset vocabulary %name to alphabetical order.', array('%name' => $this->entity->label()));
drupal_set_message($this->t('Reset vocabulary %name to alphabetical order.', ['%name' => $this->entity->label()]));
$this->logger('taxonomy')->notice('Reset vocabulary %name to alphabetical order.', ['%name' => $this->entity->label()]);
$form_state->setRedirectUrl($this->getCancelUrl());
}
@@ -49,10 +49,11 @@ class TermSelection extends DefaultSelection {
*/
public function getReferenceableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
if ($match || $limit) {
$this->configuration['handler_settings']['sort'] = ['field' => 'name', 'direction' => 'asc'];
return parent::getReferenceableEntities($match, $match_operator, $limit);
}
$options = array();
$options = [];
$bundles = $this->entityManager->getBundleInfo('taxonomy_term');
$handler_settings = $this->configuration['handler_settings'];
@@ -25,16 +25,16 @@ class EntityReferenceTaxonomyTermRssFormatter extends EntityReferenceFormatterBa
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$parent_entity = $items->getEntity();
$elements = array();
$elements = [];
foreach ($this->getEntitiesToView($items, $langcode) as $delta => $entity) {
$parent_entity->rss_elements[] = array(
$parent_entity->rss_elements[] = [
'key' => 'category',
'value' => $entity->label(),
'attributes' => array(
'domain' => $entity->id() ? \Drupal::url('entity.taxonomy_term.canonical', ['taxonomy_term' => $entity->id()], array('absolute' => TRUE)) : '',
),
);
'attributes' => [
'domain' => $entity->id() ? \Drupal::url('entity.taxonomy_term.canonical', ['taxonomy_term' => $entity->id()], ['absolute' => TRUE]) : '',
],
];
}
return $elements;
@@ -0,0 +1,170 @@
<?php
namespace Drupal\taxonomy\Plugin\migrate;
use Drupal\Component\Plugin\Derivative\DeriverBase;
use Drupal\Component\Plugin\Exception\PluginNotFoundException;
use Drupal\Core\Database\DatabaseExceptionWrapper;
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
use Drupal\migrate\Exception\RequirementsException;
use Drupal\migrate\Plugin\MigrationDeriverTrait;
use Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface;
use Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Deriver for Drupal 7 taxonomy term migrations based on vocabularies.
*/
class D7TaxonomyTermDeriver extends DeriverBase implements ContainerDeriverInterface {
use MigrationDeriverTrait;
/**
* The base plugin ID this derivative is for.
*
* @var string
*/
protected $basePluginId;
/**
* Already-instantiated cckfield plugins, keyed by ID.
*
* @var \Drupal\migrate_drupal\Plugin\MigrateCckFieldInterface[]
*/
protected $cckPluginCache;
/**
* The CCK plugin manager.
*
* @var \Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface
*/
protected $cckPluginManager;
/**
* Already-instantiated field plugins, keyed by ID.
*
* @var \Drupal\migrate_drupal\Plugin\MigrateFieldInterface[]
*/
protected $fieldPluginCache;
/**
* The field plugin manager.
*
* @var \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface
*/
protected $fieldPluginManager;
/**
* D7TaxonomyTermDeriver constructor.
*
* @param string $base_plugin_id
* The base plugin ID for the plugin ID.
* @param \Drupal\migrate_drupal\Plugin\MigrateCckFieldPluginManagerInterface $cck_manager
* The CCK plugin manager.
* @param \Drupal\migrate_drupal\Plugin\MigrateFieldPluginManagerInterface $field_manager
* The field plugin manager.
*/
public function __construct($base_plugin_id, MigrateCckFieldPluginManagerInterface $cck_manager, MigrateFieldPluginManagerInterface $field_manager) {
$this->basePluginId = $base_plugin_id;
$this->cckPluginManager = $cck_manager;
$this->fieldPluginManager = $field_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, $base_plugin_id) {
return new static(
$base_plugin_id,
$container->get('plugin.manager.migrate.cckfield'),
$container->get('plugin.manager.migrate.field')
);
}
/**
* {@inheritdoc}
*/
public function getDerivativeDefinitions($base_plugin_definition) {
$fields = [];
try {
$source_plugin = static::getSourcePlugin('d7_field_instance');
$source_plugin->checkRequirements();
// Read all field instance definitions in the source database.
foreach ($source_plugin as $row) {
if ($row->getSourceProperty('entity_type') == 'taxonomy_term') {
$fields[$row->getSourceProperty('bundle')][$row->getSourceProperty('field_name')] = $row->getSource();
}
}
}
catch (RequirementsException $e) {
// If checkRequirements() failed then the field module did not exist and
// we do not have any fields. Therefore, $fields will be empty and below
// we'll create a migration just for the node properties.
}
$vocabulary_source_plugin = static::getSourcePlugin('d7_taxonomy_vocabulary');
try {
$vocabulary_source_plugin->checkRequirements();
}
catch (RequirementsException $e) {
// If the d7_taxonomy_vocabulary requirements failed, that means we do not
// have a Drupal source database configured - there is nothing to
// generate.
return $this->derivatives;
}
try {
foreach ($vocabulary_source_plugin as $row) {
$bundle = $row->getSourceProperty('machine_name');
$values = $base_plugin_definition;
$values['label'] = t('@label (@type)', [
'@label' => $values['label'],
'@type' => $row->getSourceProperty('name'),
]);
$values['source']['bundle'] = $bundle;
$values['destination']['default_bundle'] = $bundle;
/** @var Migration $migration */
$migration = \Drupal::service('plugin.manager.migration')->createStubMigration($values);
if (isset($fields[$bundle])) {
foreach ($fields[$bundle] as $field_name => $info) {
$field_type = $info['type'];
try {
$plugin_id = $this->fieldPluginManager->getPluginIdFromFieldType($field_type, ['core' => 7], $migration);
if (!isset($this->fieldPluginCache[$field_type])) {
$this->fieldPluginCache[$field_type] = $this->fieldPluginManager->createInstance($plugin_id, ['core' => 7], $migration);
}
$this->fieldPluginCache[$field_type]
->processFieldValues($migration, $field_name, $info);
}
catch (PluginNotFoundException $ex) {
try {
$plugin_id = $this->cckPluginManager->getPluginIdFromFieldType($field_type, ['core' => 7], $migration);
if (!isset($this->cckPluginCache[$field_type])) {
$this->cckPluginCache[$field_type] = $this->cckPluginManager->createInstance($plugin_id, ['core' => 7], $migration);
}
$this->cckPluginCache[$field_type]
->processCckFieldValues($migration, $field_name, $info);
}
catch (PluginNotFoundException $ex) {
$migration->setProcessOfProperty($field_name, $field_name);
}
}
}
}
$this->derivatives[$bundle] = $migration->getPluginDefinition();
}
}
catch (DatabaseExceptionWrapper $e) {
// Once we begin iterating the source plugin it is possible that the
// source tables will not exist. This can happen when the
// MigrationPluginManager gathers up the migration definitions but we do
// not actually have a Drupal 7 source database.
}
return $this->derivatives;
}
}
@@ -20,20 +20,20 @@ class TaxonomyTermReference extends CckFieldPluginBase {
* {@inheritdoc}
*/
public function getFieldFormatterMap() {
return array();
return [];
}
/**
* {@inheritdoc}
*/
public function processCckFieldValues(MigrationInterface $migration, $field_name, $data) {
$process = array(
$process = [
'plugin' => 'iterator',
'source' => $field_name,
'process' => array(
'process' => [
'target_id' => 'tid',
),
);
],
];
$migration->setProcessOfProperty($field_name, $process);
}
@@ -14,6 +14,12 @@ use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
* id = "taxonomy_term",
* source_provider = "taxonomy"
* )
*
* @deprecated in Drupal 8.3.0, intended to be removed in Drupal 9.0.0.
* Use \Drupal\taxonomy\Plugin\migrate\source\d6\Term or
* \Drupal\taxonomy\Plugin\migrate\source\d7\Term.
*
* @see https://www.drupal.org/node/2879193
*/
class Term extends DrupalSqlBase {
@@ -50,7 +56,7 @@ class Term extends DrupalSqlBase {
->orderBy('td.tid');
if (isset($this->configuration['vocabulary'])) {
$query->condition('td.vid', $this->configuration['vocabulary'], 'IN');
$query->condition('td.vid', (array) $this->configuration['vocabulary'], 'IN');
}
return $query;
@@ -60,14 +66,14 @@ class Term extends DrupalSqlBase {
* {@inheritdoc}
*/
public function fields() {
$fields = array(
$fields = [
'tid' => $this->t('The term ID.'),
'vid' => $this->t('Existing term VID'),
'name' => $this->t('The name of the term.'),
'description' => $this->t('The term description.'),
'weight' => $this->t('Weight'),
'parent' => $this->t("The Drupal term IDs of the term's parents."),
);
];
if ($this->getModuleSchemaVersion('taxonomy') >= 7000) {
$fields['format'] = $this->t('Format of the term description.');
}
@@ -80,7 +86,7 @@ class Term extends DrupalSqlBase {
public function prepareRow(Row $row) {
// Find parents for this row.
$parents = $this->select($this->termHierarchyTable, 'th')
->fields('th', array('parent', 'tid'))
->fields('th', ['parent', 'tid'])
->condition('tid', $row->getSourceProperty('tid'))
->execute()
->fetchCol();
@@ -0,0 +1,78 @@
<?php
namespace Drupal\taxonomy\Plugin\migrate\source\d6;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* Taxonomy term source from database.
*
* @todo Support term_relation, term_synonym table if possible.
*
* @MigrateSource(
* id = "d6_taxonomy_term",
* source_provider = "taxonomy"
* )
*/
class Term extends DrupalSqlBase {
/**
* {@inheritdoc}
*/
public function query() {
$query = $this->select('term_data', 'td')
->fields('td')
->distinct()
->orderBy('td.tid');
if (isset($this->configuration['bundle'])) {
$query->condition('td.vid', (array) $this->configuration['bundle'], 'IN');
}
return $query;
}
/**
* {@inheritdoc}
*/
public function fields() {
$fields = [
'tid' => $this->t('The term ID.'),
'vid' => $this->t('Existing term VID'),
'name' => $this->t('The name of the term.'),
'description' => $this->t('The term description.'),
'weight' => $this->t('Weight'),
'parent' => $this->t("The Drupal term IDs of the term's parents."),
];
if (isset($this->configuration['translations'])) {
$fields['language'] = $this->t('The term language.');
$fields['trid'] = $this->t('Translation ID.');
}
return $fields;
}
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
// Find parents for this row.
$parents = $this->select('term_hierarchy', 'th')
->fields('th', ['parent', 'tid'])
->condition('tid', $row->getSourceProperty('tid'))
->execute()
->fetchCol();
$row->setSourceProperty('parent', $parents);
return parent::prepareRow($row);
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['tid']['type'] = 'integer';
return $ids;
}
}
@@ -26,10 +26,10 @@ class TermNode extends DrupalSqlBase {
public function query() {
$query = $this->select('term_node', 'tn')
->distinct()
->fields('tn', array('nid', 'vid'))
->fields('n', array('type'));
->fields('tn', ['nid', 'vid'])
->fields('n', ['type']);
// Because this is an inner join it enforces the current revision.
$query->innerJoin('term_data', 'td', 'td.tid = tn.tid AND td.vid = :vid', array(':vid' => $this->configuration['vid']));
$query->innerJoin('term_data', 'td', 'td.tid = tn.tid AND td.vid = :vid', [':vid' => $this->configuration['vid']]);
$query->innerJoin('node', 'n', static::JOIN);
return $query;
}
@@ -38,11 +38,11 @@ class TermNode extends DrupalSqlBase {
* {@inheritdoc}
*/
public function fields() {
return array(
return [
'nid' => $this->t('The node revision ID.'),
'vid' => $this->t('The node revision ID.'),
'tid' => $this->t('The term ID.'),
);
];
}
/**
@@ -51,10 +51,10 @@ class TermNode extends DrupalSqlBase {
public function prepareRow(Row $row) {
// Select the terms belonging to the revision selected.
$query = $this->select('term_node', 'tn')
->fields('tn', array('tid'))
->fields('tn', ['tid'])
->condition('n.nid', $row->getSourceProperty('nid'));
$query->join('node', 'n', static::JOIN);
$query->innerJoin('term_data', 'td', 'td.tid = tn.tid AND td.vid = :vid', array(':vid' => $this->configuration['vid']));
$query->innerJoin('term_data', 'td', 'td.tid = tn.tid AND td.vid = :vid', [':vid' => $this->configuration['vid']]);
$row->setSourceProperty('tid', $query->execute()->fetchCol());
return parent::prepareRow($row);
}
@@ -21,7 +21,7 @@ class Vocabulary extends DrupalSqlBase {
*/
public function query() {
$query = $this->select('vocabulary', 'v')
->fields('v', array(
->fields('v', [
'vid',
'name',
'description',
@@ -33,7 +33,7 @@ class Vocabulary extends DrupalSqlBase {
'tags',
'module',
'weight',
));
]);
return $query;
}
@@ -41,7 +41,7 @@ class Vocabulary extends DrupalSqlBase {
* {@inheritdoc}
*/
public function fields() {
return array(
return [
'vid' => $this->t('The vocabulary ID.'),
'name' => $this->t('The name of the vocabulary.'),
'description' => $this->t('The description of the vocabulary.'),
@@ -54,7 +54,7 @@ class Vocabulary extends DrupalSqlBase {
'weight' => $this->t('The weight of the vocabulary in relation to other vocabularies.'),
'parents' => $this->t("The Drupal term IDs of the term's parents."),
'node_types' => $this->t('The names of the node types the vocabulary may be used with.'),
);
];
}
/**
@@ -63,7 +63,7 @@ class Vocabulary extends DrupalSqlBase {
public function prepareRow(Row $row) {
// Find node types for this row.
$node_types = $this->select('vocabulary_node_types', 'nt')
->fields('nt', array('type', 'vid'))
->fields('nt', ['type', 'vid'])
->condition('vid', $row->getSourceProperty('vid'))
->execute()
->fetchCol();
@@ -18,7 +18,7 @@ class VocabularyPerType extends Vocabulary {
public function query() {
$query = parent::query();
$query->join('vocabulary_node_types', 'nt', 'v.vid = nt.vid');
$query->fields('nt', array('type'));
$query->fields('nt', ['type']);
return $query;
}
@@ -0,0 +1,57 @@
<?php
namespace Drupal\taxonomy\Plugin\migrate\source\d6;
use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
/**
* Drupal 6 vocabulary translations from source database.
*
* @MigrateSource(
* id = "d6_taxonomy_vocabulary_translation",
* source_provider = "taxonomy"
* )
*/
class VocabularyTranslation extends DrupalSqlBase {
/**
* {@inheritdoc}
*/
public function query() {
$query = $this->select('vocabulary', 'v')
->fields('v', ['vid', 'name', 'description'])
->fields('i18n', ['lid', 'type', 'property', 'objectid'])
->fields('lt', ['lid', 'translation'])
->condition('i18n.type', 'vocabulary');
$query->addField('lt', 'language', 'language');
// The i18n_strings table has two columns containing the object ID, objectid
// and objectindex. The objectid column is a text field. Therefore, for the
// join to work in PostgreSQL, use the objectindex field as this is numeric
// like the vid field.
$query->join('i18n_strings', 'i18n', 'v.vid = i18n.objectindex');
$query->leftJoin('locales_target', 'lt', 'lt.lid = i18n.lid');
return $query;
}
/**
* {@inheritdoc}
*/
public function fields() {
return [
'vid' => $this->t('The vocabulary ID.'),
'language' => $this->t('Language for this field.'),
'property' => $this->t('Name of property being translated.'),
'translation' => $this->t('Translation of either the title or explanation.'),
];
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['vid']['type'] = 'integer';
return $ids;
}
}
@@ -0,0 +1,84 @@
<?php
namespace Drupal\taxonomy\Plugin\migrate\source\d7;
use Drupal\migrate\Row;
use Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity;
/**
* Taxonomy term source from database.
*
* @todo Support term_relation, term_synonym table if possible.
*
* @MigrateSource(
* id = "d7_taxonomy_term",
* source_provider = "taxonomy"
* )
*/
class Term extends FieldableEntity {
/**
* {@inheritdoc}
*/
public function query() {
$query = $this->select('taxonomy_term_data', 'td')
->fields('td')
->distinct()
->orderBy('tid');
$query->leftJoin('taxonomy_vocabulary', 'tv', 'td.vid = tv.vid');
$query->addField('tv', 'machine_name');
if (isset($this->configuration['bundle'])) {
$query->condition('tv.machine_name', (array) $this->configuration['bundle'], 'IN');
}
return $query;
}
/**
* {@inheritdoc}
*/
public function fields() {
$fields = [
'tid' => $this->t('The term ID.'),
'vid' => $this->t('Existing term VID'),
'machine_name' => $this->t('Vocabulary machine name'),
'name' => $this->t('The name of the term.'),
'description' => $this->t('The term description.'),
'weight' => $this->t('Weight'),
'parent' => $this->t("The Drupal term IDs of the term's parents."),
'format' => $this->t("Format of the term description."),
];
return $fields;
}
/**
* {@inheritdoc}
*/
public function prepareRow(Row $row) {
// Get Field API field values.
foreach (array_keys($this->getFields('taxonomy_term', $row->getSourceProperty('machine_name'))) as $field) {
$tid = $row->getSourceProperty('tid');
$row->setSourceProperty($field, $this->getFieldValues('taxonomy_term', $field, $tid));
}
// Find parents for this row.
$parents = $this->select('taxonomy_term_hierarchy', 'th')
->fields('th', ['parent', 'tid'])
->condition('tid', $row->getSourceProperty('tid'))
->execute()
->fetchCol();
$row->setSourceProperty('parent', $parents);
return parent::prepareRow($row);
}
/**
* {@inheritdoc}
*/
public function getIds() {
$ids['tid']['type'] = 'integer';
return $ids;
}
}
@@ -19,7 +19,7 @@ class Vocabulary extends DrupalSqlBase {
*/
public function query() {
$query = $this->select('taxonomy_vocabulary', 'v')
->fields('v', array(
->fields('v', [
'vid',
'name',
'description',
@@ -27,7 +27,7 @@ class Vocabulary extends DrupalSqlBase {
'module',
'weight',
'machine_name',
));
]);
return $query;
}
@@ -35,7 +35,7 @@ class Vocabulary extends DrupalSqlBase {
* {@inheritdoc}
*/
public function fields() {
return array(
return [
'vid' => $this->t('The vocabulary ID.'),
'name' => $this->t('The name of the vocabulary.'),
'description' => $this->t('The description of the vocabulary.'),
@@ -43,7 +43,7 @@ class Vocabulary extends DrupalSqlBase {
'module' => $this->t('Module responsible for the vocabulary.'),
'weight' => $this->t('The weight of the vocabulary in relation to other vocabularies.'),
'machine_name' => $this->t('Unique machine name of the vocabulary.')
);
];
}
/**
@@ -15,7 +15,7 @@ use Drupal\views\Plugin\views\argument\ManyToOne;
class IndexTid extends ManyToOne {
public function titleQuery() {
$titles = array();
$titles = [];
$terms = Term::loadMultiple($this->value);
foreach ($terms as $term) {
$titles[] = \Drupal::entityManager()->getTranslationFromContext($term)->label();
@@ -44,27 +44,27 @@ class IndexTidDepth extends ArgumentPluginBase implements ContainerFactoryPlugin
protected function defineOptions() {
$options = parent::defineOptions();
$options['depth'] = array('default' => 0);
$options['break_phrase'] = array('default' => FALSE);
$options['use_taxonomy_term_path'] = array('default' => FALSE);
$options['depth'] = ['default' => 0];
$options['break_phrase'] = ['default' => FALSE];
$options['use_taxonomy_term_path'] = ['default' => FALSE];
return $options;
}
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
$form['depth'] = array(
$form['depth'] = [
'#type' => 'weight',
'#title' => $this->t('Depth'),
'#default_value' => $this->options['depth'],
'#description' => $this->t('The depth will match nodes tagged with terms in the hierarchy. For example, if you have the term "fruit" and a child term "apple", with a depth of 1 (or higher) then filtering for the term "fruit" will get nodes that are tagged with "apple" as well as "fruit". If negative, the reverse is true; searching for "apple" will also pick up nodes tagged with "fruit" if depth is -1 (or lower).'),
);
];
$form['break_phrase'] = array(
$form['break_phrase'] = [
'#type' => 'checkbox',
'#title' => $this->t('Allow multiple values'),
'#description' => $this->t('If selected, users can enter multiple values in the form of 1+2+3. Due to the number of JOINs it would require, AND will be treated as OR with this filter.'),
'#default_value' => !empty($this->options['break_phrase']),
);
];
parent::buildOptionsForm($form, $form_state);
}
@@ -74,7 +74,7 @@ class IndexTidDepth extends ArgumentPluginBase implements ContainerFactoryPlugin
*/
protected function defaultActions($which = NULL) {
if ($which) {
if (in_array($which, array('ignore', 'not found', 'empty', 'default'))) {
if (in_array($which, ['ignore', 'not found', 'empty', 'default'])) {
return parent::defaultActions($which);
}
return;
@@ -92,7 +92,7 @@ class IndexTidDepth extends ArgumentPluginBase implements ContainerFactoryPlugin
if (!empty($this->options['break_phrase'])) {
$break = static::breakString($this->argument);
if ($break->value === array(-1)) {
if ($break->value === [-1]) {
return FALSE;
}
@@ -130,7 +130,7 @@ class IndexTidDepth extends ArgumentPluginBase implements ContainerFactoryPlugin
$this->query->addWhere(0, "$this->tableAlias.$this->realField", $subquery, 'IN');
}
function title() {
public function title() {
$term = $this->termStorage->load($this->argument);
if (!empty($term)) {
return $term->getName();
@@ -45,7 +45,7 @@ class Taxonomy extends NumericArgument implements ContainerFactoryPluginInterfac
/**
* Override the behavior of title(). Get the title of the node.
*/
function title() {
public function title() {
// There might be no valid argument.
if ($this->argument) {
$term = $this->termStorage->load($this->argument);
@@ -54,7 +54,7 @@ class VocabularyVid extends NumericArgument {
/**
* Override the behavior of title(). Get the name of the vocabulary.
*/
function title() {
public function title() {
$vocabulary = $this->vocabularyStorage->load($this->argument);
if ($vocabulary) {
return $vocabulary->label();
@@ -96,11 +96,11 @@ class Tid extends ArgumentDefaultPluginBase implements CacheableDependencyInterf
protected function defineOptions() {
$options = parent::defineOptions();
$options['term_page'] = array('default' => TRUE);
$options['node'] = array('default' => FALSE);
$options['anyall'] = array('default' => ',');
$options['limit'] = array('default' => FALSE);
$options['vids'] = array('default' => array());
$options['term_page'] = ['default' => TRUE];
$options['node'] = ['default' => FALSE];
$options['anyall'] = ['default' => ','];
$options['limit'] = ['default' => FALSE];
$options['vids'] = ['default' => []];
return $options;
}
@@ -109,67 +109,67 @@ class Tid extends ArgumentDefaultPluginBase implements CacheableDependencyInterf
* {@inheritdoc}
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
$form['term_page'] = array(
$form['term_page'] = [
'#type' => 'checkbox',
'#title' => $this->t('Load default filter from term page'),
'#default_value' => $this->options['term_page'],
);
$form['node'] = array(
];
$form['node'] = [
'#type' => 'checkbox',
'#title' => $this->t('Load default filter from node page, that\'s good for related taxonomy blocks'),
'#default_value' => $this->options['node'],
);
];
$form['limit'] = array(
$form['limit'] = [
'#type' => 'checkbox',
'#title' => $this->t('Limit terms by vocabulary'),
'#default_value' => $this->options['limit'],
'#states' => array(
'visible' => array(
':input[name="options[argument_default][taxonomy_tid][node]"]' => array('checked' => TRUE),
),
),
);
'#states' => [
'visible' => [
':input[name="options[argument_default][taxonomy_tid][node]"]' => ['checked' => TRUE],
],
],
];
$options = array();
$options = [];
$vocabularies = $this->vocabularyStorage->loadMultiple();
foreach ($vocabularies as $voc) {
$options[$voc->id()] = $voc->label();
}
$form['vids'] = array(
$form['vids'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Vocabularies'),
'#options' => $options,
'#default_value' => $this->options['vids'],
'#states' => array(
'visible' => array(
':input[name="options[argument_default][taxonomy_tid][limit]"]' => array('checked' => TRUE),
':input[name="options[argument_default][taxonomy_tid][node]"]' => array('checked' => TRUE),
),
),
);
'#states' => [
'visible' => [
':input[name="options[argument_default][taxonomy_tid][limit]"]' => ['checked' => TRUE],
':input[name="options[argument_default][taxonomy_tid][node]"]' => ['checked' => TRUE],
],
],
];
$form['anyall'] = array(
$form['anyall'] = [
'#type' => 'radios',
'#title' => $this->t('Multiple-value handling'),
'#default_value' => $this->options['anyall'],
'#options' => array(
'#options' => [
',' => $this->t('Filter to items that share all terms'),
'+' => $this->t('Filter to items that share any term'),
),
'#states' => array(
'visible' => array(
':input[name="options[argument_default][taxonomy_tid][node]"]' => array('checked' => TRUE),
),
),
);
],
'#states' => [
'visible' => [
':input[name="options[argument_default][taxonomy_tid][node]"]' => ['checked' => TRUE],
],
],
];
}
/**
* {@inheritdoc}
*/
public function submitOptionsForm(&$form, FormStateInterface $form_state, &$options = array()) {
public function submitOptionsForm(&$form, FormStateInterface $form_state, &$options = []) {
// Filter unselected items so we don't unnecessarily store giant arrays.
$options['vids'] = array_filter($options['vids']);
}
@@ -188,7 +188,7 @@ class Tid extends ArgumentDefaultPluginBase implements CacheableDependencyInterf
if (!empty($this->options['node'])) {
// Just check, if a node could be detected.
if (($node = $this->routeMatch->getParameter('node')) && $node instanceof NodeInterface) {
$taxonomy = array();
$taxonomy = [];
foreach ($node->getFieldDefinitions() as $field) {
if ($field->getType() == 'entity_reference' && $field->getSetting('target_type') == 'taxonomy_term') {
$taxonomy_terms = $node->{$field->getName()}->referencedEntities();
@@ -199,7 +199,7 @@ class Tid extends ArgumentDefaultPluginBase implements CacheableDependencyInterf
}
}
if (!empty($this->options['limit'])) {
$tids = array();
$tids = [];
// filter by vocabulary
foreach ($taxonomy as $tid => $vocab) {
if (!empty($this->options['vids'][$vocab])) {
@@ -39,7 +39,7 @@ class TermName extends Entity {
*/
protected function defineOptions() {
$options = parent::defineOptions();
$options['transform'] = array('default' => FALSE);
$options['transform'] = ['default' => FALSE];
return $options;
}
@@ -50,11 +50,11 @@ class TermName extends Entity {
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
parent::buildOptionsForm($form, $form_state);
$form['transform'] = array(
$form['transform'] = [
'#type' => 'checkbox',
'#title' => $this->t('Transform dashes in URL to spaces in term name filter values'),
'#default_value' => $this->options['transform'],
);
];
}
/**
@@ -64,7 +64,7 @@ class TermName extends Entity {
if ($this->options['transform']) {
$argument = str_replace('-', ' ', $argument);
}
$terms = $this->termStorage->loadByProperties(array('name' => $argument));
$terms = $this->termStorage->loadByProperties(['name' => $argument]);
if (!$terms) {
// Returned empty array no terms with the name.
@@ -62,19 +62,19 @@ class TaxonomyIndexTid extends PrerenderList {
// @todo: Wouldn't it be possible to use $this->base_table and no if here?
if ($view->storage->get('base_table') == 'node_field_revision') {
$this->additional_fields['nid'] = array('table' => 'node_field_revision', 'field' => 'nid');
$this->additional_fields['nid'] = ['table' => 'node_field_revision', 'field' => 'nid'];
}
else {
$this->additional_fields['nid'] = array('table' => 'node_field_data', 'field' => 'nid');
$this->additional_fields['nid'] = ['table' => 'node_field_data', 'field' => 'nid'];
}
}
protected function defineOptions() {
$options = parent::defineOptions();
$options['link_to_taxonomy'] = array('default' => TRUE);
$options['limit'] = array('default' => FALSE);
$options['vids'] = array('default' => array());
$options['link_to_taxonomy'] = ['default' => TRUE];
$options['limit'] = ['default' => FALSE];
$options['vids'] = ['default' => []];
return $options;
}
@@ -83,36 +83,36 @@ class TaxonomyIndexTid extends PrerenderList {
* Provide "link to term" option.
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
$form['link_to_taxonomy'] = array(
$form['link_to_taxonomy'] = [
'#title' => $this->t('Link this field to its term page'),
'#type' => 'checkbox',
'#default_value' => !empty($this->options['link_to_taxonomy']),
);
];
$form['limit'] = array(
$form['limit'] = [
'#type' => 'checkbox',
'#title' => $this->t('Limit terms by vocabulary'),
'#default_value' => $this->options['limit'],
);
];
$options = array();
$options = [];
$vocabularies = $this->vocabularyStorage->loadMultiple();
foreach ($vocabularies as $voc) {
$options[$voc->id()] = $voc->label();
}
$form['vids'] = array(
$form['vids'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Vocabularies'),
'#options' => $options,
'#default_value' => $this->options['vids'],
'#states' => array(
'visible' => array(
':input[name="options[limit]"]' => array('checked' => TRUE),
),
),
'#states' => [
'visible' => [
':input[name="options[limit]"]' => ['checked' => TRUE],
],
],
);
];
parent::buildOptionsForm($form, $form_state);
}
@@ -127,7 +127,7 @@ class TaxonomyIndexTid extends PrerenderList {
public function preRender(&$values) {
$vocabularies = $this->vocabularyStorage->loadMultiple();
$this->field_alias = $this->aliases['nid'];
$nids = array();
$nids = [];
foreach ($values as $result) {
if (!empty($result->{$this->aliases['nid']})) {
$nids[] = $result->{$this->aliases['nid']};
@@ -137,7 +137,7 @@ class TaxonomyIndexTid extends PrerenderList {
if ($nids) {
$vocabs = array_filter($this->options['vids']);
if (empty($this->options['limit'])) {
$vocabs = array();
$vocabs = [];
}
$result = \Drupal::entityManager()->getStorage('taxonomy_term')->getNodeTerms($nids, $vocabs);
@@ -157,7 +157,7 @@ class TaxonomyIndexTid extends PrerenderList {
}
}
function render_item($count, $item) {
public function render_item($count, $item) {
return $item['name'];
}
@@ -169,7 +169,7 @@ class TaxonomyIndexTid extends PrerenderList {
}
protected function addSelfTokens(&$tokens, $item) {
foreach (array('tid', 'name', 'vocabulary_vid', 'vocabulary') as $token) {
foreach (['tid', 'name', 'vocabulary_vid', 'vocabulary'] as $token) {
$tokens['{{ ' . $this->options['id'] . '__' . $token . ' }}'] = isset($item[$token]) ? $item[$token] : '';
}
}
@@ -3,7 +3,7 @@
namespace Drupal\taxonomy\Plugin\views\field;
use Drupal\Core\Form\FormStateInterface;
use Drupal\views\Plugin\views\field\Field;
use Drupal\views\Plugin\views\field\EntityField;
use Drupal\views\ResultRow;
/**
@@ -13,7 +13,7 @@ use Drupal\views\ResultRow;
*
* @ViewsField("term_name")
*/
class TermName extends Field {
class TermName extends EntityField {
/**
* {@inheritdoc}
@@ -37,7 +37,7 @@ class TermName extends Field {
*/
protected function defineOptions() {
$options = parent::defineOptions();
$options['convert_spaces'] = array('default' => FALSE);
$options['convert_spaces'] = ['default' => FALSE];
return $options;
}
@@ -45,11 +45,11 @@ class TermName extends Field {
* {@inheritdoc}
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
$form['convert_spaces'] = array(
$form['convert_spaces'] = [
'#title' => $this->t('Convert spaces in term names to hyphens'),
'#type' => 'checkbox',
'#default_value' => !empty($this->options['convert_spaces']),
);
];
parent::buildOptionsForm($form, $form_state);
}
@@ -94,18 +94,18 @@ class TaxonomyIndexTid extends ManyToOne {
protected function defineOptions() {
$options = parent::defineOptions();
$options['type'] = array('default' => 'textfield');
$options['limit'] = array('default' => TRUE);
$options['vid'] = array('default' => '');
$options['hierarchy'] = array('default' => FALSE);
$options['error_message'] = array('default' => TRUE);
$options['type'] = ['default' => 'textfield'];
$options['limit'] = ['default' => TRUE];
$options['vid'] = ['default' => ''];
$options['hierarchy'] = ['default' => FALSE];
$options['error_message'] = ['default' => TRUE];
return $options;
}
public function buildExtraOptionsForm(&$form, FormStateInterface $form_state) {
$vocabularies = $this->vocabularyStorage->loadMultiple();
$options = array();
$options = [];
foreach ($vocabularies as $voc) {
$options[$voc->id()] = $voc->label();
}
@@ -118,56 +118,56 @@ class TaxonomyIndexTid extends ManyToOne {
}
if (empty($this->definition['vocabulary'])) {
$form['vid'] = array(
$form['vid'] = [
'#type' => 'radios',
'#title' => $this->t('Vocabulary'),
'#options' => $options,
'#description' => $this->t('Select which vocabulary to show terms for in the regular options.'),
'#default_value' => $this->options['vid'],
);
];
}
}
$form['type'] = array(
$form['type'] = [
'#type' => 'radios',
'#title' => $this->t('Selection type'),
'#options' => array('select' => $this->t('Dropdown'), 'textfield' => $this->t('Autocomplete')),
'#options' => ['select' => $this->t('Dropdown'), 'textfield' => $this->t('Autocomplete')],
'#default_value' => $this->options['type'],
);
];
$form['hierarchy'] = array(
$form['hierarchy'] = [
'#type' => 'checkbox',
'#title' => $this->t('Show hierarchy in dropdown'),
'#default_value' => !empty($this->options['hierarchy']),
'#states' => array(
'visible' => array(
':input[name="options[type]"]' => array('value' => 'select'),
),
),
);
'#states' => [
'visible' => [
':input[name="options[type]"]' => ['value' => 'select'],
],
],
];
}
protected function valueForm(&$form, FormStateInterface $form_state) {
$vocabulary = $this->vocabularyStorage->load($this->options['vid']);
if (empty($vocabulary) && $this->options['limit']) {
$form['markup'] = array(
$form['markup'] = [
'#markup' => '<div class="js-form-item form-item">' . $this->t('An invalid vocabulary is selected. Please change it in the options.') . '</div>',
);
];
return;
}
if ($this->options['type'] == 'textfield') {
$terms = $this->value ? Term::loadMultiple(($this->value)) : array();
$form['value'] = array(
'#title' => $this->options['limit'] ? $this->t('Select terms from vocabulary @voc', array('@voc' => $vocabulary->label())) : $this->t('Select terms'),
$terms = $this->value ? Term::loadMultiple(($this->value)) : [];
$form['value'] = [
'#title' => $this->options['limit'] ? $this->t('Select terms from vocabulary @voc', ['@voc' => $vocabulary->label()]) : $this->t('Select terms'),
'#type' => 'textfield',
'#default_value' => EntityAutocomplete::getEntityLabels($terms),
);
];
if ($this->options['limit']) {
$form['value']['#type'] = 'entity_autocomplete';
$form['value']['#target_type'] = 'taxonomy_term';
$form['value']['#selection_settings']['target_bundles'] = array($vocabulary->id());
$form['value']['#selection_settings']['target_bundles'] = [$vocabulary->id()];
$form['value']['#tags'] = TRUE;
$form['value']['#process_default_value'] = FALSE;
}
@@ -175,24 +175,24 @@ class TaxonomyIndexTid extends ManyToOne {
else {
if (!empty($this->options['hierarchy']) && $this->options['limit']) {
$tree = $this->termStorage->loadTree($vocabulary->id(), 0, NULL, TRUE);
$options = array();
$options = [];
if ($tree) {
foreach ($tree as $term) {
$choice = new \stdClass();
$choice->option = array($term->id() => str_repeat('-', $term->depth) . \Drupal::entityManager()->getTranslationFromContext($term)->label());
$choice->option = [$term->id() => str_repeat('-', $term->depth) . \Drupal::entityManager()->getTranslationFromContext($term)->label()];
$options[] = $choice;
}
}
}
else {
$options = array();
$options = [];
$query = \Drupal::entityQuery('taxonomy_term')
// @todo Sorting on vocabulary properties -
// https://www.drupal.org/node/1821274.
->sort('weight')
->sort('name')
->addTag('term_access');
->addTag('taxonomy_term_access');
if ($this->options['limit']) {
$query->condition('vid', $vocabulary->id());
}
@@ -211,7 +211,7 @@ class TaxonomyIndexTid extends ManyToOne {
$options = $this->reduceValueOptions($options);
if (!empty($this->options['expose']['multiple']) && empty($this->options['expose']['required'])) {
$default_value = array();
$default_value = [];
}
}
@@ -225,7 +225,7 @@ class TaxonomyIndexTid extends ManyToOne {
}
// Due to #1464174 there is a chance that array('') was saved in the admin ui.
// Let's choose a safe default value.
elseif ($default_value == array('')) {
elseif ($default_value == ['']) {
$default_value = 'All';
}
else {
@@ -234,14 +234,14 @@ class TaxonomyIndexTid extends ManyToOne {
}
}
}
$form['value'] = array(
$form['value'] = [
'#type' => 'select',
'#title' => $this->options['limit'] ? $this->t('Select terms from vocabulary @voc', array('@voc' => $vocabulary->label())) : $this->t('Select terms'),
'#title' => $this->options['limit'] ? $this->t('Select terms from vocabulary @voc', ['@voc' => $vocabulary->label()]) : $this->t('Select terms'),
'#multiple' => TRUE,
'#options' => $options,
'#size' => min(9, count($options)),
'#default_value' => $default_value,
);
];
$user_input = $form_state->getUserInput();
if ($exposed && isset($identifier) && !isset($user_input[$identifier])) {
@@ -265,13 +265,13 @@ class TaxonomyIndexTid extends ManyToOne {
return;
}
$tids = array();
if ($values = $form_state->getValue(array('options', 'value'))) {
$tids = [];
if ($values = $form_state->getValue(['options', 'value'])) {
foreach ($values as $value) {
$tids[] = $value['target_id'];
}
}
$form_state->setValue(array('options', 'value'), $tids);
$form_state->setValue(['options', 'value'], $tids);
}
public function acceptExposedInput($input) {
@@ -348,16 +348,16 @@ class TaxonomyIndexTid extends ManyToOne {
if ($this->options['type'] != 'select') {
unset($form['expose']['reduce']);
}
$form['error_message'] = array(
$form['error_message'] = [
'#type' => 'checkbox',
'#title' => $this->t('Display error message'),
'#default_value' => !empty($this->options['error_message']),
);
];
}
public function adminSummary() {
// set up $this->valueOptions for the parent summary
$this->valueOptions = array();
$this->valueOptions = [];
if ($this->value) {
$this->value = array_filter($this->value);
@@ -17,15 +17,15 @@ use Drupal\Core\Form\FormStateInterface;
class TaxonomyIndexTidDepth extends TaxonomyIndexTid {
public function operatorOptions($which = 'title') {
return array(
return [
'or' => $this->t('Is one of'),
);
];
}
protected function defineOptions() {
$options = parent::defineOptions();
$options['depth'] = array('default' => 0);
$options['depth'] = ['default' => 0];
return $options;
}
@@ -33,12 +33,12 @@ class TaxonomyIndexTidDepth extends TaxonomyIndexTid {
public function buildExtraOptionsForm(&$form, FormStateInterface $form_state) {
parent::buildExtraOptionsForm($form, $form_state);
$form['depth'] = array(
$form['depth'] = [
'#type' => 'weight',
'#title' => $this->t('Depth'),
'#default_value' => $this->options['depth'],
'#description' => $this->t('The depth will match nodes tagged with terms in the hierarchy. For example, if you have the term "fruit" and a child term "apple", with a depth of 1 (or higher) then filtering for the term "fruit" will get nodes that are tagged with "apple" as well as "fruit". If negative, the reverse is true; searching for "apple" will also pick up nodes tagged with "fruit" if depth is -1 (or lower).'),
);
];
}
public function query() {
@@ -74,24 +74,24 @@ class NodeTermData extends RelationshipPluginBase {
protected function defineOptions() {
$options = parent::defineOptions();
$options['vids'] = array('default' => array());
$options['vids'] = ['default' => []];
return $options;
}
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
$vocabularies = $this->vocabularyStorage->loadMultiple();
$options = array();
$options = [];
foreach ($vocabularies as $voc) {
$options[$voc->id()] = $voc->label();
}
$form['vids'] = array(
$form['vids'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Vocabularies'),
'#options' => $options,
'#default_value' => $this->options['vids'],
'#description' => $this->t('Choose which vocabularies you wish to relate. Remember that every term found will create a new record, so this relationship is best used on just one vocabulary that has only one term per node.'),
);
];
parent::buildOptionsForm($form, $form_state);
}
@@ -132,9 +132,9 @@ class NodeTermData extends RelationshipPluginBase {
$query = db_select('taxonomy_term_field_data', 'td');
$query->addJoin($def['type'], 'taxonomy_index', 'tn', 'tn.tid = td.tid');
$query->condition('td.vid', array_filter($this->options['vids']), 'IN');
$query->addTag('term_access');
$query->addTag('taxonomy_term_access');
$query->fields('td');
$query->fields('tn', array('nid'));
$query->fields('tn', ['nid']);
$def['table formula'] = $query;
}
@@ -21,15 +21,12 @@ class TermAccessControlHandler extends EntityAccessControlHandler {
switch ($operation) {
case 'view':
return AccessResult::allowedIfHasPermission($account, 'access content');
break;
case 'update':
return AccessResult::allowedIfHasPermissions($account, ["edit terms in {$entity->bundle()}", 'administer taxonomy'], 'OR');
break;
case 'delete':
return AccessResult::allowedIfHasPermissions($account, ["delete terms in {$entity->bundle()}", 'administer taxonomy'], 'OR');
break;
default:
// No opinion.
@@ -68,7 +68,7 @@ class TermBreadcrumbBuilder implements BreadcrumbBuilderInterface {
foreach (array_reverse($parents) as $term) {
$term = $this->entityManager->getTranslationFromContext($term);
$breadcrumb->addCacheableDependency($term);
$breadcrumb->addLink(Link::createFromRoute($term->getName(), 'entity.taxonomy_term.canonical', array('taxonomy_term' => $term->id())));
$breadcrumb->addLink(Link::createFromRoute($term->getName(), 'entity.taxonomy_term.canonical', ['taxonomy_term' => $term->id()]));
}
// This breadcrumb builder is based on a route parameter, and hence it
+23 -22
View File
@@ -23,12 +23,12 @@ class TermForm extends ContentEntityForm {
$form_state->set(['taxonomy', 'parent'], $parent);
$form_state->set(['taxonomy', 'vocabulary'], $vocabulary);
$form['relations'] = array(
$form['relations'] = [
'#type' => 'details',
'#title' => $this->t('Relations'),
'#open' => $vocabulary->getHierarchy() == TAXONOMY_HIERARCHY_MULTIPLE,
'#open' => $vocabulary->getHierarchy() == VocabularyInterface::HIERARCHY_MULTIPLE,
'#weight' => 10,
);
];
// \Drupal\taxonomy\TermStorageInterface::loadTree() and
// \Drupal\taxonomy\TermStorageInterface::loadParents() may contain large
@@ -46,9 +46,9 @@ class TermForm extends ContentEntityForm {
$exclude[] = $term->id();
$tree = $taxonomy_storage->loadTree($vocabulary->id());
$options = array('<' . $this->t('root') . '>');
$options = ['<' . $this->t('root') . '>'];
if (empty($parent)) {
$parent = array(0);
$parent = [0];
}
foreach ($tree as $item) {
@@ -57,33 +57,33 @@ class TermForm extends ContentEntityForm {
}
}
$form['relations']['parent'] = array(
$form['relations']['parent'] = [
'#type' => 'select',
'#title' => $this->t('Parent terms'),
'#options' => $options,
'#default_value' => $parent,
'#multiple' => TRUE,
);
];
}
$form['relations']['weight'] = array(
$form['relations']['weight'] = [
'#type' => 'textfield',
'#title' => $this->t('Weight'),
'#size' => 6,
'#default_value' => $term->getWeight(),
'#description' => $this->t('Terms are displayed in ascending order by weight.'),
'#required' => TRUE,
);
];
$form['vid'] = array(
$form['vid'] = [
'#type' => 'value',
'#value' => $vocabulary->id(),
);
];
$form['tid'] = array(
$form['tid'] = [
'#type' => 'value',
'#value' => $term->id(),
);
];
return parent::form($form, $form_state, $term);
}
@@ -123,24 +123,25 @@ class TermForm extends ContentEntityForm {
$result = $term->save();
$link = $term->link($this->t('Edit'), 'edit-form');
$edit_link = $term->link($this->t('Edit'), 'edit-form');
$view_link = $term->link($term->getName());
switch ($result) {
case SAVED_NEW:
drupal_set_message($this->t('Created new term %term.', array('%term' => $term->getName())));
$this->logger('taxonomy')->notice('Created new term %term.', array('%term' => $term->getName(), 'link' => $link));
drupal_set_message($this->t('Created new term %term.', ['%term' => $view_link]));
$this->logger('taxonomy')->notice('Created new term %term.', ['%term' => $term->getName(), 'link' => $edit_link]);
break;
case SAVED_UPDATED:
drupal_set_message($this->t('Updated term %term.', array('%term' => $term->getName())));
$this->logger('taxonomy')->notice('Updated term %term.', array('%term' => $term->getName(), 'link' => $link));
drupal_set_message($this->t('Updated term %term.', ['%term' => $view_link]));
$this->logger('taxonomy')->notice('Updated term %term.', ['%term' => $term->getName(), 'link' => $edit_link]);
break;
}
$current_parent_count = count($form_state->getValue('parent'));
$previous_parent_count = count($form_state->get(['taxonomy', 'parent']));
// Root doesn't count if it's the only parent.
if ($current_parent_count == 1 && $form_state->hasValue(array('parent', 0))) {
if ($current_parent_count == 1 && $form_state->hasValue(['parent', 0])) {
$current_parent_count = 0;
$form_state->setValue('parent', array());
$form_state->setValue('parent', []);
}
// If the number of parents has been reduced to one or none, do a check on the
@@ -151,8 +152,8 @@ class TermForm extends ContentEntityForm {
}
// If we've increased the number of parents and this is a single or flat
// hierarchy, update the vocabulary immediately.
elseif ($current_parent_count > $previous_parent_count && $vocabulary->getHierarchy() != TAXONOMY_HIERARCHY_MULTIPLE) {
$vocabulary->setHierarchy($current_parent_count == 1 ? TAXONOMY_HIERARCHY_SINGLE : TAXONOMY_HIERARCHY_MULTIPLE);
elseif ($current_parent_count > $previous_parent_count && $vocabulary->getHierarchy() != VocabularyInterface::HIERARCHY_MULTIPLE) {
$vocabulary->setHierarchy($current_parent_count == 1 ? VocabularyInterface::HIERARCHY_SINGLE : VocabularyInterface::HIERARCHY_MULTIPLE);
$vocabulary->save();
}
+1 -1
View File
@@ -85,7 +85,7 @@ interface TermInterface extends ContentEntityInterface, EntityChangedInterface {
/**
* Get the taxonomy vocabulary id this term belongs to.
*
* @return int
* @return string
* The id of the vocabulary.
*/
public function getVocabularyId();
+46 -46
View File
@@ -15,49 +15,49 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac
*
* @var array
*/
protected $parents = array();
protected $parents = [];
/**
* Array of all loaded term ancestry keyed by ancestor term ID.
*
* @var array
*/
protected $parentsAll = array();
protected $parentsAll = [];
/**
* Array of child terms keyed by parent term ID.
*
* @var array
*/
protected $children = array();
protected $children = [];
/**
* Array of term parents keyed by vocabulary ID and child term ID.
*
* @var array
*/
protected $treeParents = array();
protected $treeParents = [];
/**
* Array of term ancestors keyed by vocabulary ID and parent term ID.
*
* @var array
*/
protected $treeChildren = array();
protected $treeChildren = [];
/**
* Array of terms in a tree keyed by vocabulary ID and term ID.
*
* @var array
*/
protected $treeTerms = array();
protected $treeTerms = [];
/**
* Array of loaded trees keyed by a cache id matching tree arguments.
*
* @var array
*/
protected $trees = array();
protected $trees = [];
/**
* {@inheritdoc}
@@ -66,10 +66,10 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac
* An array of values to set, keyed by property name. A value for the
* vocabulary ID ('vid') is required.
*/
public function create(array $values = array()) {
public function create(array $values = []) {
// Save new terms with no parents by default.
if (empty($values['parent'])) {
$values['parent'] = array(0);
$values['parent'] = [0];
}
$entity = parent::create($values);
return $entity;
@@ -80,13 +80,13 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac
*/
public function resetCache(array $ids = NULL) {
drupal_static_reset('taxonomy_term_count_nodes');
$this->parents = array();
$this->parentsAll = array();
$this->children = array();
$this->treeChildren = array();
$this->treeParents = array();
$this->treeTerms = array();
$this->trees = array();
$this->parents = [];
$this->parentsAll = [];
$this->children = [];
$this->treeChildren = [];
$this->treeParents = [];
$this->treeTerms = [];
$this->trees = [];
parent::resetCache($ids);
}
@@ -104,13 +104,13 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac
*/
public function updateTermHierarchy(EntityInterface $term) {
$query = $this->database->insert('taxonomy_term_hierarchy')
->fields(array('tid', 'parent'));
->fields(['tid', 'parent']);
foreach ($term->parent as $parent) {
$query->values(array(
$query->values([
'tid' => $term->id(),
'parent' => (int) $parent->target_id,
));
]);
}
$query->execute();
}
@@ -120,13 +120,13 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac
*/
public function loadParents($tid) {
if (!isset($this->parents[$tid])) {
$parents = array();
$parents = [];
$query = $this->database->select('taxonomy_term_field_data', 't');
$query->join('taxonomy_term_hierarchy', 'h', 'h.parent = t.tid');
$query->addField('t', 'tid');
$query->condition('h.tid', $tid);
$query->condition('t.default_langcode', 1);
$query->addTag('term_access');
$query->addTag('taxonomy_term_access');
$query->orderBy('t.weight');
$query->orderBy('t.name');
if ($ids = $query->execute()->fetchCol()) {
@@ -142,7 +142,7 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac
*/
public function loadAllParents($tid) {
if (!isset($this->parentsAll[$tid])) {
$parents = array();
$parents = [];
if ($term = $this->load($tid)) {
$parents[$term->id()] = $term;
$terms_to_search[] = $term->id();
@@ -169,7 +169,7 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac
*/
public function loadChildren($tid, $vid = NULL) {
if (!isset($this->children[$tid])) {
$children = array();
$children = [];
$query = $this->database->select('taxonomy_term_field_data', 't');
$query->join('taxonomy_term_hierarchy', 'h', 'h.tid = t.tid');
$query->addField('t', 'tid');
@@ -178,7 +178,7 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac
$query->condition('t.vid', $vid);
}
$query->condition('t.default_langcode', 1);
$query->addTag('term_access');
$query->addTag('taxonomy_term_access');
$query->orderBy('t.weight');
$query->orderBy('t.name');
if ($ids = $query->execute()->fetchCol()) {
@@ -198,15 +198,15 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac
// We cache trees, so it's not CPU-intensive to call on a term and its
// children, too.
if (!isset($this->treeChildren[$vid])) {
$this->treeChildren[$vid] = array();
$this->treeParents[$vid] = array();
$this->treeTerms[$vid] = array();
$this->treeChildren[$vid] = [];
$this->treeParents[$vid] = [];
$this->treeTerms[$vid] = [];
$query = $this->database->select('taxonomy_term_field_data', 't');
$query->join('taxonomy_term_hierarchy', 'h', 'h.tid = t.tid');
$result = $query
->addTag('term_access')
->addTag('taxonomy_term_access')
->fields('t')
->fields('h', array('parent'))
->fields('h', ['parent'])
->condition('t.vid', $vid)
->condition('t.default_langcode', 1)
->orderBy('t.weight')
@@ -221,17 +221,17 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac
// Load full entities, if necessary. The entity controller statically
// caches the results.
$term_entities = array();
$term_entities = [];
if ($load_entities) {
$term_entities = $this->loadMultiple(array_keys($this->treeTerms[$vid]));
}
$max_depth = (!isset($max_depth)) ? count($this->treeChildren[$vid]) : $max_depth;
$tree = array();
$tree = [];
// Keeps track of the parents we have to process, the last entry is used
// for the next processing step.
$process_parents = array();
$process_parents = [];
$process_parents[] = $parent;
// Loops over the parent terms and adds its children to the tree array.
@@ -304,7 +304,7 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac
*/
public function resetWeights($vid) {
$this->database->update('taxonomy_term_field_data')
->fields(array('weight' => 0))
->fields(['weight' => 0])
->condition('vid', $vid)
->execute();
}
@@ -312,15 +312,15 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac
/**
* {@inheritdoc}
*/
public function getNodeTerms(array $nids, array $vocabs = array(), $langcode = NULL) {
public function getNodeTerms(array $nids, array $vocabs = [], $langcode = NULL) {
$query = db_select('taxonomy_term_field_data', 'td');
$query->innerJoin('taxonomy_index', 'tn', 'td.tid = tn.tid');
$query->fields('td', array('tid'));
$query->fields('td', ['tid']);
$query->addField('tn', 'nid', 'node_nid');
$query->orderby('td.weight');
$query->orderby('td.name');
$query->condition('tn.nid', $nids, 'IN');
$query->addTag('term_access');
$query->addTag('taxonomy_term_access');
if (!empty($vocabs)) {
$query->condition('td.vid', $vocabs, 'IN');
}
@@ -328,15 +328,15 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac
$query->condition('td.langcode', $langcode);
}
$results = array();
$all_tids = array();
$results = [];
$all_tids = [];
foreach ($query->execute() as $term_record) {
$results[$term_record->node_nid][] = $term_record->tid;
$all_tids[] = $term_record->tid;
}
$all_terms = $this->loadMultiple($all_tids);
$terms = array();
$terms = [];
foreach ($results as $nid => $tids) {
foreach ($tids as $tid) {
$terms[$nid][$tid] = $all_terms[$tid];
@@ -361,13 +361,13 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac
public function __wakeup() {
parent::__wakeup();
// Initialize static caches.
$this->parents = array();
$this->parentsAll = array();
$this->children = array();
$this->treeChildren = array();
$this->treeParents = array();
$this->treeTerms = array();
$this->trees = array();
$this->parents = [];
$this->parentsAll = [];
$this->children = [];
$this->treeChildren = [];
$this->treeParents = [];
$this->treeTerms = [];
$this->trees = [];
}
}
@@ -116,6 +116,6 @@ interface TermStorageInterface extends ContentEntityStorageInterface {
* @return array
* An array of nids and the term entities they were tagged with.
*/
public function getNodeTerms(array $nids, array $vocabs = array(), $langcode = NULL);
public function getNodeTerms(array $nids, array $vocabs = [], $langcode = NULL);
}
+47 -47
View File
@@ -17,93 +17,93 @@ class TermStorageSchema extends SqlContentEntityStorageSchema {
protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $reset = FALSE) {
$schema = parent::getEntitySchema($entity_type, $reset = FALSE);
$schema['taxonomy_term_field_data']['indexes'] += array(
'taxonomy_term__tree' => array('vid', 'weight', 'name'),
'taxonomy_term__vid_name' => array('vid', 'name'),
);
$schema['taxonomy_term_field_data']['indexes'] += [
'taxonomy_term__tree' => ['vid', 'weight', 'name'],
'taxonomy_term__vid_name' => ['vid', 'name'],
];
$schema['taxonomy_term_hierarchy'] = array(
$schema['taxonomy_term_hierarchy'] = [
'description' => 'Stores the hierarchical relationship between terms.',
'fields' => array(
'tid' => array(
'fields' => [
'tid' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'Primary Key: The {taxonomy_term_data}.tid of the term.',
),
'parent' => array(
],
'parent' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => "Primary Key: The {taxonomy_term_data}.tid of the term's parent. 0 indicates no parent.",
),
),
'indexes' => array(
'parent' => array('parent'),
),
'foreign keys' => array(
'taxonomy_term_data' => array(
],
],
'indexes' => [
'parent' => ['parent'],
],
'foreign keys' => [
'taxonomy_term_data' => [
'table' => 'taxonomy_term_data',
'columns' => array('tid' => 'tid'),
),
),
'primary key' => array('tid', 'parent'),
);
'columns' => ['tid' => 'tid'],
],
],
'primary key' => ['tid', 'parent'],
];
$schema['taxonomy_index'] = array(
$schema['taxonomy_index'] = [
'description' => 'Maintains denormalized information about node/term relationships.',
'fields' => array(
'nid' => array(
'fields' => [
'nid' => [
'description' => 'The {node}.nid this record tracks.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'tid' => array(
],
'tid' => [
'description' => 'The term ID.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'status' => array(
],
'status' => [
'description' => 'Boolean indicating whether the node is published (visible to non-administrators).',
'type' => 'int',
'not null' => TRUE,
'default' => 1,
),
'sticky' => array(
],
'sticky' => [
'description' => 'Boolean indicating whether the node is sticky.',
'type' => 'int',
'not null' => FALSE,
'default' => 0,
'size' => 'tiny',
),
'created' => array(
],
'created' => [
'description' => 'The Unix timestamp when the node was created.',
'type' => 'int',
'not null' => TRUE,
'default' => 0,
),
),
'primary key' => array('nid', 'tid'),
'indexes' => array(
'term_node' => array('tid', 'status', 'sticky', 'created'),
),
'foreign keys' => array(
'tracked_node' => array(
],
],
'primary key' => ['nid', 'tid'],
'indexes' => [
'term_node' => ['tid', 'status', 'sticky', 'created'],
],
'foreign keys' => [
'tracked_node' => [
'table' => 'node',
'columns' => array('nid' => 'nid'),
),
'term' => array(
'columns' => ['nid' => 'nid'],
],
'term' => [
'table' => 'taxonomy_term_data',
'columns' => array('tid' => 'tid'),
),
),
);
'columns' => ['tid' => 'tid'],
],
],
];
return $schema;
}
@@ -16,7 +16,7 @@ class TermTranslationHandler extends ContentTranslationHandler {
*/
public function entityFormAlter(array &$form, FormStateInterface $form_state, EntityInterface $entity) {
parent::entityFormAlter($form, $form_state, $entity);
$form['actions']['submit']['#submit'][] = array($this, 'entityFormSave');
$form['actions']['submit']['#submit'][] = [$this, 'entityFormSave'];
}
/**
@@ -26,7 +26,7 @@ class TermTranslationHandler extends ContentTranslationHandler {
*
* @see \Drupal\Core\Entity\EntityForm::build()
*/
function entityFormSave(array $form, FormStateInterface $form_state) {
public function entityFormSave(array $form, FormStateInterface $form_state) {
if ($this->getSourceLangcode($form_state)) {
$entity = $form_state->getFormObject()->getEntity();
// We need a redirect here, otherwise we would get an access denied page,
@@ -16,10 +16,10 @@ class TermViewBuilder extends EntityViewBuilder {
*/
protected function alterBuild(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
parent::alterBuild($build, $entity, $display, $view_mode);
$build['#contextual_links']['taxonomy_term'] = array(
'route_parameters' => array('taxonomy_term' => $entity->id()),
'metadata' => array('changed' => $entity->getChangedTime()),
);
$build['#contextual_links']['taxonomy_term'] = [
'route_parameters' => ['taxonomy_term' => $entity->id()],
'metadata' => ['changed' => $entity->getChangedTime()],
];
}
}
+70 -70
View File
@@ -16,16 +16,16 @@ class TermViewsData extends EntityViewsData {
$data = parent::getViewsData();
$data['taxonomy_term_field_data']['table']['base']['help'] = $this->t('Taxonomy terms are attached to nodes.');
$data['taxonomy_term_field_data']['table']['base']['access query tag'] = 'term_access';
$data['taxonomy_term_field_data']['table']['base']['access query tag'] = 'taxonomy_term_access';
$data['taxonomy_term_field_data']['table']['wizard_id'] = 'taxonomy_term';
$data['taxonomy_term_field_data']['table']['join'] = array(
$data['taxonomy_term_field_data']['table']['join'] = [
// This is provided for the many_to_one argument.
'taxonomy_index' => array(
'taxonomy_index' => [
'field' => 'tid',
'left_field' => 'tid',
),
);
],
];
$data['taxonomy_term_field_data']['tid']['help'] = $this->t('The tid of a taxonomy term.');
@@ -39,18 +39,18 @@ class TermViewsData extends EntityViewsData {
$data['taxonomy_term_field_data']['tid']['filter']['hierarchy table'] = 'taxonomy_term_hierarchy';
$data['taxonomy_term_field_data']['tid']['filter']['numeric'] = TRUE;
$data['taxonomy_term_field_data']['tid_raw'] = array(
$data['taxonomy_term_field_data']['tid_raw'] = [
'title' => $this->t('Term ID'),
'help' => $this->t('The tid of a taxonomy term.'),
'real field' => 'tid',
'filter' => array(
'filter' => [
'id' => 'numeric',
'allow empty' => TRUE,
),
);
],
];
$data['taxonomy_term_field_data']['tid_representative'] = array(
'relationship' => array(
$data['taxonomy_term_field_data']['tid_representative'] = [
'relationship' => [
'title' => $this->t('Representative node'),
'label' => $this->t('Representative node'),
'help' => $this->t('Obtains a single representative node for each term, according to a chosen sort criterion.'),
@@ -62,12 +62,12 @@ class TermViewsData extends EntityViewsData {
'base' => 'node_field_data',
'field' => 'nid',
'relationship' => 'node_field_data:term_node_tid'
),
);
],
];
$data['taxonomy_term_field_data']['vid']['help'] = $this->t('Filter the results of "Taxonomy: Term" to a particular vocabulary.');
unset($data['taxonomy_term_field_data']['vid']['field']);
unset($data['taxonomy_term_field_data']['vid']['argument']);
$data['taxonomy_term_field_data']['vid']['argument']['id'] = 'vocabulary_vid';
unset($data['taxonomy_term_field_data']['vid']['sort']);
$data['taxonomy_term_field_data']['name']['field']['id'] = 'term_name';
@@ -79,114 +79,114 @@ class TermViewsData extends EntityViewsData {
$data['taxonomy_term_field_data']['changed']['title'] = $this->t('Updated date');
$data['taxonomy_term_field_data']['changed']['help'] = $this->t('The date the term was last updated.');
$data['taxonomy_term_field_data']['changed_fulldate'] = array(
$data['taxonomy_term_field_data']['changed_fulldate'] = [
'title' => $this->t('Updated date'),
'help' => $this->t('Date in the form of CCYYMMDD.'),
'argument' => array(
'argument' => [
'field' => 'changed',
'id' => 'date_fulldate',
),
);
],
];
$data['taxonomy_term_field_data']['changed_year_month'] = array(
$data['taxonomy_term_field_data']['changed_year_month'] = [
'title' => $this->t('Updated year + month'),
'help' => $this->t('Date in the form of YYYYMM.'),
'argument' => array(
'argument' => [
'field' => 'changed',
'id' => 'date_year_month',
),
);
],
];
$data['taxonomy_term_field_data']['changed_year'] = array(
$data['taxonomy_term_field_data']['changed_year'] = [
'title' => $this->t('Updated year'),
'help' => $this->t('Date in the form of YYYY.'),
'argument' => array(
'argument' => [
'field' => 'changed',
'id' => 'date_year',
),
);
],
];
$data['taxonomy_term_field_data']['changed_month'] = array(
$data['taxonomy_term_field_data']['changed_month'] = [
'title' => $this->t('Updated month'),
'help' => $this->t('Date in the form of MM (01 - 12).'),
'argument' => array(
'argument' => [
'field' => 'changed',
'id' => 'date_month',
),
);
],
];
$data['taxonomy_term_field_data']['changed_day'] = array(
$data['taxonomy_term_field_data']['changed_day'] = [
'title' => $this->t('Updated day'),
'help' => $this->t('Date in the form of DD (01 - 31).'),
'argument' => array(
'argument' => [
'field' => 'changed',
'id' => 'date_day',
),
);
],
];
$data['taxonomy_term_field_data']['changed_week'] = array(
$data['taxonomy_term_field_data']['changed_week'] = [
'title' => $this->t('Updated week'),
'help' => $this->t('Date in the form of WW (01 - 53).'),
'argument' => array(
'argument' => [
'field' => 'changed',
'id' => 'date_week',
),
);
],
];
$data['taxonomy_index']['table']['group'] = $this->t('Taxonomy term');
$data['taxonomy_index']['table']['join'] = array(
'taxonomy_term_field_data' => array(
$data['taxonomy_index']['table']['join'] = [
'taxonomy_term_field_data' => [
// links directly to taxonomy_term_field_data via tid
'left_field' => 'tid',
'field' => 'tid',
),
'node_field_data' => array(
],
'node_field_data' => [
// links directly to node via nid
'left_field' => 'nid',
'field' => 'nid',
),
'taxonomy_term_hierarchy' => array(
],
'taxonomy_term_hierarchy' => [
'left_field' => 'tid',
'field' => 'tid',
),
);
],
];
$data['taxonomy_index']['nid'] = array(
$data['taxonomy_index']['nid'] = [
'title' => $this->t('Content with term'),
'help' => $this->t('Relate all content tagged with a term.'),
'relationship' => array(
'relationship' => [
'id' => 'standard',
'base' => 'node',
'base field' => 'nid',
'label' => $this->t('node'),
'skip base' => 'node',
),
);
],
];
// @todo This stuff needs to move to a node field since really it's all
// about nodes.
$data['taxonomy_index']['tid'] = array(
$data['taxonomy_index']['tid'] = [
'group' => $this->t('Content'),
'title' => $this->t('Has taxonomy term ID'),
'help' => $this->t('Display content if it has the selected taxonomy terms.'),
'argument' => array(
'argument' => [
'id' => 'taxonomy_index_tid',
'name table' => 'taxonomy_term_field_data',
'name field' => 'name',
'empty field name' => $this->t('Uncategorized'),
'numeric' => TRUE,
'skip base' => 'taxonomy_term_field_data',
),
'filter' => array(
],
'filter' => [
'title' => $this->t('Has taxonomy term'),
'id' => 'taxonomy_index_tid',
'hierarchy table' => 'taxonomy_term_hierarchy',
'numeric' => TRUE,
'skip base' => 'taxonomy_term_field_data',
'allow empty' => TRUE,
),
);
],
];
$data['taxonomy_index']['status'] = [
'title' => $this->t('Publish status'),
@@ -226,37 +226,37 @@ class TermViewsData extends EntityViewsData {
$data['taxonomy_term_hierarchy']['table']['group'] = $this->t('Taxonomy term');
$data['taxonomy_term_hierarchy']['table']['provider'] = 'taxonomy';
$data['taxonomy_term_hierarchy']['table']['join'] = array(
'taxonomy_term_hierarchy' => array(
$data['taxonomy_term_hierarchy']['table']['join'] = [
'taxonomy_term_hierarchy' => [
// Link to self through left.parent = right.tid (going down in depth).
'left_field' => 'tid',
'field' => 'parent',
),
'taxonomy_term_field_data' => array(
],
'taxonomy_term_field_data' => [
// Link directly to taxonomy_term_field_data via tid.
'left_field' => 'tid',
'field' => 'tid',
),
);
],
];
$data['taxonomy_term_hierarchy']['parent'] = array(
$data['taxonomy_term_hierarchy']['parent'] = [
'title' => $this->t('Parent term'),
'help' => $this->t('The parent term of the term. This can produce duplicate entries if you are using a vocabulary that allows multiple parents.'),
'relationship' => array(
'relationship' => [
'base' => 'taxonomy_term_field_data',
'field' => 'parent',
'label' => $this->t('Parent'),
'id' => 'standard',
),
'filter' => array(
],
'filter' => [
'help' => $this->t('Filter the results of "Taxonomy: Term" by the parent pid.'),
'id' => 'numeric',
),
'argument' => array(
],
'argument' => [
'help' => $this->t('The parent term of the term.'),
'id' => 'taxonomy',
),
);
],
];
return $data;
}
+17 -16
View File
@@ -18,7 +18,7 @@ class RssTest extends TaxonomyTestBase {
*
* @var array
*/
public static $modules = array('node', 'field_ui', 'views');
public static $modules = ['node', 'field_ui', 'views'];
/**
* Vocabulary for testing.
@@ -41,23 +41,23 @@ class RssTest extends TaxonomyTestBase {
$this->vocabulary = $this->createVocabulary();
$this->fieldName = 'taxonomy_' . $this->vocabulary->id();
$handler_settings = array(
'target_bundles' => array(
$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, array(
->setComponent($this->fieldName, [
'type' => 'options_select',
))
])
->save();
entity_get_display('node', 'article', 'default')
->setComponent($this->fieldName, array(
->setComponent($this->fieldName, [
'type' => 'entity_reference_label',
))
])
->save();
}
@@ -66,26 +66,27 @@ class RssTest extends TaxonomyTestBase {
*
* Create a node and assert that taxonomy terms appear in rss.xml.
*/
function testTaxonomyRss() {
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 = array(
$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 = array(
$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 = array();
$edit = [];
$edit['title[0][value]'] = $this->randomMachineName();
$edit[$this->fieldName . '[]'] = $term1->id();
$this->drupalPostForm('node/add/article', $edit, t('Save'));
@@ -94,7 +95,7 @@ class RssTest extends TaxonomyTestBase {
$this->drupalGet('rss.xml');
$test_element = sprintf(
'<category %s>%s</category>',
'domain="' . $term1->url('canonical', array('absolute' => TRUE)) . '"',
'domain="' . $term1->url('canonical', ['absolute' => TRUE]) . '"',
$term1->getName()
);
$this->assertRaw($test_element, 'Term is displayed when viewing the rss feed.');
@@ -14,7 +14,7 @@ class TaxonomyTermIndentationTest extends TaxonomyTestBase {
*
* @var array
*/
public static $modules = array('taxonomy');
public static $modules = ['taxonomy'];
/**
* Vocabulary for testing.
@@ -32,7 +32,7 @@ class TaxonomyTermIndentationTest extends TaxonomyTestBase {
/**
* Tests term indentation.
*/
function testTermIndentation() {
public function testTermIndentation() {
// Create three taxonomy terms.
$term1 = $this->createTerm($this->vocabulary);
$term2 = $this->createTerm($this->vocabulary);
@@ -42,12 +42,12 @@ class TaxonomyTermIndentationTest extends TaxonomyTestBase {
$taxonomy_storage = $this->container->get('entity.manager')->getStorage('taxonomy_term');
// Indent the second term under the first one.
$edit = array(
$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,
'terms[tid:' . $term2->id() . ':0][weight]' => 1,
);
];
// Submit the edited form and check for HTML indentation element presence.
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->get('vid') . '/overview', $edit, t('Save'));
@@ -58,12 +58,12 @@ class TaxonomyTermIndentationTest extends TaxonomyTestBase {
$this->assertEqual(key($parents), 1, 'Term 1 is the term 2\'s parent');
// Move the second term back out to the root level.
$edit = array(
$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,
'terms[tid:' . $term2->id() . ':0][weight]' => 1,
);
];
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->get('vid' ) . '/overview', $edit, t('Save'));
// All terms back at the root level, no indentation should be present.
@@ -2,11 +2,17 @@
namespace Drupal\taxonomy\Tests;
@trigger_error(__NAMESPACE__ . '\TaxonomyTestBase is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\taxonomy\Functional\TaxonomyTestBase', E_USER_DEPRECATED);
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\simpletest\WebTestBase;
use Drupal\Tests\taxonomy\Functional\TaxonomyTestTrait;
/**
* Provides common helper methods for Taxonomy module tests.
*
* @deprecated Scheduled for removal in Drupal 9.0.0.
* Use \Drupal\Tests\taxonomy\Functional\TaxonomyTestBase instead.
*/
abstract class TaxonomyTestBase extends WebTestBase {
@@ -18,7 +24,7 @@ abstract class TaxonomyTestBase extends WebTestBase {
*
* @var array
*/
public static $modules = array('taxonomy', 'block');
public static $modules = ['taxonomy', 'block'];
/**
* {@inheritdoc}
@@ -29,7 +35,7 @@ abstract class TaxonomyTestBase extends WebTestBase {
// Create Basic page and Article node types.
if ($this->profile != 'standard') {
$this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
}
}
@@ -2,6 +2,8 @@
namespace Drupal\taxonomy\Tests;
@trigger_error(__NAMESPACE__ . '\TaxonomyTestTrait is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\taxonomy\Functional\TaxonomyTestTrait', E_USER_DEPRECATED);
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Language\LanguageInterface;
use Drupal\taxonomy\Entity\Vocabulary;
@@ -9,13 +11,16 @@ use Drupal\taxonomy\Entity\Term;
/**
* Provides common helper methods for Taxonomy module tests.
*
* @deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0.
* Use \Drupal\Tests\taxonomy\Functional\TaxonomyTestTrait
*/
trait TaxonomyTestTrait {
/**
* Returns a new vocabulary with random properties.
*/
function createVocabulary() {
public function createVocabulary() {
// Create a vocabulary.
$vocabulary = Vocabulary::create([
'name' => $this->randomMachineName(),
@@ -40,7 +45,7 @@ trait TaxonomyTestTrait {
* @return \Drupal\taxonomy\Entity\Term
* The new taxonomy term object.
*/
function createTerm(Vocabulary $vocabulary, $values = array()) {
public function createTerm(Vocabulary $vocabulary, $values = []) {
$filter_formats = filter_formats();
$format = array_pop($filter_formats);
$term = Term::create($values + [
@@ -2,6 +2,8 @@
namespace Drupal\taxonomy\Tests;
@trigger_error(__NAMESPACE__ . '\TaxonomyTranslationTestTrait is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Instead, use \Drupal\Tests\taxonomy\Functional\TaxonomyTranslationTestTrait', E_USER_DEPRECATED);
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\field\Entity\FieldStorageConfig;
@@ -9,6 +11,9 @@ use Drupal\language\Entity\ConfigurableLanguage;
/**
* Provides common testing base for translated taxonomy terms.
*
* @deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0.
* Use \Drupal\Tests\taxonomy\Functional\TaxonomyTranslationTestTrait
*/
trait TaxonomyTranslationTestTrait {
@@ -79,26 +84,26 @@ trait TaxonomyTranslationTestTrait {
* to FALSE.
*/
protected function setUpTermReferenceField() {
$handler_settings = array(
'target_bundles' => array(
$handler_settings = [
'target_bundles' => [
$this->vocabulary->id() => $this->vocabulary->id(),
),
],
'auto_create' => TRUE,
);
];
$this->createEntityReferenceField('node', 'article', $this->termFieldName, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
$field_storage = FieldStorageConfig::loadByName('node', $this->termFieldName);
$field_storage->setTranslatable(FALSE);
$field_storage->save();
entity_get_form_display('node', 'article', 'default')
->setComponent($this->termFieldName, array(
->setComponent($this->termFieldName, [
'type' => 'entity_reference_autocomplete_tags',
))
])
->save();
entity_get_display('node', 'article', 'default')
->setComponent($this->termFieldName, array(
->setComponent($this->termFieldName, [
'type' => 'entity_reference_label',
))
])
->save();
}
@@ -0,0 +1,204 @@
<?php
namespace Drupal\taxonomy\Tests;
use Drupal\Component\Utility\Unicode;
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 {
/**
* 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 = Unicode::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]['data-autocomplete-path']);
}
/**
* 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);
}
}
+64 -59
View File
@@ -52,31 +52,31 @@ class TermTest extends TaxonomyTestBase {
$field_name = 'taxonomy_' . $this->vocabulary->id();
$handler_settings = array(
'target_bundles' => array(
$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, array(
->setComponent($field_name, [
'type' => 'options_select',
))
])
->save();
entity_get_display('node', 'article', 'default')
->setComponent($field_name, array(
->setComponent($field_name, [
'type' => 'entity_reference_label',
))
])
->save();
}
/**
* Test terms in a single and multiple hierarchy.
*/
function testTaxonomyTermHierarchy() {
public function testTaxonomyTermHierarchy() {
// Create two taxonomy terms.
$term1 = $this->createTerm($this->vocabulary);
$term2 = $this->createTerm($this->vocabulary);
@@ -89,8 +89,8 @@ class TermTest extends TaxonomyTestBase {
$this->assertEqual(0, $vocabulary->getHierarchy(), 'Vocabulary is flat.');
// Edit $term2, setting $term1 as parent.
$edit = array();
$edit['parent[]'] = array($term1->id());
$edit = [];
$edit['parent[]'] = [$term1->id()];
$this->drupalPostForm('taxonomy/term/' . $term2->id() . '/edit', $edit, t('Save'));
// Check the hierarchy.
@@ -107,7 +107,7 @@ class TermTest extends TaxonomyTestBase {
// Create a third term and save this as a parent of term2.
$term3 = $this->createTerm($this->vocabulary);
$term2->parent = array($term1->id(), $term3->id());
$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.');
@@ -116,18 +116,18 @@ class TermTest extends TaxonomyTestBase {
/**
* Tests that many terms with parents show on each page
*/
function testTaxonomyTermChildTerms() {
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 = '';
$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 = array();
$edit = [];
// Set terms in order so we know which terms will be on which pages.
$edit['weight'] = $x;
@@ -149,14 +149,14 @@ class TermTest extends TaxonomyTestBase {
}
// Get Page 2.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview', array('query' => array('page' => 1)));
$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', array('query' => array('page' => 2)));
$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');
@@ -171,13 +171,13 @@ class TermTest extends TaxonomyTestBase {
*
* Save & edit a node and assert that taxonomy terms are saved/loaded properly.
*/
function testTaxonomyNode() {
public function testTaxonomyNode() {
// Create two taxonomy terms.
$term1 = $this->createTerm($this->vocabulary);
$term2 = $this->createTerm($this->vocabulary);
// Post an article.
$edit = array();
$edit = [];
$edit['title[0][value]'] = $this->randomMachineName();
$edit['body[0][value]'] = $this->randomMachineName();
$edit[$this->field->getName() . '[]'] = $term1->id();
@@ -190,7 +190,7 @@ class TermTest extends TaxonomyTestBase {
$this->clickLink(t('Edit'));
$this->assertText($term1->getName(), 'Term is displayed when editing the node.');
$this->drupalPostForm(NULL, array(), t('Save'));
$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.
@@ -210,28 +210,28 @@ class TermTest extends TaxonomyTestBase {
/**
* Test term creation with a free-tagging vocabulary from the node form.
*/
function testNodeTermCreationAndDeletion() {
public function testNodeTermCreationAndDeletion() {
// Enable tags in the vocabulary.
$field = $this->field;
entity_get_form_display($field->getTargetEntityTypeId(), $field->getTargetBundle(), 'default')
->setComponent($field->getName(), array(
->setComponent($field->getName(), [
'type' => 'entity_reference_autocomplete_tags',
'settings' => array(
'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 = array(
$terms = [
'term1' => 'a' . $this->randomMachineName(),
'term2' => 'b' . $this->randomMachineName(),
'term3' => 'c' . $this->randomMachineName() . ', ' . $this->randomMachineName(),
'term4' => 'd' . $this->randomMachineName(),
);
];
$edit = array();
$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
@@ -255,13 +255,18 @@ class TermTest extends TaxonomyTestBase {
// 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.');
$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 = array();
$term_objects = [];
foreach ($terms as $key => $term) {
$term_objects[$key] = taxonomy_term_load_multiple_by_name($term);
$term_objects[$key] = reset($term_objects[$key]);
@@ -283,30 +288,30 @@ class TermTest extends TaxonomyTestBase {
// 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->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.', array('%name' => $term_name, '%deleted1' => $term_objects['term1']->getName(), '%deleted2' => $term_objects['term2']->getName())));
$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.', 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())));
$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.
*/
function testTermInterface() {
\Drupal::service('module_installer')->install(array('views'));
$edit = array(
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[]'] = array(0);
$edit['parent[]'] = [0];
// Create the term to edit.
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add', $edit, t('Save'));
@@ -323,10 +328,10 @@ class TermTest extends TaxonomyTestBase {
$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 = array(
$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'));
@@ -375,7 +380,7 @@ class TermTest extends TaxonomyTestBase {
/**
* Save, edit and delete a term using the user interface.
*/
function testTermReorder() {
public function testTermReorder() {
$this->createTerm($this->vocabulary);
$this->createTerm($this->vocabulary);
$this->createTerm($this->vocabulary);
@@ -393,7 +398,7 @@ class TermTest extends TaxonomyTestBase {
// "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.
$edit = array(
$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,
@@ -406,18 +411,18 @@ class TermTest extends TaxonomyTestBase {
'terms[tid:' . $term1->id() . ':0][term][parent]' => 0,
'terms[tid:' . $term1->id() . ':0][term][depth]' => 0,
'terms[tid:' . $term1->id() . ':0][weight]' => 2,
);
];
$this->drupalPostForm(NULL, $edit, t('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, array($term2->id()), 'Term 3 was made a child of term 2.');
$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', array(), t('Reset to alphabetical'));
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview', [], t('Reset to alphabetical'));
// Submit confirmation form.
$this->drupalPostForm(NULL, array(), t('Reset to alphabetical'));
$this->drupalPostForm(NULL, [], t('Reset to alphabetical'));
// Ensure form redirected back to overview.
$this->assertUrl('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview');
@@ -426,22 +431,22 @@ class TermTest extends TaxonomyTestBase {
$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, array($term2->id()), 'Term 3 is still a child of 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.
*/
function testTermMultipleParentsInterface() {
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 = array(
$edit = [
'name[0][value]' => $this->randomMachineName(12),
'description[0][value]' => $this->randomMachineName(100),
'parent[]' => array(0, $parent->id()),
);
'parent[]' => [0, $parent->id()],
];
// Save the new term.
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add', $edit, t('Save'));
@@ -461,7 +466,7 @@ class TermTest extends TaxonomyTestBase {
/**
* Test taxonomy_term_load_multiple_by_name().
*/
function testTaxonomyGetTermByName() {
public function testTaxonomyGetTermByName() {
$term = $this->createTerm($this->vocabulary);
// Load the term with the exact name.
@@ -521,18 +526,18 @@ class TermTest extends TaxonomyTestBase {
/**
* Tests that editing and saving a node with no changes works correctly.
*/
function testReSavingTags() {
public function testReSavingTags() {
// Enable tags in the vocabulary.
$field = $this->field;
entity_get_form_display($field->getTargetEntityTypeId(), $field->getTargetBundle(), 'default')
->setComponent($field->getName(), array(
->setComponent($field->getName(), [
'type' => 'entity_reference_autocomplete_tags',
))
])
->save();
// Create a term and a node using it.
$term = $this->createTerm($this->vocabulary);
$edit = array();
$edit = [];
$edit['title[0][value]'] = $this->randomMachineName(8);
$edit['body[0][value]'] = $this->randomMachineName(16);
$edit[$this->field->getName() . '[target_id]'] = $term->getName();
@@ -542,7 +547,7 @@ class TermTest extends TaxonomyTestBase {
// changes.
$this->clickLink(t('Edit'));
$this->assertRaw($term->getName(), 'Term is displayed when editing the node.');
$this->drupalPostForm(NULL, array(), t('Save'));
$this->drupalPostForm(NULL, [], t('Save'));
$this->assertRaw($term->getName(), 'Term is displayed after saving the node with no changes.');
}
@@ -20,23 +20,23 @@ class TermTranslationTest extends TaxonomyTestBase {
*
* @var array
*/
protected $termTranslationMap = array(
protected $termTranslationMap = [
'one' => 'translatedOne',
'two' => 'translatedTwo',
'three' => 'translatedThree',
);
];
/**
* Created terms.
*
* @var \Drupal\taxonomy\Entity\Term[]
*/
protected $terms = array();
protected $terms = [];
/**
* {@inheritdoc}
*/
public static $modules = array('taxonomy', 'language', 'content_translation');
public static $modules = ['taxonomy', 'language', 'content_translation'];
/**
* {@inheritdoc}
@@ -55,7 +55,7 @@ class TermTranslationTest extends TaxonomyTestBase {
*/
public function testTranslatedBreadcrumbs() {
// Ensure non-translated breadcrumb is correct.
$breadcrumb = array(Url::fromRoute('<front>')->toString() => 'Home');
$breadcrumb = [Url::fromRoute('<front>')->toString() => 'Home'];
foreach ($this->terms as $term) {
$breadcrumb[$term->url()] = $term->label();
}
@@ -69,7 +69,7 @@ class TermTranslationTest extends TaxonomyTestBase {
$languages = \Drupal::languageManager()->getLanguages();
// Construct the expected translated breadcrumb.
$breadcrumb = array(Url::fromRoute('<front>', [], ['language' => $languages[$this->translateToLangcode]])->toString() => 'Home');
$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]]);
@@ -87,14 +87,14 @@ class TermTranslationTest extends TaxonomyTestBase {
/**
* Test translation of terms are showed in the node.
*/
protected function testTermsTranslation() {
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, array(
->setComponent($this->termFieldName, [
'type' => 'options_buttons',
))
])
->save();
$this->drupalLogin($this->drupalCreateUser(['create article content']));
@@ -118,15 +118,15 @@ class TermTranslationTest extends TaxonomyTestBase {
$parent_vid = 0;
foreach ($this->termTranslationMap as $name => $translation) {
$term = $this->createTerm($this->vocabulary, array(
$term = $this->createTerm($this->vocabulary, [
'name' => $name,
'langcode' => $this->baseLangcode,
'parent' => $parent_vid,
));
]);
$term->addTranslation($this->translateToLangcode, array(
$term->addTranslation($this->translateToLangcode, [
'name' => $translation,
));
]);
$term->save();
// Each term is nested under the last.
+24 -24
View File
@@ -52,59 +52,59 @@ class VocabularyForm extends BundleEntityFormBase {
$form['#title'] = $this->t('Edit vocabulary');
}
$form['name'] = array(
$form['name'] = [
'#type' => 'textfield',
'#title' => $this->t('Name'),
'#default_value' => $vocabulary->label(),
'#maxlength' => 255,
'#required' => TRUE,
);
$form['vid'] = array(
];
$form['vid'] = [
'#type' => 'machine_name',
'#default_value' => $vocabulary->id(),
'#maxlength' => EntityTypeInterface::BUNDLE_MAX_LENGTH,
'#machine_name' => array(
'exists' => array($this, 'exists'),
'source' => array('name'),
),
);
$form['description'] = array(
'#machine_name' => [
'exists' => [$this, 'exists'],
'source' => ['name'],
],
];
$form['description'] = [
'#type' => 'textfield',
'#title' => $this->t('Description'),
'#default_value' => $vocabulary->getDescription(),
);
];
// $form['langcode'] is not wrapped in an
// if ($this->moduleHandler->moduleExists('language')) check because the
// language_select form element works also without the language module being
// installed. https://www.drupal.org/node/1749954 documents the new element.
$form['langcode'] = array(
$form['langcode'] = [
'#type' => 'language_select',
'#title' => $this->t('Vocabulary language'),
'#languages' => LanguageInterface::STATE_ALL,
'#default_value' => $vocabulary->language()->getId(),
);
];
if ($this->moduleHandler->moduleExists('language')) {
$form['default_terms_language'] = array(
$form['default_terms_language'] = [
'#type' => 'details',
'#title' => $this->t('Terms language'),
'#open' => TRUE,
);
$form['default_terms_language']['default_language'] = array(
];
$form['default_terms_language']['default_language'] = [
'#type' => 'language_configuration',
'#entity_information' => array(
'#entity_information' => [
'entity_type' => 'taxonomy_term',
'bundle' => $vocabulary->id(),
),
],
'#default_value' => ContentLanguageSettings::loadByEntityTypeBundle('taxonomy_term', $vocabulary->id()),
);
];
}
// Set the hierarchy to "multiple parents" by default. This simplifies the
// vocabulary form and standardizes the term form.
$form['hierarchy'] = array(
$form['hierarchy'] = [
'#type' => 'value',
'#value' => '0',
);
];
$form = parent::form($form, $form_state);
return $this->protectBundleIdElement($form);
@@ -123,14 +123,14 @@ class VocabularyForm extends BundleEntityFormBase {
$edit_link = $this->entity->link($this->t('Edit'));
switch ($status) {
case SAVED_NEW:
drupal_set_message($this->t('Created new vocabulary %name.', array('%name' => $vocabulary->label())));
$this->logger('taxonomy')->notice('Created new vocabulary %name.', array('%name' => $vocabulary->label(), 'link' => $edit_link));
drupal_set_message($this->t('Created new vocabulary %name.', ['%name' => $vocabulary->label()]));
$this->logger('taxonomy')->notice('Created new vocabulary %name.', ['%name' => $vocabulary->label(), 'link' => $edit_link]);
$form_state->setRedirectUrl($vocabulary->urlInfo('overview-form'));
break;
case SAVED_UPDATED:
drupal_set_message($this->t('Updated vocabulary %name.', array('%name' => $vocabulary->label())));
$this->logger('taxonomy')->notice('Updated vocabulary %name.', array('%name' => $vocabulary->label(), 'link' => $edit_link));
drupal_set_message($this->t('Updated vocabulary %name.', ['%name' => $vocabulary->label()]));
$this->logger('taxonomy')->notice('Updated vocabulary %name.', ['%name' => $vocabulary->label(), 'link' => $edit_link]);
$form_state->setRedirectUrl($vocabulary->urlInfo('collection'));
break;
}
@@ -9,6 +9,21 @@ use Drupal\Core\Config\Entity\ConfigEntityInterface;
*/
interface VocabularyInterface extends ConfigEntityInterface {
/**
* Denotes that no term in the vocabulary has a parent.
*/
const HIERARCHY_DISABLED = 0;
/**
* Denotes that one or more terms in the vocabulary has a single parent.
*/
const HIERARCHY_SINGLE = 1;
/**
* Denotes that one or more terms in the vocabulary have multiple parents.
*/
const HIERARCHY_MULTIPLE = 2;
/**
* Returns the vocabulary hierarchy.
*
@@ -23,9 +38,9 @@ interface VocabularyInterface extends ConfigEntityInterface {
* @param int $hierarchy
* The hierarchy type of vocabulary.
* Possible values:
* - TAXONOMY_HIERARCHY_DISABLED: No parents.
* - TAXONOMY_HIERARCHY_SINGLE: Single parent.
* - TAXONOMY_HIERARCHY_MULTIPLE: Multiple parents.
* - VocabularyInterface::HIERARCHY_DISABLED: No parents.
* - VocabularyInterface::HIERARCHY_SINGLE: Single parent.
* - VocabularyInterface::HIERARCHY_MULTIPLE: Multiple parents.
*
* @return $this
*/
@@ -36,16 +36,16 @@ class VocabularyListBuilder extends DraggableListBuilder {
$operations['edit']['title'] = t('Edit vocabulary');
}
$operations['list'] = array(
$operations['list'] = [
'title' => t('List terms'),
'weight' => 0,
'url' => $entity->urlInfo('overview-form'),
);
$operations['add'] = array(
];
$operations['add'] = [
'title' => t('Add terms'),
'weight' => 10,
'url' => Url::fromRoute('entity.taxonomy_term.add_form', ['taxonomy_vocabulary' => $entity->id()]),
);
];
unset($operations['delete']);
return $operations;
@@ -56,6 +56,7 @@ class VocabularyListBuilder extends DraggableListBuilder {
*/
public function buildHeader() {
$header['label'] = t('Vocabulary name');
$header['description'] = t('Description');
return $header + parent::buildHeader();
}
@@ -64,6 +65,7 @@ class VocabularyListBuilder extends DraggableListBuilder {
*/
public function buildRow(EntityInterface $entity) {
$row['label'] = $entity->label();
$row['description']['data'] = ['#markup' => $entity->getDescription()];
return $row + parent::buildRow($entity);
}
@@ -78,7 +80,7 @@ class VocabularyListBuilder extends DraggableListBuilder {
unset($this->weightKey);
}
$build = parent::render();
$build['table']['#empty'] = t('No vocabularies available. <a href=":link">Add vocabulary</a>.', array(':link' => \Drupal::url('entity.taxonomy_vocabulary.add_form')));
$build['table']['#empty'] = t('No vocabularies available. <a href=":link">Add vocabulary</a>.', [':link' => \Drupal::url('entity.taxonomy_vocabulary.add_form')]);
return $build;
}
@@ -87,7 +89,7 @@ class VocabularyListBuilder extends DraggableListBuilder {
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form = parent::buildForm($form, $form_state);
$form['vocabularies']['#attributes'] = array('id' => 'taxonomy');
$form['vocabularies']['#attributes'] = ['id' => 'taxonomy'];
$form['actions']['submit']['#value'] = t('Save');
return $form;
@@ -21,7 +21,7 @@ class VocabularyStorage extends ConfigEntityStorage implements VocabularyStorage
* {@inheritdoc}
*/
public function getToplevelTids($vids) {
return db_query('SELECT t.tid FROM {taxonomy_term_data} t INNER JOIN {taxonomy_term_hierarchy} th ON th.tid = t.tid WHERE t.vid IN ( :vids[] ) AND th.parent = 0', array(':vids[]' => $vids))->fetchCol();
return db_query('SELECT t.tid FROM {taxonomy_term_data} t INNER JOIN {taxonomy_term_hierarchy} th ON th.tid = t.tid WHERE t.vid IN ( :vids[] ) AND th.parent = 0', [':vids[]' => $vids])->fetchCol();
}
}
+3 -3
View File
@@ -9,8 +9,8 @@ dependencies:
- text
configure: entity.taxonomy_vocabulary.collection
# Information added by Drupal.org packaging script on 2016-08-03
version: '8.1.8'
# Information added by Drupal.org packaging script on 2017-08-16
version: '8.3.7'
core: '8.x'
project: 'drupal'
datestamp: 1470233792
datestamp: 1502903957
+55 -45
View File
@@ -7,8 +7,8 @@
use Drupal\Component\Utility\Tags;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
use Drupal\Core\Render\Element;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
@@ -19,16 +19,25 @@ use Drupal\taxonomy\VocabularyInterface;
/**
* Denotes that no term in the vocabulary has a parent.
*
* @deprecated in Drupal 8.2.x and will be removed before 9.0.0. Use
* \Drupal\taxonomy\VocabularyInterface::HIERARCHY_DISABLED instead.
*/
const TAXONOMY_HIERARCHY_DISABLED = 0;
/**
* Denotes that one or more terms in the vocabulary has a single parent.
*
* @deprecated in Drupal 8.2.x and will be removed before 9.0.0. Use
* \Drupal\taxonomy\VocabularyInterface::HIERARCHY_SINGLE instead.
*/
const TAXONOMY_HIERARCHY_SINGLE = 1;
/**
* Denotes that one or more terms in the vocabulary have multiple parents.
*
* @deprecated in Drupal 8.2.x and will be removed before 9.0.0. Use
* \Drupal\taxonomy\VocabularyInterface::HIERARCHY_MULTIPLE instead.
*/
const TAXONOMY_HIERARCHY_MULTIPLE = 2;
@@ -38,23 +47,23 @@ const TAXONOMY_HIERARCHY_MULTIPLE = 2;
function taxonomy_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.taxonomy':
$field_ui_url = \Drupal::moduleHandler()->moduleExists('field_ui') ? \Drupal::url('help.page', array('name' => 'field_ui')) : '#';
$field_ui_url = \Drupal::moduleHandler()->moduleExists('field_ui') ? \Drupal::url('help.page', ['name' => 'field_ui']) : '#';
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('The Taxonomy module allows users who have permission to create and edit content to categorize (tag) content of that type. Users who have the <em>Administer vocabularies and terms</em> <a href=":permissions" title="Taxonomy module permissions">permission</a> can add <em>vocabularies</em> that contain a set of related <em>terms</em>. The terms in a vocabulary can either be pre-set by an administrator or built gradually as content is added and edited. Terms may be organized hierarchically if desired.', array(':permissions' => \Drupal::url('user.admin_permissions', array(), array('fragment' => 'module-taxonomy')))) . '</p>';
$output .= '<p>' . t('For more information, see the <a href=":taxonomy">online documentation for the Taxonomy module</a>.', array(':taxonomy' => 'https://www.drupal.org/documentation/modules/taxonomy/')) . '</p>';
$output .= '<p>' . t('The Taxonomy module allows users who have permission to create and edit content to categorize (tag) content of that type. Users who have the <em>Administer vocabularies and terms</em> <a href=":permissions" title="Taxonomy module permissions">permission</a> can add <em>vocabularies</em> that contain a set of related <em>terms</em>. The terms in a vocabulary can either be pre-set by an administrator or built gradually as content is added and edited. Terms may be organized hierarchically if desired.', [':permissions' => \Drupal::url('user.admin_permissions', [], ['fragment' => 'module-taxonomy'])]) . '</p>';
$output .= '<p>' . t('For more information, see the <a href=":taxonomy">online documentation for the Taxonomy module</a>.', [':taxonomy' => 'https://www.drupal.org/documentation/modules/taxonomy/']) . '</p>';
$output .= '<h3>' . t('Uses') . '</h3>';
$output .= '<dl>';
$output .= '<dt>' . t('Managing vocabularies') . '</dt>';
$output .= '<dd>' . t('Users who have the <em>Administer vocabularies and terms</em> permission can add and edit vocabularies from the <a href=":taxonomy_admin">Taxonomy administration page</a>. Vocabularies can be deleted from their <em>Edit vocabulary</em> page. Users with the <em>Taxonomy term: Administer fields</em> permission may add additional fields for terms in that vocabulary using the <a href=":field_ui">Field UI module</a>.', array(':taxonomy_admin' => \Drupal::url('entity.taxonomy_vocabulary.collection'), ':field_ui' => $field_ui_url)) . '</dd>';
$output .= '<dd>' . t('Users who have the <em>Administer vocabularies and terms</em> permission can add and edit vocabularies from the <a href=":taxonomy_admin">Taxonomy administration page</a>. Vocabularies can be deleted from their <em>Edit vocabulary</em> page. Users with the <em>Taxonomy term: Administer fields</em> permission may add additional fields for terms in that vocabulary using the <a href=":field_ui">Field UI module</a>.', [':taxonomy_admin' => \Drupal::url('entity.taxonomy_vocabulary.collection'), ':field_ui' => $field_ui_url]) . '</dd>';
$output .= '<dt>' . t('Managing terms') . '</dt>';
$output .= '<dd>' . t('Users who have the <em>Administer vocabularies and terms</em> permission or the <em>Edit terms</em> permission for a particular vocabulary can add, edit, and organize the terms in a vocabulary from a vocabulary\'s term listing page, which can be accessed by going to the <a href=":taxonomy_admin">Taxonomy administration page</a> and clicking <em>List terms</em> in the <em>Operations</em> column. Users must have the <em>Administer vocabularies and terms</em> permission or the <em>Delete terms</em> permission for a particular vocabulary to delete terms.', array(':taxonomy_admin' => \Drupal::url('entity.taxonomy_vocabulary.collection'))) . ' </dd>';
$output .= '<dd>' . t('Users who have the <em>Administer vocabularies and terms</em> permission or the <em>Edit terms</em> permission for a particular vocabulary can add, edit, and organize the terms in a vocabulary from a vocabulary\'s term listing page, which can be accessed by going to the <a href=":taxonomy_admin">Taxonomy administration page</a> and clicking <em>List terms</em> in the <em>Operations</em> column. Users must have the <em>Administer vocabularies and terms</em> permission or the <em>Delete terms</em> permission for a particular vocabulary to delete terms.', [':taxonomy_admin' => \Drupal::url('entity.taxonomy_vocabulary.collection')]) . ' </dd>';
$output .= '<dt>' . t('Classifying entity content') . '</dt>';
$output .= '<dd>' . t('A user with the <em>Administer fields</em> permission for a certain entity type may add <em>Taxonomy term</em> reference fields to the entity type, which will allow entities to be classified using taxonomy terms. See the <a href=":entity_reference">Entity Reference help</a> for more information about reference fields. See the <a href=":field">Field module help</a> and the <a href=":field_ui">Field UI help</a> pages for general information on fields and how to create and manage them.', array(':field_ui' => $field_ui_url, ':field' => \Drupal::url('help.page', array('name' => 'field')), ':entity_reference' => \Drupal::url('help.page', array('name' => 'entity_reference')))) . '</dd>';
$output .= '<dd>' . t('A user with the <em>Administer fields</em> permission for a certain entity type may add <em>Taxonomy term</em> reference fields to the entity type, which will allow entities to be classified using taxonomy terms. See the <a href=":entity_reference">Entity Reference help</a> for more information about reference fields. See the <a href=":field">Field module help</a> and the <a href=":field_ui">Field UI help</a> pages for general information on fields and how to create and manage them.', [':field_ui' => $field_ui_url, ':field' => \Drupal::url('help.page', ['name' => 'field']), ':entity_reference' => \Drupal::url('help.page', ['name' => 'entity_reference'])]) . '</dd>';
$output .= '<dt>' . t('Adding new terms during content creation') . '</dt>';
$output .= '<dd>' . t('Allowing users to add new terms gradually builds a vocabulary as content is added and edited. Users can add new terms if either of the two <em>Autocomplete</em> widgets is chosen for the Taxonomy term reference field in the <em>Manage form display</em> page for the field. You will also need to enable the <em>Create referenced entities if they don\'t already exist</em> option, and restrict the field to one vocabulary.') . '</dd>';
$output .= '<dt>' . t('Configuring displays and form displays') . '</dt>';
$output .= '<dd>' . t('See the <a href=":entity_reference">Entity Reference help</a> page for the field widgets and formatters that can be configured for any reference field on the <em>Manage display</em> and <em>Manage form display</em> pages. Taxonomy additionally provides an <em>RSS category</em> formatter that displays nothing when the entity item is displayed as HTML, but displays an RSS category instead of a list when the entity item is displayed in an RSS feed.', array(':entity_reference' => \Drupal::url('help.page', array('name' => 'entity_reference')))) . '</li>';
$output .= '<dd>' . t('See the <a href=":entity_reference">Entity Reference help</a> page for the field widgets and formatters that can be configured for any reference field on the <em>Manage display</em> and <em>Manage form display</em> pages. Taxonomy additionally provides an <em>RSS category</em> formatter that displays nothing when the entity item is displayed as HTML, but displays an RSS category instead of a list when the entity item is displayed in an RSS feed.', [':entity_reference' => \Drupal::url('help.page', ['name' => 'entity_reference'])]) . '</li>';
$output .= '</ul>';
$output .= '</dd>';
$output .= '</dl>';
@@ -67,12 +76,12 @@ function taxonomy_help($route_name, RouteMatchInterface $route_match) {
case 'entity.taxonomy_vocabulary.overview_form':
$vocabulary = $route_match->getParameter('taxonomy_vocabulary');
switch ($vocabulary->getHierarchy()) {
case TAXONOMY_HIERARCHY_DISABLED:
return '<p>' . t('You can reorganize the terms in %capital_name using their drag-and-drop handles, and group terms under a parent term by sliding them under and to the right of the parent.', array('%capital_name' => Unicode::ucfirst($vocabulary->label()), '%name' => $vocabulary->label())) . '</p>';
case TAXONOMY_HIERARCHY_SINGLE:
return '<p>' . t('%capital_name contains terms grouped under parent terms. You can reorganize the terms in %capital_name using their drag-and-drop handles.', array('%capital_name' => Unicode::ucfirst($vocabulary->label()), '%name' => $vocabulary->label())) . '</p>';
case TAXONOMY_HIERARCHY_MULTIPLE:
return '<p>' . t('%capital_name contains terms with multiple parents. Drag and drop of terms with multiple parents is not supported, but you can re-enable drag-and-drop support by editing each term to include only a single parent.', array('%capital_name' => Unicode::ucfirst($vocabulary->label()))) . '</p>';
case VocabularyInterface::HIERARCHY_DISABLED:
return '<p>' . t('You can reorganize the terms in %capital_name using their drag-and-drop handles, and group terms under a parent term by sliding them under and to the right of the parent.', ['%capital_name' => Unicode::ucfirst($vocabulary->label()), '%name' => $vocabulary->label()]) . '</p>';
case VocabularyInterface::HIERARCHY_SINGLE:
return '<p>' . t('%capital_name contains terms grouped under parent terms. You can reorganize the terms in %capital_name using their drag-and-drop handles.', ['%capital_name' => Unicode::ucfirst($vocabulary->label()), '%name' => $vocabulary->label()]) . '</p>';
case VocabularyInterface::HIERARCHY_MULTIPLE:
return '<p>' . t('%capital_name contains terms with multiple parents. Drag and drop of terms with multiple parents is not supported, but you can re-enable drag-and-drop support by editing each term to include only a single parent.', ['%capital_name' => Unicode::ucfirst($vocabulary->label())]) . '</p>';
}
}
}
@@ -81,9 +90,9 @@ function taxonomy_help($route_name, RouteMatchInterface $route_match) {
* Entity URI callback.
*/
function taxonomy_term_uri($term) {
return new Url('entity.taxonomy_term.canonical', array(
return new Url('entity.taxonomy_term.canonical', [
'taxonomy_term' => $term->id(),
));
]);
}
/**
@@ -94,24 +103,24 @@ function taxonomy_page_attachments_alter(array &$page) {
if ($route_match->getRouteName() == 'entity.taxonomy_term.canonical' && ($term = $route_match->getParameter('taxonomy_term')) && $term instanceof TermInterface) {
foreach ($term->uriRelationships() as $rel) {
// Set the URI relationships, like canonical.
$page['#attached']['html_head_link'][] = array(
array(
$page['#attached']['html_head_link'][] = [
[
'rel' => $rel,
'href' => $term->url($rel),
),
],
TRUE,
);
];
// Set the term path as the canonical URL to prevent duplicate content.
if ($rel == 'canonical') {
// Set the non-aliased canonical path as a default shortlink.
$page['#attached']['html_head_link'][] = array(
array(
$page['#attached']['html_head_link'][] = [
[
'rel' => 'shortlink',
'href' => $term->url($rel, array('alias' => TRUE)),
),
'href' => $term->url($rel, ['alias' => TRUE]),
],
TRUE,
);
];
}
}
}
@@ -121,11 +130,11 @@ function taxonomy_page_attachments_alter(array &$page) {
* Implements hook_theme().
*/
function taxonomy_theme() {
return array(
'taxonomy_term' => array(
return [
'taxonomy_term' => [
'render element' => 'elements',
),
);
],
];
}
/**
@@ -134,10 +143,11 @@ function taxonomy_theme() {
* Checks the current parents of all terms in a vocabulary and updates the
* vocabulary's hierarchy setting to the lowest possible level. If no term
* has parent terms then the vocabulary will be given a hierarchy of
* TAXONOMY_HIERARCHY_DISABLED. If any term has a single parent then the
* vocabulary will be given a hierarchy of TAXONOMY_HIERARCHY_SINGLE. If any
* term has multiple parents then the vocabulary will be given a hierarchy of
* TAXONOMY_HIERARCHY_MULTIPLE.
* VocabularyInterface::HIERARCHY_DISABLED. If any term has a single parent then
* the vocabulary will be given a hierarchy of
* VocabularyInterface::HIERARCHY_SINGLE. If any term has multiple parents then
* the vocabulary will be given a hierarchy of
* VocabularyInterface::HIERARCHY_MULTIPLE.
*
* @param \Drupal\taxonomy\VocabularyInterface $vocabulary
* A taxonomy vocabulary entity.
@@ -149,7 +159,7 @@ function taxonomy_theme() {
*/
function taxonomy_check_vocabulary_hierarchy(VocabularyInterface $vocabulary, $changed_term) {
$tree = \Drupal::entityManager()->getStorage('taxonomy_term')->loadTree($vocabulary->id());
$hierarchy = TAXONOMY_HIERARCHY_DISABLED;
$hierarchy = VocabularyInterface::HIERARCHY_DISABLED;
foreach ($tree as $term) {
// Update the changed term with the new parent value before comparison.
if ($term->tid == $changed_term['tid']) {
@@ -158,11 +168,11 @@ function taxonomy_check_vocabulary_hierarchy(VocabularyInterface $vocabulary, $c
}
// Check this term's parent count.
if (count($term->parents) > 1) {
$hierarchy = TAXONOMY_HIERARCHY_MULTIPLE;
$hierarchy = VocabularyInterface::HIERARCHY_MULTIPLE;
break;
}
elseif (count($term->parents) == 1 && !isset($term->parents[0])) {
$hierarchy = TAXONOMY_HIERARCHY_SINGLE;
$hierarchy = VocabularyInterface::HIERARCHY_SINGLE;
}
}
if ($hierarchy != $vocabulary->getHierarchy()) {
@@ -213,7 +223,7 @@ function taxonomy_term_view_multiple(array $terms, $view_mode = 'full', $langcod
* Implements hook_theme_suggestions_HOOK().
*/
function taxonomy_theme_suggestions_taxonomy_term(array $variables) {
$suggestions = array();
$suggestions = [];
/** @var \Drupal\taxonomy\TermInterface $term */
$term = $variables['elements']['#taxonomy_term'];
@@ -251,7 +261,7 @@ function template_preprocess_taxonomy_term(&$variables) {
$variables['page'] = $variables['view_mode'] == 'full' && taxonomy_term_is_page($term);
// Helpful $content variable for templates.
$variables['content'] = array();
$variables['content'] = [];
foreach (Element::children($variables['elements']) as $key) {
$variables['content'][$key] = $variables['elements'][$key];
}
@@ -297,7 +307,7 @@ function taxonomy_vocabulary_get_names() {
$names = &drupal_static(__FUNCTION__);
if (!isset($names)) {
$names = array();
$names = [];
$config_names = \Drupal::configFactory()->listAll('taxonomy.vocabulary.');
foreach ($config_names as $config_name) {
$id = substr($config_name, strlen('taxonomy.vocabulary.'));
@@ -323,7 +333,7 @@ function taxonomy_vocabulary_get_names() {
* An array of matching term objects.
*/
function taxonomy_term_load_multiple_by_name($name, $vocabulary = NULL) {
$values = array('name' => trim($name));
$values = ['name' => trim($name)];
if (isset($vocabulary)) {
$vocabularies = taxonomy_vocabulary_get_names();
if (isset($vocabularies[$vocabulary])) {
@@ -331,7 +341,7 @@ function taxonomy_term_load_multiple_by_name($name, $vocabulary = NULL) {
}
else {
// Return an empty array when filtering by a non-existing vocabulary.
return array();
return [];
}
}
return entity_load_multiple_by_properties('taxonomy_term', $values);
@@ -426,7 +436,7 @@ function taxonomy_term_load($tid) {
* @see \Drupal\Component\Utility\Tags::explode()
*/
function taxonomy_implode_tags($tags, $vid = NULL) {
$typed_tags = array();
$typed_tags = [];
foreach ($tags as $tag) {
// Extract terms belonging to the vocabulary in question.
if (!isset($vid) || $tag->bundle() == $vid) {
@@ -500,7 +510,7 @@ function taxonomy_build_node_index($node) {
// We only maintain the taxonomy index for published nodes.
if ($status && $node->isDefaultRevision()) {
// Collect a unique list of all the term IDs from all node fields.
$tid_all = array();
$tid_all = [];
$entity_reference_class = 'Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem';
foreach ($node->getFieldDefinitions() as $field) {
$field_name = $field->getName();
@@ -520,8 +530,8 @@ function taxonomy_build_node_index($node) {
if (!empty($tid_all)) {
foreach ($tid_all as $tid) {
db_merge('taxonomy_index')
->key(array('nid' => $node->id(), 'tid' => $tid, 'status' => $node->isPublished()))
->fields(array('sticky' => $sticky, 'created' => $node->getCreatedTime()))
->key(['nid' => $node->id(), 'tid' => $tid, 'status' => $node->isPublished()])
->fields(['sticky' => $sticky, 'created' => $node->getCreatedTime()])
->execute();
}
}
+36 -36
View File
@@ -12,80 +12,80 @@ use Drupal\taxonomy\Entity\Vocabulary;
* Implements hook_token_info().
*/
function taxonomy_token_info() {
$types['term'] = array(
$types['term'] = [
'name' => t("Taxonomy terms"),
'description' => t("Tokens related to taxonomy terms."),
'needs-data' => 'term',
);
$types['vocabulary'] = array(
];
$types['vocabulary'] = [
'name' => t("Vocabularies"),
'description' => t("Tokens related to taxonomy vocabularies."),
'needs-data' => 'vocabulary',
);
];
// Taxonomy term related variables.
$term['tid'] = array(
$term['tid'] = [
'name' => t("Term ID"),
'description' => t("The unique ID of the taxonomy term."),
);
$term['name'] = array(
];
$term['name'] = [
'name' => t("Name"),
'description' => t("The name of the taxonomy term."),
);
$term['description'] = array(
];
$term['description'] = [
'name' => t("Description"),
'description' => t("The optional description of the taxonomy term."),
);
$term['node-count'] = array(
];
$term['node-count'] = [
'name' => t("Node count"),
'description' => t("The number of nodes tagged with the taxonomy term."),
);
$term['url'] = array(
];
$term['url'] = [
'name' => t("URL"),
'description' => t("The URL of the taxonomy term."),
);
];
// Taxonomy vocabulary related variables.
$vocabulary['vid'] = array(
$vocabulary['vid'] = [
'name' => t("Vocabulary ID"),
'description' => t("The unique ID of the taxonomy vocabulary."),
);
$vocabulary['name'] = array(
];
$vocabulary['name'] = [
'name' => t("Name"),
'description' => t("The name of the taxonomy vocabulary."),
);
$vocabulary['description'] = array(
];
$vocabulary['description'] = [
'name' => t("Description"),
'description' => t("The optional description of the taxonomy vocabulary."),
);
$vocabulary['node-count'] = array(
];
$vocabulary['node-count'] = [
'name' => t("Node count"),
'description' => t("The number of nodes tagged with terms belonging to the taxonomy vocabulary."),
);
$vocabulary['term-count'] = array(
];
$vocabulary['term-count'] = [
'name' => t("Term count"),
'description' => t("The number of terms belonging to the taxonomy vocabulary."),
);
];
// Chained tokens for taxonomies
$term['vocabulary'] = array(
$term['vocabulary'] = [
'name' => t("Vocabulary"),
'description' => t("The vocabulary the taxonomy term belongs to."),
'type' => 'vocabulary',
);
$term['parent'] = array(
];
$term['parent'] = [
'name' => t("Parent term"),
'description' => t("The parent term of the taxonomy term, if one exists."),
'type' => 'term',
);
];
return array(
return [
'types' => $types,
'tokens' => array(
'tokens' => [
'term' => $term,
'vocabulary' => $vocabulary,
),
);
],
];
}
/**
@@ -94,7 +94,7 @@ function taxonomy_token_info() {
function taxonomy_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
$token_service = \Drupal::token();
$replacements = array();
$replacements = [];
$taxonomy_storage = \Drupal::entityManager()->getStorage('taxonomy_term');
if ($type == 'term' && !empty($data['term'])) {
$term = $data['term'];
@@ -116,7 +116,7 @@ function taxonomy_tokens($type, $tokens, array $data, array $options, Bubbleable
break;
case 'url':
$replacements[$original] = $term->url('canonical', array('absolute' => TRUE));
$replacements[$original] = $term->url('canonical', ['absolute' => TRUE]);
break;
case 'node-count':
@@ -145,12 +145,12 @@ function taxonomy_tokens($type, $tokens, array $data, array $options, Bubbleable
if ($vocabulary_tokens = $token_service->findWithPrefix($tokens, 'vocabulary')) {
$vocabulary = Vocabulary::load($term->bundle());
$replacements += $token_service->generate('vocabulary', $vocabulary_tokens, array('vocabulary' => $vocabulary), $options, $bubbleable_metadata);
$replacements += $token_service->generate('vocabulary', $vocabulary_tokens, ['vocabulary' => $vocabulary], $options, $bubbleable_metadata);
}
if (($vocabulary_tokens = $token_service->findWithPrefix($tokens, 'parent')) && $parents = $taxonomy_storage->loadParents($term->id())) {
$parent = array_pop($parents);
$replacements += $token_service->generate('term', $vocabulary_tokens, array('term' => $parent), $options, $bubbleable_metadata);
$replacements += $token_service->generate('term', $vocabulary_tokens, ['term' => $parent], $options, $bubbleable_metadata);
}
}
+16 -16
View File
@@ -11,44 +11,44 @@ use Drupal\field\FieldStorageConfigInterface;
* Implements hook_views_data_alter().
*/
function taxonomy_views_data_alter(&$data) {
$data['node_field_data']['term_node_tid'] = array(
$data['node_field_data']['term_node_tid'] = [
'title' => t('Taxonomy terms on node'),
'help' => t('Relate nodes to taxonomy terms, specifying which vocabulary or vocabularies to use. This relationship will cause duplicated records if there are multiple terms.'),
'relationship' => array(
'relationship' => [
'id' => 'node_term_data',
'label' => t('term'),
'base' => 'taxonomy_term_field_data',
),
'field' => array(
],
'field' => [
'title' => t('All taxonomy terms'),
'help' => t('Display all taxonomy terms associated with a node from specified vocabularies.'),
'id' => 'taxonomy_index_tid',
'no group by' => TRUE,
'click sortable' => FALSE,
),
);
],
];
$data['node_field_data']['term_node_tid_depth'] = array(
$data['node_field_data']['term_node_tid_depth'] = [
'help' => t('Display content if it has the selected taxonomy terms, or children of the selected terms. Due to additional complexity, this has fewer options than the versions without depth.'),
'real field' => 'nid',
'argument' => array(
'argument' => [
'title' => t('Has taxonomy term ID (with depth)'),
'id' => 'taxonomy_index_tid_depth',
'accept depth modifier' => TRUE,
),
'filter' => array(
],
'filter' => [
'title' => t('Has taxonomy terms (with depth)'),
'id' => 'taxonomy_index_tid_depth',
),
);
],
];
$data['node_field_data']['term_node_tid_depth_modifier'] = array(
$data['node_field_data']['term_node_tid_depth_modifier'] = [
'title' => t('Has taxonomy term ID depth modifier'),
'help' => t('Allows the "depth" for Taxonomy: Term ID (with depth) to be modified via an additional contextual filter value.'),
'argument' => array(
'argument' => [
'id' => 'taxonomy_index_tid_depth_modifier',
),
);
],
];
}
/**
@@ -7,8 +7,8 @@ package: Testing
dependencies:
- taxonomy
# Information added by Drupal.org packaging script on 2016-08-03
version: '8.1.8'
# Information added by Drupal.org packaging script on 2017-08-16
version: '8.3.7'
core: '8.x'
project: 'drupal'
datestamp: 1470233792
datestamp: 1502903957
@@ -19,7 +19,7 @@ process:
name: name
weight: weight
parent:
plugin: migration
plugin: migration_lookup
migration: taxonomy_term_stub_test
source: parent
destination:
@@ -27,3 +27,6 @@ destination:
migration_dependencies:
required:
- vocabularies
provider:
- migrate_drupal
- taxonomy
@@ -8,8 +8,8 @@ dependencies:
- taxonomy
- migrate
# Information added by Drupal.org packaging script on 2016-08-03
version: '8.1.8'
# Information added by Drupal.org packaging script on 2017-08-16
version: '8.3.7'
core: '8.x'
project: 'drupal'
datestamp: 1470233792
datestamp: 1502903957
@@ -0,0 +1,14 @@
name: 'Taxonomy test'
type: module
description: 'Provides test hook implementations for taxonomy tests'
package: Testing
# version: VERSION
# core: 8.x
dependencies:
- taxonomy
# Information added by Drupal.org packaging script on 2017-08-16
version: '8.3.7'
core: '8.x'
project: 'drupal'
datestamp: 1502903957
@@ -0,0 +1,38 @@
<?php
/**
* @file
* Provides test hook implementations for taxonomy tests.
*/
use Drupal\Core\Database\Query\AlterableInterface;
/**
* Implements hook_query_alter().
*/
function taxonomy_test_query_alter(AlterableInterface $query) {
$value = \Drupal::state()->get(__FUNCTION__);
if (isset($value)) {
\Drupal::state()->set(__FUNCTION__, ++$value);
}
}
/**
* Implements hook_query_TAG_alter().
*/
function taxonomy_test_query_term_access_alter(AlterableInterface $query) {
$value = \Drupal::state()->get(__FUNCTION__);
if (isset($value)) {
\Drupal::state()->set(__FUNCTION__, ++$value);
}
}
/**
* Implements hook_query_TAG_alter().
*/
function taxonomy_test_query_taxonomy_term_access_alter(AlterableInterface $query) {
$value = \Drupal::state()->get(__FUNCTION__);
if (isset($value)) {
\Drupal::state()->set(__FUNCTION__, ++$value);
}
}
@@ -8,8 +8,8 @@ dependencies:
- taxonomy
- views
# Information added by Drupal.org packaging script on 2016-08-03
version: '8.1.8'
# Information added by Drupal.org packaging script on 2017-08-16
version: '8.3.7'
core: '8.x'
project: 'drupal'
datestamp: 1470233792
datestamp: 1502903957
@@ -130,7 +130,7 @@ display:
field_api_classes: false
filters:
status:
value: true
value: '1'
table: node_field_data
field: status
plugin_id: boolean
@@ -0,0 +1,174 @@
langcode: en
status: true
dependencies:
module:
- taxonomy
- user
id: test_argument_taxonomy_vocabulary
label: test_argument_taxonomy_vocabulary
module: views
description: ''
tag: ''
base_table: taxonomy_term_field_data
base_field: tid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: 0
display_options:
access:
type: perm
options:
perm: 'access content'
cache:
type: tag
options: { }
query:
type: views_query
options:
disable_sql_rewrite: false
distinct: false
replica: false
query_comment: ''
query_tags: { }
exposed_form:
type: basic
options:
submit_button: Apply
reset_button: false
reset_button_label: Reset
exposed_sorts_label: 'Sort by'
expose_sort_order: true
sort_asc_label: Asc
sort_desc_label: Desc
pager:
type: none
options:
offset: 0
style:
type: default
row:
type: 'entity:taxonomy_term'
fields:
name:
id: name
table: taxonomy_term_field_data
field: name
entity_type: taxonomy_term
entity_field: name
label: ''
alter:
alter_text: false
make_link: false
absolute: false
trim: false
word_boundary: false
ellipsis: false
strip_tags: false
html: false
hide_empty: false
empty_zero: false
type: string
settings:
link_to_entity: true
plugin_id: term_name
relationship: none
group_type: group
admin_label: ''
exclude: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_alter_empty: true
click_sort_column: value
group_column: value
group_columns: { }
group_rows: true
delta_limit: 0
delta_offset: 0
delta_reversed: false
delta_first_last: false
multi_type: separator
separator: ', '
field_api_classes: false
convert_spaces: false
filters: { }
sorts: { }
title: ''
header: { }
footer: { }
empty: { }
relationships: { }
arguments:
vid:
id: vid
table: taxonomy_term_field_data
field: vid
relationship: none
group_type: group
admin_label: ''
default_action: ignore
exception:
value: all
title_enable: false
title: All
title_enable: false
title: ''
default_argument_type: fixed
default_argument_options:
argument: ''
default_argument_skip_url: false
summary_options:
base_path: ''
count: true
items_per_page: 25
override: false
summary:
sort_order: asc
number_of_records: 0
format: default_summary
specify_validation: false
validate:
type: none
fail: 'not found'
validate_options: { }
break_phrase: false
not: false
entity_type: taxonomy_term
entity_field: vid
plugin_id: vocabulary_vid
display_extenders: { }
cache_metadata:
max-age: -1
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- url
- user.permissions
tags: { }
page_1:
display_plugin: page
id: page_1
display_title: Page
position: 1
display_options:
display_extenders: { }
path: test_argument_taxonomy_vocabulary
cache_metadata:
max-age: -1
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- url
- user.permissions
tags: { }
@@ -116,7 +116,7 @@ display:
entity_field: title
filters:
status:
value: true
value: '1'
table: node_field_data
field: status
id: status
@@ -116,7 +116,7 @@ display:
entity_field: title
filters:
status:
value: true
value: '1'
table: node_field_data
field: status
id: status
@@ -116,7 +116,7 @@ display:
entity_field: title
filters:
status:
value: true
value: '1'
table: node_field_data
field: status
id: status
@@ -0,0 +1,19 @@
<?php
namespace Drupal\vocabulary_serialization_test;
use Drupal\Core\Cache\CacheableResponse;
use Drupal\taxonomy\VocabularyInterface;
class VocabularyResponse extends CacheableResponse {
/**
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
public function setVocabulary(VocabularyInterface $vocabulary) {
$this->vocabulary = $vocabulary;
}
}
@@ -0,0 +1,15 @@
<?php
namespace Drupal\vocabulary_serialization_test;
use Drupal\taxonomy\VocabularyInterface;
class VocabularySerializationTestController {
public function vocabularyResponse(VocabularyInterface $taxonomy_vocabulary) {
$response = new VocabularyResponse('this is the output');
$response->setVocabulary($taxonomy_vocabulary);
return $response;
}
}
@@ -0,0 +1,13 @@
name: 'Vocabulary serialization test'
type: module
package: Testing
# version: VERSION
# core: 8.x
dependencies:
- taxonomy
# Information added by Drupal.org packaging script on 2017-08-16
version: '8.3.7'
core: '8.x'
project: 'drupal'
datestamp: 1502903957
@@ -0,0 +1,6 @@
vocabulary_serialization_test:
path: '/vocabulary_serialization_test/{taxonomy_vocabulary}'
defaults:
_controller: 'Drupal\vocabulary_serialization_test\VocabularySerializationTestController::vocabularyResponse'
requirements:
_access: 'TRUE'
@@ -0,0 +1,69 @@
<?php
namespace Drupal\Tests\taxonomy\Functional;
/**
* Verifies operation of a taxonomy-based Entity Query.
*
* @group taxonomy
*/
class EfqTest extends TaxonomyTestBase {
/**
* Vocabulary for testing.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
protected function setUp() {
parent::setUp();
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy']));
$this->vocabulary = $this->createVocabulary();
}
/**
* Tests that a basic taxonomy entity query works.
*/
public function testTaxonomyEfq() {
$terms = [];
for ($i = 0; $i < 5; $i++) {
$term = $this->createTerm($this->vocabulary);
$terms[$term->id()] = $term;
}
$result = \Drupal::entityQuery('taxonomy_term')->execute();
sort($result);
$this->assertEqual(array_keys($terms), $result, 'Taxonomy terms were retrieved by entity query.');
$tid = reset($result);
$ids = (object) [
'entity_type' => 'taxonomy_term',
'entity_id' => $tid,
'bundle' => $this->vocabulary->id(),
];
$term = _field_create_entity_from_ids($ids);
$this->assertEqual($term->id(), $tid, 'Taxonomy term can be created based on the IDs.');
// Create a second vocabulary and five more terms.
$vocabulary2 = $this->createVocabulary();
$terms2 = [];
for ($i = 0; $i < 5; $i++) {
$term = $this->createTerm($vocabulary2);
$terms2[$term->id()] = $term;
}
$result = \Drupal::entityQuery('taxonomy_term')
->condition('vid', $vocabulary2->id())
->execute();
sort($result);
$this->assertEqual(array_keys($terms2), $result, format_string('Taxonomy terms from the %name vocabulary were retrieved by entity query.', ['%name' => $vocabulary2->label()]));
$tid = reset($result);
$ids = (object) [
'entity_type' => 'taxonomy_term',
'entity_id' => $tid,
'bundle' => $vocabulary2->id(),
];
$term = _field_create_entity_from_ids($ids);
$this->assertEqual($term->id(), $tid, 'Taxonomy term can be created based on the IDs.');
}
}
@@ -0,0 +1,69 @@
<?php
namespace Drupal\Tests\taxonomy\Functional;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use \Drupal\taxonomy\Entity\Vocabulary;
/**
* Posts an article with a taxonomy term and a date prior to 1970.
*
* @group taxonomy
*/
class LegacyTest extends TaxonomyTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['node', 'datetime'];
protected function setUp() {
parent::setUp();
// Create a tags vocabulary for the 'article' content type.
$vocabulary = Vocabulary::create([
'name' => 'Tags',
'vid' => 'tags',
]);
$vocabulary->save();
$field_name = 'field_' . $vocabulary->id();
$handler_settings = [
'target_bundles' => [
$vocabulary->id() => $vocabulary->id(),
],
'auto_create' => TRUE,
];
$this->createEntityReferenceField('node', 'article', $field_name, 'Tags', 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
entity_get_form_display('node', 'article', 'default')
->setComponent($field_name, [
'type' => 'entity_reference_autocomplete_tags',
])
->save();
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy', 'administer nodes', 'bypass node access']));
}
/**
* Test taxonomy functionality with nodes prior to 1970.
*/
public function testTaxonomyLegacyNode() {
// Posts an article with a taxonomy term and a date prior to 1970.
$date = new DrupalDateTime('1969-01-01 00:00:00');
$edit = [];
$edit['title[0][value]'] = $this->randomMachineName();
$edit['created[0][value][date]'] = $date->format('Y-m-d');
$edit['created[0][value][time]'] = $date->format('H:i:s');
$edit['body[0][value]'] = $this->randomMachineName();
$edit['field_tags[target_id]'] = $this->randomMachineName();
$this->drupalPostForm('node/add/article', $edit, t('Save and publish'));
// Checks that the node has been saved.
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
$this->assertEqual($node->getCreatedTime(), $date->getTimestamp(), 'Legacy node was saved with the right date.');
}
}
@@ -0,0 +1,62 @@
<?php
namespace Drupal\Tests\taxonomy\Functional;
use Drupal\taxonomy\Entity\Term;
/**
* Tests the loading of multiple taxonomy terms at once.
*
* @group taxonomy
*/
class LoadMultipleTest extends TaxonomyTestBase {
protected function setUp() {
parent::setUp();
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy']));
}
/**
* Create a vocabulary and some taxonomy terms, ensuring they're loaded
* correctly using entity_load_multiple().
*/
public function testTaxonomyTermMultipleLoad() {
// Create a vocabulary.
$vocabulary = $this->createVocabulary();
// Create five terms in the vocabulary.
$i = 0;
while ($i < 5) {
$i++;
$this->createTerm($vocabulary);
}
// Load the terms from the vocabulary.
$terms = entity_load_multiple_by_properties('taxonomy_term', ['vid' => $vocabulary->id()]);
$count = count($terms);
$this->assertEqual($count, 5, format_string('Correct number of terms were loaded. @count terms.', ['@count' => $count]));
// Load the same terms again by tid.
$terms2 = Term::loadMultiple(array_keys($terms));
$this->assertEqual($count, count($terms2), 'Five terms were loaded by tid.');
$this->assertEqual($terms, $terms2, 'Both arrays contain the same terms.');
// Remove one term from the array, then delete it.
$deleted = array_shift($terms2);
$deleted->delete();
$deleted_term = Term::load($deleted->id());
$this->assertFalse($deleted_term);
// Load terms from the vocabulary by vid.
$terms3 = entity_load_multiple_by_properties('taxonomy_term', ['vid' => $vocabulary->id()]);
$this->assertEqual(count($terms3), 4, 'Correct number of terms were loaded.');
$this->assertFalse(isset($terms3[$deleted->id()]));
// Create a single term and load it by name.
$term = $this->createTerm($vocabulary);
$loaded_terms = entity_load_multiple_by_properties('taxonomy_term', ['name' => $term->getName()]);
$this->assertEqual(count($loaded_terms), 1, 'One term was loaded.');
$loaded_term = reset($loaded_terms);
$this->assertEqual($term->id(), $loaded_term->id(), 'Term loaded by name successfully.');
}
}
@@ -0,0 +1,103 @@
<?php
namespace Drupal\Tests\taxonomy\Functional;
use Drupal\field\Entity\FieldConfig;
use Drupal\Tests\TestFileCreationTrait;
use Drupal\user\RoleInterface;
use Drupal\file\Entity\File;
use Drupal\field\Entity\FieldStorageConfig;
/**
* Tests access checks of private image fields.
*
* @group taxonomy
*/
class TaxonomyImageTest extends TaxonomyTestBase {
use TestFileCreationTrait {
getTestFiles as drupalGetTestFiles;
compareFiles as drupalCompareFiles;
}
/**
* Used taxonomy vocabulary.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['image'];
protected function setUp() {
parent::setUp();
// Remove access content permission from registered users.
user_role_revoke_permissions(RoleInterface::AUTHENTICATED_ID, ['access content']);
$this->vocabulary = $this->createVocabulary();
// Add a field to the vocabulary.
$entity_type = 'taxonomy_term';
$name = 'field_test';
FieldStorageConfig::create([
'field_name' => $name,
'entity_type' => $entity_type,
'type' => 'image',
'settings' => [
'uri_scheme' => 'private',
],
])->save();
FieldConfig::create([
'field_name' => $name,
'entity_type' => $entity_type,
'bundle' => $this->vocabulary->id(),
'settings' => [],
])->save();
entity_get_display($entity_type, $this->vocabulary->id(), 'default')
->setComponent($name, [
'type' => 'image',
'settings' => [],
])
->save();
entity_get_form_display($entity_type, $this->vocabulary->id(), 'default')
->setComponent($name, [
'type' => 'image_image',
'settings' => [],
])
->save();
}
public function testTaxonomyImageAccess() {
$user = $this->drupalCreateUser(['administer site configuration', 'administer taxonomy', 'access user profiles']);
$this->drupalLogin($user);
// Create a term and upload the image.
$files = $this->drupalGetTestFiles('image');
$image = array_pop($files);
$edit['name[0][value]'] = $this->randomMachineName();
$edit['files[field_test_0]'] = drupal_realpath($image->uri);
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add', $edit, t('Save'));
$this->drupalPostForm(NULL, ['field_test[0][alt]' => $this->randomMachineName()], t('Save'));
$terms = entity_load_multiple_by_properties('taxonomy_term', ['name' => $edit['name[0][value]']]);
$term = reset($terms);
$this->assertText(t('Created new term @name.', ['@name' => $term->getName()]));
// Create a user that should have access to the file and one that doesn't.
$access_user = $this->drupalCreateUser(['access content']);
$no_access_user = $this->drupalCreateUser();
$image = File::load($term->field_test->target_id);
$this->drupalLogin($access_user);
$this->drupalGet(file_create_url($image->getFileUri()));
$this->assertResponse(200, 'Private image on term is accessible with right permission');
$this->drupalLogin($no_access_user);
$this->drupalGet(file_create_url($image->getFileUri()));
$this->assertResponse(403, 'Private image on term not accessible without right permission');
}
}
@@ -0,0 +1,119 @@
<?php
namespace Drupal\Tests\taxonomy\Functional;
use Drupal\Tests\BrowserTestBase;
/**
* Tests that appropriate query tags are added.
*
* @group taxonomy
*/
class TaxonomyQueryAlterTest extends BrowserTestBase {
use TaxonomyTestTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['taxonomy', 'taxonomy_test'];
/**
* Tests that appropriate tags are added when querying the database.
*/
public function testTaxonomyQueryAlter() {
// Create a new vocabulary and add a few terms to it.
$vocabulary = $this->createVocabulary();
$terms = [];
for ($i = 0; $i < 5; $i++) {
$terms[$i] = $this->createTerm($vocabulary);
}
// Set up hierarchy. Term 2 is a child of 1.
$terms[2]->parent = $terms[1]->id();
$terms[2]->save();
$term_storage = \Drupal::entityManager()->getStorage('taxonomy_term');
$this->setupQueryTagTestHooks();
$loaded_term = $term_storage->load($terms[0]->id());
$this->assertEqual($loaded_term->id(), $terms[0]->id(), 'First term was loaded');
$this->assertQueryTagTestResult(1, 0, 'TermStorage::load()');
$this->setupQueryTagTestHooks();
$loaded_terms = $term_storage->loadTree($vocabulary->id());
$this->assertEqual(count($loaded_terms), count($terms), 'All terms were loaded');
$this->assertQueryTagTestResult(1, 1, 'TermStorage::loadTree()');
$this->setupQueryTagTestHooks();
$loaded_terms = $term_storage->loadParents($terms[2]->id());
$this->assertEqual(count($loaded_terms), 1, 'All parent terms were loaded');
$this->assertQueryTagTestResult(2, 1, 'TermStorage::loadParents()');
$this->setupQueryTagTestHooks();
$loaded_terms = $term_storage->loadChildren($terms[1]->id());
$this->assertEqual(count($loaded_terms), 1, 'All child terms were loaded');
$this->assertQueryTagTestResult(2, 1, 'TermStorage::loadChildren()');
$this->setupQueryTagTestHooks();
$query = db_select('taxonomy_term_data', 't');
$query->addField('t', 'tid');
$query->addTag('taxonomy_term_access');
$tids = $query->execute()->fetchCol();
$this->assertEqual(count($tids), count($terms), 'All term IDs were retrieved');
$this->assertQueryTagTestResult(1, 1, 'custom db_select() with taxonomy_term_access tag (preferred)');
$this->setupQueryTagTestHooks();
$query = db_select('taxonomy_term_data', 't');
$query->addField('t', 'tid');
$query->addTag('term_access');
$tids = $query->execute()->fetchCol();
$this->assertEqual(count($tids), count($terms), 'All term IDs were retrieved');
$this->assertQueryTagTestResult(1, 1, 'custom db_select() with term_access tag (deprecated)');
$this->setupQueryTagTestHooks();
$query = \Drupal::entityQuery('taxonomy_term');
$query->addTag('taxonomy_term_access');
$result = $query->execute();
$this->assertEqual(count($result), count($terms), 'All term IDs were retrieved');
$this->assertQueryTagTestResult(1, 1, 'custom EntityFieldQuery with taxonomy_term_access tag (preferred)');
$this->setupQueryTagTestHooks();
$query = \Drupal::entityQuery('taxonomy_term');
$query->addTag('term_access');
$result = $query->execute();
$this->assertEqual(count($result), count($terms), 'All term IDs were retrieved');
$this->assertQueryTagTestResult(1, 1, 'custom EntityFieldQuery with term_access tag (deprecated)');
}
/**
* Sets up the hooks in the test module.
*/
protected function setupQueryTagTestHooks() {
taxonomy_terms_static_reset();
\Drupal::state()->set('taxonomy_test_query_alter', 0);
\Drupal::state()->set('taxonomy_test_query_term_access_alter', 0);
\Drupal::state()->set('taxonomy_test_query_taxonomy_term_access_alter', 0);
}
/**
* Verifies invocation of the hooks in the test module.
*
* @param int $expected_generic_invocations
* The number of times the generic query_alter hook is expected to have
* been invoked.
* @param int $expected_specific_invocations
* The number of times the tag-specific query_alter hooks are expected to
* have been invoked.
* @param string $method
* A string describing the invoked function which generated the query.
*/
protected function assertQueryTagTestResult($expected_generic_invocations, $expected_specific_invocations, $method) {
$this->assertIdentical($expected_generic_invocations, \Drupal::state()->get('taxonomy_test_query_alter'), 'hook_query_alter() invoked when executing ' . $method);
$this->assertIdentical($expected_specific_invocations, \Drupal::state()->get('taxonomy_test_query_term_access_alter'), 'Deprecated hook_query_term_access_alter() invoked when executing ' . $method);
$this->assertIdentical($expected_specific_invocations, \Drupal::state()->get('taxonomy_test_query_taxonomy_term_access_alter'), 'Preferred hook_query_taxonomy_term_access_alter() invoked when executing ' . $method);
}
}
@@ -0,0 +1,67 @@
<?php
namespace Drupal\Tests\taxonomy\Functional;
/**
* Ensures that the term pager works properly.
*
* @group taxonomy
*/
class TaxonomyTermPagerTest extends TaxonomyTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['taxonomy'];
/**
* Vocabulary for testing.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy', 'bypass node access']));
$this->vocabulary = $this->createVocabulary();
}
/**
* Tests that the pager is displayed properly on the term overview page.
*/
public function testTaxonomyTermOverviewPager() {
// Set limit to 3 terms per page.
$this->config('taxonomy.settings')
->set('terms_per_page_admin', '3')
->save();
// Create 3 terms.
for ($x = 1; $x <= 3; $x++) {
$this->createTerm($this->vocabulary);
}
// Get Page 1.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview');
$this->assertNoPattern('|<nav class="pager" [^>]*>|', 'Pager is not visible on page 1');
// Create 3 more terms to show pager.
for ($x = 1; $x <= 3; $x++) {
$this->createTerm($this->vocabulary);
}
// Get Page 1.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview');
$this->assertPattern('|<nav class="pager" [^>]*>|', 'Pager is visible on page 1');
// Get Page 2.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview', ['query' => ['page' => 1]]);
$this->assertPattern('|<nav class="pager" [^>]*>|', 'Pager is visible on page 2');
}
}
@@ -0,0 +1,36 @@
<?php
namespace Drupal\Tests\taxonomy\Functional;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\Tests\BrowserTestBase;
/**
* Provides common helper methods for Taxonomy module tests.
*/
abstract class TaxonomyTestBase extends BrowserTestBase {
use TaxonomyTestTrait;
use EntityReferenceTestTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['taxonomy', 'block'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->drupalPlaceBlock('system_breadcrumb_block');
// Create Basic page and Article node types.
if ($this->profile != 'standard') {
$this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
}
}
}
@@ -0,0 +1,60 @@
<?php
namespace Drupal\Tests\taxonomy\Functional;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Language\LanguageInterface;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\taxonomy\Entity\Term;
/**
* Provides common helper methods for Taxonomy module tests.
*/
trait TaxonomyTestTrait {
/**
* Returns a new vocabulary with random properties.
*/
public function createVocabulary() {
// Create a vocabulary.
$vocabulary = Vocabulary::create([
'name' => $this->randomMachineName(),
'description' => $this->randomMachineName(),
'vid' => Unicode::strtolower($this->randomMachineName()),
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
'weight' => mt_rand(0, 10),
]);
$vocabulary->save();
return $vocabulary;
}
/**
* Returns a new term with random properties in vocabulary $vid.
*
* @param \Drupal\taxonomy\Entity\Vocabulary $vocabulary
* The vocabulary object.
* @param array $values
* (optional) An array of values to set, keyed by property name. If the
* entity type has bundles, the bundle key has to be specified.
*
* @return \Drupal\taxonomy\Entity\Term
* The new taxonomy term object.
*/
public function createTerm(Vocabulary $vocabulary, $values = []) {
$filter_formats = filter_formats();
$format = array_pop($filter_formats);
$term = Term::create($values + [
'name' => $this->randomMachineName(),
'description' => [
'value' => $this->randomMachineName(),
// Use the first available text format.
'format' => $format->id(),
],
'vid' => $vocabulary->id(),
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
]);
$term->save();
return $term;
}
}
@@ -0,0 +1,105 @@
<?php
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;
/**
* Provides common testing base for translated taxonomy terms.
*/
trait TaxonomyTranslationTestTrait {
use EntityReferenceTestTrait;
/**
* The vocabulary.
*
* @var \Drupal\taxonomy\Entity\Vocabulary;
*/
protected $vocabulary;
/**
* The field name for our taxonomy term field.
*
* @var string
*/
protected $termFieldName = 'field_tag';
/**
* The langcode of the source language.
*
* @var string
*/
protected $baseLangcode = 'en';
/**
* Target langcode for translation.
*
* @var string
*/
protected $translateToLangcode = 'hu';
/**
* The node to check the translated value on.
*
* @var \Drupal\node\Entity\Node
*/
protected $node;
/**
* Adds additional languages.
*/
protected function setupLanguages() {
ConfigurableLanguage::createFromLangcode($this->translateToLangcode)->save();
$this->rebuildContainer();
}
/**
* Enables translations where it needed.
*/
protected function enableTranslation() {
// Enable translation for the current entity type and ensure the change is
// picked up.
\Drupal::service('content_translation.manager')->setEnabled('node', 'article', TRUE);
\Drupal::service('content_translation.manager')->setEnabled('taxonomy_term', $this->vocabulary->id(), TRUE);
drupal_static_reset();
\Drupal::entityManager()->clearCachedDefinitions();
\Drupal::service('router.builder')->rebuild();
\Drupal::service('entity.definition_update_manager')->applyUpdates();
}
/**
* Adds term reference field for the article content type.
*
* @param bool $translatable
* (optional) If TRUE, create a translatable term reference field. Defaults
* to FALSE.
*/
protected function setUpTermReferenceField() {
$handler_settings = [
'target_bundles' => [
$this->vocabulary->id() => $this->vocabulary->id(),
],
'auto_create' => TRUE,
];
$this->createEntityReferenceField('node', 'article', $this->termFieldName, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
$field_storage = FieldStorageConfig::loadByName('node', $this->termFieldName);
$field_storage->setTranslatable(FALSE);
$field_storage->save();
entity_get_form_display('node', 'article', 'default')
->setComponent($this->termFieldName, [
'type' => 'entity_reference_autocomplete_tags',
])
->save();
entity_get_display('node', 'article', 'default')
->setComponent($this->termFieldName, [
'type' => 'entity_reference_label',
])
->save();
}
}
@@ -0,0 +1,42 @@
<?php
namespace Drupal\Tests\taxonomy\Functional;
use Drupal\system\Tests\Entity\EntityWithUriCacheTagsTestBase;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\taxonomy\Entity\Term;
/**
* Tests the Taxonomy term entity's cache tags.
*
* @group taxonomy
*/
class TermCacheTagsTest extends EntityWithUriCacheTagsTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['taxonomy'];
/**
* {@inheritdoc}
*/
protected function createEntity() {
// Create a "Camelids" vocabulary.
$vocabulary = Vocabulary::create([
'name' => 'Camelids',
'vid' => 'camelids',
]);
$vocabulary->save();
// Create a "Llama" taxonomy term.
$term = Term::create([
'name' => 'Llama',
'vid' => $vocabulary->id(),
]);
$term->save();
return $term;
}
}
@@ -0,0 +1,79 @@
<?php
namespace Drupal\Tests\taxonomy\Functional;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\Entity\FieldConfig;
/**
* Tests the settings of restricting term selection to a single vocabulary.
*
* @group taxonomy
*/
class TermEntityReferenceTest extends TaxonomyTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['entity_reference_test', 'entity_test'];
/**
* Tests an entity reference field restricted to a single vocabulary.
*
* Creates two vocabularies with a term, then set up the entity reference
* field to limit the target vocabulary to one of them, ensuring that
* the restriction applies.
*/
public function testSelectionTestVocabularyRestriction() {
// Create two vocabularies.
$vocabulary = $this->createVocabulary();
$vocabulary2 = $this->createVocabulary();
$term = $this->createTerm($vocabulary);
$term2 = $this->createTerm($vocabulary2);
// Create an entity reference field.
$field_name = 'taxonomy_' . $vocabulary->id();
$field_storage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'entity_test',
'translatable' => FALSE,
'settings' => [
'target_type' => 'taxonomy_term',
],
'type' => 'entity_reference',
'cardinality' => 1,
]);
$field_storage->save();
$field = FieldConfig::create([
'field_storage' => $field_storage,
'entity_type' => 'entity_test',
'bundle' => 'test_bundle',
'settings' => [
'handler' => 'default',
'handler_settings' => [
// Restrict selection of terms to a single vocabulary.
'target_bundles' => [
$vocabulary->id() => $vocabulary->id(),
],
],
],
]);
$field->save();
$handler = $this->container->get('plugin.manager.entity_reference_selection')->getSelectionHandler($field);
$result = $handler->getReferenceableEntities();
$expected_result = [
$vocabulary->id() => [
$term->id() => $term->getName(),
],
];
$this->assertIdentical($result, $expected_result, 'Terms selection restricted to a single vocabulary.');
}
}
@@ -0,0 +1,214 @@
<?php
namespace Drupal\Tests\taxonomy\Functional;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
/**
* Tests the hook implementations that maintain the taxonomy index.
*
* @group taxonomy
*/
class TermIndexTest extends TaxonomyTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['views'];
/**
* Vocabulary for testing.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
/**
* Name of the taxonomy term reference field.
*
* @var string
*/
protected $fieldName1;
/**
* Name of the taxonomy term reference field.
*
* @var string
*/
protected $fieldName2;
protected function setUp() {
parent::setUp();
// Create an administrative user.
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy', 'bypass node access']));
// Create a vocabulary and add two term reference fields to article nodes.
$this->vocabulary = $this->createVocabulary();
$this->fieldName1 = Unicode::strtolower($this->randomMachineName());
$handler_settings = [
'target_bundles' => [
$this->vocabulary->id() => $this->vocabulary->id(),
],
'auto_create' => TRUE,
];
$this->createEntityReferenceField('node', 'article', $this->fieldName1, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
entity_get_form_display('node', 'article', 'default')
->setComponent($this->fieldName1, [
'type' => 'options_select',
])
->save();
entity_get_display('node', 'article', 'default')
->setComponent($this->fieldName1, [
'type' => 'entity_reference_label',
])
->save();
$this->fieldName2 = Unicode::strtolower($this->randomMachineName());
$this->createEntityReferenceField('node', 'article', $this->fieldName2, NULL, 'taxonomy_term', 'default', $handler_settings, FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
entity_get_form_display('node', 'article', 'default')
->setComponent($this->fieldName2, [
'type' => 'options_select',
])
->save();
entity_get_display('node', 'article', 'default')
->setComponent($this->fieldName2, [
'type' => 'entity_reference_label',
])
->save();
}
/**
* Tests that the taxonomy index is maintained properly.
*/
public function testTaxonomyIndex() {
$node_storage = $this->container->get('entity.manager')->getStorage('node');
// Create terms in the vocabulary.
$term_1 = $this->createTerm($this->vocabulary);
$term_2 = $this->createTerm($this->vocabulary);
// Post an article.
$edit = [];
$edit['title[0][value]'] = $this->randomMachineName();
$edit['body[0][value]'] = $this->randomMachineName();
$edit["{$this->fieldName1}[]"] = $term_1->id();
$edit["{$this->fieldName2}[]"] = $term_1->id();
$this->drupalPostForm('node/add/article', $edit, t('Save'));
// Check that the term is indexed, and only once.
$node = $this->drupalGetNodeByTitle($edit['title[0][value]']);
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [
':nid' => $node->id(),
':tid' => $term_1->id(),
])->fetchField();
$this->assertEqual(1, $index_count, 'Term 1 is indexed once.');
// Update the article to change one term.
$edit["{$this->fieldName1}[]"] = $term_2->id();
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
// Check that both terms are indexed.
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [
':nid' => $node->id(),
':tid' => $term_1->id(),
])->fetchField();
$this->assertEqual(1, $index_count, 'Term 1 is indexed.');
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [
':nid' => $node->id(),
':tid' => $term_2->id(),
])->fetchField();
$this->assertEqual(1, $index_count, 'Term 2 is indexed.');
// Update the article to change another term.
$edit["{$this->fieldName2}[]"] = $term_2->id();
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
// Check that only one term is indexed.
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [
':nid' => $node->id(),
':tid' => $term_1->id(),
])->fetchField();
$this->assertEqual(0, $index_count, 'Term 1 is not indexed.');
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [
':nid' => $node->id(),
':tid' => $term_2->id(),
])->fetchField();
$this->assertEqual(1, $index_count, 'Term 2 is indexed once.');
// Redo the above tests without interface.
$node_storage->resetCache([$node->id()]);
$node = $node_storage->load($node->id());
$node->title = $this->randomMachineName();
// Update the article with no term changed.
$node->save();
// Check that the index was not changed.
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [
':nid' => $node->id(),
':tid' => $term_1->id(),
])->fetchField();
$this->assertEqual(0, $index_count, 'Term 1 is not indexed.');
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [
':nid' => $node->id(),
':tid' => $term_2->id(),
])->fetchField();
$this->assertEqual(1, $index_count, 'Term 2 is indexed once.');
// Update the article to change one term.
$node->{$this->fieldName1} = [['target_id' => $term_1->id()]];
$node->save();
// Check that both terms are indexed.
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [
':nid' => $node->id(),
':tid' => $term_1->id(),
])->fetchField();
$this->assertEqual(1, $index_count, 'Term 1 is indexed.');
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [
':nid' => $node->id(),
':tid' => $term_2->id(),
])->fetchField();
$this->assertEqual(1, $index_count, 'Term 2 is indexed.');
// Update the article to change another term.
$node->{$this->fieldName2} = [['target_id' => $term_1->id()]];
$node->save();
// Check that only one term is indexed.
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [
':nid' => $node->id(),
':tid' => $term_1->id(),
])->fetchField();
$this->assertEqual(1, $index_count, 'Term 1 is indexed once.');
$index_count = db_query('SELECT COUNT(*) FROM {taxonomy_index} WHERE nid = :nid AND tid = :tid', [
':nid' => $node->id(),
':tid' => $term_2->id(),
])->fetchField();
$this->assertEqual(0, $index_count, 'Term 2 is not indexed.');
}
/**
* Tests that there is a link to the parent term on the child term page.
*/
public function testTaxonomyTermHierarchyBreadcrumbs() {
// Create two taxonomy terms and set term2 as the parent of term1.
$term1 = $this->createTerm($this->vocabulary);
$term2 = $this->createTerm($this->vocabulary);
$term1->parent = [$term2->id()];
$term1->save();
// Verify that the page breadcrumbs include a link to the parent term.
$this->drupalGet('taxonomy/term/' . $term1->id());
// Breadcrumbs are not rendered with a language, prevent the term
// language from being added to the options.
$this->assertRaw(\Drupal::l($term2->getName(), $term2->urlInfo('canonical', ['language' => NULL])), 'Parent term link is displayed when viewing the node.');
}
}
@@ -0,0 +1,143 @@
<?php
namespace Drupal\Tests\taxonomy\Functional;
use Drupal\Core\Language\LanguageInterface;
use Drupal\language\Entity\ConfigurableLanguage;
/**
* Tests the language functionality for the taxonomy terms.
*
* @group taxonomy
*/
class TermLanguageTest extends TaxonomyTestBase {
public static $modules = ['language'];
/**
* Vocabulary for testing.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
protected function setUp() {
parent::setUp();
// Create an administrative user.
$this->drupalLogin($this->drupalCreateUser(['administer taxonomy']));
// Create a vocabulary to which the terms will be assigned.
$this->vocabulary = $this->createVocabulary();
// Add some custom languages.
foreach (['aa', 'bb', 'cc'] as $language_code) {
ConfigurableLanguage::create([
'id' => $language_code,
'label' => $this->randomMachineName(),
])->save();
}
}
public function testTermLanguage() {
// Configure the vocabulary to not hide the language selector.
$edit = [
'default_language[language_alterable]' => TRUE,
];
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id(), $edit, t('Save'));
// Add a term.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add');
// Check that we have the language selector.
$this->assertField('edit-langcode-0-value', t('The language selector field was found on the page.'));
// Submit the term.
$edit = [
'name[0][value]' => $this->randomMachineName(),
'langcode[0][value]' => 'aa',
];
$this->drupalPostForm(NULL, $edit, t('Save'));
$terms = taxonomy_term_load_multiple_by_name($edit['name[0][value]']);
$term = reset($terms);
$this->assertEqual($term->language()->getId(), $edit['langcode[0][value]'], 'The term contains the correct langcode.');
// Check if on the edit page the language is correct.
$this->drupalGet('taxonomy/term/' . $term->id() . '/edit');
$this->assertOptionSelected('edit-langcode-0-value', $edit['langcode[0][value]'], 'The term language was correctly selected.');
// Change the language of the term.
$edit['langcode[0][value]'] = 'bb';
$this->drupalPostForm('taxonomy/term/' . $term->id() . '/edit', $edit, t('Save'));
// Check again that on the edit page the language is correct.
$this->drupalGet('taxonomy/term/' . $term->id() . '/edit');
$this->assertOptionSelected('edit-langcode-0-value', $edit['langcode[0][value]'], 'The term language was correctly selected.');
}
public function testDefaultTermLanguage() {
// Configure the vocabulary to not hide the language selector, and make the
// default language of the terms fixed.
$edit = [
'default_language[langcode]' => 'bb',
'default_language[language_alterable]' => TRUE,
];
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id(), $edit, t('Save'));
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add');
$this->assertOptionSelected('edit-langcode-0-value', 'bb', 'The expected langcode was selected.');
// Make the default language of the terms to be the current interface.
$edit = [
'default_language[langcode]' => 'current_interface',
'default_language[language_alterable]' => TRUE,
];
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id(), $edit, t('Save'));
$this->drupalGet('aa/admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add');
$this->assertOptionSelected('edit-langcode-0-value', 'aa', "The expected langcode, 'aa', was selected.");
$this->drupalGet('bb/admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add');
$this->assertOptionSelected('edit-langcode-0-value', 'bb', "The expected langcode, 'bb', was selected.");
// Change the default language of the site and check if the default terms
// language is still correctly selected.
$this->config('system.site')->set('default_langcode', 'cc')->save();
$edit = [
'default_language[langcode]' => LanguageInterface::LANGCODE_SITE_DEFAULT,
'default_language[language_alterable]' => TRUE,
];
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id(), $edit, t('Save'));
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add');
$this->assertOptionSelected('edit-langcode-0-value', 'cc', "The expected langcode, 'cc', was selected.");
}
/**
* Tests that translated terms are displayed correctly on the term overview.
*/
public function testTermTranslatedOnOverviewPage() {
// Configure the vocabulary to not hide the language selector.
$edit = [
'default_language[language_alterable]' => TRUE,
];
$this->drupalPostForm('admin/structure/taxonomy/manage/' . $this->vocabulary->id(), $edit, t('Save'));
// Add a term.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/add');
// Submit the term.
$edit = [
'name[0][value]' => $this->randomMachineName(),
'langcode[0][value]' => 'aa',
];
$this->drupalPostForm(NULL, $edit, t('Save'));
$terms = taxonomy_term_load_multiple_by_name($edit['name[0][value]']);
$term = reset($terms);
// Add a translation for that term.
$translated_title = $this->randomMachineName();
$term->addTranslation('bb', [
'name' => $translated_title,
]);
$term->save();
// Overview page in the other language shows the translated term
$this->drupalGet('bb/admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview');
$this->assertPattern('|<a[^>]*>' . $translated_title . '</a>|', 'The term language is correct');
}
}
@@ -0,0 +1,105 @@
<?php
namespace Drupal\Tests\taxonomy\Functional;
use Drupal\node\Entity\Node;
/**
* Tests the translation of taxonomy terms field on nodes.
*
* @group taxonomy
*/
class TermTranslationFieldViewTest extends TaxonomyTestBase {
use TaxonomyTranslationTestTrait;
/**
* The term that should be translated.
*
* @var \Drupal\taxonomy\Entity\Term
*/
protected $term;
/**
* The tag in the source language.
*
* @var string
*/
protected $baseTagName = 'OriginalTagName';
/**
* The translated value for the tag.
*
* @var string
*/
protected $translatedTagName = 'TranslatedTagName';
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['language', 'content_translation', 'taxonomy'];
protected function setUp() {
parent::setUp();
$this->setupLanguages();
$this->vocabulary = $this->createVocabulary();
$this->enableTranslation();
$this->setUpTerm();
$this->setUpTermReferenceField();
$this->setUpNode();
}
/**
* Tests if the translated taxonomy term is displayed.
*/
public function testTranslatedTaxonomyTermReferenceDisplay() {
$path = 'node/' . $this->node->id();
$translation_path = $this->translateToLangcode . '/' . $path;
$this->drupalGet($path);
$this->assertNoText($this->translatedTagName);
$this->assertText($this->baseTagName);
$this->drupalGet($translation_path);
$this->assertText($this->translatedTagName);
$this->assertNoText($this->baseTagName);
}
/**
* Creates a test subject node, with translation.
*/
protected function setUpNode() {
/** @var \Drupal\node\Entity\Node $node */
$node = Node::create([
'title' => $this->randomMachineName(),
'type' => 'article',
'description' => [[
'value' => $this->randomMachineName(),
'format' => 'basic_html'
]],
$this->termFieldName => [['target_id' => $this->term->id()]],
'langcode' => $this->baseLangcode,
]);
$node->save();
$node->addTranslation($this->translateToLangcode, $node->toArray());
$node->save();
$this->node = $node;
}
/**
* Creates a test subject term, with translation.
*/
protected function setUpTerm() {
$this->term = $this->createTerm($this->vocabulary, [
'name' => $this->baseTagName,
'langcode' => $this->baseLangcode,
]);
$this->term->addTranslation($this->translateToLangcode, [
'name' => $this->translatedTagName,
]);
$this->term->save();
}
}
@@ -0,0 +1,164 @@
<?php
namespace Drupal\Tests\taxonomy\Functional;
use Drupal\Tests\content_translation\Functional\ContentTranslationUITestBase;
use Drupal\Core\Language\LanguageInterface;
use Drupal\taxonomy\Entity\Vocabulary;
/**
* Tests the Term Translation UI.
*
* @group taxonomy
*/
class TermTranslationUITest extends ContentTranslationUITestBase {
/**
* The vocabulary used for creating terms.
*
* @var \Drupal\taxonomy\VocabularyInterface
*/
protected $vocabulary;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['language', 'content_translation', 'taxonomy'];
protected function setUp() {
$this->entityTypeId = 'taxonomy_term';
$this->bundle = 'tags';
parent::setUp();
}
/**
* {@inheritdoc}
*/
protected function setupBundle() {
parent::setupBundle();
// Create a vocabulary.
$this->vocabulary = Vocabulary::create([
'name' => $this->bundle,
'description' => $this->randomMachineName(),
'vid' => $this->bundle,
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
'weight' => mt_rand(0, 10),
]);
$this->vocabulary->save();
}
/**
* {@inheritdoc}
*/
protected function getTranslatorPermissions() {
return array_merge(parent::getTranslatorPermissions(), ['administer taxonomy']);
}
/**
* {@inheritdoc}
*/
protected function getNewEntityValues($langcode) {
return ['name' => $this->randomMachineName()] + parent::getNewEntityValues($langcode);
}
/**
* Returns an edit array containing the values to be posted.
*/
protected function getEditValues($values, $langcode, $new = FALSE) {
$edit = parent::getEditValues($values, $langcode, $new);
// To be able to post values for the configurable base fields (name,
// description) have to be suffixed with [0][value].
foreach ($edit as $property => $value) {
foreach (['name', 'description'] as $key) {
if ($property == $key) {
$edit[$key . '[0][value]'] = $value;
unset($edit[$property]);
}
}
}
return $edit;
}
/**
* {@inheritdoc}
*/
public function testTranslationUI() {
parent::testTranslationUI();
// Make sure that no row was inserted for taxonomy vocabularies which do
// not have translations enabled.
$rows = db_query('SELECT tid, count(tid) AS count FROM {taxonomy_term_field_data} WHERE vid <> :vid GROUP BY tid', [':vid' => $this->bundle])->fetchAll();
foreach ($rows as $row) {
$this->assertTrue($row->count < 2, 'Term does not have translations.');
}
}
/**
* Tests translate link on vocabulary term list.
*/
public function testTranslateLinkVocabularyAdminPage() {
$this->drupalLogin($this->drupalCreateUser(array_merge(parent::getTranslatorPermissions(), ['access administration pages', 'administer taxonomy'])));
$values = [
'name' => $this->randomMachineName(),
];
$translatable_tid = $this->createEntity($values, $this->langcodes[0], $this->vocabulary->id());
// Create an untranslatable vocabulary.
$untranslatable_vocabulary = Vocabulary::create([
'name' => 'untranslatable_voc',
'description' => $this->randomMachineName(),
'vid' => 'untranslatable_voc',
'langcode' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
'weight' => mt_rand(0, 10),
]);
$untranslatable_vocabulary->save();
$values = [
'name' => $this->randomMachineName(),
];
$untranslatable_tid = $this->createEntity($values, $this->langcodes[0], $untranslatable_vocabulary->id());
// Verify translation links.
$this->drupalGet('admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview');
$this->assertResponse(200, 'The translatable vocabulary page was found.');
$this->assertLinkByHref('term/' . $translatable_tid . '/translations', 0, 'The translations link exists for a translatable vocabulary.');
$this->assertLinkByHref('term/' . $translatable_tid . '/edit', 0, 'The edit link exists for a translatable vocabulary.');
$this->drupalGet('admin/structure/taxonomy/manage/' . $untranslatable_vocabulary->id() . '/overview');
$this->assertResponse(200);
$this->assertLinkByHref('term/' . $untranslatable_tid . '/edit');
$this->assertNoLinkByHref('term/' . $untranslatable_tid . '/translations');
}
/**
* {@inheritdoc}
*/
protected function doTestTranslationEdit() {
$storage = $this->container->get('entity_type.manager')
->getStorage($this->entityTypeId);
$storage->resetCache([$this->entityId]);
$entity = $storage->load($this->entityId);
$languages = $this->container->get('language_manager')->getLanguages();
foreach ($this->langcodes as $langcode) {
// We only want to test the title for non-english translations.
if ($langcode != 'en') {
$options = ['language' => $languages[$langcode]];
$url = $entity->urlInfo('edit-form', $options);
$this->drupalGet($url);
$title = t('@title [%language translation]', [
'@title' => $entity->getTranslation($langcode)->label(),
'%language' => $languages[$langcode]->getName(),
]);
$this->assertRaw($title);
}
}
}
}
@@ -0,0 +1,49 @@
<?php
namespace Drupal\Tests\taxonomy\Functional;
/**
* Verifies that various taxonomy pages use the expected theme.
*
* @group taxonomy
*/
class ThemeTest extends TaxonomyTestBase {
protected function setUp() {
parent::setUp();
// Make sure we are using distinct default and administrative themes for
// the duration of these tests.
\Drupal::service('theme_handler')->install(['bartik', 'seven']);
$this->config('system.theme')
->set('default', 'bartik')
->set('admin', 'seven')
->save();
// Create and log in as a user who has permission to add and edit taxonomy
// terms and view the administrative theme.
$admin_user = $this->drupalCreateUser(['administer taxonomy', 'view the administration theme']);
$this->drupalLogin($admin_user);
}
/**
* Test the theme used when adding, viewing and editing taxonomy terms.
*/
public function testTaxonomyTermThemes() {
// Adding a term to a vocabulary is considered an administrative action and
// should use the administrative theme.
$vocabulary = $this->createVocabulary();
$this->drupalGet('admin/structure/taxonomy/manage/' . $vocabulary->id() . '/add');
$this->assertRaw('seven/css/base/elements.css', t("The administrative theme's CSS appears on the page for adding a taxonomy term."));
// Viewing a taxonomy term should use the default theme.
$term = $this->createTerm($vocabulary);
$this->drupalGet('taxonomy/term/' . $term->id());
$this->assertRaw('bartik/css/base/elements.css', t("The default theme's CSS appears on the page for viewing a taxonomy term."));
// Editing a taxonomy term should use the same theme as adding one.
$this->drupalGet('taxonomy/term/' . $term->id() . '/edit');
$this->assertRaw('seven/css/base/elements.css', t("The administrative theme's CSS appears on the page for editing a taxonomy term."));
}
}

Some files were not shown because too many files have changed in this diff Show More