Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • project/nodeorder
  • issue/nodeorder-3072720
  • issue/nodeorder-2878320
  • issue/nodeorder-3321564
  • issue/nodeorder-3350621
  • issue/nodeorder-3364912
  • issue/nodeorder-3413248
  • issue/nodeorder-2993147
  • issue/nodeorder-3433619
  • issue/nodeorder-3415452
  • issue/nodeorder-3132575
  • issue/nodeorder-3132150
12 results
Select Git revision
Show changes
Commits on Source (6)
Showing
with 588 additions and 156 deletions
......@@ -3,3 +3,4 @@ override_taxonomy_page: true
show_links_on_node: true
link_to_ordering_page: true
link_to_ordering_page_taxonomy_admin: true
entity_list_limit: 50
......@@ -10,6 +10,8 @@ nodeorder.settings:
type: boolean
link_to_ordering_page_taxonomy_admin:
type: boolean
entity_list_limit:
type: integer
vocabularies:
type: sequence
label: 'types'
......
......@@ -63,3 +63,15 @@ function nodeorder_update_9001(&$sandbox) {
ConfigManagerInterface::KEY_VOCABULARIES => array_combine($vocabularies, $vocabularies),
]);
}
/**
* Set default value for entity_list_limit config property.
*/
function nodeorder_update_9002(&$sandbox) {
/** @var \Drupal\nodeorder\ConfigManagerInterface $configManager */
$configManager = \Drupal::service('nodeorder.config_manager');
$configManager->updateConfigValues([
ConfigManagerInterface::KEY_ENTITY_LIST_LIMIT => 50,
]);
}
......@@ -5,13 +5,14 @@
* Nodeorder module.
*/
use Drupal\Core\Cache\Cache;
use Drupal\Core\Batch\BatchBuilder;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Drupal\node\NodeInterface;
use Drupal\nodeorder\ConfigManagerInterface;
use Drupal\nodeorder\Batch\SwitchToNonOrderableBatch;
use Drupal\nodeorder\Batch\SwitchToOrderableBatch;
use Drupal\taxonomy\Entity\Term;
/**
......@@ -86,81 +87,44 @@ function nodeorder_form_taxonomy_vocabulary_form_alter(&$form, FormStateInterfac
* Submit handler for nodeorder_form_taxonomy_vocabulary_form_alter().
*/
function nodeorder_taxonomy_vocabulary_form_submit($form, FormStateInterface $form_state) {
/** @var \Drupal\nodeorder\NodeOrderManagerInterface $nodeorder_manager */
$nodeorder_manager = \Drupal::service('nodeorder.manager');
/** @var \Drupal\nodeorder\ConfigManagerInterface $configManager */
$configManager = \Drupal::service('nodeorder.config_manager');
$config = $configManager->config();
$vocabulary = $form_state->getFormObject()->getEntity();
$term_storage = \Drupal::entityTypeManager()->getStorage('taxonomy_term');
$orderable = $form_state->getValue('orderable');
$vocabularies = $config->get(ConfigManagerInterface::KEY_VOCABULARIES);
if ($orderable && empty($vocabularies[$vocabulary->id()])) {
// Switching from non-orderable to orderable.
Cache::invalidateTags(['nodeorder']);
// Set weight to nid for all rows in term_node where the tid is in this
// vocabulary.
$tree = $term_storage->loadTree($vocabulary->id());
$tids = [];
foreach ($tree as $term) {
$tids[] = $term->tid;
}
if (count($tids) > 0) {
$order = 'n.sticky DESC, tn0.weight';
$tid = 0;
$query_max = \Drupal::database()->select('taxonomy_index', 'ti')
->condition('tid', $tid);
$query_max->addExpression('MAX(weight)', 'mweight');
foreach ($tids as $tid) {
// Select *current* nodes for the current term.
// @todo Replace this hacked function call.
$result = $nodeorder_manager->selectNodes([$tid], 'and', 0, FALSE, $order, 0);
foreach ($result as $node) {
$max = $query_max->execute()->fetchField();
$max = (int) $max + 1;
\Drupal::database()->update('taxonomy_index')
->condition('nid', $node->nid)
->condition('tid', $tid)
->fields(['weight' => $max])
->execute();
}
try {
/** @var \Drupal\nodeorder\NodeOrderManagerInterface $nodeorderManager */
$nodeorderManager = \Drupal::service('nodeorder.manager');
$vocabularyId = $form_state->getFormObject()->getEntity()->id();
$isNewStateOrderable = (bool) $form_state->getValue('orderable');
$isVocabularyOrderable = $nodeorderManager->vocabularyIsOrderable($vocabularyId);
$isStateChanged = $isNewStateOrderable !== $isVocabularyOrderable;
if ($isStateChanged) {
$treeLoader = \Drupal::service('nodeorder.term_tree_loader');
$termIds = $treeLoader->descendantTids($vocabularyId);
/** @var \Drupal\nodeorder\Batch\SwitchOrderableStateBatchInterface $batchCallback */
$batchCallback = $isNewStateOrderable && !$isVocabularyOrderable
? SwitchToOrderableBatch::class
: SwitchToNonOrderableBatch::class;
$batchBuilder = (new BatchBuilder())
->setTitle(('Updating vocabulary orderable configuration.'))
->setFinishCallback([$batchCallback, 'finish'])
->setInitMessage(t('Starting process vocabulary terms.'))
->setProgressMessage(t('Completed @current step of @total.'))
->setErrorMessage(t('Vocabulary orederable state update has encountered an error.'));
foreach ($termIds as $termId) {
$batchBuilder->addOperation([$batchCallback, 'processTerm'], [$vocabularyId, $termId]);
}
}
\Drupal::messenger()->addStatus(t('You may now order nodes within this vocabulary.'));
}
elseif (!$orderable && !empty($vocabularies[$vocabulary->id()])) {
// Switching from orderable to non-orderable.
Cache::invalidateTags(['nodeorder']);
// Set weight to 0 for all rows in term_node where the tid is in this
// vocabulary.
$tree = $term_storage->loadTree($vocabulary->id());
$tids = [];
foreach ($tree as $term) {
$tids[] = $term->tid;
}
$batchBuilder->addOperation([$batchCallback, 'updateConfig'], [$vocabularyId]);
if (count($tids) > 0) {
\Drupal::database()->update('taxonomy_index')
->fields(['weight' => 0])
->condition('tid', $tids, 'IN')
->execute();
batch_set($batchBuilder->toArray());
}
\Drupal::messenger()->addStatus(t('You may no longer order nodes within this vocabulary.'));
}
// Update config.
$configManager->updateOrderableValue($vocabulary->id(), $orderable);
catch (\Throwable $exception) {
\Drupal::logger('nodeorder')->error($exception);
\Drupal::messenger()->addError(t('Vocabulary settings update failed.'));
}
}
/**
......
......@@ -7,8 +7,12 @@ services:
nodeorder.manager:
class: Drupal\nodeorder\NodeOrderManager
arguments: ['@nodeorder.config_manager', '@database', '@entity_type.manager', '@cache.default']
arguments: ['@nodeorder.config_manager', '@database', '@nodeorder.term_tree_loader', '@cache.default']
nodeorder.config_manager:
class: Drupal\nodeorder\ConfigManager
arguments: ['@config.factory']
nodeorder.term_tree_loader:
class: Drupal\nodeorder\TermTreeLoader
arguments: ['@entity_type.manager']
<?php
namespace Drupal\nodeorder\Batch;
/**
* Interface for switch orderable state batch implementations.
*/
interface SwitchOrderableStateBatchInterface {
/**
* Process term batch callback.
*
* @param int|string $vocabularyId
* An id of vocabulary.
* @param int|string $termId
* An id of term.
* @param array $context
* Batch context.
*
* @return void
*/
public static function processTerm($vocabularyId, $termId, array &$context);
/**
* Update config batch callback.
*
* @param int|string $vocabularyId
* An id of vocabulary.
*
* @return void
*/
public static function updateConfig($vocabularyId);
/**
* Finis batch callback.
*
* @param bool $success
* Indicate that the batch API tasks were all completed successfully.
* @param array $results
* An array of all the results that were updated in update_do_one().
* @param array $operations
* A list of the operations that had not been completed by the batch API.
*
* @return void
*/
public static function finish($success, $results, $operations);
}
<?php
namespace Drupal\nodeorder\Batch;
use Drupal\Core\Cache\Cache;
/**
* Switching vocabulary from orderable to non-orderable.
*/
class SwitchToNonOrderableBatch implements SwitchOrderableStateBatchInterface {
/**
* {@inheritdoc}
*/
public static function processTerm($vocabularyId, $termId, array &$context) {}
/**
* {@inheritdoc}
*/
public static function updateConfig($vocabularyId) {
/** @var \Drupal\nodeorder\ConfigManagerInterface $configManager */
$configManager = \Drupal::service('nodeorder.config_manager');
$configManager->updateOrderableValue($vocabularyId, FALSE);
}
/**
* {@inheritdoc}
*/
public static function finish($success, $results, $operations) {
Cache::invalidateTags(['nodeorder']);
\Drupal::messenger()
->addStatus(t('You may no longer order nodes within this vocabulary.'));
}
}
<?php
namespace Drupal\nodeorder\Batch;
use Drupal\Core\Cache\Cache;
/**
* Switching vocabulary from non-orderable to orderable.
*/
class SwitchToOrderableBatch implements SwitchOrderableStateBatchInterface {
/**
* {@inheritdoc}
*/
public static function processTerm($vocabularyId, $termId, array &$context) {
$nodes = static::getTermNodes($termId);
foreach ($nodes as $node) {
static::processTermNode($termId, $node->nid);
}
}
/**
* Retrieve *current* nodes for the current term.
*
* @todo Replace this hacked function call.
*
* @param int|string $termId
* An id of term.
*
* @return \Drupal\Core\Database\StatementInterface
* A resource identifier pointing to the query results.
*/
public static function getTermNodes($termId) {
$order = 'n.sticky DESC, tn0.weight';
/** @var \Drupal\nodeorder\NodeOrderManagerInterface $manager */
$manager = \Drupal::service('nodeorder.manager');
return $manager->selectNodes([$termId], 'and', 0, FALSE, $order, 0);
}
/**
* Update node weight in term index.
*
* @param int|string $termId
* An id of term.
* @param int|string $nodeId
* An id of node.
*
* @return void
*/
public static function processTermNode($termId, $nodeId) {
$maxQuery = \Drupal::database()
->select('taxonomy_index', 'ti')
->condition('tid', $termId);
$maxQuery->addExpression('MAX(weight)', 'mweight');
$currentMaxWeight = $maxQuery->execute()->fetchField();
$newMaxWeight = (int) $currentMaxWeight + 1;
\Drupal::database()->update('taxonomy_index')
->condition('nid', $nodeId)
->condition('tid', $termId)
->fields(['weight' => $newMaxWeight])
->execute();
}
/**
* {@inheritdoc}
*/
public static function updateConfig($vocabularyId) {
/** @var \Drupal\nodeorder\ConfigManagerInterface $configManager */
$configManager = \Drupal::service('nodeorder.config_manager');
$configManager->updateOrderableValue($vocabularyId, TRUE);
}
/**
* {@inheritdoc}
*/
public static function finish($success, $results, $operations) {
Cache::invalidateTags(['nodeorder']);
\Drupal::messenger()
->addStatus(t('You may now order nodes within this vocabulary.'));
}
}
......@@ -11,12 +11,14 @@ interface ConfigManagerInterface {
public const KEY_LINK_TO_ORDERING_PAGE = 'link_to_ordering_page';
public const KEY_LINK_TO_ORDERING_PAGE_TAXONOMY_ADMIN = 'link_to_ordering_page_taxonomy_admin';
public const KEY_OVERRIDE_TAXONOMY_PAGE = 'override_taxonomy_page';
public const KEY_ENTITY_LIST_LIMIT = 'entity_list_limit';
public const KEY_VOCABULARIES = 'vocabularies';
public const CONFIG_KEYS = [
self::KEY_SHOW_LINKS_ON_NODE,
self::KEY_LINK_TO_ORDERING_PAGE,
self::KEY_LINK_TO_ORDERING_PAGE_TAXONOMY_ADMIN,
self::KEY_OVERRIDE_TAXONOMY_PAGE,
self::KEY_ENTITY_LIST_LIMIT,
self::KEY_VOCABULARIES,
];
......
......@@ -2,8 +2,6 @@
namespace Drupal\nodeorder\Form;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\nodeorder\ConfigManagerInterface;
......@@ -28,35 +26,16 @@ class NodeorderAdminForm extends ConfigFormBase {
*/
protected $configManager;
/**
* Constructs a NodeorderAdminForm object.
*
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The factory for configuration objects.
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
* The entity type bundle info service.
* @param \Drupal\nodeorder\ConfigManagerInterface $config_manager
* The nodeorder config manager.
*/
public function __construct(
ConfigFactoryInterface $config_factory,
EntityTypeBundleInfoInterface $entity_type_bundle_info,
ConfigManagerInterface $config_manager,
) {
parent::__construct($config_factory);
$this->entityTypeBundleInfo = $entity_type_bundle_info;
$this->configManager = $config_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('config.factory'),
$container->get('entity_type.bundle.info'),
$container->get('nodeorder.config_manager'),
);
$instance = parent::create($container);
$instance->entityTypeBundleInfo = $container->get('entity_type.bundle.info');
$instance->configManager = $container->get('nodeorder.config_manager');
return $instance;
}
/**
......@@ -77,6 +56,7 @@ class NodeorderAdminForm extends ConfigFormBase {
'#title' => $this->t('Display ordering links'),
'#description' => $this->t('Choose whether to show ordering links. Links can be shown for all categories associated to a node or for the currently active category. It is also possible to not show the ordering links at all.'),
];
$form['nodeorder_show_links']['nodeorder_show_links_on_node'] = [
'#type' => 'radios',
'#title' => $this->t('Choose how to display ordering links'),
......@@ -119,6 +99,13 @@ class NodeorderAdminForm extends ConfigFormBase {
'#default_value' => $config->get(ConfigManagerInterface::KEY_OVERRIDE_TAXONOMY_PAGE),
];
$form['entity_list_limit'] = [
'#type' => 'number',
'#title' => $this->t('Max entities per page'),
'#description' => $this->t('How many entities can be listed on a page.'),
'#default_value' => $config->get(ConfigManagerInterface::KEY_ENTITY_LIST_LIMIT),
];
return parent::buildForm($form, $form_state);
}
......@@ -143,6 +130,7 @@ class NodeorderAdminForm extends ConfigFormBase {
ConfigManagerInterface::KEY_LINK_TO_ORDERING_PAGE => $form_state->getValue('nodeorder_link_to_ordering_page'),
ConfigManagerInterface::KEY_LINK_TO_ORDERING_PAGE_TAXONOMY_ADMIN => $form_state->getValue('nodeorder_link_to_ordering_page_taxonomy_admin'),
ConfigManagerInterface::KEY_OVERRIDE_TAXONOMY_PAGE => $form_state->getValue('nodeorder_override_taxonomy_page'),
ConfigManagerInterface::KEY_ENTITY_LIST_LIMIT => $form_state->getValue('entity_list_limit'),
ConfigManagerInterface::KEY_VOCABULARIES => $vocabularies,
]);
......
......@@ -2,15 +2,11 @@
namespace Drupal\nodeorder;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Cache\CacheTagsInvalidator;
use Drupal\Core\Database\Connection;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Database\Query\PagerSelectExtender;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityListBuilder;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\taxonomy\Entity\Term;
......@@ -63,13 +59,6 @@ class NodeOrderListBuilder extends EntityListBuilder implements FormInterface {
*/
protected $cacheTagsInvalidator;
/**
* Default cache bin.
*
* @var \Drupal\Core\Cache\CacheBackendInterface
*/
protected $cacheDefault;
/**
* Nodes weight.
*
......@@ -84,32 +73,23 @@ class NodeOrderListBuilder extends EntityListBuilder implements FormInterface {
*/
private $entitiesCount = 0;
/**
* {@inheritdoc}
*/
public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, Connection $database, FormBuilderInterface $form_builder, CacheTagsInvalidator $cache_tags_invalidator, CacheBackendInterface $cache_default, Term $taxonomy_term) {
parent::__construct($entity_type, $storage);
$this->database = $database;
$this->formBuilder = $form_builder;
$this->taxonomyTerm = $taxonomy_term;
$this->cacheTagsInvalidator = $cache_tags_invalidator;
$this->cacheDefault = $cache_default;
}
/**
* {@inheritdoc}
*/
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type, Term $taxonomy_term = NULL) {
return new static(
$entity_type,
$container->get('entity_type.manager')->getStorage($entity_type->id()),
$container->get('database'),
$container->get('form_builder'),
$container->get('cache_tags.invalidator'),
$container->get('cache.default'),
$taxonomy_term
);
$instance = parent::createInstance($container, $entity_type);
$instance->database = $container->get('database');
$instance->formBuilder = $container->get('form_builder');
$instance->taxonomyTerm = $taxonomy_term;
$instance->cacheTagsInvalidator = $container->get('cache_tags.invalidator');
/** @var \Drupal\nodeorder\ConfigManagerInterface $config_manager */
$config_manager = $container->get('nodeorder.config_manager');
$config = $config_manager->config();
$instance->limit = $config->get(ConfigManagerInterface::KEY_ENTITY_LIST_LIMIT) ?: $instance->limit;
return $instance;
}
/**
......@@ -275,7 +255,7 @@ class NodeOrderListBuilder extends EntityListBuilder implements FormInterface {
$nodes = $form_state->getValue($this->entitiesKey);
$nids = array_keys($nodes);
$tags = [];
$cache_tags = [];
$entities = $this->storage->loadMultiple($nids);
foreach ($entities as $nid => $node) {
// Only take form elements that are blocks.
......@@ -286,17 +266,16 @@ class NodeOrderListBuilder extends EntityListBuilder implements FormInterface {
->condition('nid', $nid)
->execute();
$tags = array_merge($tags, $node->getCacheTags());
$cache_tags = Cache::mergeTags($cache_tags, $node->getCacheTags());
}
}
$this->messenger()->addStatus($this->t('The node orders have been updated.'));
if (!empty($tags)) {
$this->cacheTagsInvalidator->invalidateTags($tags);
if (!empty($cache_tags)) {
$cache_tags[] = 'node_list';
$this->cacheTagsInvalidator->invalidateTags($cache_tags);
}
$this->cacheDefault->deleteAll();
}
}
......@@ -5,7 +5,6 @@ namespace Drupal\nodeorder;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\node\NodeInterface;
use Drupal\taxonomy\Entity\Vocabulary;
......@@ -29,11 +28,11 @@ class NodeOrderManager implements NodeOrderManagerInterface {
protected $database;
/**
* Taxonomy term storage.
* Term tree loader.
*
* @var \Drupal\taxonomy\TermStorageInterface
* @var \Drupal\nodeorder\TermTreeLoaderInterface
*/
protected $termStorage;
protected $treeLoader;
/**
* Default cache bin.
......@@ -49,17 +48,17 @@ class NodeOrderManager implements NodeOrderManagerInterface {
* The nodeorder config manager.
* @param \Drupal\Core\Database\Connection $database
* The current database connection.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity manager.
* @param \Drupal\nodeorder\TermTreeLoaderInterface $treeLoader
* Term tree loader.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache
* Default cache bin.
*
* @throws \Throwable
*/
public function __construct(ConfigManagerInterface $config_manager, Connection $database, EntityTypeManagerInterface $entity_type_manager, CacheBackendInterface $cache) {
public function __construct(ConfigManagerInterface $config_manager, Connection $database, TermTreeLoaderInterface $treeLoader, CacheBackendInterface $cache) {
$this->database = $database;
$this->configManager = $config_manager;
$this->termStorage = $entity_type_manager->getStorage('taxonomy_term');
$this->treeLoader = $treeLoader;
$this->cache = $cache;
}
......@@ -176,16 +175,13 @@ class NodeOrderManager implements NodeOrderManagerInterface {
$depth = NULL;
}
foreach ($tids as $index => $tid) {
$term = $this->termStorage->load($tid);
$tree = $this->termStorage->loadTree($term->bundle(), $tid, $depth);
$descendant_tids[] = array_merge([$tid], array_map(function ($value) {
return $value->id();
}, $tree));
$tree = $this->treeLoader->descendantTidsByTermId($tid, $depth);
$descendant_tids[] = array_merge([$tid], $tree);
}
if ($operator == 'or') {
$args = call_user_func_array('array_merge', $descendant_tids);
$placeholders = db_placeholders($args, 'int');
$placeholders = $this->database->placeholders($args, 'int');
$sql = 'SELECT DISTINCT(n.nid), nd.sticky, nd.title, nd.created, tn.weight FROM {node} n LEFT JOIN {node_field_data} nd INNER JOIN {taxonomy_index} tn ON n.vid = tn.vid WHERE tn.tid IN (' . $placeholders . ') AND n.status = 1 ORDER BY ' . $order;
$sql_count = 'SELECT COUNT(DISTINCT(n.nid)) FROM {node} n INNER JOIN {taxonomy_index} tn ON n.vid = tn.vid WHERE tn.tid IN (' . $placeholders . ') AND n.status = 1';
}
......@@ -210,7 +206,8 @@ class NodeOrderManager implements NodeOrderManagerInterface {
if ($count == -1) {
$count = $config->get('default_nodes_main');
}
$result = pager_query($sql, $count, 0, $sql_count, $args);
$query = $this->database->query($sql, $args);
$result = $query->extend('Drupal\Core\Database\Query\PagerSelectExtender')->limit($count);
}
else {
if ($count == -1) {
......@@ -223,7 +220,7 @@ class NodeOrderManager implements NodeOrderManagerInterface {
}
else {
// @todo Please convert this statement to the D7 database API syntax.
$database = \Drupal::database();
$database = $this->database;
$result = $database->queryRange($sql, $args);
}
}
......
<?php
namespace Drupal\nodeorder;
use Drupal\Core\Entity\EntityTypeManagerInterface;
/**
* TermTreeLoader service to handle tree load.
*/
class TermTreeLoader implements TermTreeLoaderInterface {
/**
* Taxonomy term storage.
*
* @var \Drupal\taxonomy\TermStorageInterface
*/
protected $termStorage;
/**
* TermTreeLoader construct.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager.
*/
public function __construct(EntityTypeManagerInterface $entityTypeManager) {
$this->termStorage = $entityTypeManager->getStorage('taxonomy_term');
}
/**
* {@inheritdoc}
*/
public function descendantTids($vid, $parent = 0, $maxDepth = NULL) {
$tree = $this->termStorage->loadTree($vid, $parent, $maxDepth, FALSE);
return array_map(function ($value) {
return $value->tid;
}, $tree);
}
/**
* {@inheritdoc}
*/
public function descendantTidsByTermId($termId, $maxDepth = NULL) {
/** @var \Drupal\taxonomy\TermInterface $term */
$term = $this->termStorage->load($termId);
return $this->descendantTids($term->bundle(), $termId, $maxDepth);
}
}
<?php
namespace Drupal\nodeorder;
/**
* Provides an interface defining a TermTreeLoader.
*/
interface TermTreeLoaderInterface {
/**
* Finds all descendant term ids in a given vocabulary ID.
*
* @param string $vid
* Vocabulary ID to retrieve terms for.
* @param int $parent
* The term ID under which to generate the tree. If 0, generate the tree
* for the entire vocabulary.
* @param int $maxDepth
* The number of levels of the tree to return. Leave NULL to return all
* levels.
*
* @return object[]|\Drupal\taxonomy\TermInterface[]
* A numerically indexed array of term objects that are the children of the
* vocabulary $vid.
*/
public function descendantTids($vid, $parent = 0, $maxDepth = NULL);
/**
* Finds all descendant term ids.
*
* @param string|int $termId
* The term ID under which to generate the tree.
* @param int $maxDepth
* The number of levels of the tree to return. Leave NULL to return all
* levels.
*
* @return object[]|\Drupal\taxonomy\TermInterface[]
* A numerically indexed array of term objects that are the children of the
* vocabulary $vid.
*/
public function descendantTidsByTermId($termId, $maxDepth = NULL);
}
<?php
namespace Drupal\Tests\nodeorder\Kernel;
use Drupal\KernelTests\KernelTestBase;
use Drupal\nodeorder\ConfigManagerInterface;
use Drupal\nodeorder\NodeOrderListBuilder;
use Drupal\Tests\taxonomy\Traits\TaxonomyTestTrait;
/**
* Tests NodeOrderListBuilder service.
*
* @group nodeorder
*/
class NodeOrderListBuilderTest extends KernelTestBase {
use TaxonomyTestTrait;
/**
* {@inheritdoc}
*/
protected static $modules = [
'system',
'text',
'filter',
'user',
'node',
'taxonomy',
'nodeorder',
];
/**
* The nodeorder config manager.
*
* @var \Drupal\nodeorder\ConfigManagerInterface
*/
protected $configManager;
/**
* Node storage.
*
* @var \Drupal\node\NodeStorage
*/
protected $nodeStorage;
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
$this->installEntitySchema('taxonomy_term');
$this->installEntitySchema('user');
$this->installEntitySchema('node');
$this->installSchema('user', ['users_data']);
$this->installConfig(['system', 'filter', 'user', 'taxonomy']);
$this->container->get('module_installer')->install(['nodeorder']);
$this->configManager = $this->container->get('nodeorder.config_manager');
$this->nodeStorage = $this->container->get('entity_type.manager')->getStorage('node');
}
/**
* Tests limit config for list builder.
*
* @dataProvider limitConfigDataProvider
*/
public function testLimitConfig(int $config_value, int $expected_limit) {
$entity_type = $this->nodeStorage->getEntityType();
$taxonomy_term = $this->createTerm($this->createVocabulary());
$this->configManager->updateConfigValues([
ConfigManagerInterface::KEY_ENTITY_LIST_LIMIT => $config_value,
]);
$builder = NodeOrderListBuilder::createInstance($this->container, $entity_type, $taxonomy_term);
self::assertEquals($expected_limit, $this->getProperty($builder, 'limit'));
}
/**
* Data provider for limitConfig with possible cases.
*
* @return array
* A list of test case arguments.
*/
public function limitConfigDataProvider() {
// $config_value, $expected_limit.
return [
[0, 50],
[50, 50],
[100, 100],
];
}
/**
* Gets the value of protected property.
*
* @param $object
* Object.
* @param $property
* Property name.
*
* @return mixed
* Property value.
*
* @throws \ReflectionException
*/
protected function getProperty($object, $property) {
$reflectedClass = new \ReflectionClass($object);
$reflection = $reflectedClass->getProperty($property);
$reflection->setAccessible(TRUE);
return $reflection->getValue($object);
}
}
......@@ -76,6 +76,7 @@ class NodeorderConfigSchemaTest extends KernelTestBase {
'show_links_on_node' => TRUE,
'link_to_ordering_page' => TRUE,
'link_to_ordering_page_taxonomy_admin' => TRUE,
'entity_list_limit' => 50,
],
TRUE,
],
......@@ -86,6 +87,7 @@ class NodeorderConfigSchemaTest extends KernelTestBase {
'show_links_on_node' => 1,
'link_to_ordering_page' => 0,
'link_to_ordering_page_taxonomy_admin' => $this->randomString(),
'entity_list_limit' => '50',
],
FALSE,
],
......
<?php
namespace Drupal\Tests\nodeorder\Kernel;
use Drupal\KernelTests\KernelTestBase;
use Drupal\Tests\taxonomy\Traits\TaxonomyTestTrait;
/**
* Tests TermTreeLoader service.
*
* @group nodeorder
*/
class TermTreeLoaderTest extends KernelTestBase {
use TaxonomyTestTrait;
/**
* {@inheritdoc}
*/
protected static $modules = ['taxonomy', 'text', 'filter', 'user', 'node', 'nodeorder'];
/**
* Term tree loader.
*
* @var \Drupal\nodeorder\TermTreeLoaderInterface
*/
protected $treeLoader;
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
$this->installEntitySchema('taxonomy_term');
$this->installConfig(['filter']);
$this->treeLoader = $this->container->get('nodeorder.term_tree_loader');
}
/**
* Tests both methods descendantTids and descendantTidsByTermId.
*/
public function testDescendantTidsSelection() {
$vocabulary1 = $this->createVocabulary(['vid' => 'vid1', 'name' => 'name1']);
$vocabulary2 = $this->createVocabulary(['vid' => 'vid2', 'name' => 'name2']);
$term1v1 = $this->createTerm($vocabulary1, ['name' => 'v1t1']);
$term11v1 = $this->createTerm($vocabulary1, ['name' => 'v1t11', 'parent' => $term1v1->id()]);
$term111v1 = $this->createTerm($vocabulary1, ['name' => 'v1t111', 'parent' => $term11v1->id()]);
$term2v1 = $this->createTerm($vocabulary1, ['name' => 'v1t2']);
$term21v1 = $this->createTerm($vocabulary1, ['name' => 'v1t21', 'parent' => $term2v1->id()]);
$this->createTerm($vocabulary2, ['name' => 'v2t1']);
// Case1: vid - vid1, parent - 0, maxDepth - null.
$this->assertEquals(
[
$term1v1->id(),
$term11v1->id(),
$term111v1->id(),
$term2v1->id(),
$term21v1->id(),
],
$this->treeLoader->descendantTids($vocabulary1->id())
);
// Case2: vid - vid1, parent - 0, maxDepth - 1.
$this->assertEquals(
[
$term1v1->id(),
$term2v1->id(),
],
$this->treeLoader->descendantTids($vocabulary1->id(), 0, 1)
);
// Case3: vid - vid1, parent - v1t2, maxDepth - null.
$this->assertEquals(
[
$term21v1->id(),
],
$this->treeLoader->descendantTids($vocabulary1->id(), $term2v1->id())
);
$this->assertEquals(
[
$term11v1->id(),
$term111v1->id(),
],
$this->treeLoader->descendantTidsByTermId($term1v1->id())
);
$this->assertEquals(
[
$term11v1->id(),
],
$this->treeLoader->descendantTidsByTermId($term1v1->id(), 1)
);
}
}