diff --git a/workflow/engine/classes/model/BpmnData.php b/workflow/engine/classes/model/BpmnData.php index 9ddcc5bef..d64d88b50 100644 --- a/workflow/engine/classes/model/BpmnData.php +++ b/workflow/engine/classes/model/BpmnData.php @@ -14,6 +14,163 @@ require_once 'classes/model/om/BaseBpmnData.php'; * * @package classes.model */ -class BpmnData extends BaseBpmnData { +class BpmnData extends BaseBpmnData +{ + private $bound; + public function __construct($generateUid = true) + { + $this->bound = new BpmnBound(); + $this->setBoundDefaults(); + } + + public function getBound() + { + return $this->bound; + } + + private function setBoundDefaults() + { + $this->bound->setBouElementType(lcfirst(str_replace(__NAMESPACE__, '', __CLASS__))); + $this->bound->setBouElement('pm_canvas'); + $this->bound->setBouContainer('bpmnDiagram'); + + $this->bound->setPrjUid($this->getPrjUid()); + $this->bound->setElementUid($this->getDatUid()); + + $process = BpmnProcessPeer::retrieveByPK($this->getProUid()); + + if (is_object($process)) { + $this->bound->setDiaUid($process->getDiaUid()); + } + } + + public static function findOneBy($field, $value) + { + $rows = self::findAllBy($field, $value); + + return empty($rows) ? null : $rows[0]; + } + + public static function findAllBy($field, $value) + { + $c = new Criteria('workflow'); + $c->add($field, $value, Criteria::EQUAL); + + return BpmnDataPeer::doSelect($c); + } + + public static function getAll($prjUid = null, $start = null, $limit = null, $filter = '', $changeCaseTo = CASE_UPPER) + { + $c = new Criteria('workflow'); + $c->addSelectColumn("BPMN_DATA.*"); + $c->addSelectColumn("BPMN_BOUND.*"); + $c->addJoin(BpmnDataPeer::DAT_UID, BpmnBoundPeer::ELEMENT_UID, Criteria::LEFT_JOIN); + + if (! is_null($prjUid)) { + $c->add(BpmnDataPeer::PRJ_UID, $prjUid, Criteria::EQUAL); + } + + $rs = BpmnDataPeer::doSelectRS($c); + $rs->setFetchmode(\ResultSet::FETCHMODE_ASSOC); + + $data = array(); + + while ($rs->next()) { + $data[] = $changeCaseTo !== CASE_UPPER ? array_change_key_case($rs->getRow(), CASE_LOWER) : $rs->getRow(); + } + + return $data; + } + + // OVERRIDES + + public function setDatUid($DatUid) + { + parent::setDatUid($DatUid); + $this->bound->setElementUid($this->getDatUid()); + } + + public function setPrjUid($prjUid) + { + parent::setPrjUid($prjUid); + $this->bound->setPrjUid($this->getPrjUid()); + } + + public function setProUid($proUid) + { + parent::setProUid($proUid); + + $process = BpmnProcessPeer::retrieveByPK($this->getProUid()); + $this->bound->setDiaUid($process->getDiaUid()); + } + + public function save($con = null) + { + parent::save($con); + + $this->setBoundDefaults(); + + if ($this->bound->getBouUid() == "") { + $this->bound->setBouUid(\ProcessMaker\Util\Common::generateUID()); + } + + $this->bound->save($con); + } + + public function delete($con = null) + { + // first, delete the related bound object + if (! is_object($this->bound) || $this->bound->getBouUid() == "") { + $this->bound = BpmnBound::findByElement('Data', $this->getDatUid()); + } + + if (is_object($this->bound)) { + $this->bound->delete($con); + } + + parent::delete($con); + } + + public function fromArray($data, $type = BasePeer::TYPE_FIELDNAME) + { + parent::fromArray($data, $type); + + $bound = BpmnBound::findByElement('Data', $this->getDatUid()); + + if (is_object($bound)) { + $this->bound = $bound; + } else { + $this->bound = new BpmnBound(); + $this->bound->setBouUid(ProcessMaker\Util\Common::generateUID()); + } + + $this->bound->fromArray($data, BasePeer::TYPE_FIELDNAME); + } + + public function toArray($type = BasePeer::TYPE_FIELDNAME) + { + $data = parent::toArray($type); + $bouUid = $this->bound->getBouUid(); + + if (empty($bouUid)) { + $bound = BpmnBound::findByElement('Data', $this->getDatUid()); + + if (is_object($bound)) { + $this->bound = $bound; + } + } + + $data = array_merge($data, $this->bound->toArray($type)); + + return $data; + } + + public static function exists($DatUid) + { + $c = new Criteria("workflow"); + $c->add(BpmnDataPeer::DAT_UID, $DatUid); + + return BpmnDataPeer::doCount($c) > 0 ? true : false; + } } // BpmnData diff --git a/workflow/engine/src/ProcessMaker/Project/Adapter/BpmnWorkflow.php b/workflow/engine/src/ProcessMaker/Project/Adapter/BpmnWorkflow.php index 638f61040..6dbdb462b 100644 --- a/workflow/engine/src/ProcessMaker/Project/Adapter/BpmnWorkflow.php +++ b/workflow/engine/src/ProcessMaker/Project/Adapter/BpmnWorkflow.php @@ -672,6 +672,7 @@ class BpmnWorkflow extends Project\Bpmn $diagram["artifacts"] = $bwp->getArtifacts($configList); $diagram["laneset"] = $bwp->getLanesets($configList); $diagram["lanes"] = $bwp->getLanes($configList); + $diagram["data"] = $bwp->getDataCollection($configList); $project["diagrams"][] = $diagram; } @@ -862,6 +863,7 @@ class BpmnWorkflow extends Project\Bpmn $bwp->removeGateway($gatewayData["GAT_UID"]); } } + /* * Diagram's Events Handling */ @@ -914,6 +916,52 @@ class BpmnWorkflow extends Project\Bpmn } } + /* + * Diagram's Data Handling + */ + $whiteList = array(); + foreach ($diagram["data"] as $i => $dataObjectData) { + $dataObjectData = array_change_key_case($dataObjectData, CASE_UPPER); + unset($dataObjectData["_EXTENDED"]); + + $dataObject = $bwp->getData($dataObjectData["DAT_UID"]); + + if ($forceInsert || is_null($dataObject)) { + if ($generateUid) { + //Event + unset($dataObjectData["BOU_UID"]); + + $uidOld = $dataObjectData["DAT_UID"]; + $dataObjectData["DAT_UID"] = Util\Common::generateUID(); + + $result[] = array( + "object" => "data", + "old_uid" => $uidOld, + "new_uid" => $dataObjectData["DAT_UID"] + ); + } + + $bwp->addData($dataObjectData); + } elseif (! $bwp->isEquals($dataObject, $dataObjectData)) { + $bwp->updateData($dataObjectData["DAT_UID"], $dataObjectData); + } else { + Util\Logger::log("Update Data ({$dataObjectData["DAT_UID"]}) Skipped - No changes required"); + } + + $diagram["data"][$i] = $dataObjectData; + $whiteList[] = $dataObjectData["DAT_UID"]; + } + + $dataCollection = $bwp->getDataCollection(); + + // looking for removed elements + foreach ($dataCollection as $dataObjectData) { + if (! in_array($dataObjectData["DAT_UID"], $whiteList)) { + // If it is not in the white list, then remove them + $bwp->removeData($dataObjectData["DAT_UID"]); + } + } + /* * Diagram's Flows Handling diff --git a/workflow/engine/src/ProcessMaker/Project/Bpmn.php b/workflow/engine/src/ProcessMaker/Project/Bpmn.php index f3da8e4ce..bd509d72e 100644 --- a/workflow/engine/src/ProcessMaker/Project/Bpmn.php +++ b/workflow/engine/src/ProcessMaker/Project/Bpmn.php @@ -71,7 +71,8 @@ class Bpmn extends Handler "PRJ_UID", "PRO_UID", "BOU_ELEMENT", "BOU_ELEMENT_TYPE", "BOU_REL_POSITION", "BOU_SIZE_IDENTICAL", "DIA_UID", "BOU_UID", "ELEMENT_UID" ), - "flow" => array("PRJ_UID", "DIA_UID", "FLO_ELEMENT_DEST_PORT", "FLO_ELEMENT_ORIGIN_PORT") + "flow" => array("PRJ_UID", "DIA_UID", "FLO_ELEMENT_DEST_PORT", "FLO_ELEMENT_ORIGIN_PORT"), + "data" => array("PRJ_UID"), ); @@ -788,6 +789,89 @@ class Bpmn extends Handler } } + //////1111 + public function addData($data) + { + // setting defaults + $data['DATA_UID'] = array_key_exists('DAT_UID', $data) ? $data['DAT_UID'] : Common::generateUID(); + try { + self::log("Add BpmnData with data: ", $data); + $bpmnData = new \BpmnData(); + $bpmnData->fromArray($data, BasePeer::TYPE_FIELDNAME); + $bpmnData->setPrjUid($this->getUid()); + $bpmnData->setProUid($this->getProcess("object")->getProUid()); + $bpmnData->save(); + self::log("Add BpmnData Success!"); + } catch (\Exception $e) { + self::log("Exception: ", $e->getMessage(), "Trace: ", $e->getTraceAsString()); + throw $e; + } + + return $bpmnData->getDatUid(); + } + + public function updateData($datUid, $data) + { + try { + self::log("Update BpmnData: $datUid", "With data: ", $data); + + $bpmnData = ArtifactPeer::retrieveByPk($datUid); + + $bpmnData->fromArray($data); + $bpmnData->save(); + + self::log("Update BpmnData Success!"); + } catch (\Exception $e) { + self::log("Exception: ", $e->getMessage(), "Trace: ", $e->getTraceAsString()); + throw $e; + } + } + + public function getData($datUid, $retType = 'array') + { + $bpmnData = ArtifactPeer::retrieveByPK($datUid); + + if ($retType != "object" && ! empty($bpmnData)) { + $bpmnData = $bpmnData->toArray(); + $bpmnData = self::filterArrayKeys($bpmnData, self::$excludeFields["data"]); + } + + return $bpmnData; + } + + public function getDataCollection($start = null, $limit = null, $filter = '', $changeCaseTo = CASE_UPPER) + { + if (is_array($start)) { + extract($start); + } + + $filter = $changeCaseTo != CASE_UPPER ? array_map("strtolower", self::$excludeFields["data"]) : self::$excludeFields["data"]; + + return self::filterCollectionArrayKeys( + \BpmnData::getAll($this->getUid(), $start, $limit, $filter, $changeCaseTo), + $filter + ); + } + + public function removeData($datUid) + { + try { + self::log("Remove BpmnData: $datUid"); + + $bpmnData = \BpmnDataPeer::retrieveByPK($datUid); + $bpmnData->delete(); + + // remove related object (flows) + Flow::removeAllRelated($datUid); + + self::log("Remove BpmnData Success!"); + } catch (\Exception $e) { + self::log("Exception: ", $e->getMessage(), "Trace: ", $e->getTraceAsString()); + throw $e; + } + } + //////2222 + public function addLane($data) { // TODO: Implement update() method.