public function testDeleteWorkflow() { $variableHandler = $this->getMock('ezcWorkflowVariableHandler'); $workflow = new \ezcWorkflow('IdentityTest'); $workflow->startNode->addOutNode($workflow->endNode); $workflow->addVariableHandler('foo', get_class($variableHandler)); $manager = new WorkflowManager($this->conn, $this->options); $manager->save($workflow); $manager->deleteWorkflow($workflow->id); $this->setExpectedException('ezcWorkflowDefinitionStorageException', 'Could not load workflow definition.'); $manager->loadWorkflowById($workflow->id); }
/** * Constructor. * * @param ezcWorkflow $workflow */ public function __construct(ezcWorkflow $workflow) { parent::__construct(); $workflow->accept($this); }
/** * Save a workflow definition to the database. * * @param ezcWorkflow $workflow * @throws ezcWorkflowDefinitionStorageException */ public function save(\ezcWorkflow $workflow) { // Verify the workflow. $workflow->verify(); if (strlen($workflow->name) == 0) { throw new \ezcWorkflowDefinitionStorageException(); } $platform = $this->conn->getDatabasePlatform(); // what mode of saving should it be? Update or Re-Generate? // // Conditions that an update sufficies: // 1. No node has been deleted // 2. No node has changed its meaning (action class or type) // 3. For simplicitly only zero or one new nodes will be created. $hasExistingNodeIds = array(); $newNodes = 0; foreach ($workflow->nodes as $node) { $oid = spl_object_hash($node); if (!isset($this->nodeMap[$oid])) { $newNodes++; } else { $hasExistingNodeIds[] = $this->nodeMap[$oid]; } } $canBeUpdate = false; if ($newNodes < 2 && count(array_diff($hasExistingNodeIds, $this->workflowNodeIds[$workflow->id])) == 0 && $workflow->id) { $canBeUpdate = true; } $this->workflowNodeIds[$workflow->id] = array(); try { $this->conn->beginTransaction(); $workflowVersion = $this->getCurrentVersion($workflow->name) + 1; $this->conn->update($this->options->workflowTable(), array('workflow_outdated' => 1), array('workflow_name' => $workflow->name)); $date = new \DateTime("now"); if ($canBeUpdate) { $this->conn->update($this->options->workflowTable(), array('workflow_version' => $workflowVersion, 'workflow_created' => $date->format($platform->getDateTimeFormatString())), array('workflow_id' => $workflow->id)); } else { $data = array('workflow_name' => $workflow->name, 'workflow_version' => $workflowVersion, 'workflow_created' => $date->format($platform->getDateTimeFormatString()), 'workflow_outdated' => 0); // For sequences: get id before insert if ($platform->prefersSequences()) { $id = (int) $this->conn->fetchColumn($platform->getSequenceNextValSQL($this->options->workflowSequence())); $data['workflow_id'] = $id; $workflow->id = $id; } $this->conn->insert($this->options->workflowTable(), $data); if ($platform->prefersIdentityColumns()) { $workflow->id = (int) $this->conn->lastInsertId(); } $workflow->definitionStorage = $this; } // Write node table rows. $nodeMap = array(); foreach ($workflow->nodes as $node) { /* @var $node \ezcWorkflowNode */ $oid = spl_object_hash($node); if ($canBeUpdate && isset($this->nodeMap[$oid])) { $nodeId = (int) $this->nodeMap[$oid]; $this->conn->update($this->options->nodeTable(), array('node_configuration' => $this->options->getSerializer()->serialize($node->getConfiguration())), array('node_id' => $nodeId)); } else { $data = array('workflow_id' => (int) $workflow->id, 'node_class' => get_class($node), 'node_configuration' => $this->options->getSerializer()->serialize($node->getConfiguration())); if ($platform->prefersSequences()) { $nodeId = (int) $this->conn->fetchColumn($platform->getSequenceNextValSQL($this->options->nodeSequence())); $data['node_id'] = $nodeId; } $this->conn->insert($this->options->nodeTable(), $data); if ($platform->prefersIdentityColumns()) { $nodeId = (int) $this->conn->lastInsertId(); } } $nodeMap[$nodeId] = $node; $this->workflowNodeIds[$workflow->id][] = $nodeId; $this->nodeMap[$oid] = $nodeId; } if ($canBeUpdate) { // Delete all the node connections, NodeMap Keys are casted to (int) so usage here is safe. $query = "DELETE FROM " . $this->options->nodeConnectionTable() . " " . "WHERE incoming_node_id IN (" . implode(",", array_keys($nodeMap)) . ") OR " . "outgoing_node_id IN (" . implode(",", array_keys($nodeMap)) . ")"; $this->conn->executeUpdate($query); } foreach ($workflow->nodes as $node) { foreach ($node->getOutNodes() as $outNode) { $incomingNodeId = null; $outgoingNodeId = null; foreach ($nodeMap as $_id => $_node) { if ($_node === $node) { $incomingNodeId = $_id; } else { if ($_node === $outNode) { $outgoingNodeId = $_id; } } if ($incomingNodeId !== NULL && $outgoingNodeId !== NULL) { break; } } $data = array('incoming_node_id' => $incomingNodeId, 'outgoing_node_id' => $outgoingNodeId); if ($platform->prefersSequences()) { $id = (int) $this->conn->fetchColumn($platform->getSequenceNextValSQL($this->options->nodeConnectionSequence())); $data['id'] = $id; } $this->conn->insert($this->options->nodeConnectionTable(), $data); } } unset($nodeMap); if ($canBeUpdate) { $this->conn->delete($this->options->variableHandlerTable(), array('workflow_id' => (int) $workflow->id)); } foreach ($workflow->getVariableHandlers() as $variable => $class) { $this->conn->insert($this->options->variableHandlerTable(), array('workflow_id' => (int) $workflow->id, 'variable' => $variable, 'class' => $class)); } $this->conn->commit(); } catch (\Exception $e) { $this->conn->rollBack(); throw new \ezcWorkflowDefinitionStorageException("Error while persisting workflow: " . $e->getMessage()); } }
/** * Save a workflow definition to a DOMDocument. * * @param ezcWorkflow $workflow * @param int $workflowVersion * @return DOMDocument */ public function saveToDocument(ezcWorkflow $workflow, $workflowVersion) { $document = new DOMDocument('1.0', 'UTF-8'); $document->formatOutput = true; $root = $document->createElement('workflow'); $document->appendChild($root); $root->setAttribute('name', $workflow->name); $root->setAttribute('version', $workflowVersion); $nodes = $workflow->nodes; $numNodes = count($nodes); // Workaround for foreach() bug in PHP 5.2.1. // http://bugs.php.net/bug.php?id=40608 $keys = array_keys($nodes); for ($i = 0; $i < $numNodes; $i++) { $id = $keys[$i]; $node = $nodes[$id]; $nodeClass = get_class($node); $xmlNode = $document->createElement('node'); $xmlNode->setAttribute('id', $id); $xmlNode->setAttribute('type', str_replace('ezcWorkflowNode', '', get_class($node))); $node->configurationtoXML($xmlNode); $root->appendChild($xmlNode); $outNodes = $node->getOutNodes(); $_keys = array_keys($outNodes); $numOutNodes = count($_keys); for ($j = 0; $j < $numOutNodes; $j++) { foreach ($nodes as $outNodeId => $_node) { if ($_node === $outNodes[$_keys[$j]]) { break; } } $xmlOutNode = $document->createElement('outNode'); $xmlOutNode->setAttribute('id', $outNodeId); if (is_subclass_of($nodeClass, 'ezcWorkflowNodeConditionalBranch') && ($condition = $node->getCondition($outNodes[$_keys[$j]]))) { if (!$node->isElse($outNodes[$_keys[$j]])) { $xmlCondition = self::conditionToXml($condition, $document); $xmlCondition->appendChild($xmlOutNode); $xmlNode->appendChild($xmlCondition); } else { $xmlElse = $xmlCondition->appendChild($document->createElement('else')); $xmlElse->appendChild($xmlOutNode); } } else { $xmlNode->appendChild($xmlOutNode); } } } foreach ($workflow->getVariableHandlers() as $variable => $class) { $variableHandler = $root->appendChild($document->createElement('variableHandler')); $variableHandler->setAttribute('variable', $variable); $variableHandler->setAttribute('class', $class); } return $document; }
public function testVerify4() { $workflow = new ezcWorkflow('Test'); $workflow->finallyNode->addOutNode(new ezcWorkflowNodeFinally()); try { $workflow->verify(); } catch (ezcWorkflowDefinitionStorageException $e) { $this->assertEquals('A workflow may have only one finally node.', $e->getMessage()); return; } $this->fail('Expected an ezcWorkflowDefinitionStorageException to be thrown.'); }
/** * Constructor */ public function __construct() { parent::__construct($this->getWorkflowName()); $pluginFinalNode = $this->define(); $pluginFinalNode->addOutNode($this->endNode); }
/** * Save a workflow definition to the database. * * @param ezcWorkflow $workflow * @throws ezcWorkflowDefinitionStorageException * @throws ezcDbException */ public function save(ezcWorkflow $workflow) { // Verify the workflow. $workflow->verify(); $this->db->beginTransaction(); // Calculate new version number. $workflowVersion = $this->getCurrentVersionNumber($workflow->name) + 1; // Write workflow table row. $query = $this->db->createInsertQuery(); $query->insertInto($this->db->quoteIdentifier($this->options['prefix'] . 'workflow'))->set($this->db->quoteIdentifier('workflow_name'), $query->bindValue($workflow->name))->set($this->db->quoteIdentifier('workflow_version'), $query->bindValue((int) $workflowVersion))->set($this->db->quoteIdentifier('workflow_created'), $query->bindValue(time())); $statement = $query->prepare(); $statement->execute(); $workflow->definitionStorage = $this; $workflow->id = (int) $this->db->lastInsertId('workflow_workflow_id_seq'); $workflow->version = (int) $workflowVersion; // Write node table rows. $nodeMap = array(); foreach ($workflow->nodes as $node) { $query = $this->db->createInsertQuery(); $query->insertInto($this->db->quoteIdentifier($this->options['prefix'] . 'node'))->set($this->db->quoteIdentifier('workflow_id'), $query->bindValue((int) $workflow->id))->set($this->db->quoteIdentifier('node_class'), $query->bindValue(get_class($node)))->set($this->db->quoteIdentifier('node_configuration'), $query->bindValue(ezcWorkflowDatabaseUtil::serialize($node->getConfiguration()))); $statement = $query->prepare(); $statement->execute(); $nodeMap[$this->db->lastInsertId($this->db->quoteIdentifier('node_node_id_seq'))] = $node; } // Connect node table rows. foreach ($workflow->nodes as $node) { foreach ($node->getOutNodes() as $outNode) { $incomingNodeId = null; $outgoingNodeId = null; foreach ($nodeMap as $_id => $_node) { if ($_node === $node) { $incomingNodeId = $_id; } else { if ($_node === $outNode) { $outgoingNodeId = $_id; } } if ($incomingNodeId !== NULL && $outgoingNodeId !== NULL) { break; } } $query = $this->db->createInsertQuery(); $query->insertInto($this->db->quoteIdentifier($this->options['prefix'] . 'node_connection'))->set($this->db->quoteIdentifier('incoming_node_id'), $query->bindValue($incomingNodeId))->set($this->db->quoteIdentifier('outgoing_node_id'), $query->bindValue($outgoingNodeId)); $statement = $query->prepare(); $statement->execute(); } } unset($nodeMap); // Write variable handler rows. foreach ($workflow->getVariableHandlers() as $variable => $class) { $query = $this->db->createInsertQuery(); $query->insertInto($this->db->quoteIdentifier($this->options['prefix'] . 'variable_handler'))->set($this->db->quoteIdentifier('workflow_id'), $query->bindValue((int) $workflow->id))->set($this->db->quoteIdentifier('variable'), $query->bindValue($variable))->set($this->db->quoteIdentifier('class'), $query->bindValue($class)); $statement = $query->prepare(); $statement->execute(); } $this->db->commit(); }
/** * Save a workflow definition to the database. * * @param ezcWorkflow $workflow * @throws ezcWorkflowDefinitionStorageException * @throws ezcDbException */ public function save(ezcWorkflow $workflow) { // Verify the workflow. $workflow->verify(); $this->db->beginTransaction(); // Calculate new version number. $workflowVersion = $this->getCurrentVersionNumber($workflow->name) + 1; // Write workflow table row. $query = $this->db->createInsertQuery(); $query->insertInto($this->db->quoteIdentifier($this->options['prefix'] . 'workflow'))->set($this->db->quoteIdentifier('workflow_name'), $query->bindValue($workflow->name))->set($this->db->quoteIdentifier('workflow_version'), $query->bindValue((int) $workflowVersion))->set($this->db->quoteIdentifier('workflow_created'), $query->bindValue(time())); $statement = $query->prepare(); $statement->execute(); $workflow->definitionStorage = $this; $workflow->id = (int) $this->db->lastInsertId('workflow_workflow_id_seq'); $workflow->version = (int) $workflowVersion; // Write node table rows. $nodes = $workflow->nodes; $keys = array_keys($nodes); $numNodes = count($nodes); for ($i = 0; $i < $numNodes; $i++) { $id = $keys[$i]; $node = $nodes[$id]; $query = $this->db->createInsertQuery(); $query->insertInto($this->db->quoteIdentifier($this->options['prefix'] . 'node'))->set($this->db->quoteIdentifier('workflow_id'), $query->bindValue((int) $workflow->id))->set($this->db->quoteIdentifier('node_class'), $query->bindValue(get_class($node)))->set($this->db->quoteIdentifier('node_configuration'), $query->bindValue(ezcWorkflowDatabaseUtil::serialize($node->getConfiguration()))); $statement = $query->prepare(); $statement->execute(); $node->setId($this->db->lastInsertId($this->db->quoteIdentifier('node_node_id_seq'))); } // Connect node table rows. for ($i = 0; $i < $numNodes; $i++) { $id = $keys[$i]; $node = $nodes[$id]; foreach ($node->getOutNodes() as $outNode) { $query = $this->db->createInsertQuery(); $query->insertInto($this->db->quoteIdentifier($this->options['prefix'] . 'node_connection'))->set($this->db->quoteIdentifier('incoming_node_id'), $query->bindValue((int) $node->getId()))->set($this->db->quoteIdentifier('outgoing_node_id'), $query->bindValue((int) $outNode->getId())); $statement = $query->prepare(); $statement->execute(); } } // Write variable handler rows. foreach ($workflow->getVariableHandlers() as $variable => $class) { $query = $this->db->createInsertQuery(); $query->insertInto($this->db->quoteIdentifier($this->options['prefix'] . 'variable_handler'))->set($this->db->quoteIdentifier('workflow_id'), $query->bindValue((int) $workflow->id))->set($this->db->quoteIdentifier('variable'), $query->bindValue($variable))->set($this->db->quoteIdentifier('class'), $query->bindValue($class)); $statement = $query->prepare(); $statement->execute(); } $this->db->commit(); }
/** * Constructor. * * @param ezcWorkflow $workflow */ public function __construct(ezcWorkflow $workflow) { $workflow->accept($this); }