diff --git a/mailpoet/lib/API/JSON/v1/Help.php b/mailpoet/lib/API/JSON/v1/Help.php index c65c93dc6a..f476b3805f 100644 --- a/mailpoet/lib/API/JSON/v1/Help.php +++ b/mailpoet/lib/API/JSON/v1/Help.php @@ -8,6 +8,7 @@ use MailPoet\API\JSON\Response; use MailPoet\Config\AccessControl; use MailPoet\Entities\ScheduledTaskEntity; use MailPoet\Newsletter\Sending\ScheduledTasksRepository; +use MailPoet\Util\DataInconsistency\DataInconsistencyController; class Help extends APIEndpoint { @@ -16,11 +17,14 @@ class Help extends APIEndpoint { ]; private ScheduledTasksRepository $scheduledTasksRepository; + private DataInconsistencyController $dataInconsistencyController; public function __construct( - ScheduledTasksRepository $scheduledTasksRepository + ScheduledTasksRepository $scheduledTasksRepository, + DataInconsistencyController $dataInconsistencyController ) { $this->scheduledTasksRepository = $scheduledTasksRepository; + $this->dataInconsistencyController = $dataInconsistencyController; } public function cancelTask($data): Response { @@ -59,6 +63,15 @@ class Help extends APIEndpoint { } } + public function fixInconsistentData($data): Response { + try { + $this->dataInconsistencyController->fixInconsistentData($data['inconsistency'] ?? ''); + } catch (\Exception $e) { + return $this->badRequest([ApiError::BAD_REQUEST => $e->getMessage()]); + } + return $this->successResponse($this->dataInconsistencyController->getInconsistentDataStatus()); + } + private function validateTaskId($data): void { $isValid = isset($data['id']) && is_numeric($data['id']); if (!$isValid) { diff --git a/mailpoet/lib/Util/DataInconsistency/DataInconsistencyController.php b/mailpoet/lib/Util/DataInconsistency/DataInconsistencyController.php index 1103a4730e..ba65323611 100644 --- a/mailpoet/lib/Util/DataInconsistency/DataInconsistencyController.php +++ b/mailpoet/lib/Util/DataInconsistency/DataInconsistencyController.php @@ -2,8 +2,14 @@ namespace MailPoet\Util\DataInconsistency; +use MailPoet\UnexpectedValueException; + class DataInconsistencyController { - const ORPHANED_TASKS = 'orphaned_tasks'; + const ORPHANED_SENDING_TASKS = 'orphaned_sending_tasks'; + + const SUPPORTED_INCONSISTENCY_CHECKS = [ + self::ORPHANED_SENDING_TASKS, + ]; private DataInconsistencyRepository $repository; @@ -15,9 +21,19 @@ class DataInconsistencyController { public function getInconsistentDataStatus(): array { $result = [ - self::ORPHANED_TASKS => $this->repository->getOrphanedSendingTasksCount(), + self::ORPHANED_SENDING_TASKS => $this->repository->getOrphanedSendingTasksCount(), ]; $result['total'] = array_sum($result); return $result; } + + public function fixInconsistentData(string $inconsistency): void { + if (!in_array($inconsistency, self::SUPPORTED_INCONSISTENCY_CHECKS, true)) { + throw new UnexpectedValueException(__('Unsupported data inconsistency check.', 'mailpoet')); + } + if ($inconsistency === self::ORPHANED_SENDING_TASKS) { + $this->repository->cleanupOrphanedSendingTasks(); + return; + } + } } diff --git a/mailpoet/tests/integration/API/JSON/v1/HelpTest.php b/mailpoet/tests/integration/API/JSON/v1/HelpTest.php index f752f4af1b..e6b47ce138 100644 --- a/mailpoet/tests/integration/API/JSON/v1/HelpTest.php +++ b/mailpoet/tests/integration/API/JSON/v1/HelpTest.php @@ -8,6 +8,7 @@ use MailPoet\API\JSON\v1\Help; use MailPoet\Entities\ScheduledTaskEntity; use MailPoet\Newsletter\Sending\ScheduledTasksRepository; use MailPoet\Test\DataFactories\ScheduledTask as ScheduledTaskFactory; +use MailPoet\Util\DataInconsistency\DataInconsistencyController; use MailPoetVendor\Carbon\Carbon; class HelpTest extends \MailPoetTest { @@ -21,7 +22,7 @@ class HelpTest extends \MailPoetTest { $this->scheduledTasksRepository = $this->diContainer->get(ScheduledTasksRepository::class); } - public function testItReturnsErrorWhenIdIsMissing() { + public function testItReturnsErrorWhenIdIsMissing(): void { /** @var ErrorResponse $response */ $response = $this->endpoint->cancelTask([]); verify($response)->instanceOf(ErrorResponse::class); @@ -35,7 +36,7 @@ class HelpTest extends \MailPoetTest { verify($response->errors[0]['message'])->equals('Invalid or missing parameter `id`.'); } - public function testItReturnsErrorWhenTaskDoesntExist() { + public function testItReturnsErrorWhenTaskDoesntExist(): void { /** @var ErrorResponse $response */ $response = $this->endpoint->cancelTask(['id' => 99999]); verify($response)->instanceOf(ErrorResponse::class); @@ -49,7 +50,7 @@ class HelpTest extends \MailPoetTest { verify($response->errors[0]['message'])->equals('Task not found.'); } - public function testItReturnsErrorWhenCancellingCompletedTask() { + public function testItReturnsErrorWhenCancellingCompletedTask(): void { $task = (new ScheduledTaskFactory())->create('sending', ScheduledTaskEntity::STATUS_COMPLETED, new \DateTime()); /** @var ErrorResponse $response */ $response = $this->endpoint->cancelTask(['id' => $task->getId()]); @@ -58,7 +59,7 @@ class HelpTest extends \MailPoetTest { verify($response->errors[0]['message'])->equals('Only scheduled and running tasks can be cancelled'); } - public function testItReturnsErrorWhenReschedulingCompletedTask() { + public function testItReturnsErrorWhenReschedulingCompletedTask(): void { $task = (new ScheduledTaskFactory())->create('sending', ScheduledTaskEntity::STATUS_COMPLETED, new \DateTime()); /** @var ErrorResponse $response */ $response = $this->endpoint->rescheduleTask(['id' => $task->getId()]); @@ -67,7 +68,7 @@ class HelpTest extends \MailPoetTest { verify($response->errors[0]['message'])->equals('Only cancelled tasks can be rescheduled'); } - public function testItCanCancelScheduledTask() { + public function testItCanCancelScheduledTask(): void { $task = (new ScheduledTaskFactory())->create('sending', ScheduledTaskEntity::STATUS_SCHEDULED, new \DateTime()); $response = $this->endpoint->cancelTask(['id' => $task->getId()]); verify($response)->instanceOf(APIResponse::class); @@ -82,7 +83,7 @@ class HelpTest extends \MailPoetTest { } } - public function testItCanCancelRunningTask() { + public function testItCanCancelRunningTask(): void { $task = (new ScheduledTaskFactory())->create('sending', null, new \DateTime()); $response = $this->endpoint->cancelTask(['id' => $task->getId()]); verify($response)->instanceOf(APIResponse::class); @@ -97,7 +98,7 @@ class HelpTest extends \MailPoetTest { } } - public function testItCanRescheduleTaskInFuture() { + public function testItCanRescheduleTaskInFuture(): void { $futureDate = Carbon::now()->addDay(); $task = (new ScheduledTaskFactory())->create('sending', ScheduledTaskEntity::STATUS_CANCELLED, $futureDate); $response = $this->endpoint->rescheduleTask(['id' => $task->getId()]); @@ -112,7 +113,7 @@ class HelpTest extends \MailPoetTest { } } - public function testItCanRescheduleTaskInProgress() { + public function testItCanRescheduleTaskInProgress(): void { $pastDate = Carbon::now()->subDay(); $task = (new ScheduledTaskFactory())->create('sending', ScheduledTaskEntity::STATUS_CANCELLED, $pastDate); $response = $this->endpoint->rescheduleTask(['id' => $task->getId()]); @@ -126,4 +127,15 @@ class HelpTest extends \MailPoetTest { verify($task->getCancelledAt())->null(); } } + + public function testItFixesInconsistentData(): void { + $task = (new ScheduledTaskFactory())->create('sending', ScheduledTaskEntity::STATUS_SCHEDULED); + $this->entityManager->detach($task); + + $response = (array)$this->endpoint->fixInconsistentData(['inconsistency' => DataInconsistencyController::ORPHANED_SENDING_TASKS]); + $task = $this->scheduledTasksRepository->findOneById($task->getId()); + verify($task)->null(); + verify($response['data']['total'] ?? null)->equals(0); + verify($response['data'][DataInconsistencyController::ORPHANED_SENDING_TASKS] ?? null)->equals(0); + } }