Skip to content
Snippets Groups Projects
Commit 499cd93e authored by Alexandre Dias's avatar Alexandre Dias
Browse files

Merge branch 'ISAICP-8933' into 'develop'

ISAICP-8933: Batch archival of solutions part 2.

See merge request digit/digit-joinup-dev!1478
parents e070e148 b8c78959
No related branches found
Tags v1.110.0
1 merge request!177Release v1.110.0
This diff is collapsed.
...@@ -14,12 +14,117 @@ ...@@ -14,12 +14,117 @@
declare(strict_types=1); declare(strict_types=1);
use Drupal\Component\Utility\Variable;
use Drupal\Core\Session\AccountSwitcherInterface;
use Drupal\Core\Utility\UpdateException;
use Drupal\joinup_workflow\WorkflowHelperInterface;
use Drupal\menu_link_content\MenuLinkContentInterface; use Drupal\menu_link_content\MenuLinkContentInterface;
use Drupal\solution\Entity\Solution;
use Drupal\user\Entity\User;
use Drupal\user\UserInterface;
// Temporary constant.
// phpcs:ignore DrupalPractice.Constants.GlobalConstant.GlobalConstant
const SOLUTION_ARCHIVAL_ACTOR_ID = 744195;
/**
* Archives solutions specified by Functional Team.
*/
function joinup_core_deploy_111001(&$sandbox): string {
if (!isset($sandbox['remaining'])) {
$stream = fopen(__DIR__ . '/solutions-to-archive.csv', 'r');
// CSV is small enough to store it in memory.
while (is_array($item = fgetcsv($stream))) {
$sandbox['remaining'][$item[0]] = $item[1] ?? $item[0];
}
// Drop header.
unset($sandbox['remaining']['ID']);
fclose($stream);
$sandbox['total'] = count($sandbox['remaining']);
$sandbox['processed'] = 0;
}
$accountSwitcher = \Drupal::service('account_switcher');
assert($accountSwitcher instanceof AccountSwitcherInterface);
$storage = \Drupal::entityTypeManager()->getStorage('rdf_entity');
$storage->resetCache();
$logger = Drupal::logger('joinup_core');
$workflowHelper = \Drupal::service('joinup_workflow.workflow_helper');
assert($workflowHelper instanceof WorkflowHelperInterface);
// We need a moderator account to perform the workflow state change.
if (!($actor = User::load(SOLUTION_ARCHIVAL_ACTOR_ID)) instanceof UserInterface) {
throw new UpdateException(sprintf(
"Cannot find the predefined actor for the operation. Was looking for user account with id '%s'.",
SOLUTION_ARCHIVAL_ACTOR_ID
));
}
if (!$actor->hasRole('moderator')) {
throw new UpdateException('The predefined actor does not have the moderator role.');
}
$items = array_splice($sandbox['remaining'], 0, 50);
$solutions = $storage->loadMultiple(array_keys($items));
$notLoadableSolutions = array_diff_key($items, $solutions);
$accountSwitcher->switchTo($actor);
foreach ($solutions as $id => $solution) {
if (!$solution instanceof Solution) {
$logger->warning(sprintf(
"The RDF entity with ID '%s' is not a solution (referred with title '%s' in the spreadsheet)",
$id,
$items[$id],
));
continue;
}
if ($solution->isArchived() || !$solution->isTargetWorkflowStateAllowed('archived')) {
$logger->warning(sprintf(
"The solution with ID '%s' (referred with title '%s' in the spreadsheet) cannot be archived. Its current state is '%s'.",
$id,
$items[$id],
$solution->getWorkflowState(),
));
continue;
}
try {
$solution->skip_notification = TRUE;
$solution->notifyContactOnly = TRUE;
$workflowHelper->archiveEntity($solution);
}
catch (\Exception $exception) {
$logger->error(sprintf(
"The solution with ID '%s' (referred with title '%s' in the spreadsheet) cannot be archived:\n%s",
$id,
$items[$id],
$exception->getMessage(),
));
}
}
if (!empty($notLoadableSolutions)) {
$logger->warning(sprintf(
"The following solutions were not found:\n%s",
Variable::export($notLoadableSolutions),
));
}
$accountSwitcher->switchBack();
$sandbox['processed'] += count($items);
$sandbox['#finished'] = (int) empty($sandbox['remaining']);
return sprintf(
"Processed %s solutions from total %s items to archive.",
$sandbox['processed'],
$sandbox['total'],
);
}
/** /**
* Add navbar link to sitewide discussions page. * Add navbar link to sitewide discussions page.
*/ */
function joinup_core_deploy_111000(): void { function joinup_core_deploy_111002(): void {
$menuLinkContentStorage = \Drupal::entityTypeManager()->getStorage('menu_link_content'); $menuLinkContentStorage = \Drupal::entityTypeManager()->getStorage('menu_link_content');
$parentId = key( $parentId = key(
$menuLinkContentStorage->getQuery() $menuLinkContentStorage->getQuery()
......
This diff is collapsed.
...@@ -128,6 +128,9 @@ public static function getSubscribedEvents(): array { ...@@ -128,6 +128,9 @@ public static function getSubscribedEvents(): array {
$events[NotificationEvents::RDF_ENTITY_ARCHIVE_COMPLETED] = [ $events[NotificationEvents::RDF_ENTITY_ARCHIVE_COMPLETED] = [
['onCompleteArchival'], ['onCompleteArchival'],
]; ];
$events[NotificationEvents::RDF_ENTITY_ARCHIVE_COMPLETED_CONTACT_ONLY] = [
['onCompleteArchival'],
];
return $events; return $events;
} }
...@@ -507,8 +510,10 @@ protected function isTransitionRequested(): bool { ...@@ -507,8 +510,10 @@ protected function isTransitionRequested(): bool {
* *
* @param \Drupal\joinup_notification\Event\NotificationEvent $event * @param \Drupal\joinup_notification\Event\NotificationEvent $event
* The notification event. * The notification event.
* @param string $eventName
* The name of the event.
*/ */
public function onCompleteArchival(NotificationEvent $event): void { public function onCompleteArchival(NotificationEvent $event, string $eventName): void {
$this->initialize($event); $this->initialize($event);
if (!$this->appliesOnSolutions()) { if (!$this->appliesOnSolutions()) {
return; return;
...@@ -528,9 +533,11 @@ public function onCompleteArchival(NotificationEvent $event): void { ...@@ -528,9 +533,11 @@ public function onCompleteArchival(NotificationEvent $event): void {
$solution->getValidatedContactInformationEmails(), $solution->getValidatedContactInformationEmails(),
); );
// Notify moderators. // Notify moderators.
$this->sendUserDataMessages([ if ($eventName !== NotificationEvents::RDF_ENTITY_ARCHIVE_COMPLETED_CONTACT_ONLY) {
self::TEMPLATE_ARCHIVAL_COMPLETE => $this->getRecipientIdsByRole('moderator'), $this->sendUserDataMessages([
]); self::TEMPLATE_ARCHIVAL_COMPLETE => $this->getRecipientIdsByRole('moderator'),
]);
}
} }
} }
...@@ -72,4 +72,13 @@ final class NotificationEvents { ...@@ -72,4 +72,13 @@ final class NotificationEvents {
*/ */
const RDF_ENTITY_ARCHIVE_COMPLETED = 'joinup_notification.rdf.archive_completed.notify'; const RDF_ENTITY_ARCHIVE_COMPLETED = 'joinup_notification.rdf.archive_completed.notify';
/**
* Solution sub-items are completely archived and only contact needs email.
*
* @Event
*
* @var string
*/
const RDF_ENTITY_ARCHIVE_COMPLETED_CONTACT_ONLY = 'joinup_notification.rdf.archive_completed.notify.contact_only';
} }
...@@ -109,6 +109,7 @@ public function queueSolutionSubContentTransition(WorkflowTransitionEvent $event ...@@ -109,6 +109,7 @@ public function queueSolutionSubContentTransition(WorkflowTransitionEvent $event
'user' => $this->currentUser->id(), 'user' => $this->currentUser->id(),
'solution' => $solution->id(), 'solution' => $solution->id(),
'transition' => $transition, 'transition' => $transition,
'notifyContactOnly' => !empty($solution->notifyContactOnly),
]); ]);
return TRUE; return TRUE;
} }
......
...@@ -118,7 +118,7 @@ public function processItem($data): void { ...@@ -118,7 +118,7 @@ public function processItem($data): void {
$this->accountSwitcher->switchTo($actor); $this->accountSwitcher->switchTo($actor);
try { try {
$this->performOperation($solution, $data['transition']); $this->performOperation($solution, $data['transition'], !empty($data['notifyContactOnly']));
} }
finally { finally {
$this->accountSwitcher->switchBack(); $this->accountSwitcher->switchBack();
...@@ -166,12 +166,14 @@ function (EntityInterface $entity): bool { ...@@ -166,12 +166,14 @@ function (EntityInterface $entity): bool {
* The solution whose sub-contents we want to archive. * The solution whose sub-contents we want to archive.
* @param \Drupal\solution\Transition $transition * @param \Drupal\solution\Transition $transition
* The transition to apply. * The transition to apply.
* @param bool $notifyContactOnly
* Whether notification should be sent only to contact email.
* *
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
* @throws \Drupal\Core\Entity\EntityStorageException * @throws \Drupal\Core\Entity\EntityStorageException
*/ */
protected function performOperation(SolutionInterface $solution, Transition $transition): void { protected function performOperation(SolutionInterface $solution, Transition $transition, bool $notifyContactOnly): void {
foreach ($this->getSolutionGroupContent($solution) as $entity) { foreach ($this->getSolutionGroupContent($solution) as $entity) {
if (!$entity instanceof ArchivableEntityInterface) { if (!$entity instanceof ArchivableEntityInterface) {
// Continue silently. // Continue silently.
...@@ -229,7 +231,10 @@ protected function performOperation(SolutionInterface $solution, Transition $tra ...@@ -229,7 +231,10 @@ protected function performOperation(SolutionInterface $solution, Transition $tra
} }
if ($transition === Transition::ARCHIVE) { if ($transition === Transition::ARCHIVE) {
joinup_notification_dispatch_notification('update', NotificationEvents::RDF_ENTITY_ARCHIVE_COMPLETED, $solution); $eventName = $notifyContactOnly
? NotificationEvents::RDF_ENTITY_ARCHIVE_COMPLETED_CONTACT_ONLY
: NotificationEvents::RDF_ENTITY_ARCHIVE_COMPLETED;
joinup_notification_dispatch_notification('update', $eventName, $solution);
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment