unused_media_filter-1.0.x-dev/src/Plugin/views/filter/UnusedMediaFilter.php
src/Plugin/views/filter/UnusedMediaFilter.php
<?php
namespace Drupal\unused_media_filter\Plugin\views\filter;
use Drupal\Core\Entity\ContentEntityTypeInterface;
use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItemInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\views\Attribute\ViewsFilter;
use Drupal\views\Plugin\views\filter\FilterPluginBase;
use Drupal\views\Views;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Unused media filter.
*
* The filter scans all content entities that have media reference fields.
*
* @ingroup views_filter_handlers
*/
#[ViewsFilter("unused_media")]
class UnusedMediaFilter extends FilterPluginBase {
/**
* Where the $query object will reside.
*
* @var \Drupal\views\Plugin\views\query\Sql
*/
public $query = NULL;
/**
* Whether to enable filtering.
*
* @var bool
*/
protected $enableFiltering = FALSE;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The entity field manager.
*
* @var \Drupal\Core\Entity\EntityFieldManagerInterface
*/
protected $entityFieldManager;
/**
* The field type plugin manager.
*
* @var \Drupal\Core\Field\FieldTypePluginManagerInterface
*/
protected $fieldTypePluginManager;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition){
$instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
$instance->entityTypeManager = $container->get('entity_type.manager');
$instance->entityFieldManager = $container->get('entity_field.manager');
$instance->fieldTypePluginManager = $container->get('plugin.manager.field.field_type');
return $instance;
}
/**
* {@inheritdoc}
*/
public function buildExposedForm(&$form, FormStateInterface $form_state) {
parent::buildExposedForm($form, $form_state);
$identifier = $this->options['expose']['identifier'];
$form[$identifier] = [
'#type' => 'checkbox',
'#title' => $this->options['expose']['label'],
];
}
/**
* {@inheritdoc}
*/
public function acceptExposedInput($input) {
$this->enableFiltering = !empty($input['unused_media']);
return parent::acceptExposedInput($input);
}
/**
* {@inheritdoc}
*/
public function query() {
if (!$this->enableFiltering) {
return;
}
// Prevent results using this filter from being cached as otherwise we need
// to implement a complex logic to invalidate cache whenever an entity is
// added as a reference somewhere.
$this->view->live_preview = TRUE;
$delta = 0;
foreach ($this->getTables() as $table => $field) {
$definition['table'] = $table;
$definition['field'] = $field;
$definition['left_table'] = 'media_field_data';
$definition['left_field'] = 'mid';
$definition['type'] = 'LEFT';
$definition['adjusted'] = TRUE;
$join = Views::pluginManager('join')->createInstance('standard', $definition);
// There is no $base as we are joining to a query.
$this->query->addRelationship("t{$delta}", $join, 'media');
$this->query->addWhere('AND', "t{$delta}.{$field}", NULL, 'IS NULL');
$delta++;
}
}
/**
* Get all tables that have file reference fields.
*
* @return array
* An array of tables and their target_id column.
*/
protected function getTables() {
$entity_types = $this->entityTypeManager->getDefinitions();
$file_reference_tables = [];
foreach ($entity_types as $entity_type_id => $entity_type) {
// Check if it is content entity type.
if ($entity_type instanceof ContentEntityTypeInterface) {
$storage = $this->entityTypeManager->getStorage($entity_type_id);
if (!$storage instanceof SqlContentEntityStorage) {
continue;
}
$table_mapping = $storage->getTableMapping();
$field_storage_definitions = $this->entityFieldManager->getFieldStorageDefinitions($entity_type_id);
foreach ($field_storage_definitions as $field_name => $field_storage) {
$field_type = $this->fieldTypePluginManager->getDefinition($field_storage->getType());
if (is_a($field_type['class'], EntityReferenceItemInterface::class, TRUE)) {
if ($field_storage->getSetting('target_type') === 'media') {
$target_id_column = $table_mapping->getColumnNames($field_name)['target_id'];
$tables = $table_mapping->getAllFieldTableNames($field_name);
$file_reference_tables = array_merge($file_reference_tables, array_combine($tables, array_fill(0, count($tables), $target_id_column)));
}
}
}
}
}
return $file_reference_tables;
}
}
