diff --git a/workflow/engine/classes/Cases.php b/workflow/engine/classes/Cases.php index deba3d144..85f17b524 100644 --- a/workflow/engine/classes/Cases.php +++ b/workflow/engine/classes/Cases.php @@ -3541,19 +3541,19 @@ class Cases */ if ($oPMScript->executedOn() === $oPMScript::AFTER_ROUTING) { //Get the variables changed with the trigger - $fieldsTrigger = arrayDiffRecursive($appDataAfterTrigger, $fieldsCase); + $fieldsTrigger = getDiffBetweenModifiedVariables($appDataAfterTrigger, $fieldsCase); + $collection = collect($fieldsCase); + $merged = $collection->merge($fieldsTrigger); + //Merge the appData with variables changed + $fieldsCase = $merged->all(); //We will be load the last appData because: //Other thread execution can be changed the variables $appUid = !empty($fieldsCase['APPLICATION']) ? $fieldsCase['APPLICATION'] : ''; - //Save the fields changed in the trigger if (!$varInAfterRouting && !empty($fieldsTrigger)) { $varInAfterRouting = true; } - - //Merge the appData with variables changed - $fieldsCase = array_merge($fieldsCase, $fieldsTrigger); } else { $fieldsCase = $appDataAfterTrigger; } diff --git a/workflow/engine/classes/PmDynaform.php b/workflow/engine/classes/PmDynaform.php index 4169c3a10..0cb611a06 100644 --- a/workflow/engine/classes/PmDynaform.php +++ b/workflow/engine/classes/PmDynaform.php @@ -1132,23 +1132,7 @@ class PmDynaform if (!isset($this->fields["APP_DATA"]["__DYNAFORM_OPTIONS"]["PREVIOUS_STEP"])) { $this->fields["APP_DATA"]["__DYNAFORM_OPTIONS"]["PREVIOUS_STEP"] = ""; } - $msg = ""; - if (isset($_SESSION['G_MESSAGE_TYPE']) && isset($_SESSION['G_MESSAGE'])) { - $color = "green"; - if ($_SESSION['G_MESSAGE_TYPE'] === "ERROR") { - $color = "red"; - } - if ($_SESSION['G_MESSAGE_TYPE'] === "WARNING") { - $color = "#C3C380"; - } - if ($_SESSION['G_MESSAGE_TYPE'] === "INFO") { - $color = "green"; - } - $msg = "
" . $_SESSION['G_MESSAGE_TYPE'] . ": " . $_SESSION['G_MESSAGE'] . "
"; - unset($_SESSION['G_MESSAGE_TYPE']); - unset($_SESSION['G_MESSAGE']); - } - $title = $msg . + $title = $this->getSessionMessage() . "\n" . " \n" . " \n" . @@ -1199,19 +1183,8 @@ class PmDynaform public function printEditSupervisor() { ob_clean(); - $json = G::json_decode($this->record["DYN_CONTENT"]); $this->jsonr($json); - - $msg = ""; - - if (isset($_SESSION["G_MESSAGE_TYPE"]) && isset($_SESSION["G_MESSAGE"])) { - $msg = "
" . G::LoadTranslation("ID_INFO") . ": " . $_SESSION["G_MESSAGE"] . "
"; - - unset($_SESSION["G_MESSAGE_TYPE"]); - unset($_SESSION["G_MESSAGE"]); - } - $javascrip = " - -
- $msg + " . $this->getSessionMessageForSupervisor() . "
@@ -1323,6 +1294,7 @@ class PmDynaform $this->getTheStringVariableForGoogleMaps() . "\n" . "\n" . "\n" . + $this->getSessionMessage() . "
\n" . " \n" . " \n" . @@ -2238,4 +2210,53 @@ class PmDynaform $result = 'var googleMaps = ' . G::json_encode($googleMaps) . ';'; return $result; } + + /** + * Get session message. + * + * @return string + * + * @see PmDynaform->printEdit() + * @see PmDynaform->printABE() + * @link https://wiki.processmaker.com/3.1/Multiple_File_Uploader#File_Extensions + */ + public function getSessionMessage() + { + $message = ""; + if (isset($_SESSION['G_MESSAGE_TYPE']) && isset($_SESSION['G_MESSAGE'])) { + $color = "green"; + if ($_SESSION['G_MESSAGE_TYPE'] === "ERROR") { + $color = "red"; + } + if ($_SESSION['G_MESSAGE_TYPE'] === "WARNING") { + $color = "#C3C380"; + } + if ($_SESSION['G_MESSAGE_TYPE'] === "INFO") { + $color = "green"; + } + $message = "
" . $_SESSION['G_MESSAGE_TYPE'] . ": " . $_SESSION['G_MESSAGE'] . "
"; + unset($_SESSION['G_MESSAGE_TYPE']); + unset($_SESSION['G_MESSAGE']); + } + return $message; + } + + /** + * Get session message for supervisor. + * + * @return string + * + * @see PmDynaform->printEditSupervisor(); + * @link https://wiki.processmaker.com/3.1/Multiple_File_Uploader#File_Extensions + */ + public function getSessionMessageForSupervisor() + { + $message = ""; + if (isset($_SESSION["G_MESSAGE_TYPE"]) && isset($_SESSION["G_MESSAGE"])) { + $message = "
" . G::LoadTranslation("ID_INFO") . ": " . $_SESSION["G_MESSAGE"] . "
"; + unset($_SESSION["G_MESSAGE_TYPE"]); + unset($_SESSION["G_MESSAGE"]); + } + return $message; + } } diff --git a/workflow/engine/classes/PmTable.php b/workflow/engine/classes/PmTable.php index b6e7eb075..11a1e7490 100644 --- a/workflow/engine/classes/PmTable.php +++ b/workflow/engine/classes/PmTable.php @@ -1006,4 +1006,24 @@ class PmTable } return $oCriteria; } + + /** + * Get the type of the column ex: string, int, double, boolean + * + * @param string $pmTablePeer + * @param string $tableName + * @param string $columnName + * + * @return string + */ + public static function getTypeOfColumn($pmTablePeer, $tableName, $columnName) + { + try { + $type = $pmTablePeer::getMapBuilder()->getDatabaseMap()->getTable($tableName)->getColumn($columnName)->getCreoleType(); + } catch (Exception $e) { + return ''; + } + + return $type; + } } diff --git a/workflow/engine/methods/cases/cases_SaveData.php b/workflow/engine/methods/cases/cases_SaveData.php index a218bd604..fe69df0c2 100644 --- a/workflow/engine/methods/cases/cases_SaveData.php +++ b/workflow/engine/methods/cases/cases_SaveData.php @@ -50,12 +50,18 @@ if (!isset($_SESSION['USER_LOGGED'])) { } } -ValidationUploadedFiles::getValidationUploadedFiles()->dispatch(function($validator) { +/** + * To do: The following evaluation must be moved after saving the data (so as not to lose the data entered in the form). + * It only remains because it is an old behavior, which must be defined by "Product Owner". + * @see workflow/engine/methods/services/ActionsByEmailDataFormPost.php + */ +$validator = ValidationUploadedFiles::getValidationUploadedFiles()->runRulesForFileEmpty(); +if ($validator->fails()) { G::SendMessageText($validator->getMessage(), "ERROR"); $url = explode("sys" . config("system.workspace"), $_SERVER['HTTP_REFERER']); G::header("location: " . "/sys" . config("system.workspace") . $url[1]); die(); -}); +} try { if ($_GET['APP_UID'] !== $_SESSION['APPLICATION']) { diff --git a/workflow/engine/methods/services/ActionsByEmailDataFormPost.php b/workflow/engine/methods/services/ActionsByEmailDataFormPost.php index 1b0c83c09..32198a3d8 100644 --- a/workflow/engine/methods/services/ActionsByEmailDataFormPost.php +++ b/workflow/engine/methods/services/ActionsByEmailDataFormPost.php @@ -5,11 +5,26 @@ * @link https://wiki.processmaker.com/3.3/Actions_by_Email#Link_to_Fill_a_Form */ -use ProcessMaker\ChangeLog\ChangeLog; use ProcessMaker\BusinessModel\Cases\InputDocument; +use ProcessMaker\ChangeLog\ChangeLog; +use ProcessMaker\Validation\ValidationUploadedFiles; if (PMLicensedFeatures::getSingleton() ->verifyfeature('zLhSk5TeEQrNFI2RXFEVktyUGpnczV1WEJNWVp6cjYxbTU3R29mVXVZNWhZQT0=')) { + + /** + * To do: The following evaluation must be moved after saving the data (so as not to lose the data entered in the form). + * It only remains because it is an old behavior, which must be defined by "Product Owner". + * @see workflow/engine/methods/cases/cases_SaveData.php + */ + $validator = ValidationUploadedFiles::getValidationUploadedFiles()->runRulesForFileEmpty(); + if ($validator->fails()) { + G::SendMessageText($validator->getMessage(), "ERROR"); + $url = explode("sys" . config("system.workspace"), $_SERVER['HTTP_REFERER']); + G::header("location: " . "/sys" . config("system.workspace") . $url[1]); + die(); + } + $G_PUBLISH = new Publisher(); try { diff --git a/workflow/engine/src/ProcessMaker/BusinessModel/Cases.php b/workflow/engine/src/ProcessMaker/BusinessModel/Cases.php index 4532b0f69..d0aa34cb7 100644 --- a/workflow/engine/src/ProcessMaker/BusinessModel/Cases.php +++ b/workflow/engine/src/ProcessMaker/BusinessModel/Cases.php @@ -21,6 +21,7 @@ use BpmnEngineServicesSearchIndex; use Cases as ClassesCases; use CasesPeer; use Configurations; +use CreoleTypes; use Criteria; use DBAdapter; use EntitySolrRequestData; @@ -32,6 +33,7 @@ use InputDocument; use InvalidIndexSearchTextException; use ListParticipatedLast; use PmDynaform; +use PmTable; use ProcessMaker\BusinessModel\ProcessSupervisor as BmProcessSupervisor; use ProcessMaker\BusinessModel\Task as BmTask; use ProcessMaker\BusinessModel\User as BmUser; @@ -39,16 +41,16 @@ use ProcessMaker\Core\System; use ProcessMaker\Exception\UploadException; use ProcessMaker\Plugins\PluginRegistry; use ProcessMaker\Services\OAuth2\Server; +use ProcessMaker\Util\DateTime as UtilDateTime; use ProcessMaker\Validation\ExceptionRestApi; use ProcessMaker\Validation\Validator as FileValidator; + use ProcessPeer; use ProcessUser; use ProcessUserPeer; use RBAC; use ResultSet; -use RoutePeer; use SubApplication; -use SubProcessPeer; use Task as ModelTask; use TaskPeer; use Tasks as ClassesTasks; @@ -3502,7 +3504,7 @@ class Cases * @param string $listPeer , name of the list class * @param string $search , the parameter for search in the table * @param string $additionalClassName , name of the className of pmtable - * @param array $additionalColumns , columns related to the custom cases list + * @param array $additionalColumns , columns related to the custom cases list ex: TABLE_NAME.COLUMN_NAME * * @throws PropelException */ @@ -3511,31 +3513,35 @@ class Cases $listPeer, $search, $additionalClassName = '', - $additionalColumns = array() + $additionalColumns = [] ) { - $oTmpCriteria = ''; + $tmpCriteria = ''; //If we have additional tables configured in the custom cases list, prepare the variables for search if (count($additionalColumns) > 0) { require_once(PATH_DATA_SITE . 'classes' . PATH_SEP . $additionalClassName . '.php'); - $oNewCriteria = new Criteria("workflow"); - $oTmpCriteria = $oNewCriteria->getNewCriterion(current($additionalColumns), "%" . $search . "%", - Criteria::LIKE); + + $columnPivot = current($additionalColumns); + $tableAndColumn = explode(".", $columnPivot); + $type = PmTable::getTypeOfColumn($listPeer, $tableAndColumn[0], $tableAndColumn[1]); + $tmpCriteria = $this->defineCriteriaByColumnType($type, $columnPivot, $search); //We prepare the query related to the custom cases list - foreach (array_slice($additionalColumns, 1) as $value) { - $oTmpCriteria = $oNewCriteria->getNewCriterion($value, "%" . $search . "%", - Criteria::LIKE)->addOr($oTmpCriteria); + foreach (array_slice($additionalColumns, 1) as $column) { + $tableAndColumn = explode(".", $column); + $type = PmTable::getTypeOfColumn($listPeer, $tableAndColumn[0], $tableAndColumn[1]); + $tmpCriteria = $this->defineCriteriaByColumnType($type, $column, $search)->addOr($tmpCriteria); + } } - if (!empty($oTmpCriteria)) { + if (!empty($tmpCriteria)) { $criteria->add( $criteria->getNewCriterion($listPeer::APP_TITLE, '%' . $search . '%', Criteria::LIKE)->addOr( $criteria->getNewCriterion($listPeer::APP_TAS_TITLE, '%' . $search . '%', Criteria::LIKE)->addOr( $criteria->getNewCriterion($listPeer::APP_PRO_TITLE, '%' . $search . '%', Criteria::LIKE)->addOr( $criteria->getNewCriterion($listPeer::APP_NUMBER, $search, Criteria::EQUAL)->addOr( - $oTmpCriteria + $tmpCriteria )))) ); } else { @@ -3549,6 +3555,58 @@ class Cases } } + /** + * Define the criteria according to the column type + * + * @param string $fieldType + * @param string $column + * @param string $search + * + * @return Criteria + */ + private function defineCriteriaByColumnType($fieldType, $column, $search) + { + $newCriteria = new Criteria("workflow"); + + switch ($fieldType) { + case CreoleTypes::BOOLEAN: + $criteria = $newCriteria->getNewCriterion($column, $search, Criteria::EQUAL); + break; + case CreoleTypes::BIGINT: + case CreoleTypes::INTEGER: + case CreoleTypes::SMALLINT: + case CreoleTypes::TINYINT: + $criteria = $newCriteria->getNewCriterion($column, $search, Criteria::EQUAL); + break; + case CreoleTypes::REAL: + case CreoleTypes::DECIMAL: + case CreoleTypes::DOUBLE: + case CreoleTypes::FLOAT: + $criteria = $newCriteria->getNewCriterion($column, $search, Criteria::LIKE); + break; + case CreoleTypes::CHAR: + case CreoleTypes::LONGVARCHAR: + case CreoleTypes::VARCHAR: + $criteria = $newCriteria->getNewCriterion($column, "%" . $search . "%", Criteria::LIKE); + break; + case CreoleTypes::DATE: + case CreoleTypes::TIME: + case CreoleTypes::TIMESTAMP://DATETIME + //@todo use the same constant in other places + if (preg_match(UtilDateTime::REGEX_IS_DATE, + $search, $arrayMatch)) { + $criteria = $newCriteria->getNewCriterion($column, $search, Criteria::GREATER_EQUAL); + } else { + $criteria = $newCriteria->getNewCriterion($column, $search, Criteria::EQUAL); + } + break; + default: + $criteria = $newCriteria->getNewCriterion($column, $search, Criteria::EQUAL); + } + + return $criteria; + } + /** * This function get the table.column by order by the result * We can include the additional table related to the custom cases list diff --git a/workflow/engine/src/ProcessMaker/Util/DateTime.php b/workflow/engine/src/ProcessMaker/Util/DateTime.php index 26dba185f..d30d35a7e 100644 --- a/workflow/engine/src/ProcessMaker/Util/DateTime.php +++ b/workflow/engine/src/ProcessMaker/Util/DateTime.php @@ -7,6 +7,7 @@ class DateTime const REGEXPDATE = '[1-9]\d{3}\-(?:0[1-9]|1[0-2])\-(?:0[1-9]|[12][0-9]|3[01])'; const REGEXPTIME = '(?:[0-1]\d|2[0-3])\:[0-5]\d\:[0-5]\d'; + const REGEX_IS_DATE = '/^([1-9]\d{3})\-(0[1-9]|1[0-2])\-(0[1-9]|[12][0-9]|3[01])(?:\s([0-1]\d|2[0-3])\:([0-5]\d)\:([0-5]\d))?$/'; /** * Get Time Zone Offset by Time Zone ID diff --git a/workflow/engine/src/ProcessMaker/Util/helpers.php b/workflow/engine/src/ProcessMaker/Util/helpers.php index 58afa158e..b3d93a2ae 100644 --- a/workflow/engine/src/ProcessMaker/Util/helpers.php +++ b/workflow/engine/src/ProcessMaker/Util/helpers.php @@ -401,27 +401,27 @@ function verifyCsrfToken($request) } /** - * Get the difference between to multidimensional array + * Get the difference between to arrays + * If the element is an array we will to keep the value from $array1 + * If the element is an object we will to keep the value from $array1 * * @param array $array1 * @param array $array2 * * @return array -*/ -function arrayDiffRecursive(array $array1, array $array2) + */ +function getDiffBetweenModifiedVariables(array $array1, array $array2) { $difference = []; foreach ($array1 as $key => $value) { if (is_array($value)) { - if (!isset($array2[$key])) { + if ($value !== $array2[$key]) { $difference[$key] = $value; - } elseif (!is_array($array2[$key])) { + } + } elseif (is_object($value)) { + // When using ===, it means object variables are identical and they refer to the same instance of the same class. + if ($value != $array2[$key]) { $difference[$key] = $value; - } else { - $new_diff = arrayDiffRecursive($value, $array2[$key]); - if (!empty($new_diff)) { - $difference[$key] = $new_diff; - } } } elseif (!isset($array2[$key]) || $array2[$key] != $value) { $difference[$key] = $value;
" . G::LoadTranslation('ID_CASE') . " #: " . $this->fields["APP_NUMBER"] . "     " . G::LoadTranslation('ID_TITLE') . ": " . $this->fields["APP_TITLE"] . "