diff --git a/workflow/engine/classes/class.case.php b/workflow/engine/classes/class.case.php index 0cd4fccb4..c42634620 100644 --- a/workflow/engine/classes/class.case.php +++ b/workflow/engine/classes/class.case.php @@ -483,7 +483,6 @@ class Cases try { $oUser->load($oApp->getAppInitUser()); $uFields = $oUser->toArray(BasePeer::TYPE_FIELDNAME); - //$aFields['TITLE'] = $oApp->getAppTitle(); $aFields['TITLE'] = $aFields['APP_TITLE']; $aFields['DESCRIPTION'] = $aFields['APP_DESCRIPTION']; $aFields['CREATOR'] = $oUser->getUsrFirstname() . ' ' . $oUser->getUsrLastname(); @@ -514,6 +513,10 @@ class Cases $aFields['DEL_TASK_DUE_DATE'] = $aAppDel['DEL_TASK_DUE_DATE']; $aFields['DEL_FINISH_DATE'] = $aAppDel['DEL_FINISH_DATE']; $aFields['CURRENT_USER_UID'] = $aAppDel['USR_UID']; + + //Update the global variables + $aFields['TASK'] = $aAppDel['TAS_UID']; + $aFields['INDEX'] = $aAppDel['DEL_INDEX']; $aFields['PRO_ID'] = $aAppDel['PRO_ID']; try { $oCurUser = new Users(); diff --git a/workflow/engine/classes/class.pmDynaform.php b/workflow/engine/classes/class.pmDynaform.php index a3dc3f43d..500bb6be1 100644 --- a/workflow/engine/classes/class.pmDynaform.php +++ b/workflow/engine/classes/class.pmDynaform.php @@ -182,6 +182,7 @@ class pmDynaform if (empty($json)) { return; } + $dataGridEnvironment = []; foreach ($json as $key => &$value) { $sw1 = is_array($value); $sw2 = is_object($value); @@ -195,8 +196,7 @@ class pmDynaform $fn($json, $key, $value); } //set properties from trigger - $prefixs = self::$prefixs; - if (is_string($value) && in_array(substr($value, 0, 2), $prefixs)) { + if (is_string($value) && in_array(substr($value, 0, 2), self::$prefixs)) { $triggerValue = substr($value, 2); if (isset($this->fields["APP_DATA"][$triggerValue])) { if (!in_array($key, $this->propertiesToExclude)) { @@ -266,7 +266,9 @@ class pmDynaform if (!isset($json->queryField) && isset($dt[0]["base_expr"])) { $col = $dt[0]["base_expr"]; $dv = str_replace("'", "''", $json->defaultValue); - $where = $isWhere ? "WHERE " . $col . "='" . $dv . "'" : $where . " AND " . $col . "='" . $dv . "'"; + if ($dv !== "") { + $where = $isWhere ? "WHERE " . $col . "='" . $dv . "'" : $where . " AND " . $col . "='" . $dv . "'"; + } } if (isset($json->queryField) && isset($dt[0]["base_expr"])) { $col = isset($dt[1]["base_expr"]) ? $dt[1]["base_expr"] : $dt[0]["base_expr"]; @@ -575,6 +577,17 @@ class pmDynaform $json->inputDocuments = array($row["INP_DOC_UID"]); } } + if ($key === "type" && ($value === "multipleFile")) { + $json->data = new stdClass(); + $json->data->value = ""; + $json->data->label = ""; + if (isset($this->fields["APP_DATA"][$json->name])) { + $json->data->value = $this->fields["APP_DATA"][$json->name]; + } + if (isset($this->fields["APP_DATA"][$json->name . "_label"])) { + $json->data->label = $this->fields["APP_DATA"][$json->name . "_label"]; + } + } //synchronize var_label if ($key === "type" && ($value === "dropdown" || $value === "suggest" || $value === "radio")) { if (isset($this->fields["APP_DATA"]["__VAR_CHANGED__"]) && in_array($json->name, explode(",", $this->fields["APP_DATA"]["__VAR_CHANGED__"]))) { @@ -632,6 +645,42 @@ class pmDynaform } //grid if ($key === "type" && ($value === "grid")) { + $columnsDataVariable = []; + //todo compatibility 'columnWidth' + foreach ($json->columns as $column) { + if (!isset($column->columnWidth) && $column->type !== "hidden") { + $json->layout = "static"; + $column->columnWidth = ""; + } + $column->parentIsGrid = true; + //save dataVariable value, only for columns control + if (!empty($column->dataVariable) && is_string($column->dataVariable)) { + if (in_array(substr($column->dataVariable, 0, 2), self::$prefixs)) { + $dataVariableValue = substr($column->dataVariable, 2); + if (!in_array($dataVariableValue, $columnsDataVariable)) { + $columnsDataVariable[] = $dataVariableValue; + } + } + } + } + //data grid environment + $json->dataGridEnvironment = "onDataGridEnvironment"; + if (isset($this->fields["APP_DATA"])) { + $dataGridEnvironment = $this->fields["APP_DATA"]; + $this->fields["APP_DATA"] = []; + //restore AppData with dataVariable definition, only for columns control + foreach ($columnsDataVariable as $dge) { + if (isset($dataGridEnvironment[$dge])) { + $this->fields["APP_DATA"][$dge] = $dataGridEnvironment[$dge]; + } + } + } + } + if ($key === "dataGridEnvironment" && ($value === "onDataGridEnvironment")) { + if (isset($this->fields["APP_DATA"])) { + $this->fields["APP_DATA"] = $dataGridEnvironment; + $dataGridEnvironment = []; + } if (isset($this->fields["APP_DATA"][$json->name])) { //rows $rows = $this->fields["APP_DATA"][$json->name]; @@ -640,7 +689,7 @@ class pmDynaform $cells = array(); foreach ($json->columns as $column) { //data - if ($column->type === "text" || $column->type === "textarea" || $column->type === "dropdown" || $column->type === "suggest" || $column->type === "datetime" || $column->type === "checkbox" || $column->type === "file" || $column->type === "link" || $column->type === "hidden") { + if ($column->type === "text" || $column->type === "textarea" || $column->type === "dropdown" || $column->type === "suggest" || $column->type === "datetime" || $column->type === "checkbox" || $column->type === "file" || $column->type === "multipleFile" || $column->type === "link" || $column->type === "hidden") { array_push($cells, array( "value" => isset($row[$column->name]) ? $row[$column->name] : "", "label" => isset($row[$column->name . "_label"]) ? $row[$column->name . "_label"] : (isset($row[$column->name]) ? $row[$column->name] : "") @@ -652,13 +701,6 @@ class pmDynaform $json->rows = count($rows); $json->data = $rows; } - //todo compatibility 'columnWidth' - foreach ($json->columns as $column) { - if (!isset($column->columnWidth) && $column->type !== "hidden") { - $json->layout = "static"; - $column->columnWidth = ""; - } - } } //languages if ($this->lang === null && $key === "language" && isset($json->language)) { @@ -708,9 +750,9 @@ class pmDynaform } $data = array(); if (isset($json->dbConnection) && isset($json->sql)) { - $salida = array(); - preg_match_all('/\@(?:([\@\%\#\=\!Qq])([a-zA-Z\_]\w*)|([a-zA-Z\_][\w\-\>\:]*)\(((?:[^\\\\\)]*?)*)\))/', $json->sql, $salida, PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE); - $variables = isset($salida[2]) ? $salida[2] : array(); + $result = array(); + preg_match_all('/\@(?:([\@\%\#\=\!Qq])([a-zA-Z\_]\w*)|([a-zA-Z\_][\w\-\>\:]*)\(((?:[^\\\\\)]*?)*)\))/', $json->sql, $result, PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE); + $variables = isset($result[2]) ? $result[2] : array(); foreach ($variables as $key => $value) { $jsonSearch = $this->jsonsf(G::json_decode($this->record["DYN_CONTENT"]), $value[0], $json->variable === "" ? "id" : "variable"); $a = $this->getValuesDependentFields($jsonSearch); @@ -719,8 +761,15 @@ class pmDynaform } } if ($json->dbConnection !== "" && $json->dbConnection !== "none" && $json->sql !== "") { - $a = G::replaceDataField($json->sql, $data); - $dt = $this->getCacheQueryData($json->dbConnection, $a, $json->type); + if (isset($this->fields["APP_DATA"])) { + foreach ($this->fields["APP_DATA"] as $keyA => $valueA) { + if (!isset($data[$keyA]) && !is_array($valueA)) { + $data[$keyA] = $valueA; + } + } + } + $sql = G::replaceDataField($json->sql, $data); + $dt = $this->getCacheQueryData($json->dbConnection, $sql, $json->type); $row = isset($dt[0]) ? $dt[0] : []; if (isset($row[0]) && $json->type !== "suggest" && $json->type !== "radio") { $data[$json->variable === "" ? $json->id : $json->variable] = $row[0]; @@ -2117,4 +2166,45 @@ class pmDynaform return defined("LEAVE_CASE_WARNING") ? LEAVE_CASE_WARNING : 0; } + /** + * Unset a json property from the following controls: text, textarea, dropdown, + * checkbox, checkgroup, radio, datetime, suggest, hidden, file, grid. + * @param stdClass $json + * @param string $property + * @return void + */ + public function jsonUnsetProperty(&$json, $property) + { + if (empty($json)) { + return; + } + foreach ($json as $key => &$value) { + $sw1 = is_array($value); + $sw2 = is_object($value); + if ($sw1 || $sw2) { + $this->jsonUnsetProperty($value, $property); + } + if (!$sw1 && !$sw2) { + if ($key === "type" && ( + $value === "text" || + $value === "textarea" || + $value === "dropdown" || + $value === "checkbox" || + $value === "checkgroup" || + $value === "radio" || + $value === "datetime" || + $value === "suggest" || + $value === "hidden" || + $value === "file" || + $value === "grid")) { + if ($value === "grid" && $property === "data") { + $json->{$property} = []; + } else { + unset($json->{$property}); + } + } + } + } + } + } diff --git a/workflow/engine/src/ProcessMaker/BusinessModel/Cases.php b/workflow/engine/src/ProcessMaker/BusinessModel/Cases.php index 8f71c8518..d75a6667d 100644 --- a/workflow/engine/src/ProcessMaker/BusinessModel/Cases.php +++ b/workflow/engine/src/ProcessMaker/BusinessModel/Cases.php @@ -3311,6 +3311,42 @@ class Cases return $arrayAccess; } + + + /** + * Get Global System Variables + * @param array $appData + * @param array $dataVariable + * @return array + * @throws \Exception + */ + public static function getGlobalVariables($appData = array(), $dataVariable = array()) + { + $appData = array_change_key_case($appData, CASE_UPPER); + $dataVariable = array_change_key_case($dataVariable, CASE_UPPER); + + if (!isset($dataVariable['APPLICATION']) || empty($dataVariable['APPLICATION'])) { + $dataVariable['APPLICATION'] = (isset($dataVariable['APP_UID']) && $dataVariable['APP_UID'] != '') ? $dataVariable['APP_UID'] : $appData['APPLICATION']; + } + if (!isset($dataVariable['PROCESS']) || empty($dataVariable['PROCESS'])) { + $dataVariable['PROCESS'] = (isset($dataVariable['PRO_UID']) && $dataVariable['PRO_UID'] != '') ? $dataVariable['PRO_UID'] : $appData['PROCESS']; + } + if (isset($appData['TASK']) && !empty($appData['TASK'])) { + $dataVariable['TASK'] = $appData['TASK']; + } + if (isset($appData['INDEX']) && !empty($appData['INDEX'])) { + $dataVariable['INDEX'] = $appData['INDEX']; + } + $dataVariable['USER_LOGGED'] = \ProcessMaker\Services\OAuth2\Server::getUserId(); + if (isset($dataVariable['USER_LOGGED']) && !empty($dataVariable['USER_LOGGED'])) { + $oUserLogged = new \Users(); + $oUserLogged->load($dataVariable['USER_LOGGED']); + $dataVariable['USR_USERNAME'] = $oUserLogged->getUsrUsername(); + } + + return $dataVariable; + } + /** * Get index last participation from a user * diff --git a/workflow/engine/src/ProcessMaker/BusinessModel/Variable.php b/workflow/engine/src/ProcessMaker/BusinessModel/Variable.php index 5c2a08274..b30cbb274 100644 --- a/workflow/engine/src/ProcessMaker/BusinessModel/Variable.php +++ b/workflow/engine/src/ProcessMaker/BusinessModel/Variable.php @@ -552,44 +552,7 @@ class Variable public function executeSql($processUid, $variableName, array $arrayVariable = array()) { try { - $arrayRecord = array(); - - //Verify data - $process = new \ProcessMaker\BusinessModel\Process(); - - $process->throwExceptionIfNotExistsProcess($processUid, strtolower("PRJ_UID")); - - //Set data - \G::LoadClass('pmDynaform'); - $pmDynaform = new \pmDynaform(); - $field = $pmDynaform->searchField($arrayVariable["dyn_uid"], $arrayVariable["field_id"], $processUid); - $dbConnection = "workflow"; - if ($field !== null && !empty($field->dbConnection)) { - $dbConnection = $field->dbConnection; - } - $variableSql = $field !== null ? $field->sql : ""; - - //Get data - $_SESSION["PROCESS"] = $processUid; - - $cnn = \Propel::getConnection($dbConnection); - $stmt = $cnn->createStatement(); - - $replaceFields = G::replaceDataField($variableSql, $arrayVariable); - - $rs = $stmt->executeQuery($replaceFields, \ResultSet::FETCHMODE_NUM); - - while ($rs->next()) { - $row = $rs->getRow(); - - $arrayRecord[] = array( - strtolower("VALUE") => $row[0], - strtolower("TEXT") => isset($row[1]) ? $row[1] : $row[0] - ); - } - - //Return - return $arrayRecord; + return $this->executeSqlControl($processUid, $arrayVariable); } catch (\Exception $e) { throw $e; } @@ -710,31 +673,7 @@ class Variable public function executeSqlSuggest($processUid, $variableName, array $arrayVariable = array()) { try { - $appData = array(); - if (isset($arrayVariable['app_uid'])) { - $case = new \ProcessMaker\BusinessModel\Cases(); - $fields = $case->getApplicationRecordByPk($arrayVariable['app_uid'], ['$applicationUid' => 'app_uid']); - $case = new \Cases(); - $appData = $case->unserializeData($fields['APP_DATA']); - } - $_SESSION["PROCESS"] = $processUid; - \G::LoadClass("pmDynaform"); - $pmDynaform = new \pmDynaform(array("APP_DATA" => $appData)); - $field = $pmDynaform->searchField($arrayVariable["dyn_uid"], $arrayVariable["field_id"], $processUid); - $field->queryField = true; - $field->queryInputData = $arrayVariable; - $field->queryFilter = isset($arrayVariable["filter"]) ? $arrayVariable["filter"] : ""; - $field->queryStart = isset($arrayVariable["start"]) ? $arrayVariable["start"] : 0; - $field->queryLimit = isset($arrayVariable["limit"]) ? $arrayVariable["limit"] : 10; - $pmDynaform->jsonr($field); - - $result = array(); - if (isset($field->queryOutputData) && is_array($field->queryOutputData)) { - foreach ($field->queryOutputData as $item) { - $result[] = ["value" => $item->value, "text" => $item->label]; - } - } - return $result; + return $this->executeSqlControl($processUid, $arrayVariable); } catch (\Exception $e) { throw $e; } @@ -818,4 +757,82 @@ class Variable } return $vType; } + + /** + * Executes the sql string of a control and returns the data in the queryOutputData + * property of the control. The control returned by the pmDynaform :: searchField + * function is the php representation of the json definition, which can be + * supported by the pmDynaform :: jsonr function. + * The params parameter must contain: dyn_uid, field_id and optionally + * app_uid, del_index, filter, start, limit, and so many related control variables + * to be sent and their corresponding value. + * The parameters: filter, start and limit, are only necessary for the suggest + * control. + * If app_uid is not sent you can not get the appData in an environment where + * only endPoint is used, it is always advisable to send the app_uid and _index. + * Note: You do not get triguer execution values where only endPoint is used. + * @param type $proUid + * @param array $params + * @return array + * @throws \Exception + */ + public function executeSqlControl($proUid, array $params = array()) + { + try { + //Get and clear vector data that does not correspond to variables + //related to a control. + $dynUid = $params["dyn_uid"]; + $fieldId = $params["field_id"]; + $filter = isset($params["filter"]) ? $params["filter"] : ""; + $start = isset($params["start"]) ? $params["start"] : 0; + $limit = isset($params["limit"]) ? $params["limit"] : 10; + $appUid = empty($params["app_uid"]) ? null : $params["app_uid"]; + $delIndex = (int) isset($params["del_index"]) ? $params["del_index"] : 0; + unset($params["dyn_uid"]); + unset($params["field_id"]); + unset($params["app_uid"]); + unset($params["del_index"]); + unset($params["filter"]); + unset($params["start"]); + unset($params["limit"]); + + //Get appData and system variables + if ($appUid !== null) { + $case = new \Cases(); + $fields = $case->loadCase($appUid, $delIndex); + $appData = $fields["APP_DATA"]; + $appData = array_merge($appData, \ProcessMaker\BusinessModel\Cases::getGlobalVariables($appData)); + $params = array_merge($appData, $params); + } + + //This value is required to be able to query the database. + $_SESSION["PROCESS"] = $proUid; + //The pmdynaform class is instantiated + \G::LoadClass("pmDynaform"); + $pmDynaform = new \pmDynaform(array("APP_DATA" => $params)); + + //Get control from dynaform. + //The parameters: queryFilter, queryStart, queryLimit, are only necessary + //for the suggest control, the rest of the controls are ignored. + $field = $pmDynaform->searchField($dynUid, $fieldId, $proUid); + $field->queryField = true; + $field->queryInputData = $params; + $field->queryFilter = $filter; + $field->queryStart = $start; + $field->queryLimit = $limit; + + //Populate control data + $pmDynaform->jsonr($field); + $result = array(); + if (isset($field->queryOutputData) && is_array($field->queryOutputData)) { + foreach ($field->queryOutputData as $item) { + $result[] = ["value" => $item->value, "text" => $item->label]; + } + } + return $result; + } catch (\Exception $e) { + throw $e; + } + } + } diff --git a/workflow/engine/src/ProcessMaker/Services/Api/Light.php b/workflow/engine/src/ProcessMaker/Services/Api/Light.php index 37ab326a2..cb7f0f76d 100644 --- a/workflow/engine/src/ProcessMaker/Services/Api/Light.php +++ b/workflow/engine/src/ProcessMaker/Services/Api/Light.php @@ -970,6 +970,40 @@ class Light extends Api return $response; } + /** + * @url GET /project/:prj_uid/dynaformprocessed/:dyn_uid + * + * @param string $dyn_uid {@min 32}{@max 32} + * @param string $prj_uid {@min 32}{@max 32} + */ + public function doGetDynaformProcessed($prj_uid, $dyn_uid, $app_uid = null, $del_index = 0) + { + try { + $dynaForm = new \ProcessMaker\BusinessModel\DynaForm(); + $dynaForm->setFormatFieldNameInUppercase(false); + $_SESSION['PROCESS'] = $prj_uid; + $response = $dynaForm->getDynaForm($dyn_uid); + $result = $this->parserDataDynaForm($response); + $result['formContent'] = (isset($result['formContent']) && $result['formContent'] != null) ? + \G::json_decode($result['formContent']) : ""; + + $caseVariables = array(); + if (!is_null($app_uid)) { + $case = new \Cases(); + $fields = $case->loadCase($app_uid, $del_index); + $caseVariables = array_merge($fields['APP_DATA'], + \ProcessMaker\BusinessModel\Cases::getGlobalVariables($fields['APP_DATA'])); + } + + \G::LoadClass("pmDynaform"); + $pmDynaform = new \pmDynaform(array("APP_DATA" => $caseVariables, "CURRENT_DYNAFORM" => $dyn_uid)); + $pmDynaform->jsonr($result['formContent']); + return $result; + } catch (\Exception $e) { + throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); + } + } + /** * @url GET /project/:prj_uid/dynaform/:dyn_uid *