From 47f991034f58a52db0fa49e29c88d422010f7d8f Mon Sep 17 00:00:00 2001 From: Erik Amaru Ortiz Date: Wed, 5 Feb 2014 11:39:15 -0400 Subject: [PATCH] More Bpmn/Workflow handling layer refactoring and improve unit tests --- gulliver/system/class.bootstrap.php | 1 + gulliver/system/class.g.php | 8 +- gulliver/system/class.soapNtlm.php | 50 +- workflow/engine/classes/class.system.php | 2 +- .../Exception/ProjectNotFound.php | 20 + .../Project/{BpmnProject.php => Bpmn.php} | 19 +- .../{ProjectHandler.php => Handler.php} | 14 +- .../Project/ProjectHandlerInterface.php | 10 - .../src/ProcessMaker/Project/Workflow.php | 530 ++++++++++++++++++ .../ProcessMaker/Project/WorkflowProject.php | 312 ----------- .../BpmnTest.php} | 52 +- .../WorkflowTest.php} | 48 +- 12 files changed, 662 insertions(+), 404 deletions(-) create mode 100644 workflow/engine/src/ProcessMaker/Exception/ProjectNotFound.php rename workflow/engine/src/ProcessMaker/Project/{BpmnProject.php => Bpmn.php} (95%) rename workflow/engine/src/ProcessMaker/Project/{ProjectHandler.php => Handler.php} (68%) delete mode 100644 workflow/engine/src/ProcessMaker/Project/ProjectHandlerInterface.php create mode 100644 workflow/engine/src/ProcessMaker/Project/Workflow.php delete mode 100644 workflow/engine/src/ProcessMaker/Project/WorkflowProject.php rename workflow/engine/src/Tests/ProcessMaker/{BpmnProjectTest.php => Project/BpmnTest.php} (82%) rename workflow/engine/src/Tests/ProcessMaker/{WorkflowProjectTest.php => Project/WorkflowTest.php} (85%) diff --git a/gulliver/system/class.bootstrap.php b/gulliver/system/class.bootstrap.php index 257948e94..3ecb98f08 100644 --- a/gulliver/system/class.bootstrap.php +++ b/gulliver/system/class.bootstrap.php @@ -382,6 +382,7 @@ class Bootstrap self::registerClass("IsoLocation", PATH_HOME . "engine" . PATH_SEP . "classes" . PATH_SEP . "model" . PATH_SEP . "IsoLocation.php"); self::registerClass("Users", PATH_HOME . "engine" . PATH_SEP . "classes" . PATH_SEP . "model" . PATH_SEP . "Users.php"); self::registerClass("UsersPeer", PATH_HOME . "engine" . PATH_SEP . "classes" . PATH_SEP . "model" . PATH_SEP . "UsersPeer.php"); + self::registerClass("ReportTables", PATH_HOME . "engine" . PATH_SEP . "classes" . PATH_SEP . "class.reportTables.php"); self::registerClass("Xml_Node", PATH_GULLIVER . "class.xmlDocument.php"); diff --git a/gulliver/system/class.g.php b/gulliver/system/class.g.php index b7216c8a9..765e54827 100755 --- a/gulliver/system/class.g.php +++ b/gulliver/system/class.g.php @@ -303,7 +303,7 @@ class G /** * ************* path functions **************** */ - public function mk_dir ($strPath, $rights = 0770) + public static function mk_dir ($strPath, $rights = 0770) { $folder_path = array ($strPath); $oldumask = umask( 0 ); @@ -444,7 +444,7 @@ class G * @param string $strPath * @return string */ - public function expandPath ($strPath = '') + public static function expandPath ($strPath = '') { $res = ""; $res = PATH_CORE; @@ -462,7 +462,7 @@ class G * @param string $strClass * @return void */ - public function LoadSystem ($strClass) + public static function LoadSystem ($strClass) { require_once (PATH_GULLIVER . 'class.' . $strClass . '.php'); } @@ -689,7 +689,7 @@ class G * @param string $strClass * @return void */ - public function LoadClass ($strClass) + public static function LoadClass ($strClass) { $classfile = G::ExpandPath( "classes" ) . 'class.' . $strClass . '.php'; if (! file_exists( $classfile )) { diff --git a/gulliver/system/class.soapNtlm.php b/gulliver/system/class.soapNtlm.php index dfc850a0d..28ff4a933 100644 --- a/gulliver/system/class.soapNtlm.php +++ b/gulliver/system/class.soapNtlm.php @@ -25,9 +25,9 @@ * Coral Gables, FL, 33134, USA, or email info@colosa.com. * */ -/* SOAP NTLM - * This class is used to extend SoapClient native PHP - * to allow NTLM authentication throw soap connection +/* SOAP NTLM + * This class is used to extend SoapClient native PHP + * to allow NTLM authentication throw soap connection */ /** @@ -64,8 +64,8 @@ class soapNtlm */ public function stream_open ($path, $mode, $options, $opened_path) { - //echo "[NTLMStream::stream_open] $path , mode=$mode
"; - //G::pr($options); + //echo "[NTLMStream::stream_open] $path , mode=$mode
"; + //G::pr($options); $this->path = $path; $this->mode = $mode; $this->options = $options; @@ -79,7 +79,7 @@ class soapNtlm */ public function stream_close () { - //echo "[NTLMStream::stream_close]
"; + //echo "[NTLMStream::stream_close]
"; curl_close( $this->ch ); } @@ -91,7 +91,7 @@ class soapNtlm */ public function stream_read ($count) { - //echo "[NTLMStream::stream_read] $count
"; + //echo "[NTLMStream::stream_read] $count
"; if (strlen( $this->buffer ) == 0) { return false; } @@ -108,7 +108,7 @@ class soapNtlm */ public function stream_write ($data) { - //echo "[NTLMStream::stream_write]
"; + //echo "[NTLMStream::stream_write]
"; if (strlen( $this->buffer ) == 0) { return false; } @@ -121,12 +121,12 @@ class soapNtlm */ public function stream_eof () { - //echo "[NTLMStream::stream_eof] "; + //echo "[NTLMStream::stream_eof] "; if ($this->pos > strlen( $this->buffer )) { - //echo "true
"; + //echo "true
"; return true; } - //echo "false
"; + //echo "false
"; return false; } @@ -136,7 +136,7 @@ class soapNtlm */ public function stream_tell () { - //echo "[NTLMStream::stream_tell]
"; + //echo "[NTLMStream::stream_tell]
"; return $this->pos; } @@ -145,7 +145,7 @@ class soapNtlm */ public function stream_flush () { - //echo "[NTLMStream::stream_flush]
"; + //echo "[NTLMStream::stream_flush]
"; $this->buffer = null; $this->pos = null; } @@ -157,7 +157,7 @@ class soapNtlm */ public function stream_stat () { - //echo "[NTLMStream::stream_stat]
"; + //echo "[NTLMStream::stream_stat]
"; $this->createBuffer( $this->path ); $stat = array ('size' => strlen( $this->buffer )); return $stat; @@ -170,8 +170,8 @@ class soapNtlm */ public function url_stat ($path, $flags) { - //G::pr($this->options); - //echo "[NTLMStream::url_stat] -> $path
"; + //G::pr($this->options); + //echo "[NTLMStream::url_stat] -> $path
"; $this->createBuffer( $path ); $stat = array ('size' => strlen( $this->buffer )); return $stat; @@ -188,14 +188,14 @@ class soapNtlm return; } - //echo "[NTLMStream::createBuffer] create buffer from : $path
"; + //echo "[NTLMStream::createBuffer] create buffer from : $path
"; $this->ch = curl_init( $path ); curl_setopt( $this->ch, CURLOPT_RETURNTRANSFER, true ); curl_setopt( $this->ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1 ); curl_setopt( $this->ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM ); - //curl_setopt($this->ch, CURLOPT_USERPWD, $this->options['auth']); // Hugo's code - curl_setopt( $this->ch, CURLOPT_USERPWD, $this->getuser() . ':' . $this->getpassword() ); // Ankit's code - //Apply proxy settings + //curl_setopt($this->ch, CURLOPT_USERPWD, $this->options['auth']); // Hugo's code + curl_setopt( $this->ch, CURLOPT_USERPWD, $this->getuser() . ':' . $this->getpassword() ); // Ankit's code + //Apply proxy settings if (class_exists( 'System' )) { $sysConf = System::getSystemConfiguration(); if ($sysConf['proxy_host'] != '') { @@ -210,7 +210,7 @@ class soapNtlm } } echo $this->buffer = curl_exec( $this->ch ); - //echo "[NTLMStream::createBuffer] buffer size : " . strlen($this->buffer) . "bytes
"; + //echo "[NTLMStream::createBuffer] buffer size : " . strlen($this->buffer) . "bytes
"; $this->pos = 0; } @@ -218,7 +218,7 @@ class soapNtlm class NTLMSoapClient extends SoapClient { - function __doRequest ($request, $location, $action, $version) + function __doRequest ($request, $location, $action, $version, $one_way = 0) { $headers = array ('Method: POST','Connection: Keep-Alive','User-Agent: PHP-SOAP-CURL','Content-Type: text/xml; charset=utf-8','SOAPAction: "' . $action . '"'); @@ -232,10 +232,10 @@ class NTLMSoapClient extends SoapClient curl_setopt( $ch, CURLOPT_POSTFIELDS, $request ); curl_setopt( $ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1 ); curl_setopt( $ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM ); - //curl_setopt($ch, CURLOPT_USERPWD, $this->options['auth']); //Hugo's Code - curl_setopt( $ch, CURLOPT_USERPWD, $this->user . ':' . $this->password ); //Ankit's Code + //curl_setopt($ch, CURLOPT_USERPWD, $this->options['auth']); //Hugo's Code + curl_setopt( $ch, CURLOPT_USERPWD, $this->user . ':' . $this->password ); //Ankit's Code - //Apply proxy settings + //Apply proxy settings if (class_exists( 'System' )) { $sysConf = System::getSystemConfiguration(); if ($sysConf['proxy_host'] != '') { diff --git a/workflow/engine/classes/class.system.php b/workflow/engine/classes/class.system.php index 337558632..6b1452f49 100755 --- a/workflow/engine/classes/class.system.php +++ b/workflow/engine/classes/class.system.php @@ -1141,7 +1141,7 @@ class System return $result; } - public function solrEnv ($sysName = '') + public static function solrEnv ($sysName = '') { if (empty( $sysName )) { $conf = System::getSystemConfiguration(); diff --git a/workflow/engine/src/ProcessMaker/Exception/ProjectNotFound.php b/workflow/engine/src/ProcessMaker/Exception/ProjectNotFound.php new file mode 100644 index 000000000..5e017eb67 --- /dev/null +++ b/workflow/engine/src/ProcessMaker/Exception/ProjectNotFound.php @@ -0,0 +1,20 @@ +code}]: {$this->message}\n"; + } +} \ No newline at end of file diff --git a/workflow/engine/src/ProcessMaker/Project/BpmnProject.php b/workflow/engine/src/ProcessMaker/Project/Bpmn.php similarity index 95% rename from workflow/engine/src/ProcessMaker/Project/BpmnProject.php rename to workflow/engine/src/ProcessMaker/Project/Bpmn.php index 6e6221375..066d83200 100644 --- a/workflow/engine/src/ProcessMaker/Project/BpmnProject.php +++ b/workflow/engine/src/ProcessMaker/Project/Bpmn.php @@ -27,20 +27,11 @@ use \BpmnArtifactPeer as ArtifactPeer; use \BasePeer; -use ProcessMaker\Project\ProjectHandler; use ProcessMaker\Util\Hash; +use ProcessMaker\Exception; -class BpmnProject //extends ProjectHandler +class Bpmn extends Handler { - protected static $diagramElements = array( - 'activities' => 'act_uid', - 'events' => 'evn_uid', - 'flows' => 'flo_uid', - 'artifacts' => 'art_uid', - 'laneset' => 'lns_uid', - 'lanes' => 'lan_uid' - ); - /** * @var \BpmnProject */ @@ -68,13 +59,13 @@ class BpmnProject //extends ProjectHandler public static function load($prjUid) { + $me = new self(); $project = ProjectPeer::retrieveByPK($prjUid); if (! is_object($project)) { - return null; + throw new Exception\ProjectNotFound($me, $prjUid); } - $me = new BpmnProject(); $me->project = $project; $me->prjUid = $me->project->getPrjUid(); @@ -82,7 +73,7 @@ class BpmnProject //extends ProjectHandler } /** - * @param array|null $data optional array attributes to create and initialize a BpmnProject + * @param array| $data array attributes to create and initialize a BpmnProject */ public function create($data) { diff --git a/workflow/engine/src/ProcessMaker/Project/ProjectHandler.php b/workflow/engine/src/ProcessMaker/Project/Handler.php similarity index 68% rename from workflow/engine/src/ProcessMaker/Project/ProjectHandler.php rename to workflow/engine/src/ProcessMaker/Project/Handler.php index 93e9e1cf3..3d402aff4 100644 --- a/workflow/engine/src/ProcessMaker/Project/ProjectHandler.php +++ b/workflow/engine/src/ProcessMaker/Project/Handler.php @@ -3,11 +3,17 @@ namespace ProcessMaker\Project; use ProcessMaker\Util\Logger; -abstract class ProjectHandler //implements ProjectHandlerInterface +abstract class Handler { - public abstract function save(); - public abstract function update(); - public abstract function delete(); + public static function load($uid) + { // This method must be implemented on children classes, this is not declared abstract since PHP 5.3.x + // don't allow any more static abstract methods. + return null; + } + + public abstract function create($data); + //public abstract function update(); + public abstract function remove(); /** * Log in ProcessMaker Standard Output if debug mode is enabled. diff --git a/workflow/engine/src/ProcessMaker/Project/ProjectHandlerInterface.php b/workflow/engine/src/ProcessMaker/Project/ProjectHandlerInterface.php deleted file mode 100644 index 536db30b4..000000000 --- a/workflow/engine/src/ProcessMaker/Project/ProjectHandlerInterface.php +++ /dev/null @@ -1,10 +0,0 @@ -create($data); + } + } + + public function setProperties($properties) + { + $this->properties = $properties; + } + + public function getProcess() + { + if (empty($this->proUid)) { + throw new \Exception("Error: There is not an initialized project."); + } + + $process = new Process(); + + return $process->load($this->proUid); + } + + public function getUid() + { + return $this->proUid; + } + + public function create($data) + { + try { + // setting defaults + $data['PRO_UID'] = array_key_exists('PRO_UID', $data) ? $data['PRO_UID'] : Hash::generateUID(); + $data['USR_UID'] = array_key_exists('PRO_CREATE_USER', $data) ? $data['PRO_CREATE_USER'] : null; + $data['PRO_CATEGORY'] = array_key_exists('PRO_CATEGORY', $data) ? $data['PRO_CATEGORY'] : ''; + + // Create project + $process = new Process(); + $this->proUid = $process->create($data, false); + + } catch (Exception $e) { + throw new \RuntimeException($e); + } + } + + public function update() + { + // TODO: Implement update() method. + } + + public function remove() + { + $this->deleteProcess($this->proUid); + } + + public static function load($proUid) + { + $me = new self(); + + try { + $process = new Process(); + $processData = $process->load($proUid); + } catch (\Exception $e) { + throw new Exception\ProjectNotFound($me, $proUid); + } + + $me->process = $processData; + $me->proUid = $processData["PRO_UID"]; + + return $me; + } + + /* + * Projects elements handlers + */ + + public function addTask($taskData) + { + // Setting defaults + $taskData['TAS_UID'] = array_key_exists('TAS_UID', $taskData) ? $taskData['TAS_UID'] : Hash::generateUID(); + $taskData['PRO_UID'] = $this->proUid; + + $task = new Task(); + + return $task->create($taskData, false); + } + + public function updateTask($tasUid, $taskData) + { + $task = new Task(); + $taskData['TAS_UID'] = $tasUid; + + return $task->update($taskData); + } + + public function removeTask($tasUid) + { + $task = new Task(); + $task->remove($tasUid); + } + + public function getTask($tasUid) + { + $task = new Task(); + return $task->load($tasUid); + } + + + public function getTasks() + { + if (empty($this->proUid)) { + return null; + } + + $tasks = new Tasks(); + + return $tasks->getAllTasks($this->proUid); + } + + public function setStartTask($tasUid) + { + $task = \TaskPeer::retrieveByPK($tasUid); + $task->setTasStart("TRUE"); + $task->save(); + } + + public function setEndTask($tasUid) + { + $this->addSequentialRoute($tasUid, "-1", "SEQUENTIAL", true); + } + + public function addSequentialRoute($fromTasUid, $toTasUid, $delete = null) + { + $this->addRoute($fromTasUid, $toTasUid, "SEQUENTIAL", $delete); + } + + public function addSelectRoute($fromTasUid, array $toTasks, $delete = null) + { + foreach ($toTasks as $toTasUid) { + $this->addRoute($fromTasUid, $toTasUid, "SELECT", $delete); + } + } + + public function addRoute($fromTasUid, $toTasUid, $type, $delete = null) + { + + /*switch ($type) { + case 0: + $sType = 'SEQUENTIAL'; + break; + case 1: + $sType = 'SELECT'; + break; + case 2: + $sType = 'EVALUATE'; + break; + case 3: + $sType = 'PARALLEL'; + break; + case 4: + $sType = 'PARALLEL-BY-EVALUATION'; + break; + case 5: + $sType = 'SEC-JOIN'; + break; + case 8: + $sType = 'DISCRIMINATOR'; + break; + default: + throw new \Exception("Invalid type code, given: $type, expected: integer [1...8]"); + } + }*/ + + $validTypes = array("SEQUENTIAL", "SELECT", "EVALUATE", "PARALLEL", "PARALLEL-BY-EVALUATION", "SEC-JOIN", "DISCRIMINATOR"); + + if (! in_array($type, $validTypes)) { + throw new \Exception("Invalid Route type, given: $type, expected: [".implode(",", $validTypes)."]"); + } + + //if ($type != 0 && $type != 5 && $type != 8) { + if ($type != 'SEQUENTIAL' && $type != 'SEC-JOIN' && $type != 'DISCRIMINATOR') { + if ($this->getNumberOfRoutes($this->proUid, $fromTasUid, $toTasUid, $type) > 0) { + // die(); ???? + throw new \RuntimeException("Unexpected behaviour"); + } + //unset($aRow); + } + //if ($delete || $type == 0 || $type == 5 || $type == 8) { + if ($delete || $type == 'SEQUENTIAL' || $type == 'SEC-JOIN' || $type == 'DISCRIMINATOR') { + $oTasks = new Tasks(); + + $oTasks->deleteAllRoutesOfTask($this->proUid, $fromTasUid); + //$oTasks->deleteAllGatewayOfTask($this->proUid, $fromTasUid); + } + return $this->saveNewPattern($this->proUid, $fromTasUid, $toTasUid, $type, $delete); + } + + public function updateRoute($rouUid, $routeData) + { + $route = new Route(); + $routeData['ROU_UID'] = $rouUid; + $route->update($routeData); + } + + public function removeRoute($rouUid) + { + $route = new Route(); + + return $route->remove($rouUid); + } + + public function getRoute($rouUid) + { + $route = new Route(); + + return $route->load($rouUid); + } + + + /**************************************************************************************************** + * Migrated Methods from class.processMap.php class * + ****************************************************************************************************/ + + private function getNumberOfRoutes($sProcessUID = '', $sTaskUID = '', $sNextTask = '', $sType = '') + { + try { + $oCriteria = new Criteria('workflow'); + $oCriteria->addSelectColumn('COUNT(*) AS ROUTE_NUMBER'); + $oCriteria->add(RoutePeer::PRO_UID, $sProcessUID); + $oCriteria->add(RoutePeer::TAS_UID, $sTaskUID); + $oCriteria->add(RoutePeer::ROU_NEXT_TASK, $sNextTask); + $oCriteria->add(RoutePeer::ROU_TYPE, $sType); + $oDataset = RoutePeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + $aRow = $oDataset->getRow(); + + return (int) $aRow['ROUTE_NUMBER']; + } catch (Exception $oError) { + throw ($oError); + } + } + + private function saveNewPattern($sProcessUID = '', $sTaskUID = '', $sNextTask = '', $sType = '', $sDelete = '') + { + try { + $oCriteria = new Criteria('workflow'); + $oCriteria->addSelectColumn('COUNT(*) AS ROUTE_NUMBER'); + //$oCriteria->addSelectColumn('GAT_UID AS GATEWAY_UID'); + $oCriteria->add(RoutePeer::PRO_UID, $sProcessUID); + $oCriteria->add(RoutePeer::TAS_UID, $sTaskUID); + $oCriteria->add(RoutePeer::ROU_TYPE, $sType); + + $oDataset = RoutePeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + $aRow = $oDataset->getRow(); + + $aFields['PRO_UID'] = $sProcessUID; + $aFields['TAS_UID'] = $sTaskUID; + $aFields['ROU_NEXT_TASK'] = $sNextTask; + $aFields['ROU_TYPE'] = $sType; + $aFields['ROU_CASE'] = (int) $aRow['ROUTE_NUMBER'] + 1; + + //$sGatewayUID = $aRow['GATEWAY_UID']; + + //if ($sDelete && $sGatewayUID != '') { + // $oGateway = new Gateway(); + // $oGateway->remove($sGatewayUID); + //} + //Getting Gateway UID after saving gateway + //if($sType != 'SEQUENTIAL' && $sGatewayUID == '' && $sDelete == '1') + + /*??? Maybe this is deprecated + if ($sType != 'SEQUENTIAL') { + $oProcessMap = new processMap(); + $sGatewayUID = $this->saveNewGateway($sProcessUID, $sTaskUID, $sNextTask); + }*/ + + //$aFields['GAT_UID'] = (isset($sGatewayUID)) ? $sGatewayUID : ''; + + $oRoute = new Route(); + + return $oRoute->create($aFields); + } catch (Exception $oError) { + throw ($oError); + } + } + + public function deleteProcess($sProcessUID) + { + try { + //G::LoadClass('case'); + //G::LoadClass('reportTables'); + + //Instance all classes necesaries + $oProcess = new \Process(); + $oDynaform = new \Dynaform(); + $oInputDocument = new \InputDocument(); + $oOutputDocument = new \OutputDocument(); + $oTrigger = new \Triggers(); + $oRoute = new \Route(); + $oGateway = new \Gateway(); + $oEvent = new \Event(); + $oSwimlaneElement = new \SwimlanesElements(); + $oConfiguration = new \Configuration(); + $oDbSource = new \DbSource(); + $oReportTable = new \ReportTables(); + $oCaseTracker = new \CaseTracker(); + $oCaseTrackerObject = new \CaseTrackerObject(); + //Delete the applications of process + $oCriteria = new \Criteria('workflow'); + $oCriteria->add(\ApplicationPeer::PRO_UID, $sProcessUID); + $oDataset = \ApplicationPeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(\ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + $oCase = new \Cases(); + + while ($aRow = $oDataset->getRow()) { + $oCase->removeCase($aRow['APP_UID']); + $oDataset->next(); + } + + //Delete the tasks of process + $oCriteria = new Criteria('workflow'); + $oCriteria->add(\TaskPeer::PRO_UID, $sProcessUID); + $oDataset = \TaskPeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + while ($aRow = $oDataset->getRow()) { + //$this->deleteTask($aRow['TAS_UID']); + $oTasks = new \Tasks(); + $oTasks->deleteTask($aRow['TAS_UID']); + + $oDataset->next(); + } + //Delete the dynaforms of process + $oCriteria = new Criteria('workflow'); + $oCriteria->add(\DynaformPeer::PRO_UID, $sProcessUID); + $oDataset = \DynaformPeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + while ($aRow = $oDataset->getRow()) { + $oDynaform->remove($aRow['DYN_UID']); + $oDataset->next(); + } + //Delete the input documents of process + $oCriteria = new Criteria('workflow'); + $oCriteria->add(\InputDocumentPeer::PRO_UID, $sProcessUID); + $oDataset = \InputDocumentPeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + while ($aRow = $oDataset->getRow()) { + $oInputDocument->remove($aRow['INP_DOC_UID']); + $oDataset->next(); + } + //Delete the output documents of process + $oCriteria = new Criteria('workflow'); + $oCriteria->add(\OutputDocumentPeer::PRO_UID, $sProcessUID); + $oDataset = \OutputDocumentPeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + while ($aRow = $oDataset->getRow()) { + $oOutputDocument->remove($aRow['OUT_DOC_UID']); + $oDataset->next(); + } + + //Delete the triggers of process + $oCriteria = new Criteria('workflow'); + $oCriteria->add(\TriggersPeer::PRO_UID, $sProcessUID); + $oDataset = \TriggersPeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + while ($aRow = $oDataset->getRow()) { + $oTrigger->remove($aRow['TRI_UID']); + $oDataset->next(); + } + + //Delete the routes of process + $oCriteria = new Criteria('workflow'); + $oCriteria->add(\RoutePeer::PRO_UID, $sProcessUID); + $oDataset = \RoutePeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + while ($aRow = $oDataset->getRow()) { + $oRoute->remove($aRow['ROU_UID']); + $oDataset->next(); + } + + //Delete the gateways of process + $oCriteria = new Criteria('workflow'); + $oCriteria->add(\GatewayPeer::PRO_UID, $sProcessUID); + $oDataset = \GatewayPeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + while ($aRow = $oDataset->getRow()) { + $oGateway->remove($aRow['GAT_UID']); + $oDataset->next(); + } + + //Delete the Event of process + $oCriteria = new Criteria('workflow'); + $oCriteria->add(\EventPeer::PRO_UID, $sProcessUID); + $oDataset = \EventPeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + while ($aRow = $oDataset->getRow()) { + $oEvent->remove($aRow['EVN_UID']); + $oDataset->next(); + } + + //Delete the swimlanes elements of process + $oCriteria = new Criteria('workflow'); + $oCriteria->add(\SwimlanesElementsPeer::PRO_UID, $sProcessUID); + $oDataset = \SwimlanesElementsPeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + while ($aRow = $oDataset->getRow()) { + $oSwimlaneElement->remove($aRow['SWI_UID']); + $oDataset->next(); + } + //Delete the configurations of process + $oCriteria = new Criteria('workflow'); + $oCriteria->add(\ConfigurationPeer::PRO_UID, $sProcessUID); + $oDataset = \ConfigurationPeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + while ($aRow = $oDataset->getRow()) { + $oConfiguration->remove($aRow['CFG_UID'], $aRow['OBJ_UID'], $aRow['PRO_UID'], $aRow['USR_UID'], $aRow['APP_UID']); + $oDataset->next(); + } + //Delete the DB sources of process + $oCriteria = new Criteria('workflow'); + $oCriteria->add(\DbSourcePeer::PRO_UID, $sProcessUID); + $oDataset = \DbSourcePeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + while ($aRow = $oDataset->getRow()) { + + /** + * note added by gustavo cruz gustavo-at-colosa-dot-com 27-01-2010 + * in order to solve the bug 0004389, we use the validation function Exists + * inside the remove function in order to verify if the DbSource record + * exists in the Database, however there is a strange behavior within the + * propel engine, when the first record is erased somehow the "_deleted" + * attribute of the next row is set to true, so when propel tries to erase + * it, obviously it can't and trows an error. With the "Exist" function + * we ensure that if there is the record in the database, the _delete attribute must be false. + * + * note added by gustavo cruz gustavo-at-colosa-dot-com 28-01-2010 + * I have just identified the source of the issue, when is created a $oDbSource DbSource object + * it's used whenever a record is erased or removed in the db, however the problem + * it's that the same object is used every time, and the delete method invoked + * sets the _deleted attribute to true when its called, of course as we use + * the same object, the first time works fine but trowns an error with the + * next record, cos it's the same object and the delete method checks if the _deleted + * attribute it's true or false, the attrib _deleted is setted to true the + * first time and later is never changed, the issue seems to be part of + * every remove function in the model classes, not only DbSource + * i recommend that a more general solution must be achieved to resolve + * this issue in every model class, to prevent future problems. + */ + $oDbSource->remove($aRow['DBS_UID'], $sProcessUID); + $oDataset->next(); + } + //Delete the supervisors + $oCriteria = new Criteria('workflow'); + $oCriteria->add(\ProcessUserPeer::PRO_UID, $sProcessUID); + \ProcessUserPeer::doDelete($oCriteria); + //Delete the object permissions + $oCriteria = new Criteria('workflow'); + $oCriteria->add(\ObjectPermissionPeer::PRO_UID, $sProcessUID); + \ObjectPermissionPeer::doDelete($oCriteria); + //Delete the step supervisors + $oCriteria = new Criteria('workflow'); + $oCriteria->add(\StepSupervisorPeer::PRO_UID, $sProcessUID); + \StepSupervisorPeer::doDelete($oCriteria); + //Delete the report tables + $oCriteria = new Criteria('workflow'); + $oCriteria->add(\ReportTablePeer::PRO_UID, $sProcessUID); + $oDataset = \ReportTablePeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + while ($aRow = $oDataset->getRow()) { + $oReportTable->deleteReportTable($aRow['REP_TAB_UID']); + $oDataset->next(); + } + //Delete case tracker configuration + $oCaseTracker->remove($sProcessUID); + //Delete case tracker objects + $oCriteria = new Criteria('workflow'); + $oCriteria->add(\CaseTrackerObjectPeer::PRO_UID, $sProcessUID); + \ProcessUserPeer::doDelete($oCriteria); + //Delete the process + try { + $oProcess->remove($sProcessUID); + } catch (Exception $oError) { + throw ($oError); + } + return true; + } catch (Exception $oError) { + throw ($oError); + } + } + +} \ No newline at end of file diff --git a/workflow/engine/src/ProcessMaker/Project/WorkflowProject.php b/workflow/engine/src/ProcessMaker/Project/WorkflowProject.php deleted file mode 100644 index 6d3cad07f..000000000 --- a/workflow/engine/src/ProcessMaker/Project/WorkflowProject.php +++ /dev/null @@ -1,312 +0,0 @@ -setProperties($data); - $this->create(); - } - } - - public function setProperties($properties) - { - $this->properties = $properties; - } - - public function getProperties() - { - $process = new Process(); - return $process->load($this->proUid); - } - - public function getUid() - { - return $this->proUid; - } - - public function create() - { - try { - // setting defaults - $this->properties['PRO_UID'] = array_key_exists('PRO_UID', $this->properties) - ? $this->properties['PRO_UID'] : Hash::generateUID(); - - $this->properties['USR_UID'] = array_key_exists('PRO_CREATE_USER', $this->properties) - ? $this->properties['PRO_CREATE_USER'] : null; - - $this->properties['PRO_CATEGORY'] = array_key_exists('PRO_CATEGORY', $this->properties) - ? $this->properties['PRO_CATEGORY'] : ''; - - - // Create project - $process = new Process(); - $this->proUid = $process->create($this->properties, false); - - } catch (Exception $e) { - //throw new \RuntimeException($e); - echo $e->getMessage() . PHP_EOL; - echo $e->getTraceAsString() . PHP_EOL; - die; - } - } - - public function update() - { - // TODO: Implement update() method. - } - - public function delete() - { - // TODO: Implement delete() method. - } - - public static function load($prjUid) - { - $process = new Process(); - return $process->load($prjUid); - } - - /* - * Projects elements handlers - */ - - public function addTask($taskData) - { - // Setting defaults - $taskData['TAS_UID'] = array_key_exists('TAS_UID', $taskData) ? $taskData['TAS_UID'] : Hash::generateUID(); - $taskData['PRO_UID'] = $this->proUid; - - $task = new Task(); - - return $task->create($taskData, false); - } - - public function updateTask($tasUid, $taskData) - { - $task = new Task(); - $taskData['TAS_UID'] = $tasUid; - - return $task->update($taskData); - } - - public function removeTask($tasUid) - { - $task = new Task(); - $task->remove($tasUid); - } - - public function getTask($tasUid) - { - $task = new Task(); - return $task->load($tasUid); - } - - - public function getTasks() - { - if (empty($this->proUid)) { - return null; - } - - $tasks = new Tasks(); - - return $tasks->getAllTasks($this->proUid); - } - - public function setStartTask($tasUid) - { - $task = \TaskPeer::retrieveByPK($tasUid); - $task->setTasStart("TRUE"); - $task->save(); - } - - public function setEndTask($tasUid) - { - $this->addSequentialRoute($tasUid, "-1", "SEQUENTIAL", true); - } - - public function addSequentialRoute($fromTasUid, $toTasUid, $delete = null) - { - $this->addRoute($fromTasUid, $toTasUid, "SEQUENTIAL", $delete); - } - - public function addSelectRoute($fromTasUid, array $toTasks, $delete = null) - { - foreach ($toTasks as $toTasUid) { - $this->addRoute($fromTasUid, $toTasUid, "SELECT", $delete); - } - } - - public function addRoute($fromTasUid, $toTasUid, $type, $delete = null) - { - - /*switch ($type) { - case 0: - $sType = 'SEQUENTIAL'; - break; - case 1: - $sType = 'SELECT'; - break; - case 2: - $sType = 'EVALUATE'; - break; - case 3: - $sType = 'PARALLEL'; - break; - case 4: - $sType = 'PARALLEL-BY-EVALUATION'; - break; - case 5: - $sType = 'SEC-JOIN'; - break; - case 8: - $sType = 'DISCRIMINATOR'; - break; - default: - throw new \Exception("Invalid type code, given: $type, expected: integer [1...8]"); - } - }*/ - - $validTypes = array("SEQUENTIAL", "SELECT", "EVALUATE", "PARALLEL", "PARALLEL-BY-EVALUATION", "SEC-JOIN", "DISCRIMINATOR"); - - if (! in_array($type, $validTypes)) { - throw new \Exception("Invalid Route type, given: $type, expected: [".implode(",", $validTypes)."]"); - } - - //if ($type != 0 && $type != 5 && $type != 8) { - if ($type != 'SEQUENTIAL' && $type != 'SEC-JOIN' && $type != 'DISCRIMINATOR') { - if ($this->getNumberOfRoutes($this->proUid, $fromTasUid, $toTasUid, $type) > 0) { - // die(); ???? - throw new \RuntimeException("Unexpected behaviour"); - } - //unset($aRow); - } - //if ($delete || $type == 0 || $type == 5 || $type == 8) { - if ($delete || $type == 'SEQUENTIAL' || $type == 'SEC-JOIN' || $type == 'DISCRIMINATOR') { - $oTasks = new Tasks(); - - $oTasks->deleteAllRoutesOfTask($this->proUid, $fromTasUid); - //$oTasks->deleteAllGatewayOfTask($this->proUid, $fromTasUid); - } - return $this->saveNewPattern($this->proUid, $fromTasUid, $toTasUid, $type, $delete); - } - - public function updateRoute($rouUid, $routeData) - { - $route = new Route(); - $routeData['ROU_UID'] = $rouUid; - $route->update($routeData); - } - - public function removeRoute($rouUid) - { - $route = new Route(); - - return $route->remove($rouUid); - } - - public function getRoute($rouUid) - { - $route = new Route(); - - return $route->load($rouUid); - } - - ///////////////////////////////// - /* - * Migrated from class.processMap.php class - */ - private function getNumberOfRoutes($sProcessUID = '', $sTaskUID = '', $sNextTask = '', $sType = '') - { - try { - $oCriteria = new Criteria('workflow'); - $oCriteria->addSelectColumn('COUNT(*) AS ROUTE_NUMBER'); - $oCriteria->add(RoutePeer::PRO_UID, $sProcessUID); - $oCriteria->add(RoutePeer::TAS_UID, $sTaskUID); - $oCriteria->add(RoutePeer::ROU_NEXT_TASK, $sNextTask); - $oCriteria->add(RoutePeer::ROU_TYPE, $sType); - $oDataset = RoutePeer::doSelectRS($oCriteria); - $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); - $oDataset->next(); - $aRow = $oDataset->getRow(); - - return (int) $aRow['ROUTE_NUMBER']; - } catch (Exception $oError) { - throw ($oError); - } - } - - private function saveNewPattern($sProcessUID = '', $sTaskUID = '', $sNextTask = '', $sType = '', $sDelete = '') - { - try { - $oCriteria = new Criteria('workflow'); - $oCriteria->addSelectColumn('COUNT(*) AS ROUTE_NUMBER'); - //$oCriteria->addSelectColumn('GAT_UID AS GATEWAY_UID'); - $oCriteria->add(RoutePeer::PRO_UID, $sProcessUID); - $oCriteria->add(RoutePeer::TAS_UID, $sTaskUID); - $oCriteria->add(RoutePeer::ROU_TYPE, $sType); - - $oDataset = RoutePeer::doSelectRS($oCriteria); - $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); - $oDataset->next(); - $aRow = $oDataset->getRow(); - - $aFields['PRO_UID'] = $sProcessUID; - $aFields['TAS_UID'] = $sTaskUID; - $aFields['ROU_NEXT_TASK'] = $sNextTask; - $aFields['ROU_TYPE'] = $sType; - $aFields['ROU_CASE'] = (int) $aRow['ROUTE_NUMBER'] + 1; - - //$sGatewayUID = $aRow['GATEWAY_UID']; - - //if ($sDelete && $sGatewayUID != '') { - // $oGateway = new Gateway(); - // $oGateway->remove($sGatewayUID); - //} - //Getting Gateway UID after saving gateway - //if($sType != 'SEQUENTIAL' && $sGatewayUID == '' && $sDelete == '1') - - /*??? Maybe this is deprecated - if ($sType != 'SEQUENTIAL') { - $oProcessMap = new processMap(); - $sGatewayUID = $this->saveNewGateway($sProcessUID, $sTaskUID, $sNextTask); - }*/ - - //$aFields['GAT_UID'] = (isset($sGatewayUID)) ? $sGatewayUID : ''; - - $oRoute = new Route(); - - return $oRoute->create($aFields); - } catch (Exception $oError) { - throw ($oError); - } - } - - - -} \ No newline at end of file diff --git a/workflow/engine/src/Tests/ProcessMaker/BpmnProjectTest.php b/workflow/engine/src/Tests/ProcessMaker/Project/BpmnTest.php similarity index 82% rename from workflow/engine/src/Tests/ProcessMaker/BpmnProjectTest.php rename to workflow/engine/src/Tests/ProcessMaker/Project/BpmnTest.php index 1305351fc..50ac2b3dc 100644 --- a/workflow/engine/src/Tests/ProcessMaker/BpmnProjectTest.php +++ b/workflow/engine/src/Tests/ProcessMaker/Project/BpmnTest.php @@ -1,19 +1,25 @@ remove(); + //cleaning DB + foreach (self::$prjUids as $prjUid) { + $bp = Project\Bpmn::load($prjUid); + $bp->remove(); + } + } public function testCreate() @@ -24,10 +30,10 @@ class BpmnProjectTest extends PHPUnit_Framework_TestCase "PRJ_AUTHOR" => "00000000000000000000000000000001" ); - // Create a new BpmnProject and save to DB - $bp = new BpmnProject($data); + // Create a new Project\Bpmn and save to DB + $bp = new Project\Bpmn($data); $projectData = $bp->getProject(); - self::$prjUid = $bp->getUid(); + self::$prjUids[] = $bp->getUid(); foreach ($data as $key => $value) { $this->assertEquals($value, $projectData[$key]); @@ -38,7 +44,7 @@ class BpmnProjectTest extends PHPUnit_Framework_TestCase /** * @depends testCreate - * @var $bp \ProcessMaker\Project\BpmnProject + * @var $bp \ProcessMaker\Project\Bpmn */ public function testAddDiagram($bp) { @@ -58,7 +64,7 @@ class BpmnProjectTest extends PHPUnit_Framework_TestCase /** * @depends testCreate - * @var $bp \ProcessMaker\Project\BpmnProject + * @var $bp \ProcessMaker\Project\Bpmn */ public function testAddProcess($bp) { @@ -81,7 +87,7 @@ class BpmnProjectTest extends PHPUnit_Framework_TestCase /** * @depends testCreate - * @var $bp \ProcessMaker\Project\BpmnProject + * @var $bp \ProcessMaker\Project\Bpmn */ public function testAddActivity($bp) { @@ -112,7 +118,7 @@ class BpmnProjectTest extends PHPUnit_Framework_TestCase /** * @depends testCreate - * @param $bp \ProcessMaker\Project\BpmnProject + * @param $bp \ProcessMaker\Project\Bpmn * @return array */ public function testAddActivityWithUid($bp) @@ -146,7 +152,7 @@ class BpmnProjectTest extends PHPUnit_Framework_TestCase /** * @depends testCreate * @depends testAddActivityWithUid - * @param $bp \ProcessMaker\Project\BpmnProject + * @param $bp \ProcessMaker\Project\Bpmn * @param $data */ public function testGetActivity($bp, $data) @@ -166,7 +172,7 @@ class BpmnProjectTest extends PHPUnit_Framework_TestCase /** * @depends testCreate * @depends testAddActivityWithUid - * @param $bp \ProcessMaker\Project\BpmnProject + * @param $bp \ProcessMaker\Project\Bpmn * @param $data */ public function testRemoveActivity($bp, $data) @@ -180,8 +186,8 @@ class BpmnProjectTest extends PHPUnit_Framework_TestCase public function testGetActivities() { - // Create a new BpmnProject and save to DB - $bp = new BpmnProject(array( + // Create a new Project\Bpmn and save to DB + $bp = new Project\Bpmn(array( "PRJ_NAME" => "Test BPMN Project #2", "PRJ_DESCRIPTION" => "Description for - Test BPMN Project #1", "PRJ_AUTHOR" => "00000000000000000000000000000001" @@ -211,13 +217,13 @@ class BpmnProjectTest extends PHPUnit_Framework_TestCase /** * @depends testGetActivities - * @param $bp \ProcessMaker\Project\BpmnProject - * @return null|\ProcessMaker\Project\BpmnProject + * @param $bp \ProcessMaker\Project\Bpmn + * @return null|\ProcessMaker\Project\Bpmn */ public function testLoad($bp) { $prjUid = $bp->getUid(); - $bp2 = BpmnProject::load($prjUid); + $bp2 = Project\Bpmn::load($prjUid); $this->assertNotNull($bp2); $this->assertEquals($bp->getActivities(), $bp2->getActivities()); @@ -229,14 +235,16 @@ class BpmnProjectTest extends PHPUnit_Framework_TestCase /** * @depends testLoad - * @param $bp \ProcessMaker\Project\BpmnProject + * @param $bp \ProcessMaker\Project\Bpmn + * @expectedException \ProcessMaker\Exception\ProjectNotFound + * @expectedExceptionCode 20 */ public function testRemove($bp) { $prjUid = $bp->getUid(); $bp->remove(); - $this->assertNull(BpmnProject::load($prjUid)); + Project\Bpmn::load($prjUid); } } diff --git a/workflow/engine/src/Tests/ProcessMaker/WorkflowProjectTest.php b/workflow/engine/src/Tests/ProcessMaker/Project/WorkflowTest.php similarity index 85% rename from workflow/engine/src/Tests/ProcessMaker/WorkflowProjectTest.php rename to workflow/engine/src/Tests/ProcessMaker/Project/WorkflowTest.php index a3a5a12cd..4d144e229 100644 --- a/workflow/engine/src/Tests/ProcessMaker/WorkflowProjectTest.php +++ b/workflow/engine/src/Tests/ProcessMaker/Project/WorkflowTest.php @@ -1,19 +1,23 @@ workflowProject = new WorkflowProject(); + //cleaning DB + foreach (self::$proUids as $proUid) { + $wp = Project\Workflow::load($proUid); + $wp->remove(); + } } public function testCreate() @@ -25,9 +29,10 @@ class WorkflowProjectTest extends PHPUnit_Framework_TestCase "PRO_CREATE_USER" => "00000000000000000000000000000001" ); - $wp = new WorkflowProject($data); + $wp = new Project\Workflow($data); + self::$proUids[] = $wp->getUid(); - $processData = $wp->getProperties(); + $processData = $wp->getProcess(); foreach ($data as $key => $value) { $this->assertEquals($data[$key], $processData[$key]); @@ -149,11 +154,13 @@ class WorkflowProjectTest extends PHPUnit_Framework_TestCase */ public function testAddRoute() { - $wp = new WorkflowProject(array( + $wp = new Project\Workflow(array( "PRO_TITLE" => "Test Project #2 (Sequential)", "PRO_CREATE_USER" => "00000000000000000000000000000001" )); + self::$proUids[] = $wp->getUid(); + $tasUid1 = $wp->addTask(array( "TAS_TITLE" => "task #1", "TAS_POSX" => "410", @@ -176,10 +183,11 @@ class WorkflowProjectTest extends PHPUnit_Framework_TestCase public function testAddSelectRoute() { - $wp = new WorkflowProject(array( + $wp = new Project\Workflow(array( "PRO_TITLE" => "Test Project #3 (Select)", "PRO_CREATE_USER" => "00000000000000000000000000000001" )); + self::$proUids[] = $wp->getUid(); $tasUid1 = $wp->addTask(array( "TAS_TITLE" => "task #1", @@ -202,7 +210,7 @@ class WorkflowProjectTest extends PHPUnit_Framework_TestCase public function testCompleteWorkflowProject() { - $wp = new WorkflowProject(array( + $wp = new Project\Workflow(array( "PRO_TITLE" => "Test Complete Project #4", "PRO_CREATE_USER" => "00000000000000000000000000000001" )); @@ -253,5 +261,21 @@ class WorkflowProjectTest extends PHPUnit_Framework_TestCase $wp->setEndTask($tasUid4); $wp->setEndTask($tasUid6); + + return $wp; + } + + /** + * @depends testCompleteWorkflowProject + * @param $wp \ProcessMaker\Project\WorkflowProject + * @expectedException \ProcessMaker\Exception\ProjectNotFound + * @expectedExceptionCode 20 + */ + public function testRemove($wp) + { + $proUid = $wp->getUid(); + $wp->remove(); + + Project\Workflow::load($proUid); } } \ No newline at end of file