flag_lists-4.0.x-dev/src/Plugin/views/field/FlaggingCollectionBulkForm.php
src/Plugin/views/field/FlaggingCollectionBulkForm.php
<?php
namespace Drupal\flag_lists\Plugin\views\field;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\views\Plugin\views\field\BulkForm;
use Drupal\flag_lists\Controller\ActionLinkController;
/**
* Defines a flagging Collection operations bulk form element.
*
* Note that actions are not used but instead the ActionLinks.
*
* @ViewsField("flagging_collection_bulk_form")
*/
class FlaggingCollectionBulkForm extends BulkForm {
/**
* Flag Lists Service injected.
*
* @var \Drupal\flag_lists\FlagListsService
*/
private $flagListsService;
/**
* Flag Service injected.
*
* @var \Drupal\flag\FlagService
*/
private $flagService;
/**
* {@inheritdoc}
*/
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
EntityTypeManagerInterface $entity_type_manager,
LanguageManagerInterface $language_manager,
MessengerInterface $messenger,
EntityRepositoryInterface $entity_repository) {
parent::__construct($configuration,
$plugin_id,
$plugin_definition,
$entity_type_manager,
$language_manager,
$messenger,
$entity_repository
);
$this->entityManager = $entity_type_manager;
$this->actionStorage = $entity_type_manager
->getStorage('action');
$this->languageManager = $language_manager;
$this->messenger = $messenger;
$this->entityRepository = $entity_repository;
$this->flagListsService = \Drupal::service('flaglists');
$this->flagService = \Drupal::service('flag');
}
/**
* {@inheritdoc}
*/
protected function emptySelectedMessage() {
return $this
->t('Please select one or more Entities to work on.');
}
/**
* {@inheritdoc}
*/
protected function getBulkOptions($filtered = TRUE) {
// Remove all existing actions and replace with our own.
$options = [];
$all_options['flag'] = $this->t('Flag the entities in the list');
$all_options['unflag'] = $this->t('Unflag the entities in the list');
foreach ($all_options as $id => $action) {
if ($filtered) {
$in_selected = in_array($id, $this->options['selected_actions']);
// If the field is configured to include only the selected actions,
// skip actions that were not selected.
if ($this->options['include_exclude'] == 'include' && !$in_selected) {
continue;
}
elseif ($this->options['include_exclude'] == 'exclude' &&
$in_selected) {
continue;
}
}
$options[$id] = $all_options[$id];
}
return $options;
}
/**
* {@inheritdoc}
*/
public function viewsForm(&$form, FormStateInterface $form_state) {
parent::viewsForm($form, $form_state);
$form['header'][$this->options['id']]['action']['#title'] =
$this->t('Flag action');
$options = ['0' => '- Create Flagging Collection -'];
foreach ($this->flagListsService->getUsersFlaggingCollections() as
$entity_id => $entity) {
// Check for right Flagging Collection is done during Validation.
$options[$entity_id] = $entity->getName();
}
$form['header'][$this->options['id']]['flaglist'] = [
'#type' => 'select',
'#title' => $this->t('Use this Flagging Collection'),
'#options' => $options,
];
$form['header'][$this->options['id']]['newlistFieldSet'] = [
'#type' => 'fieldset',
'#title' => $this->t('New Flagging Collection'),
'#states' => [
'visible' => [
':input[name="flaglist"]' => ['value' => '0'],
],
],
];
$form['header'][$this->options['id']]['newlistFieldSet']['newlist'] = [
'#type' => 'textfield',
'#title' => $this->t('Name'),
'#states' => [
'visible' => [
':input[name="flaglist"]' => ['value' => '0'],
],
],
];
$options = [];
foreach ($this->flagListsService->getAllFlagForList() as
$list_id => $list) {
$options[$list_id] = $list->get('label');
// Dig out if this is the right template.
}
$form['header'][$this->options['id']]['newlistFieldSet']['template'] = [
'#type' => 'select',
'#title' => $this->t('Template flag'),
'#options' => $options,
'#states' => [
'visible' => [
':input[name="flaglist"]' => ['value' => '0'],
],
],
];
$options = [];
$count = 0;
foreach ($this->flagListsService->getAllFlaggingCollectionTypes() as
$list_id => $list) {
$options[$list_id] = $list->get('label');
$count = $count + 1;
}
$count > 1 ?
$form['header'][$this->options['id']]['newlistFieldSet']['type'] = [
'#type' => 'select',
'#title' => $this->t('Flagging Collection Type'),
'#options' => $options,
] :
$form['header'][$this->options['id']]['newlistFieldSet']['type'] = [
'#type' => 'hidden',
'#title' => $this->t('Flagging Collection Type'),
'#value' => array_key_first($options),
];
}
/**
* {@inheritdoc}
*/
public function viewsFormSubmit(&$form, FormStateInterface $form_state) {
if ($form_state
->get('step') == 'views_form_views_form') {
$user_input = $form_state->getUserInput();
$baseFlag = $this->flagListsService
->getFlagForListById($user_input['template'])->getBaseFlag();
if ($user_input['flaglist'] == 0) {
// Create a new flaglist with name $newlist.
// No cleaning of input?
$template = [
'id' => 'tmp_id',
'name' => $user_input['newlist'],
'type' => $user_input['type'],
];
$flaggingCollection = $this
->entityTypeManager
->getStorage('flagging_collection')
->create($template);
$flaggingCollection->setBaseFlag($user_input['template']);
$flaggingCollection->save();
// Reload the newly saved Flagging Collection
$flaggingCollection = $flaggingCollection
->load($flaggingCollection->id());
$flag = $flaggingCollection
->getRelatedFlag();
$flagList = $flaggingCollection->id();
}
else {
$flag = $this->flagListsService
->getFlaggingCollectionById($user_input['flaglist'])
->getRelatedFlag();
$flagList = $user_input['flaglist'];
}
// Find the entities to execute the action on.
$selected = array_filter($user_input[$this->options['id']]);
$entities = [];
$count = 0;
foreach ($selected as $bulk_form_key) {
$entity = $this
->loadEntityFromBulkFormKey($bulk_form_key);
// Skip execution if current entity does not exist.
if (empty($entity)) {
continue;
}
if ($user_input['action'] == 'flag' &&
!empty($this->flagListsService->getFlagListItemIds($flag->id(),
$flagList,
$entity->id()))) {
// Skip execution if the entity is already in the collection.
continue;
}
elseif ($user_input['action'] == 'unflag' &&
empty($this->flagListsService->getFlagListItemIds($flag->id(),
$flagList,
$entity->id()))) {
// Skip execution if the entity isn't in the collection.
continue;
}
$count++;
$entities[$bulk_form_key] = $entity;
}
// If there were entities selected but the action isn't allowed on any of
// them, we don't need to do anything further.
if (!$count) {
// Maybe call the parent?
// parent::viewsFormSubmit($form, $form_state).
return;
}
// Execute the action via its link.
//
// Due to the following
// https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Action%21ActionInterface.php/interface/ActionInterface/8.9.x
// it is not implemented as an Action as it might break Drupal 9.
foreach ($entities as $entity_id => $entity) {
$actionLink = new ActionLinkController(
\Drupal::service('flag'),
$this->flagListsService,
\Drupal::service('renderer')
);
switch ($user_input['action']) {
case 'flag':
$actionLink->flag($flag,
$entity->id(),
$flagList
);
break;
case 'unflag':
$actionLink->unflag($flag,
$entity->id(),
$flagList
);
break;
default:
break;
}
}
$this->messenger
->addStatus($this
->formatPlural($count, '@count entity affected in %flaglists.', '@count entities affected in %flaglist.', [
'%flaglist' => $this->flagListsService->getFlaggingCollectionById($flagList)->getName(),
]));
}
}
/**
* {@inheritdoc}
*/
public function viewsFormValidate(&$form, FormStateInterface $form_state) {
if ($form_state->getValue('flaglist') == 0 &&
empty($form_state->getValue('newlist')) &&
$form_state->getValue('action') == 'flag') {
// A new Flagging Collection must have a name.
$form_state
->setErrorByName('newlist', $this
->t('Please set a name for the new Flagging Collection.'));
}
if (!empty($form_state->getValue('newlist'))) {
$listName = $this->flagListsService->getFlaggingCollectionIdByName(
$form_state->getValue('newlist'));
if (!empty($listName)) {
// The new name must not already exist.
$form_state
->setErrorByName('newlist', $this
->t('The new Flagging Collection name exists already.'));
}
}
if (($form_state->getValue('flaglist') == 0) &&
($form_state->getvalue('action') <> 'flag')) {
// It is only possible to unflag from existing Collections.
$form_state
->setErrorByName('flaglist', $this
->t('Please select an existing Flagging Collection.'));
}
$selected = $form_state->getValue($this->options['id']);
if (empty($selected) || empty(array_filter($selected))) {
// The action must have some target Entities.
$form_state
->setErrorByName('', $this
->emptySelectedMessage());
}
$user_input = $form_state->getUserInput();
if ($user_input['flaglist'] <> 0) {
// This is an existing flag.
$flagEntityType = $this->flagListsService
->getFlaggingCollectionById($user_input['flaglist'])
->getRelatedFlag()
->get('entity_type');
}
else {
// This is a just created flag.
$flagEntityType = $this->flagService
->getFlagById($user_input['template'])
->get('entity_type');
}
foreach ($selected as $bulk_form_key) {
// Skip execution if current entity does not exist.
if (empty($bulk_form_key)) {
continue;
}
$entity = $this
->loadEntityFromBulkFormKey($bulk_form_key);
if ($entity->getEntityTypeId() <> $flagEntityType) {
// Flagging Collection Entitiy must match the Listed ones.
$form_state
->setErrorByName('flaglist', $this
->t('Incorrect target Flagging Collection chosen for the listed entity type.'));
}
}
}
}
