og-8.x-1.x-dev/src/Plugin/views/argument_validator/Group.php
src/Plugin/views/argument_validator/Group.php
<?php
namespace Drupal\og\Plugin\views\argument_validator;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\Context\EntityContextDefinition;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\og\GroupTypeManagerInterface;
use Drupal\views\Plugin\views\argument_validator\ArgumentValidatorPluginBase;
use Drupal\views\Attribute\ViewsArgumentValidator;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Validate whether an argument is a valid group.
*
* This supports numeric arguments group entity id. This validator also sets the
* argument's title to the group label, which is the main reason behind this
* validator.
*/
#[ViewsArgumentValidator(
id: "og_group",
title: new TranslatableMarkup("OG group")
)]
class Group extends ArgumentValidatorPluginBase implements ContainerFactoryPluginInterface {
/**
* If this validator can handle multiple arguments.
*/
protected bool $multipleCapable = TRUE;
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
protected readonly EntityTypeManagerInterface $entityTypeManager,
protected readonly EntityTypeBundleInfoInterface $entityTypeBundleInfo,
protected readonly GroupTypeManagerInterface $groupTypeManager,
) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
}
/**
* {@inheritdoc}
*/
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('entity_type.bundle.info'),
$container->get('og.group_type_manager')
);
}
/**
* {@inheritdoc}
*/
public function defineOptions() {
$options = parent::defineOptions();
$options['group_type'] = ['default' => 'node'];
$options['access'] = ['default' => FALSE];
$options['operation'] = ['default' => 'view'];
$options['multiple'] = ['default' => FALSE];
return $options;
}
/**
* {@inheritdoc}
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
$group_types = $this->groupTypeManager->getGroupMap();
// If no groups have been created yet, show only the error message and hide
// the other elements.
if (empty($group_types)) {
$form['empty'] = [
'#type' => 'html_tag',
'#tag' => 'p',
'#value' => $this->t('No groups have been set up yet.'),
];
return $form;
}
$entity_type_options = [];
foreach ($group_types as $entity_type => $bundles) {
$definition = $this->entityTypeManager->getDefinition($entity_type);
$entity_type_options[$entity_type] = $definition->getLabel();
}
$form['group_type'] = [
'#type' => 'select',
'#title' => $this->t('Entity type'),
'#options' => $entity_type_options,
'#default_value' => $this->options['group_type'],
'#required' => TRUE,
];
// Offer the option to filter by access to the entity in the argument.
$form['access'] = [
'#type' => 'checkbox',
'#title' => $this->t('Validate user has access to the OG Group'),
'#default_value' => $this->options['access'],
];
$form['operation'] = [
'#type' => 'radios',
'#title' => $this->t('Access operation to check'),
'#options' => [
'view' => $this->t('View'),
'update' => $this->t('Edit'),
'delete' => $this->t('Delete'),
],
'#default_value' => $this->options['operation'],
'#states' => [
'visible' => [
':input[name="options[validate][options][og_group][access]"]' => ['checked' => TRUE],
],
],
];
// If class is multiple capable give the option to validate single/multiple.
if ($this->multipleCapable) {
$form['multiple'] = [
'#type' => 'radios',
'#title' => $this->t('Multiple arguments'),
'#options' => [
0 => $this->t('Single ID'),
1 => $this->t('One or more IDs separated by , or +'),
],
'#default_value' => (string) $this->options['multiple'],
];
}
return $form;
}
/**
* {@inheritdoc}
*/
public function validateArgument($argument) {
if ($this->multipleCapable && $this->options['multiple'] && isset($argument)) {
// At this point only interested in individual IDs no matter what type,
// just splitting by the allowed delimiters.
$ids = array_filter(preg_split('/[,+ ]/', $argument));
}
elseif ($argument) {
$ids = [$argument];
}
// No specified argument should be invalid.
else {
return FALSE;
}
$group_type = $this->options['group_type'];
$entities = $this->entityTypeManager->getStorage($group_type)->loadMultiple($ids);
$labels = [];
// Validate each id => entity. If any fails break out and return false.
foreach ($ids as $id) {
// There is no entity for this ID.
if (!isset($entities[$id])) {
return FALSE;
}
if (!$this->validateEntity($entities[$id])) {
return FALSE;
}
$labels[] = $entities[$id]->label();
}
$this->argument->argument = $argument;
$this->argument->validated_title = implode(' + ', $labels);
return TRUE;
}
/**
* Validates an individual entity against class access settings.
*/
protected function validateEntity(EntityInterface $entity): bool {
// If access restricted by entity operation.
if ($this->options['access'] && !$entity->access($this->options['operation'])) {
return FALSE;
}
$entity_type = $entity->getEntityTypeId();
$bundle = $entity->bundle();
// If entity is not a group type.
if (!$this->groupTypeManager->isGroup($entity_type, $bundle)) {
return FALSE;
}
return TRUE;
}
/**
* {@inheritdoc}
*/
public function calculateDependencies() {
$dependencies = parent::calculateDependencies();
$entity_type_id = $this->options['group_type'];
$bundle_entity_type = $this->entityTypeManager->getDefinition($entity_type_id)->getBundleEntityType();
// The bundle entity type might not exist. For example, users do not have
// bundles.
if ($this->entityTypeManager->hasHandler($bundle_entity_type, 'storage')) {
$bundle_entity_storage = $this->entityTypeManager->getStorage($bundle_entity_type);
$group_types = $this->groupTypeManager->getGroupMap();
foreach ($bundle_entity_storage->loadMultiple($group_types[$this->options['group_type']]) as $bundle_entity) {
$dependencies[$bundle_entity->getConfigDependencyKey()][] = $bundle_entity->getConfigDependencyName();
}
}
return $dependencies;
}
/**
* {@inheritdoc}
*/
public function getContextDefinition() {
return EntityContextDefinition::fromEntityTypeId($this->options['group_type'])
->setLabel($this->argument->adminLabel())
->setRequired(FALSE);
}
}
