diff --git a/mailpoet/lib/Automation/Engine/Migrations/Migrator.php b/mailpoet/lib/Automation/Engine/Migrations/Migrator.php index 9728c74c83..add328a14e 100644 --- a/mailpoet/lib/Automation/Engine/Migrations/Migrator.php +++ b/mailpoet/lib/Automation/Engine/Migrations/Migrator.php @@ -29,6 +29,14 @@ class Migrator { created_at timestamp NOT NULL, updated_at timestamp NOT NULL, deleted_at timestamp NULL, + PRIMARY KEY (id) + ); + "); + + $this->runQuery(" + CREATE TABLE {$this->prefix}workflow_versions ( + id int(11) unsigned NOT NULL AUTO_INCREMENT, + workflow_id int(11) unsigned NOT NULL, trigger_keys longtext NOT NULL, steps longtext, PRIMARY KEY (id) @@ -53,6 +61,7 @@ class Migrator { $this->removeOldSchema(); $this->runQuery("DROP TABLE IF EXISTS {$this->prefix}workflows"); $this->runQuery("DROP TABLE IF EXISTS {$this->prefix}workflow_runs"); + $this->runQuery("DROP TABLE IF EXISTS {$this->prefix}workflow_versions"); // clean Action Scheduler data $this->runQuery(" diff --git a/mailpoet/lib/Automation/Engine/Storage/WorkflowStorage.php b/mailpoet/lib/Automation/Engine/Storage/WorkflowStorage.php index 4af7b59fc1..e839156f0a 100644 --- a/mailpoet/lib/Automation/Engine/Storage/WorkflowStorage.php +++ b/mailpoet/lib/Automation/Engine/Storage/WorkflowStorage.php @@ -10,43 +10,80 @@ use wpdb; class WorkflowStorage { /** @var string */ - private $table; + private $workflowTable; + /** @var string */ + private $versionsTable; /** @var wpdb */ private $wpdb; public function __construct() { global $wpdb; - $this->table = $wpdb->prefix . 'mailpoet_workflows'; + $this->workflowTable = $wpdb->prefix . 'mailpoet_workflows'; + $this->versionsTable = $wpdb->prefix . 'mailpoet_workflow_versions'; $this->wpdb = $wpdb; } public function createWorkflow(Workflow $workflow): int { - $result = $this->wpdb->insert($this->table, $workflow->toArray()); + $result = $this->wpdb->insert($this->workflowTable, $this->workflowHeaderData($workflow)); if (!$result) { throw Exceptions::databaseError($this->wpdb->last_error); } - return $this->wpdb->insert_id; + $id = (int)$this->wpdb->insert_id; + $this->insertWorkflowVersion($id, $workflow); + return $id; } public function updateWorkflow(Workflow $workflow): void { - $result = $this->wpdb->update($this->table, $workflow->toArray(), ['id' => $workflow->getId()]); + $result = $this->wpdb->update($this->workflowTable, $this->workflowHeaderData($workflow), ['id' => $workflow->getId()]); if ($result === false) { throw Exceptions::databaseError($this->wpdb->last_error); } + $this->insertWorkflowVersion($workflow->getId(), $workflow); } public function getWorkflow(int $id): ?Workflow { - $table = esc_sql($this->table); - $query = (string)$this->wpdb->prepare("SELECT * FROM $table WHERE id = %d", $id); + $workflowTable = esc_sql($this->workflowTable); + $versionTable = esc_sql($this->versionsTable); + $query = (string)$this->wpdb->prepare(" +SELECT + workflow.*, + version.id AS version_id, + version.steps, + version.trigger_keys +FROM + $workflowTable as workflow, + $versionTable as version +WHERE + version.workflow_id = workflow.id +ORDER BY + version.id DESC +LIMIT + 0,1; ", + $id + ); $data = $this->wpdb->get_row($query, ARRAY_A); return $data ? Workflow::fromArray((array)$data) : null; } /** @return Workflow[] */ public function getWorkflows(): array { - $table = esc_sql($this->table); - $query = "SELECT * FROM $table ORDER BY id DESC"; + $workflowTable = esc_sql($this->workflowTable); + $versionTable = esc_sql($this->versionsTable); + $query = " +SELECT + workflow.*, + version.id AS version_id, + version.steps, + version.trigger_keys +FROM + $workflowTable AS workflow + LEFT JOIN + $versionTable as version ON (version.workflow_id=workflow.id) +WHERE + version.id = (SELECT Max(id) FROM $versionTable WHERE workflow_id= version.workflow_id) +ORDER BY + workflow.id DESC; "; $data = $this->wpdb->get_results($query, ARRAY_A); return array_map(function (array $workflowData) { return Workflow::fromArray($workflowData); @@ -55,9 +92,20 @@ class WorkflowStorage { /** @return string[] */ public function getActiveTriggerKeys(): array { - $table = esc_sql($this->table); + $workflowTable = esc_sql($this->workflowTable); + $versionTable = esc_sql($this->versionsTable); $query = (string)$this->wpdb->prepare( - "SELECT DISTINCT trigger_keys FROM $table WHERE status = %s", + " +SELECT + DISTINCT version.trigger_keys +FROM + $workflowTable AS workflow, + $versionTable as version +WHERE + workflow.status = %s AND + workflow.id=version.workflow_id +ORDER BY + version.id DESC", Workflow::STATUS_ACTIVE ); $result = $this->wpdb->get_col($query); @@ -73,9 +121,24 @@ class WorkflowStorage { /** @return Workflow[] */ public function getActiveWorkflowsByTrigger(Trigger $trigger): array { - $table = esc_sql($this->table); + $workflowTable = esc_sql($this->workflowTable); + $versionTable = esc_sql($this->versionsTable); $query = (string)$this->wpdb->prepare( - "SELECT * FROM $table WHERE status = %s AND trigger_keys LIKE %s", + " +SELECT + workflow.*, + version.id AS version_id, + version.steps, + version.trigger_keys +FROM + $workflowTable AS workflow + LEFT JOIN + $versionTable as version ON (version.workflow_id=workflow.id) +WHERE + workflow.status = %s AND + version.trigger_keys LIKE %s AND + version.id = (SELECT Max(id) FROM $versionTable WHERE workflow_id= version.workflow_id) + ", Workflow::STATUS_ACTIVE, '%' . $this->wpdb->esc_like($trigger->getKey()) . '%' ); @@ -85,4 +148,24 @@ class WorkflowStorage { return Workflow::fromArray($workflowData); }, (array)$data); } + + private function workflowHeaderData(Workflow $workflow): array { + $workflowHeader = $workflow->toArray(); + unset($workflowHeader['steps']); + unset($workflowHeader['trigger_keys']); + return $workflowHeader; + } + + private function insertWorkflowVersion(int $workflowId, Workflow $workflow): void { + + $data = [ + 'workflow_id' => $workflowId, + 'steps' => $workflow->toArray()['steps'], + 'trigger_keys' => $workflow->toArray()['trigger_keys'], + ]; + $result = $this->wpdb->insert($this->versionsTable, $data); + if (!$result) { + throw Exceptions::databaseError($this->wpdb->last_error); + } + } }