Mercurial > hg > isophonics-drupal-site
diff core/modules/taxonomy/src/TermStorage.php @ 17:129ea1e6d783
Update, including to Drupal core 8.6.10
author | Chris Cannam |
---|---|
date | Thu, 28 Feb 2019 13:21:36 +0000 |
parents | 4c8ae668cc8c |
children | af1871eacc83 |
line wrap: on
line diff
--- a/core/modules/taxonomy/src/TermStorage.php Tue Jul 10 15:07:59 2018 +0100 +++ b/core/modules/taxonomy/src/TermStorage.php Thu Feb 28 13:21:36 2019 +0000 @@ -2,8 +2,8 @@ namespace Drupal\taxonomy; +use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\Sql\SqlContentEntityStorage; -use Drupal\Core\Entity\EntityInterface; /** * Defines a Controller class for taxonomy terms. @@ -11,27 +11,6 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterface { /** - * Array of loaded parents keyed by child term ID. - * - * @var array - */ - protected $parents = []; - - /** - * Array of all loaded term ancestry keyed by ancestor term ID. - * - * @var array - */ - protected $parentsAll = []; - - /** - * Array of child terms keyed by parent term ID. - * - * @var array - */ - protected $children = []; - - /** * Array of term parents keyed by vocabulary ID and child term ID. * * @var array @@ -60,6 +39,14 @@ protected $trees = []; /** + * Array of all loaded term ancestry keyed by ancestor term ID, keyed by term + * ID. + * + * @var \Drupal\taxonomy\TermInterface[][] + */ + protected $ancestors; + + /** * {@inheritdoc} * * @param array $values @@ -80,9 +67,7 @@ */ public function resetCache(array $ids = NULL) { drupal_static_reset('taxonomy_term_count_nodes'); - $this->parents = []; - $this->parentsAll = []; - $this->children = []; + $this->ancestors = []; $this->treeChildren = []; $this->treeParents = []; $this->treeTerms = []; @@ -93,100 +78,125 @@ /** * {@inheritdoc} */ - public function deleteTermHierarchy($tids) { - $this->database->delete('taxonomy_term_hierarchy') - ->condition('tid', $tids, 'IN') - ->execute(); - } + public function deleteTermHierarchy($tids) {} /** * {@inheritdoc} */ - public function updateTermHierarchy(EntityInterface $term) { - $query = $this->database->insert('taxonomy_term_hierarchy') - ->fields(['tid', 'parent']); - - foreach ($term->parent as $parent) { - $query->values([ - 'tid' => $term->id(), - 'parent' => (int) $parent->target_id, - ]); - } - $query->execute(); - } + public function updateTermHierarchy(EntityInterface $term) {} /** * {@inheritdoc} */ public function loadParents($tid) { - if (!isset($this->parents[$tid])) { - $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('taxonomy_term_access'); - $query->orderBy('t.weight'); - $query->orderBy('t.name'); - if ($ids = $query->execute()->fetchCol()) { - $parents = $this->loadMultiple($ids); + $terms = []; + /** @var \Drupal\taxonomy\TermInterface $term */ + if ($tid && $term = $this->load($tid)) { + foreach ($this->getParents($term) as $id => $parent) { + // This method currently doesn't return the <root> parent. + // @see https://www.drupal.org/node/2019905 + if (!empty($id)) { + $terms[$id] = $parent; + } } - $this->parents[$tid] = $parents; } - return $this->parents[$tid]; + + return $terms; + } + + /** + * Returns a list of parents of this term. + * + * @return \Drupal\taxonomy\TermInterface[] + * The parent taxonomy term entities keyed by term ID. If this term has a + * <root> parent, that item is keyed with 0 and will have NULL as value. + * + * @internal + * @todo Refactor away when TreeInterface is introduced. + */ + protected function getParents(TermInterface $term) { + $parents = $ids = []; + // Cannot use $this->get('parent')->referencedEntities() here because that + // strips out the '0' reference. + foreach ($term->get('parent') as $item) { + if ($item->target_id == 0) { + // The <root> parent. + $parents[0] = NULL; + continue; + } + $ids[] = $item->target_id; + } + + // @todo Better way to do this? AND handle the NULL/0 parent? + // Querying the terms again so that the same access checks are run when + // getParents() is called as in Drupal version prior to 8.3. + $loaded_parents = []; + + if ($ids) { + $query = \Drupal::entityQuery('taxonomy_term') + ->condition('tid', $ids, 'IN'); + + $loaded_parents = static::loadMultiple($query->execute()); + } + + return $parents + $loaded_parents; } /** * {@inheritdoc} */ public function loadAllParents($tid) { - if (!isset($this->parentsAll[$tid])) { - $parents = []; - if ($term = $this->load($tid)) { - $parents[$term->id()] = $term; - $terms_to_search[] = $term->id(); + /** @var \Drupal\taxonomy\TermInterface $term */ + return (!empty($tid) && $term = $this->load($tid)) ? $this->getAncestors($term) : []; + } - while ($tid = array_shift($terms_to_search)) { - if ($new_parents = $this->loadParents($tid)) { - foreach ($new_parents as $new_parent) { - if (!isset($parents[$new_parent->id()])) { - $parents[$new_parent->id()] = $new_parent; - $terms_to_search[] = $new_parent->id(); - } - } + /** + * Returns all ancestors of this term. + * + * @return \Drupal\taxonomy\TermInterface[] + * A list of ancestor taxonomy term entities keyed by term ID. + * + * @internal + * @todo Refactor away when TreeInterface is introduced. + */ + protected function getAncestors(TermInterface $term) { + if (!isset($this->ancestors[$term->id()])) { + $this->ancestors[$term->id()] = [$term->id() => $term]; + $search[] = $term->id(); + + while ($tid = array_shift($search)) { + foreach ($this->getParents(static::load($tid)) as $id => $parent) { + if ($parent && !isset($this->ancestors[$term->id()][$id])) { + $this->ancestors[$term->id()][$id] = $parent; + $search[] = $id; } } } - - $this->parentsAll[$tid] = $parents; } - return $this->parentsAll[$tid]; + return $this->ancestors[$term->id()]; } /** * {@inheritdoc} */ public function loadChildren($tid, $vid = NULL) { - if (!isset($this->children[$tid])) { - $children = []; - $query = $this->database->select('taxonomy_term_field_data', 't'); - $query->join('taxonomy_term_hierarchy', 'h', 'h.tid = t.tid'); - $query->addField('t', 'tid'); - $query->condition('h.parent', $tid); - if ($vid) { - $query->condition('t.vid', $vid); - } - $query->condition('t.default_langcode', 1); - $query->addTag('taxonomy_term_access'); - $query->orderBy('t.weight'); - $query->orderBy('t.name'); - if ($ids = $query->execute()->fetchCol()) { - $children = $this->loadMultiple($ids); - } - $this->children[$tid] = $children; - } - return $this->children[$tid]; + /** @var \Drupal\taxonomy\TermInterface $term */ + return (!empty($tid) && $term = $this->load($tid)) ? $this->getChildren($term) : []; + } + + /** + * Returns all children terms of this term. + * + * @return \Drupal\taxonomy\TermInterface[] + * A list of children taxonomy term entities keyed by term ID. + * + * @internal + * @todo Refactor away when TreeInterface is introduced. + */ + public function getChildren(TermInterface $term) { + $query = \Drupal::entityQuery('taxonomy_term') + ->condition('parent', $term->id()); + return static::loadMultiple($query->execute()); } /** @@ -201,12 +211,12 @@ $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'); + $query = $this->database->select($this->getDataTable(), 't'); + $query->join('taxonomy_term__parent', 'p', 't.tid = p.entity_id'); + $query->addExpression('parent_target_id', 'parent'); $result = $query ->addTag('taxonomy_term_access') ->fields('t') - ->fields('h', ['parent']) ->condition('t.vid', $vid) ->condition('t.default_langcode', 1) ->orderBy('t.weight') @@ -254,7 +264,9 @@ $term = clone $term; } $term->depth = $depth; - unset($term->parent); + if (!$load_entities) { + unset($term->parent); + } $tid = $load_entities ? $term->id() : $term->tid; $term->parents = $this->treeParents[$vid][$tid]; $tree[] = $term; @@ -293,7 +305,7 @@ public function nodeCount($vid) { $query = $this->database->select('taxonomy_index', 'ti'); $query->addExpression('COUNT(DISTINCT ti.nid)'); - $query->leftJoin('taxonomy_term_data', 'td', 'ti.tid = td.tid'); + $query->leftJoin($this->getBaseTable(), 'td', 'ti.tid = td.tid'); $query->condition('td.vid', $vid); $query->addTag('vocabulary_node_count'); return $query->execute()->fetchField(); @@ -303,7 +315,7 @@ * {@inheritdoc} */ public function resetWeights($vid) { - $this->database->update('taxonomy_term_field_data') + $this->database->update($this->getDataTable()) ->fields(['weight' => 0]) ->condition('vid', $vid) ->execute(); @@ -313,7 +325,7 @@ * {@inheritdoc} */ public function getNodeTerms(array $nids, array $vocabs = [], $langcode = NULL) { - $query = db_select('taxonomy_term_field_data', 'td'); + $query = db_select($this->getDataTable(), 'td'); $query->innerJoin('taxonomy_index', 'tn', 'td.tid = tn.tid'); $query->fields('td', ['tid']); $query->addField('tn', 'nid', 'node_nid'); @@ -351,7 +363,7 @@ public function __sleep() { $vars = parent::__sleep(); // Do not serialize static cache. - unset($vars['parents'], $vars['parentsAll'], $vars['children'], $vars['treeChildren'], $vars['treeParents'], $vars['treeTerms'], $vars['trees']); + unset($vars['ancestors'], $vars['treeChildren'], $vars['treeParents'], $vars['treeTerms'], $vars['trees']); return $vars; } @@ -361,9 +373,7 @@ public function __wakeup() { parent::__wakeup(); // Initialize static caches. - $this->parents = []; - $this->parentsAll = []; - $this->children = []; + $this->ancestors = []; $this->treeChildren = []; $this->treeParents = []; $this->treeTerms = [];