page archives projets filters
This commit is contained in:
@@ -80,3 +80,18 @@ function leshed_helpers_ensure_term_alias(EntityInterface $entity) {
|
||||
'langcode' => $langcode,
|
||||
])->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Déclare le plugin d'area "liste de termes en liens" pour les vues.
|
||||
*/
|
||||
function leshed_helpers_views_data() {
|
||||
$data['views']['leshed_helpers_term_links'] = [
|
||||
'title' => t('Liste de termes en liens (Le Shed)'),
|
||||
'help' => t("Liste les termes d'un vocabulaire en liens vers un chemin de base suivi du tid."),
|
||||
'area' => [
|
||||
'id' => 'leshed_helpers_term_links',
|
||||
],
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Plugin d'area Views listant les termes d'un vocabulaire en liens.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Drupal\leshed_helpers\Plugin\views\area;
|
||||
|
||||
use Drupal\Core\Database\Connection;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\views\Attribute\ViewsArea;
|
||||
use Drupal\views\Plugin\views\area\AreaPluginBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Affiche les termes d'un vocabulaire en liens vers un chemin filtré par tid.
|
||||
*
|
||||
* Chaque terme pointe vers <base_path>/<tid> ; l'alias géré par
|
||||
* leshed_helpers (ou pathauto) est appliqué automatiquement à la génération
|
||||
* du lien.
|
||||
*/
|
||||
#[ViewsArea('leshed_helpers_term_links')]
|
||||
class TermLinks extends AreaPluginBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* Le gestionnaire d'entités.
|
||||
*/
|
||||
protected EntityTypeManagerInterface $entityTypeManager;
|
||||
|
||||
/**
|
||||
* La connexion à la base de données.
|
||||
*/
|
||||
protected Connection $connection;
|
||||
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, Connection $connection) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->connection = $connection;
|
||||
}
|
||||
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('entity_type.manager'),
|
||||
$container->get('database')
|
||||
);
|
||||
}
|
||||
|
||||
protected function defineOptions() {
|
||||
$options = parent::defineOptions();
|
||||
$options['vocabulary'] = ['default' => ''];
|
||||
$options['base_path'] = ['default' => ''];
|
||||
$options['list_title'] = ['default' => ''];
|
||||
$options['show_all'] = ['default' => TRUE];
|
||||
$options['only_used'] = ['default' => FALSE];
|
||||
$options['used_bundle'] = ['default' => ''];
|
||||
return $options;
|
||||
}
|
||||
|
||||
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
|
||||
parent::buildOptionsForm($form, $form_state);
|
||||
|
||||
$vocabularies = [];
|
||||
foreach ($this->entityTypeManager->getStorage('taxonomy_vocabulary')->loadMultiple() as $vocabulary) {
|
||||
$vocabularies[$vocabulary->id()] = $vocabulary->label();
|
||||
}
|
||||
|
||||
$form['vocabulary'] = [
|
||||
'#type' => 'select',
|
||||
'#title' => $this->t('Vocabulaire'),
|
||||
'#options' => $vocabularies,
|
||||
'#default_value' => $this->options['vocabulary'],
|
||||
'#required' => TRUE,
|
||||
];
|
||||
$form['base_path'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Chemin de base'),
|
||||
'#description' => $this->t('Chemin de la vue filtrée, sans slash initial. Exemple : projets.'),
|
||||
'#default_value' => $this->options['base_path'],
|
||||
'#required' => TRUE,
|
||||
];
|
||||
$form['list_title'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Titre de la liste'),
|
||||
'#default_value' => $this->options['list_title'],
|
||||
];
|
||||
$form['show_all'] = [
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Ajouter un lien « Tous » vers la page non filtrée'),
|
||||
'#default_value' => $this->options['show_all'],
|
||||
];
|
||||
$form['only_used'] = [
|
||||
'#type' => 'checkbox',
|
||||
'#title' => $this->t("N'afficher que les termes utilisés par au moins un contenu publié"),
|
||||
'#default_value' => $this->options['only_used'],
|
||||
];
|
||||
$node_types = [];
|
||||
foreach ($this->entityTypeManager->getStorage('node_type')->loadMultiple() as $node_type) {
|
||||
$node_types[$node_type->id()] = $node_type->label();
|
||||
}
|
||||
$form['used_bundle'] = [
|
||||
'#type' => 'select',
|
||||
'#title' => $this->t('Type de contenu'),
|
||||
'#options' => $node_types,
|
||||
'#empty_option' => $this->t('- Tous types de contenu -'),
|
||||
'#empty_value' => '',
|
||||
'#default_value' => $this->options['used_bundle'],
|
||||
'#states' => [
|
||||
'visible' => [
|
||||
':input[name="options[only_used]"]' => ['checked' => TRUE],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function render($empty = FALSE) {
|
||||
if (empty($this->options['vocabulary']) || empty($this->options['base_path'])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$storage = $this->entityTypeManager->getStorage('taxonomy_term');
|
||||
$tree = $storage->loadTree($this->options['vocabulary']);
|
||||
if (empty($tree)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// tids des termes du vocabulaire, dans l'ordre de l'arborescence.
|
||||
$tids = array_map(static fn($term) => (int) $term->tid, $tree);
|
||||
|
||||
if (!empty($this->options['only_used'])) {
|
||||
// taxonomy_index ne référence que les contenus publiés ; jointure sur
|
||||
// node_field_data pour restreindre au type de contenu voulu. Une seule
|
||||
// requête pour tout le vocabulaire.
|
||||
$query = $this->connection->select('taxonomy_index', 'ti');
|
||||
$query->distinct();
|
||||
$query->fields('ti', ['tid']);
|
||||
$query->condition('ti.tid', $tids, 'IN');
|
||||
$query->join('node_field_data', 'nfd', 'nfd.nid = ti.nid AND nfd.status = 1');
|
||||
if (!empty($this->options['used_bundle'])) {
|
||||
$query->condition('nfd.type', $this->options['used_bundle']);
|
||||
}
|
||||
$used = array_map('intval', $query->execute()->fetchCol());
|
||||
$tids = array_values(array_intersect($tids, $used));
|
||||
}
|
||||
|
||||
$entities = $storage->loadMultiple($tids);
|
||||
|
||||
// tids présents dans les arguments de la vue, pour marquer le lien actif.
|
||||
$current_tids = [];
|
||||
foreach ($this->view->args as $arg) {
|
||||
foreach (explode(',', (string) $arg) as $tid) {
|
||||
$current_tids[] = trim($tid);
|
||||
}
|
||||
}
|
||||
|
||||
$base_path = '/' . trim($this->options['base_path'], '/');
|
||||
$items = [];
|
||||
|
||||
if (!empty($this->options['show_all'])) {
|
||||
$items[] = [
|
||||
'#type' => 'link',
|
||||
'#title' => $this->t('Tous'),
|
||||
'#url' => Url::fromUserInput($base_path),
|
||||
'#attributes' => $current_tids ? [] : ['class' => ['is-active']],
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($tree as $position) {
|
||||
$term = $entities[(int) $position->tid] ?? NULL;
|
||||
if ($term === NULL || !$term->isPublished()) {
|
||||
continue;
|
||||
}
|
||||
$items[] = [
|
||||
'#type' => 'link',
|
||||
'#title' => $term->label(),
|
||||
'#url' => Url::fromUserInput($base_path . '/' . $term->id()),
|
||||
'#attributes' => in_array((string) $term->id(), $current_tids, TRUE)
|
||||
? ['class' => ['is-active']]
|
||||
: [],
|
||||
];
|
||||
}
|
||||
|
||||
$cache_tags = ['taxonomy_term_list:' . $this->options['vocabulary']];
|
||||
if (!empty($this->options['only_used'])) {
|
||||
// Le filtrage par usage dépend des contenus publiés.
|
||||
$cache_tags[] = 'node_list';
|
||||
}
|
||||
|
||||
return [
|
||||
'#theme' => 'item_list',
|
||||
'#title' => $this->options['list_title'],
|
||||
'#list_type' => 'ul',
|
||||
'#items' => $items,
|
||||
'#attributes' => ['class' => ['leshed-term-links']],
|
||||
'#cache' => [
|
||||
'tags' => $cache_tags,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user