X-Git-Url: http://www.aleph1.co.uk/gitweb/?a=blobdiff_plain;ds=sidebyside;f=web%2Fcore%2Fmodules%2Ftaxonomy%2Fsrc%2FTermStorage.php;fp=web%2Fcore%2Fmodules%2Ftaxonomy%2Fsrc%2FTermStorage.php;h=2d47722faeae5350efbd3118b9a99ce7d681f942;hb=0bf8d09d2542548982e81a441b1f16e75873a04f;hp=0a00c13de5652eb1e81b268c2aa74039570caad7;hpb=74df008bdbb3a11eeea356744f39b802369bda3c;p=yaffs-website diff --git a/web/core/modules/taxonomy/src/TermStorage.php b/web/core/modules/taxonomy/src/TermStorage.php index 0a00c13de..2d47722fa 100644 --- a/web/core/modules/taxonomy/src/TermStorage.php +++ b/web/core/modules/taxonomy/src/TermStorage.php @@ -2,35 +2,14 @@ namespace Drupal\taxonomy; -use Drupal\Core\Entity\Sql\SqlContentEntityStorage; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\Sql\SqlContentEntityStorage; /** * Defines a Controller class for taxonomy terms. */ 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. * @@ -59,6 +38,14 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac */ protected $trees = []; + /** + * Array of all loaded term ancestry keyed by ancestor term ID, keyed by term + * ID. + * + * @var \Drupal\taxonomy\TermInterface[][] + */ + protected $ancestors; + /** * {@inheritdoc} * @@ -80,9 +67,7 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac */ 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 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac /** * {@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 parent. + // @see https://www.drupal.org/node/2019905 + if (!empty($id)) { + $terms[$id] = $parent; + } + } + } + + 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 + * 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 parent. + $parents[0] = NULL; + continue; } - $this->parents[$tid] = $parents; + $ids[] = $item->target_id; } - return $this->parents[$tid]; + + // @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(); - - 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(); - } - } + /** @var \Drupal\taxonomy\TermInterface $term */ + return (!empty($tid) && $term = $this->load($tid)) ? $this->getAncestors($term) : []; + } + + /** + * 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 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac $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 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac $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 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac 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 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac * {@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 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac * {@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 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac 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 @@ class TermStorage extends SqlContentEntityStorage implements TermStorageInterfac public function __wakeup() { parent::__wakeup(); // Initialize static caches. - $this->parents = []; - $this->parentsAll = []; - $this->children = []; + $this->ancestors = []; $this->treeChildren = []; $this->treeParents = []; $this->treeTerms = [];