diff --git a/services/drupal/config/sync/danse.settings.yml b/services/drupal/config/sync/danse.settings.yml index fa8df76d3..1bd2522e5 100644 --- a/services/drupal/config/sync/danse.settings.yml +++ b/services/drupal/config/sync/danse.settings.yml @@ -10,5 +10,5 @@ recipient_selection_plugin: content_moderation: 'transition_entity:epa_content_about_to_expire,transition_entity:epa_content_has_been_approved,transition_entity:epa_content_has_been_published,transition_entity:epa_content_has_been_unpublished,transition_entity:epa_content_has_expired,transition_entity:epa_content_needs_approval,transition_entity:epa_content_needs_review,transition_entity:epa_content_needs_review_manual,transition_entity:epa_content_will_expire,transition_entity:epa_draft_approval_denied' prune: content_moderation: - value: '1000' - type: records + value: '14' + type: days diff --git a/services/drupal/config/sync/user.role.authenticated.yml b/services/drupal/config/sync/user.role.authenticated.yml index 5768de270..16211048a 100644 --- a/services/drupal/config/sync/user.role.authenticated.yml +++ b/services/drupal/config/sync/user.role.authenticated.yml @@ -105,6 +105,8 @@ permissions: - 'execute entity:unpublish_action paragraphs_library_item' - 'execute entity:unpublish_action path_alias' - 'execute entity:unpublish_action taxonomy_term' + - 'execute epa_flag_on_behalf_of_user node' + - 'execute epa_unflag_on_behalf_of_user node' - 'execute epa_web_areas_update_media_group_association media' - 'execute epa_web_areas_update_node_group_association node' - 'execute moderation_state_change block_content' diff --git a/services/drupal/config/sync/views.view.moderated_content.yml b/services/drupal/config/sync/views.view.moderated_content.yml index 1038dc435..3d51f2b47 100644 --- a/services/drupal/config/sync/views.view.moderated_content.yml +++ b/services/drupal/config/sync/views.view.moderated_content.yml @@ -3552,16 +3552,21 @@ display: action_id: epa_flag_on_behalf_of_user preconfiguration: add_confirmation: false - label_override: 'Toggle content to be "Watched" for user' + label_override: ' Set content to be "watched" for user' 4: - action_id: 'flag_action:notification_opt_in_flag' + action_id: epa_unflag_on_behalf_of_user preconfiguration: add_confirmation: false + label_override: ' Set content to be "un-watched" for user' 5: - action_id: 'flag_action:notification_opt_in_unflag' + action_id: 'flag_action:notification_opt_in_flag' preconfiguration: add_confirmation: false 6: + action_id: 'flag_action:notification_opt_in_unflag' + preconfiguration: + add_confirmation: false + 7: action_id: node_assign_owner_action preconfiguration: add_confirmation: false diff --git a/services/drupal/web/modules/custom/epa_workflow/src/Plugin/Action/EPAFlagUsersAction.php b/services/drupal/web/modules/custom/epa_workflow/src/Plugin/Action/EPAFlagUsersAction.php index 6cd07d6de..b8042ff6f 100644 --- a/services/drupal/web/modules/custom/epa_workflow/src/Plugin/Action/EPAFlagUsersAction.php +++ b/services/drupal/web/modules/custom/epa_workflow/src/Plugin/Action/EPAFlagUsersAction.php @@ -2,19 +2,8 @@ namespace Drupal\epa_workflow\Plugin\Action; -use Drupal\Component\Render\FormattableMarkup; -use Drupal\Core\Access\AccessResult; -use Drupal\Core\Entity\EntityTypeManager; -use Drupal\Core\Form\FormStateInterface; -use Drupal\Core\Plugin\ContainerFactoryPluginInterface; -use Drupal\Core\Session\AccountInterface; -use Drupal\flag\FlagService; -use Drupal\views_bulk_operations\Action\ViewsBulkOperationsActionBase; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\HttpFoundation\RedirectResponse; - /** - * Provides the 'Update Group Association' action. + * Provides the 'Flag content on behalf of user' action. * * @Action( * id = "epa_flag_on_behalf_of_user", @@ -23,105 +12,7 @@ * category = @Translation("Custom") * ) */ -class EPAFlagUsersAction extends ViewsBulkOperationsActionBase implements ContainerFactoryPluginInterface { - - const NOTIFICATION_FLAG_ID = 'notification_opt_in'; - - /** - * The flag service. - * - * @var \Drupal\flag\FlagService - */ - protected $flagService; - - /** - * The entity type manager service. - * - * @var \Drupal\Core\Entity\EntityTypeManager - */ - protected $entityTypeManager; - - /** - * {@inheritDoc} - */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { - return new static( - $configuration, - $plugin_id, - $plugin_definition, - $container->get('flag'), - $container->get('entity_type.manager') - ); - } - - /** - * @param \Drupal\flag\FlagService $flag_service - * @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager - */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, FlagService $flag_service, EntityTypeManager $entity_type_manager) { - parent::__construct($configuration, $plugin_id, $plugin_definition); - $this->flagService = $flag_service; - $this->entityTypeManager = $entity_type_manager; - } - - /** - * {@inheritDoc} - */ - public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) { - if ($account->hasPermission('execute watch content on behalf of user')) { - return AccessResult::allowed(); - } - - $grp_membership_service = \Drupal::service('group.membership_loader'); - /** @var \Drupal\group\GroupMembership[] $grps */ - $grps = $grp_membership_service->loadByUser($account); - - foreach ($grps as $grp) { - if ($grp->hasPermission('execute watch content on behalf of user')) { - return AccessResult::allowed(); - } - } - - - return AccessResult::forbidden(); - } - - /** - * {@inheritdoc} - */ - public function defaultConfiguration() { - return [ - 'selected_users' => NULL - ]; - } - - /** - * {@inheritDoc} - */ - public function buildConfigurationForm(array $form, FormStateInterface $form_state) { - $form['selected_users'] = [ - '#type' => 'entity_autocomplete', - '#tags' => TRUE, - '#title' => t('Select user(s) to watch on behalf of'), - '#target_type' => 'user', - '#required' => TRUE, - ]; - - return $form; - } - - /** - * {@inheritDoc} - */ - public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { - parent::submitConfigurationForm($form, $form_state); - - // Gets the full user object and stores that in the configuration instead. - foreach ($this->configuration['selected_users'] as $key => $value) { - $user = $this->entityTypeManager->getStorage('user')->load($value['target_id']); - $this->configuration['selected_users'][$key] = $user; - } - } +class EPAFlagUsersAction extends EPAFlagUsersActionBase { /** * {@inheritDoc} @@ -133,41 +24,27 @@ public function execute($entity = NULL) { if ($entity && !empty($selected_users)) { $entity = $this->entityTypeManager->getStorage($entity->getEntityTypeId())->load($entity->id()); - // Arrays to keep track of flagged and unflagged users. + // Arrays to keep track of users. $flagged_users = []; - $unflagged_users = []; foreach ($selected_users as $user) { $flag_service = $this->flagService; /** @var \Drupal\flag\Entity\Flag $flag */ $flag = $flag_service->getFlagById(self::NOTIFICATION_FLAG_ID); - - if ($flag->isFlagged($entity, $user)) { - // Unflag the entity for the user. - $flag_service->unflag($flag, $entity, $user); - $unflagged_users[] = $user->getAccountName(); - } - else { + if (!$flag->isFlagged($entity, $user)) { // Flag the entity for the user. $flag_service->flag($flag, $entity, $user); - $flagged_users[] = $user->getAccountName(); } + $flagged_users[] = $user->getAccountName(); } - // Create messages based on flagged and unflagged users. + // Create messages based on flagged users. $messages = []; if (!empty($flagged_users)) { $flagged_users_string = implode(', ', $flagged_users); $messages[] = $this->t('Successfully flagged node @id for user(s): @users', [ '@id' => $entity->id(), - '@users' => $flagged_users_string, - ]); - } - if (!empty($unflagged_users)) { - $unflagged_users_string = implode(', ', $unflagged_users); - $messages[] = $this->t('Successfully unflagged node @id for user(s): @users', [ - '@id' => $entity->id(), - '@users' => $unflagged_users_string, + '@users' => trim($flagged_users_string), ]); } @@ -177,40 +54,4 @@ public function execute($entity = NULL) { return NULL; } - - - /** - * {@inheritDoc} - */ - public static function finished($success, array $results, array $operations): ?RedirectResponse { - if ($success) { - foreach ($results['operations'] as $item) { - // Default fallback to maintain backwards compatibility: - // if api version equals to "1" and type equals to "status", - // previous message is displayed, otherwise we display exactly what's - // specified in the action. - if ($item['type'] === 'status' && $results['api_version'] === '1') { - $message = static::translate('@operation.', [ - '@operation' => $item['message'], - ]); - } - else { - $message = new FormattableMarkup('@message', [ - '@message' => $item['message'], - ]); - } - static::message($message, $item['type']); - } - $batch = &batch_get(); - /** @var \Drupal\Core\Url $redirect_url */ - $redirect_url = $batch['batch_redirect']; - return new RedirectResponse($redirect_url->toString()); - } - else { - $message = static::translate('Finished with an error.'); - static::message($message, 'error'); - } - return NULL; - } - } diff --git a/services/drupal/web/modules/custom/epa_workflow/src/Plugin/Action/EPAFlagUsersActionBase.php b/services/drupal/web/modules/custom/epa_workflow/src/Plugin/Action/EPAFlagUsersActionBase.php new file mode 100644 index 000000000..3a5db3196 --- /dev/null +++ b/services/drupal/web/modules/custom/epa_workflow/src/Plugin/Action/EPAFlagUsersActionBase.php @@ -0,0 +1,154 @@ +get('flag'), + $container->get('entity_type.manager') + ); + } + + /** + * EPAFlagUsersActionBase constructor. + * + * @param \Drupal\flag\FlagService $flag_service + * @param \Drupal\Core\Entity\EntityTypeManager $entity_type_manager + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, FlagService $flag_service, EntityTypeManager $entity_type_manager) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + $this->flagService = $flag_service; + $this->entityTypeManager = $entity_type_manager; + } + + /** + * {@inheritdoc} + */ + public function defaultConfiguration() { + return [ + 'selected_users' => NULL, + ]; + } + + public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) { + if ($account->hasPermission('execute watch content on behalf of user')) { + return AccessResult::allowed(); + } + + $grp_membership_service = \Drupal::service('group.membership_loader'); + /** @var \Drupal\group\GroupMembership[] $grps */ + $grps = $grp_membership_service->loadByUser($account); + + foreach ($grps as $grp) { + if ($grp->hasPermission('execute watch content on behalf of user')) { + return AccessResult::allowed(); + } + } + + return AccessResult::forbidden(); + } + + /** + * {@inheritDoc} + */ + public function buildConfigurationForm(array $form, FormStateInterface $form_state) { + $form['selected_users'] = [ + '#type' => 'entity_autocomplete', + '#tags' => TRUE, + '#title' => t('Select user(s) to watch on behalf of'), + '#target_type' => 'user', + '#required' => TRUE, + ]; + + return $form; + } + + /** + * {@inheritDoc} + */ + public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { + parent::submitConfigurationForm($form, $form_state); + + // Gets the full user object and stores that in the configuration instead. + foreach ($this->configuration['selected_users'] as $key => $value) { + $user = $this->entityTypeManager->getStorage('user')->load($value['target_id']); + $this->configuration['selected_users'][$key] = $user; + } + } + + /** + * {@inheritDoc} + */ + abstract public function execute(); + + + /** + * {@inheritDoc} + */ + public static function finished($success, array $results, array $operations): ?RedirectResponse { + if ($success) { + foreach ($results['operations'] as $item) { + // Default fallback to maintain backwards compatibility: + // if api version equals to "1" and type equals to "status", + // previous message is displayed, otherwise we display exactly what's + // specified in the action. + if ($item['type'] === 'status' && $results['api_version'] === '1') { + $message = static::translate('@operation.', [ + '@operation' => $item['message'], + ]); + } + else { + $message = new FormattableMarkup('@message', [ + '@message' => $item['message'], + ]); + } + static::message($message, $item['type']); + } + $batch = &batch_get(); + /** @var \Drupal\Core\Url $redirect_url */ + $redirect_url = $batch['batch_redirect']; + return new RedirectResponse($redirect_url->toString()); + } + else { + $message = static::translate('Finished with an error.'); + static::message($message, 'error'); + } + return NULL; + } + +} diff --git a/services/drupal/web/modules/custom/epa_workflow/src/Plugin/Action/EPAUnflagUsersAction.php b/services/drupal/web/modules/custom/epa_workflow/src/Plugin/Action/EPAUnflagUsersAction.php new file mode 100644 index 000000000..2c0e91e32 --- /dev/null +++ b/services/drupal/web/modules/custom/epa_workflow/src/Plugin/Action/EPAUnflagUsersAction.php @@ -0,0 +1,76 @@ + 'entity_autocomplete', + '#tags' => TRUE, + '#title' => t('Select user(s) to un-watch on behalf of'), + '#target_type' => 'user', + '#required' => TRUE, + ]; + + return $form; + } + + /** + * {@inheritDoc} + */ + public function execute($entity = NULL) { + /** @var \Drupal\user\Entity\User[] $selected_users */ + $selected_users = $this->configuration['selected_users']; + + if ($entity && !empty($selected_users)) { + $entity = $this->entityTypeManager->getStorage($entity->getEntityTypeId())->load($entity->id()); + + // Arrays to keep track of users. + $unflagged_users = []; + + foreach ($selected_users as $user) { + $flag_service = $this->flagService; + /** @var \Drupal\flag\Entity\Flag $flag */ + $flag = $flag_service->getFlagById(self::NOTIFICATION_FLAG_ID); + + if ($flag->isFlagged($entity, $user)) { + // Flag the entity for the user. + $flag_service->unflag($flag, $entity, $user); + } + + $unflagged_users[] = $user->getAccountName(); + } + + // Create messages based on unflagged users. + $messages = []; + if (!empty($unflagged_users)) { + $unflagged_users_string = implode(', ', $unflagged_users); + $messages[] = $this->t('Successfully unflagged node @id for user(s): @users', [ + '@id' => $entity->id(), + '@users' => trim($unflagged_users_string), + ]); + } + + // Join messages with line breaks for clarity. + return implode("\n", $messages); + } + + return NULL; + } +}