Last month we implemented the 'Resources' page on iias.asia, as you can see: you can filter the Resource nodes on this page in the right of the screen. This is a Drupal View with exposed filters, which are placed via a block via Twig Tweak module.
There is a 'Region' Filter and a 'Tags' taxonomy reference field, which are also used in other content types.
We only wanted to show used terms in the drop downs.
So, there are other pages (Views) that also implemented this tag as a filter (like the Alumni page). But of course: those pages have other content types, so 'used tags' are also different.
So here is how we limited the used tags, per Drupal View, this article gave us a kickstart.
YOURMODULE.module:
/**
* Implements hook_form_alter()
*
*/
function YOURMODULE_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
// Id's of the forms we want to alter.
$form_ids = [
'views-exposed-form-resources-page-1' => 'resource',
'views-exposed-form-reviews-page-1' => 'review',
'views-exposed-form-available-for-review-page-1' => 'review',
];
// Targeted taxonomy term fields.
$select_fields = ['tid_2', 'field_tags_target_id'];
// Continue only if current form_id is one in defined array.
if (array_key_exists($form['#id'], $form_ids)) {
// Loop through targeted fields.
foreach ($select_fields as $select_field) {
// Get 'terms in use', switch query on which field is currently in the loop.
// This only works if you have 1 or 2 targeted filters.
$available_terms = ($select_field == 'tid_2')
? _get_available_terms_region($form_ids[$form['#id']], $form['#id'])
: _get_available_terms_tags($form_ids[$form['#id']], $form['#id']);
// Continue if $available_terms exists.
if (isset($available_terms)) {
// Unset the existing list.
unset($form[$select_field]['#options']);
// Build new list with 'terms in use'.
$form[$select_field]['#options']['All'] = '- Any -';
foreach ($available_terms as $available_term) {
$tid = $available_term[0];
$name = $available_term[1];
$form[$select_field]['#options'][$tid] = $name;
}
}
}
}
}
/**
* Custom function to query and build new filter list.
*
* @param $node_type
* @param $exposed_block_id
* @return array
*/
function _get_available_terms_region($node_type, $exposed_block_id) {
// Table name of tags field.
$node_tags_table = 'node__field_profile_region';
// Query data.
$query = \Drupal::database()->select($node_tags_table, 'nft');
$query->distinct();
$query->join('taxonomy_term_field_data', 'tname', 'tname.tid = nft.field_profile_region_target_id');
$query->join('node', 'node', 'node.nid = nft.entity_id');
$query->fields('nft', ['field_profile_region_target_id']);
$query->fields('tname', ['name']);
$query->orderBy('tname.name');
// Dynamically query node type.
$query->condition('node.type', $node_type);
if($exposed_block_id == 'views-exposed-form-available-for-review-page-1') {
$query->join('node__field_boolean_1', 'available', 'available.entity_id = nft.entity_id');
$query->condition('available.field_boolean_1_value', 1);
}
$result = $query->execute();
// Build term list.
$term_list = [];
while ($row = $result->fetchAssoc()) {
array_push($term_list, [$row['field_profile_region_target_id'], $row['name']]);
}
// Return term list.
return $term_list;
}
/**
* Custom function to query and build new filter list.
*
* @param $node_type
* @param $exposed_block_id
* @return array
*/
function _get_available_terms_tags($node_type, $exposed_block_id) {
// Table name of tags field
$node_tags_table = 'node__field_tags';
// Query data.
$query = \Drupal::database()->select($node_tags_table, 'nft');
$query->distinct();
$query->join('taxonomy_term_field_data', 'tname', 'tname.tid = nft.field_tags_target_id');
$query->join('node', 'node', 'node.nid = nft.entity_id');
$query->fields('nft', ['field_tags_target_id']);
$query->fields('tname', ['name']);
$query->orderBy('tname.name');
// Dynamically query node type.
$query->condition('node.type', $node_type);
if($exposed_block_id == 'views-exposed-form-available-for-review-page-1') {
$query->join('node__field_boolean_1', 'available', 'available.entity_id = nft.entity_id');
$query->condition('available.field_boolean_1_value', 1);
}
$result = $query->execute();
// Build term list.
$term_list = [];
while ($row = $result->fetchAssoc()) {
array_push($term_list, [$row['field_tags_target_id'], $row['name']]);
}
// Return list.
return $term_list;
}
Custom functions in the block above, we put these in the same .module file, but maybe it's better to place it in a Drupal service for example. Of course you can always refactor this into one function -more dynamic. But I'll leave that up to you :)
I hope this gives you a head start, please let me know if you have any questions or improvements.