Add ability to permanently delete workflow
[MAILPOET-4540]
This commit is contained in:
committed by
David Remer
parent
a4c8caa664
commit
4e82c5334b
@@ -0,0 +1,42 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace MailPoet\Automation\Engine\Endpoints\Workflows;
|
||||
|
||||
use MailPoet\API\REST\Request;
|
||||
use MailPoet\API\REST\Response;
|
||||
use MailPoet\Automation\Engine\API\Endpoint;
|
||||
use MailPoet\Automation\Engine\Data\Workflow;
|
||||
use MailPoet\Automation\Engine\Exceptions\InvalidStateException;
|
||||
use MailPoet\Automation\Engine\Storage\WorkflowStorage;
|
||||
use MailPoet\Validator\Builder;
|
||||
|
||||
class WorkflowsDeleteEndpoint extends Endpoint {
|
||||
/** @var WorkflowStorage */
|
||||
private $workflowStorage;
|
||||
|
||||
public function __construct(
|
||||
WorkflowStorage $workflowStorage
|
||||
) {
|
||||
$this->workflowStorage = $workflowStorage;
|
||||
}
|
||||
|
||||
public function handle(Request $request): Response {
|
||||
$workflowId = $request->getParam('id');
|
||||
if (!is_int($workflowId)) {
|
||||
throw InvalidStateException::create();
|
||||
}
|
||||
$existingWorkflow = $this->workflowStorage->getWorkflow($workflowId);
|
||||
if (!$existingWorkflow instanceof Workflow) {
|
||||
throw InvalidStateException::create();
|
||||
}
|
||||
$this->workflowStorage->deleteWorkflow($existingWorkflow);
|
||||
|
||||
return new Response(null);
|
||||
}
|
||||
|
||||
public static function getRequestSchema(): array {
|
||||
return [
|
||||
'id' => Builder::integer()->required(),
|
||||
];
|
||||
}
|
||||
}
|
@@ -8,6 +8,7 @@ use MailPoet\Automation\Engine\Control\TriggerHandler;
|
||||
use MailPoet\Automation\Engine\Endpoints\System\DatabaseDeleteEndpoint;
|
||||
use MailPoet\Automation\Engine\Endpoints\System\DatabasePostEndpoint;
|
||||
use MailPoet\Automation\Engine\Endpoints\Workflows\WorkflowsCreateFromTemplateEndpoint;
|
||||
use MailPoet\Automation\Engine\Endpoints\Workflows\WorkflowsDeleteEndpoint;
|
||||
use MailPoet\Automation\Engine\Endpoints\Workflows\WorkflowsDuplicateEndpoint;
|
||||
use MailPoet\Automation\Engine\Endpoints\Workflows\WorkflowsGetEndpoint;
|
||||
use MailPoet\Automation\Engine\Endpoints\Workflows\WorkflowsPutEndpoint;
|
||||
@@ -73,8 +74,9 @@ class Engine {
|
||||
$this->wordPress->addAction(Hooks::API_INITIALIZE, function (API $api) {
|
||||
$api->registerGetRoute('workflows', WorkflowsGetEndpoint::class);
|
||||
$api->registerPutRoute('workflows/(?P<id>\d+)', WorkflowsPutEndpoint::class);
|
||||
$api->registerPostRoute('workflows/create-from-template', WorkflowsCreateFromTemplateEndpoint::class);
|
||||
$api->registerDeleteRoute('workflows/(?P<id>\d+)', WorkflowsDeleteEndpoint::class);
|
||||
$api->registerPostRoute('workflows/(?P<id>\d+)/duplicate', WorkflowsDuplicateEndpoint::class);
|
||||
$api->registerPostRoute('workflows/create-from-template', WorkflowsCreateFromTemplateEndpoint::class);
|
||||
$api->registerPostRoute('system/database', DatabasePostEndpoint::class);
|
||||
$api->registerDeleteRoute('system/database', DatabaseDeleteEndpoint::class);
|
||||
$api->registerGetRoute('workflow-templates', WorkflowTemplatesGetEndpoint::class);
|
||||
|
@@ -59,6 +59,7 @@ class Migrator {
|
||||
updated_at timestamp NOT NULL,
|
||||
subjects longtext,
|
||||
PRIMARY KEY (id),
|
||||
INDEX (workflow_id),
|
||||
INDEX (status)
|
||||
);
|
||||
");
|
||||
|
@@ -142,6 +142,44 @@ class WorkflowStorage {
|
||||
}, (array)$data);
|
||||
}
|
||||
|
||||
public function deleteWorkflow(Workflow $workflow): void {
|
||||
$workflowTable = esc_sql($this->workflowTable);
|
||||
$versionTable = esc_sql($this->versionsTable);
|
||||
$workflowRunTable = esc_sql($this->wpdb->prefix . 'mailpoet_workflow_runs');
|
||||
$workflowRunLogTable = esc_sql($this->wpdb->prefix . 'mailpoet_workflow_run_logs');
|
||||
$workflowId = $workflow->getId();
|
||||
$runLogsQuery = $this->wpdb->prepare(
|
||||
"
|
||||
DELETE FROM $workflowRunLogTable
|
||||
WHERE workflow_run_id IN (
|
||||
SELECT id FROM $workflowRunTable
|
||||
WHERE workflow_id = %d
|
||||
)
|
||||
",
|
||||
$workflowId
|
||||
);
|
||||
|
||||
if (!is_string($runLogsQuery)) {
|
||||
throw Exceptions\InvalidStateException::create();
|
||||
}
|
||||
$logsDeleted = $this->wpdb->query($runLogsQuery);
|
||||
if (!is_int($logsDeleted)) {
|
||||
throw Exceptions::databaseError($this->wpdb->last_error);
|
||||
}
|
||||
$runsDeleted = $this->wpdb->delete($this->wpdb->prefix . 'mailpoet_workflow_runs', ['workflow_id' => $workflowId]);
|
||||
if (!is_int($runsDeleted)) {
|
||||
throw Exceptions::databaseError($this->wpdb->last_error);
|
||||
}
|
||||
$versionsDeleted = $this->wpdb->delete($versionTable, ['workflow_id' => $workflowId]);
|
||||
if (!is_int($versionsDeleted)) {
|
||||
throw Exceptions::databaseError($this->wpdb->last_error);
|
||||
}
|
||||
$workflowDeleted = $this->wpdb->delete($workflowTable, ['id' => $workflowId]);
|
||||
if (!is_int($workflowDeleted)) {
|
||||
throw Exceptions::databaseError($this->wpdb->last_error);
|
||||
}
|
||||
}
|
||||
|
||||
public function truncate(): bool {
|
||||
$workflowTable = esc_sql($this->workflowTable);
|
||||
$versionTable = esc_sql($this->versionsTable);
|
||||
|
@@ -143,6 +143,7 @@ class ContainerConfigurator implements IContainerConfigurator {
|
||||
$container->autowire(\MailPoet\Automation\Engine\Endpoints\Workflows\WorkflowsPutEndpoint::class)->setPublic(true);
|
||||
$container->autowire(\MailPoet\Automation\Engine\Endpoints\Workflows\WorkflowsCreateFromTemplateEndpoint::class)->setPublic(true);
|
||||
$container->autowire(\MailPoet\Automation\Engine\Endpoints\Workflows\WorkflowsDuplicateEndpoint::class)->setPublic(true);
|
||||
$container->autowire(\MailPoet\Automation\Engine\Endpoints\Workflows\WorkflowsDeleteEndpoint::class)->setPublic(true);
|
||||
$container->autowire(\MailPoet\Automation\Engine\Endpoints\System\DatabasePostEndpoint::class)->setPublic(true);
|
||||
$container->autowire(\MailPoet\Automation\Engine\Endpoints\System\DatabaseDeleteEndpoint::class)->setPublic(true);
|
||||
// Automation - core integration
|
||||
|
@@ -4,6 +4,10 @@ namespace MailPoet\Test\Automation\Engine\Storage;
|
||||
|
||||
use MailPoet\Automation\Engine\Data\Step;
|
||||
use MailPoet\Automation\Engine\Data\Workflow;
|
||||
use MailPoet\Automation\Engine\Data\WorkflowRun;
|
||||
use MailPoet\Automation\Engine\Data\WorkflowRunLog;
|
||||
use MailPoet\Automation\Engine\Storage\WorkflowRunLogStorage;
|
||||
use MailPoet\Automation\Engine\Storage\WorkflowRunStorage;
|
||||
use MailPoet\Automation\Engine\Storage\WorkflowStorage;
|
||||
use MailPoet\Automation\Integrations\MailPoet\Triggers\SomeoneSubscribesTrigger;
|
||||
|
||||
@@ -73,6 +77,60 @@ class WorkflowStorageTest extends \MailPoetTest
|
||||
$this->assertEmpty($this->testee->getActiveWorkflowsByTrigger($subscriberTrigger));
|
||||
}
|
||||
|
||||
public function testItCanDeleteAWorkflow() {
|
||||
$workflowToDelete = $this->createEmptyWorkflow();
|
||||
$workflowToKeep = $this->createEmptyWorkflow();
|
||||
expect($this->testee->getWorkflows())->count(2);
|
||||
$this->testee->deleteWorkflow($workflowToDelete);
|
||||
expect($this->testee->getWorkflows())->count(1);
|
||||
expect($this->testee->getWorkflow($workflowToDelete->getId()))->null();
|
||||
$workflowToKeepFromDatabase = $this->testee->getWorkflow($workflowToKeep->getId());
|
||||
$this->assertInstanceOf(Workflow::class, $workflowToKeepFromDatabase);
|
||||
expect($workflowToKeepFromDatabase->getVersionId())->notNull();
|
||||
}
|
||||
|
||||
public function testItCanDeleteWorkflowsRelatedData() {
|
||||
$workflowRunStorage = $this->diContainer->get(WorkflowRunStorage::class);
|
||||
$workflowRunLogStorage = $this->diContainer->get(WorkflowRunLogStorage::class);
|
||||
$workflows = [
|
||||
'toDelete' => $this->createEmptyWorkflow(),
|
||||
'toKeep' => $this->createEmptyWorkflow()
|
||||
];
|
||||
$runs = [
|
||||
'toDelete' => [],
|
||||
'toKeep' => []
|
||||
];
|
||||
$runLogs = [
|
||||
'toDelete' => [],
|
||||
'toKeep' => []
|
||||
];
|
||||
foreach ($workflows as $type => $workflow) {
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
$workflowRun = new WorkflowRun($workflow->getId(), $workflow->getVersionId(), 'trigger-key', []);
|
||||
$runId = $workflowRunStorage->createWorkflowRun($workflowRun);
|
||||
$runs[$type][] = $runId;
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
$log = new WorkflowRunLog($runId, "step-{$i}");
|
||||
$logId = $workflowRunLogStorage->createWorkflowRunLog($log);
|
||||
$runLogs[$type][] = $logId;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->testee->deleteWorkflow($workflows['toDelete']);
|
||||
foreach ($runs['toDelete'] as $runId) {
|
||||
expect($workflowRunStorage->getWorkflowRun($runId))->null();
|
||||
}
|
||||
foreach ($runs['toKeep'] as $runId) {
|
||||
expect($workflowRunStorage->getWorkflowRun($runId))->notNull();
|
||||
}
|
||||
foreach ($runLogs['toDelete'] as $runLogId) {
|
||||
expect($workflowRunLogStorage->getWorkflowRunLog($runLogId))->null();
|
||||
}
|
||||
foreach ($runLogs['toKeep'] as $runLogId) {
|
||||
expect($workflowRunLogStorage->getWorkflowRunLog($runLogId))->notNull();
|
||||
}
|
||||
}
|
||||
|
||||
private function createEmptyWorkflow(string $name="test"): Workflow {
|
||||
$workflow = new Workflow($name, [], new \WP_User());
|
||||
$workflowId = $this->testee->createWorkflow($workflow);
|
||||
|
Reference in New Issue
Block a user