diff --git a/gulliver/js/ext/min/ext-all.js b/gulliver/js/ext/min/ext-all.js index 5ef5532a2..157fc1e90 100644 --- a/gulliver/js/ext/min/ext-all.js +++ b/gulliver/js/ext/min/ext-all.js @@ -69,8 +69,8 @@ function getBrowserTimeZoneOffset() {return-1*((new Date()).getTimezoneOffset()*60);} function setExtStateManagerSetProvider(cache,additionalPrefix){var workspace='ws-undefined';var pathname=location.pathname.split('/');var cookieProvider=new Ext.state.CookieProvider();var i;if(additionalPrefix===undefined){additionalPrefix='';} if(pathname.length>1){workspace=pathname[1].replace('sys','');} -workspace=workspace+additionalPrefix;cookieProvider.on('statechange',function(provider,key,value){if(value!==null&&JSON.stringify(Ext.state.Manager.get(workspace+cache))!==JSON.stringify(value)){Ext.state.Manager.set(workspace+cache,value);}});Ext.state.Manager.setProvider(cookieProvider);Ext.state.Manager.clear(cache);try{if(window.extJsViewState!==undefined){for(i in extJsViewState){Ext.state.Manager.clear(i);} -Ext.state.Manager.set(cache,Ext.state.Manager.getProvider().decodeValue(extJsViewState[workspace+cache]));}}catch(e){}} +workspace=workspace+additionalPrefix;cookieProvider.on('statechange',function(provider,key,value){if(value!==null&&JSON.stringify(Ext.state.Manager.get(workspace+window.userUid+cache))!==JSON.stringify(value)){Ext.state.Manager.set(workspace+window.userUid+cache,value);}});Ext.state.Manager.setProvider(cookieProvider);Ext.state.Manager.clear(cache);try{if(window.extJsViewState!==undefined){for(i in extJsViewState){Ext.state.Manager.clear(i);} +Ext.state.Manager.set(cache,Ext.state.Manager.getProvider().decodeValue(extJsViewState[workspace+window.userUid+cache]));}}catch(e){}} function downloadFile(method,url,headers,formData,callBack){var xhr,win=window,value='blob',loadingFile=new Ext.LoadMask(Ext.getBody(),{msg:_('ID_LOADING')});method=method||'POST';loadingFile.show();if(win.XMLHttpRequest){xhr=new XMLHttpRequest();}else if(win.ActiveXObject){xhr=new ActiveXObject('Microsoft.XMLHTTP');} win.URL=win.URL||win.webkitURL;xhr.open(method,url,true);xhr.responseType=value;Object.keys(headers).forEach(function(key){xhr.setRequestHeader(key,headers[key]);});xhr.onload=function(e){loadingFile.hide();if(xhr.status===200){if(xhr.getResponseHeader("Content-Disposition")!==null){var fileName=xhr.getResponseHeader("Content-Disposition").match(/\sfilename="([^"]+)"(\s|$)/)[1];var blob=xhr.response;if((navigator.userAgent.indexOf("MSIE")!==-1)||(navigator.userAgent.indexOf("Trident")!==-1)||(navigator.userAgent.indexOf("Edge")!==-1)){win.navigator.msSaveBlob(blob,fileName);}else{var doc=win.document,a=doc.createElementNS('http://www.w3.org/1999/xhtml','a'),event=doc.createEvent('MouseEvents');event.initMouseEvent('click',true,false,win,0,0,0,0,0,false,false,false,false,0,null);a.href=win.URL.createObjectURL(blob);a.download=fileName;a.dispatchEvent(event);} if(typeof(callBack)!=='undefined'){callBack(xhr);}}else{PMExt.error(_('ID_ERROR'),_('ID_UNEXPECTED_ERROR_OCCURRED_PLEASE'));}}else{PMExt.error(_('ID_ERROR'),xhr.statusText);}};xhr.send(formData);} diff --git a/gulliver/js/ext/pmos-common.js b/gulliver/js/ext/pmos-common.js index 8a774e61d..d75b8b77c 100644 --- a/gulliver/js/ext/pmos-common.js +++ b/gulliver/js/ext/pmos-common.js @@ -609,8 +609,8 @@ function setExtStateManagerSetProvider(cache, additionalPrefix) { } workspace = workspace + additionalPrefix; cookieProvider.on('statechange', function (provider, key, value) { - if (value !== null && JSON.stringify(Ext.state.Manager.get(workspace + cache)) !== JSON.stringify(value)) { - Ext.state.Manager.set(workspace + cache, value); + if (value !== null && JSON.stringify(Ext.state.Manager.get(workspace + window.userUid + cache)) !== JSON.stringify(value)) { + Ext.state.Manager.set(workspace + window.userUid + cache, value); } }); Ext.state.Manager.setProvider(cookieProvider); @@ -620,7 +620,7 @@ function setExtStateManagerSetProvider(cache, additionalPrefix) { for (i in extJsViewState) { Ext.state.Manager.clear(i); } - Ext.state.Manager.set(cache, Ext.state.Manager.getProvider().decodeValue(extJsViewState[workspace + cache])); + Ext.state.Manager.set(cache, Ext.state.Manager.getProvider().decodeValue(extJsViewState[workspace + window.userUid + cache])); } } catch (e) { } diff --git a/gulliver/system/class.bootstrap.php b/gulliver/system/class.bootstrap.php index a5874a76b..9eb567d9c 100644 --- a/gulliver/system/class.bootstrap.php +++ b/gulliver/system/class.bootstrap.php @@ -207,7 +207,7 @@ class Bootstrap * = local path * @return boolean */ - public function virtualURI($url, $convertionTable, &$realPath) + public static function virtualURI($url, $convertionTable, &$realPath) { foreach ($convertionTable as $urlPattern => $localPath) { // $urlPattern = addcslashes( $urlPattern , '/'); @@ -240,7 +240,7 @@ class Bootstrap * @param string $downloadFileName * @return string */ - public function streamFile($file, $download = false, $downloadFileName = '', $forceLoad = false) + public static function streamFile($file, $download = false, $downloadFileName = '', $forceLoad = false) { $filter = new InputFilter(); $file = $filter->xssFilterHard($file); @@ -399,7 +399,7 @@ class Bootstrap * nameWorkspace to specific workspace * return true if the file exists, otherwise false. */ - public function isPMUnderUpdating($setFlag = 2, $content="true") + public static function isPMUnderUpdating($setFlag = 2, $content="true") { if (!defined('PATH_DATA')) { return false; @@ -438,7 +438,7 @@ class Bootstrap * array containig the template data * @return $content string containing the parsed template content */ - public function parseTemplate($template, $data = array()) + public static function parseTemplate($template, $data = array()) { $content = ''; @@ -556,7 +556,7 @@ class Bootstrap * @param string $strSkin * @return void */ - public function RenderPage($strTemplate = "default", $strSkin = SYS_SKIN, $objContent = null, $layout = '') + public static function RenderPage($strTemplate = "default", $strSkin = SYS_SKIN, $objContent = null, $layout = '') { global $G_CONTENT; global $G_TEMPLATE; @@ -617,7 +617,7 @@ class Bootstrap * * @return void */ - public function SendTemporalMessage($msgID, $strType, $sType = 'LABEL', $time = null, $width = null, $customLabels = null) + public static function SendTemporalMessage($msgID, $strType, $sType = 'LABEL', $time = null, $width = null, $customLabels = null) { if (isset($width)) { $_SESSION ['G_MESSAGE_WIDTH'] = $width; @@ -653,7 +653,7 @@ class Bootstrap * @param string $parameter * @return string */ - public function header($parameter) + public static function header($parameter) { if (defined('ENABLE_ENCRYPT') && (ENABLE_ENCRYPT == 'yes') && (substr($parameter, 0, 9) == 'location:')) { $url = Bootstrap::encrypt(substr($parameter, 10), URL_KEY); @@ -673,7 +673,7 @@ class Bootstrap * @access public * @return void */ - public function LoadAllPluginModelClasses() + public static function LoadAllPluginModelClasses() { // Get the current Include path, where the plugins directories should be if (!defined('PATH_SEPARATOR')) { @@ -723,7 +723,7 @@ class Bootstrap /** * function to calculate the time used to render a page */ - public function logTimeByPage() + public static function logTimeByPage() { if (!defined(PATH_DATA)) { return false; @@ -748,7 +748,7 @@ class Bootstrap * @param string $downloadFileName * @return string */ - public function streamJSTranslationFile($filename, $locale = 'en') + public static function streamJSTranslationFile($filename, $locale = 'en') { $typearray = explode('.', basename($filename)); $typeCount = count($typearray); @@ -808,7 +808,7 @@ class Bootstrap * @param string $file * @return string */ - public function streamCSSBigFile($filename) + public static function streamCSSBigFile($filename) { header('Content-Type: text/css'); @@ -964,7 +964,7 @@ class Bootstrap * * @return void */ - public function sendHeaders($filename, $contentType = '', $download = false, $downloadFileName = '') + public static function sendHeaders($filename, $contentType = '', $download = false, $downloadFileName = '') { if ($download) { if ($downloadFileName == '') { @@ -1115,7 +1115,7 @@ class Bootstrap * strip_slashes * @param vVar */ - public function strip_slashes($vVar) + public static function strip_slashes($vVar) { if (is_array($vVar)) { foreach ($vVar as $sKey => $vValue) { @@ -1142,7 +1142,7 @@ class Bootstrap * @param eter array data // erik: associative array within data input to replace for formatted string i.e "any messsage {replaced_label} that contains a replace label" * @return string */ - public function LoadTranslation($msgID, $lang = SYS_LANG, $data = null) + public static function LoadTranslation($msgID, $lang = SYS_LANG, $data = null) { global $translation; @@ -1182,7 +1182,7 @@ class Bootstrap * @param $pattern pattern to filter some specified files * @return array containing the recursive glob results */ - public function rglob($pattern = '*', $flags = 0, $path = '') + public static function rglob($pattern = '*', $flags = 0, $path = '') { $paths = glob($path . '*', GLOB_MARK | GLOB_ONLYDIR | GLOB_NOSORT); $files = glob($path . $pattern, $flags); @@ -1197,7 +1197,7 @@ class Bootstrap * * @author Erik A.O. */ - public function json_encode($Json) + public static function json_encode($Json) { if (function_exists('json_encode')) { return json_encode($Json); @@ -1229,7 +1229,7 @@ class Bootstrap * * @author Erik Amaru Ortiz */ - public function xmlParser(&$string) + public static function xmlParser(&$string) { $parser = xml_parser_create(); xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); @@ -1304,7 +1304,7 @@ class Bootstrap * @param unknown_type $maxmtime * @return Ambigous */ - public function getDirectorySize($path, $maxmtime = 0) + public static function getDirectorySize($path, $maxmtime = 0) { $totalsize = 0; $totalcount = 0; @@ -1365,7 +1365,7 @@ class Bootstrap * @author Ralph A. * @return multitype:array containing browser name and type */ - public function get_current_browser() + public static function get_current_browser() { static $a_full_assoc_data, $a_mobile_data, $browser_user_agent; static $browser_working, $moz_type, $webkit_type; @@ -1563,7 +1563,7 @@ class Bootstrap * @param unknown_type $pv_extra_search * @return string */ - public function get_item_version($pv_browser_user_agent, $pv_search_string, $pv_b_break_last = '', $pv_extra_search = '') + public static function get_item_version($pv_browser_user_agent, $pv_search_string, $pv_b_break_last = '', $pv_extra_search = '') { $substring_length = 15; $start_pos = 0; // set $start_pos to 0 for first iteration @@ -1594,7 +1594,7 @@ class Bootstrap * @param unknown_type $pv_type * @param unknown_type $pv_value */ - public function get_set_count($pv_type, $pv_value = '') + public static function get_set_count($pv_type, $pv_value = '') { static $slice_increment; $return_value = ''; @@ -1743,7 +1743,7 @@ class Bootstrap * @param unknown_type $pv_browser_user_agent * @return string */ - public function check_is_mobile($pv_browser_user_agent) + public static function check_is_mobile($pv_browser_user_agent) { $mobile_working_test = ''; $a_mobile_search = array( @@ -1771,7 +1771,7 @@ class Bootstrap * * @param unknown_type $pv_browser_user_agent */ - public function get_mobile_data($pv_browser_user_agent) + public static function get_mobile_data($pv_browser_user_agent) { $mobile_browser = ''; $mobile_browser_number = ''; @@ -1943,7 +1943,7 @@ class Bootstrap * @param string $key * @return string */ - public function encrypt($string, $key) + public static function encrypt($string, $key) { //print $string; // if ( defined ( 'ENABLE_ENCRYPT' ) && ENABLE_ENCRYPT == 'yes' ) { @@ -1973,7 +1973,7 @@ class Bootstrap * @param string $key * @return string */ - public function decrypt($string, $key) + public static function decrypt($string, $key) { // if ( defined ( 'ENABLE_ENCRYPT' ) && ENABLE_ENCRYPT == 'yes' ) { //if (strpos($string, '|', 0) !== false) return $string; @@ -2066,7 +2066,7 @@ class Bootstrap * @param string $array_i * @return array */ - public function array_merge_2(&$array, &$array_i) + public static function array_merge_2(&$array, &$array_i) { foreach ($array_i as $k => $v) { if (is_array($v)) { @@ -2095,7 +2095,7 @@ class Bootstrap * @return array_sum(explode(' ',microtime())) */ /* public static */ - public function microtime_float() + public static function microtime_float() { return array_sum(explode(' ', microtime())); } @@ -2344,7 +2344,7 @@ class Bootstrap * @author Erik Amaru Ortiz * @name complete_field($string, $lenght, $type={1:number/2:string/3:float}) */ - public function complete_field($campo, $long, $tipo) + public static function complete_field($campo, $long, $tipo) { $campo = trim($campo); switch ($tipo) { @@ -2580,7 +2580,7 @@ class Bootstrap * @param string $userPass hash of password * @return bool true or false */ - public function verifyHashPassword($pass, $userPass) + public static function verifyHashPassword($pass, $userPass) { global $RBAC; $passwordHashConfig = Bootstrap::getPasswordHashConfig(); @@ -2610,7 +2610,7 @@ class Bootstrap * @param $string * @return mixed */ - public function encryptOld($string) + public static function encryptOld($string) { $consthashFx = self::hashFx; return $consthashFx($string); diff --git a/gulliver/system/class.form.php b/gulliver/system/class.form.php index 9814d8e5f..96cfb7cbb 100644 --- a/gulliver/system/class.form.php +++ b/gulliver/system/class.form.php @@ -105,6 +105,10 @@ class Form extends XmlForm $filename = $filename . '.xml'; } $this->home = $home; + + //to do: This must be removed, the post validation should only be done for the classic version. + self::createXMLFileIfNotExists($this->home . $filename); + $res = parent::parseFile( $filename, $language, $forceParse ); if ($res == 1) { trigger_error( 'Faild to parse file ' . $filename . '.', E_USER_ERROR ); @@ -751,5 +755,53 @@ class Form extends XmlForm } return $data; } + + /** + * Create XML file if not exists. + * + * @param string $filepath + * + * @see Form->__construct() + * @@link https://wiki.processmaker.com/3.1/Cases + * @link https://wiki.processmaker.com/index.php/2.5.X/DynaForms#XML_tab + */ + public static function createXMLFileIfNotExists($filepath) + { + if (file_exists($filepath)) { + return; + } + $pathParts = pathinfo($filepath); + if (empty($pathParts)) { + return; + } + $dynUid = $pathParts["filename"]; + $proUid = basename($pathParts["dirname"]); + $pathHome = dirname($pathParts["dirname"]) . PATH_SEP; + self::createXMLFile($proUid, $dynUid, 'xmlform', $pathHome); + } + + /** + * Create XML file. + * + * @param string $proUid + * @param string $dynUid + * @param string $dynType + * @param string $pathHome + * + * @see Dynaform->create() + * @see Form::createXMLFileIfNotExists() + * @link https://wiki.processmaker.com/3.1/Cases + * @link https://wiki.processmaker.com/index.php/2.5.X/DynaForms#XML_tab + */ + public static function createXMLFile($proUid, $dynUid, $dynType = 'xmlform', $pathHome = PATH_XMLFORM) + { + $xml = '' . "\n"; + $xml .= '' . "\n"; + $xml .= ''; + G::verifyPath($pathHome . $proUid, true); + $file = fopen($pathHome . $proUid . '/' . $dynUid . '.xml', 'w'); + fwrite($file, $xml); + fclose($file); + } } diff --git a/gulliver/system/class.headPublisher.php b/gulliver/system/class.headPublisher.php index 8204a05e0..b153f05a7 100644 --- a/gulliver/system/class.headPublisher.php +++ b/gulliver/system/class.headPublisher.php @@ -746,11 +746,11 @@ class headPublisher * * @return array $views */ - public function getExtJsViewState() + public function getExtJsViewState($userUid = '') { $json = new stdClass(); $views = array(); - $keyState = "extJsViewState"; + $keyState = "extJsViewState" . $userUid; $prefixExtJs = "ys-"; $oServerConf = ServerConf::getSingleton(); $deleteCache = true; diff --git a/workflow/engine/bin/cron_single.php b/workflow/engine/bin/cron_single.php index 8adce7d00..01103adb5 100644 --- a/workflow/engine/bin/cron_single.php +++ b/workflow/engine/bin/cron_single.php @@ -327,6 +327,7 @@ function processWorkspace() executeScheduledCases(); executeUpdateAppTitle(); executeCaseSelfService(); + cleanSelfServiceTables(); executePlugins(); /*----------------------------------********---------------------------------*/ fillReportByUser(); @@ -1056,3 +1057,46 @@ function sendNotifications() saveLog("ExecuteSendNotifications", "error", "Error when sending notifications " . $e->getMessage()); } } + +/** + * Clean unused records in tables related to the Self-Service Value Based feature + * + * @see processWorkspace() + * + * @link https://wiki.processmaker.com/3.2/Executing_cron.php#Syntax_of_cron.php_Options + */ +function cleanSelfServiceTables() +{ + try { + global $argvx; + + // Check if the action can be executed + if ($argvx !== "" && strpos($argvx, "clean-self-service-tables") === false) { + return false; + } + + // Start message + setExecutionMessage("Clean unused records for Self-Service Value Based feature"); + + // Get Propel connection + $cnn = Propel::getConnection(AppAssignSelfServiceValueGroupPeer::DATABASE_NAME); + + // Delete related rows and missing relations, criteria don't execute delete with joins + $cnn->begin(); + $stmt = $cnn->createStatement(); + $stmt->executeQuery("DELETE " . AppAssignSelfServiceValueGroupPeer::TABLE_NAME . " + FROM " . AppAssignSelfServiceValueGroupPeer::TABLE_NAME . " + LEFT JOIN " . AppAssignSelfServiceValuePeer::TABLE_NAME . " + ON (" . AppAssignSelfServiceValueGroupPeer::ID . " = " . AppAssignSelfServiceValuePeer::ID . ") + WHERE " . AppAssignSelfServiceValuePeer::ID . " IS NULL"); + $cnn->commit(); + + // Success message + setExecutionResultMessage("DONE"); + } catch (Exception $e) { + $cnn->rollback(); + setExecutionResultMessage("WITH ERRORS", "error"); + eprintln(" '-" . $e->getMessage(), "red"); + saveLog("ExecuteCleanSelfServiceTables", "error", "Error when try to clean self-service tables " . $e->getMessage()); + } +} diff --git a/workflow/engine/classes/Cases.php b/workflow/engine/classes/Cases.php index bbad083b1..deba3d144 100644 --- a/workflow/engine/classes/Cases.php +++ b/workflow/engine/classes/Cases.php @@ -468,44 +468,44 @@ class Cases { try { $oApp = new Application; - $aFields = $oApp->Load($sAppUid); + $fields = $oApp->Load($sAppUid); - $appData = self::unserializeData($aFields['APP_DATA']); + $appData = self::unserializeData($fields['APP_DATA']); - $aFields['APP_DATA'] = G::array_merges(G::getSystemConstants(), $appData); + $fields['APP_DATA'] = G::array_merges(G::getSystemConstants(), $appData); switch ($oApp->getAppStatus()) { case 'COMPLETED': - $aFields['STATUS'] = G::LoadTranslation('ID_COMPLETED'); + $fields['STATUS'] = G::LoadTranslation('ID_COMPLETED'); break; case 'CANCELLED': - $aFields['STATUS'] = G::LoadTranslation('ID_CANCELLED'); + $fields['STATUS'] = G::LoadTranslation('ID_CANCELLED'); break; case 'PAUSED': - $aFields['STATUS'] = G::LoadTranslation('ID_PAUSED'); + $fields['STATUS'] = G::LoadTranslation('ID_PAUSED'); break; case 'DRAFT': - $aFields['STATUS'] = G::LoadTranslation('ID_DRAFT'); + $fields['STATUS'] = G::LoadTranslation('ID_DRAFT'); break; case 'TO_DO': - $aFields['STATUS'] = G::LoadTranslation('ID_TO_DO'); + $fields['STATUS'] = G::LoadTranslation('ID_TO_DO'); break; } $oUser = new Users(); try { $oUser->load($oApp->getAppInitUser()); $uFields = $oUser->toArray(BasePeer::TYPE_FIELDNAME); - $aFields['TITLE'] = $aFields['APP_TITLE']; - $aFields['DESCRIPTION'] = $aFields['APP_DESCRIPTION']; - $aFields['CREATOR'] = $oUser->getUsrFirstname() . ' ' . $oUser->getUsrLastname(); - $aFields['CREATE_DATE'] = $oApp->getAppCreateDate(); - $aFields['UPDATE_DATE'] = $oApp->getAppUpdateDate(); + $fields['TITLE'] = $fields['APP_TITLE']; + $fields['DESCRIPTION'] = $fields['APP_DESCRIPTION']; + $fields['CREATOR'] = $oUser->getUsrFirstname() . ' ' . $oUser->getUsrLastname(); + $fields['CREATE_DATE'] = $oApp->getAppCreateDate(); + $fields['UPDATE_DATE'] = $oApp->getAppUpdateDate(); } catch (Exception $oError) { - $aFields['TITLE'] = $oApp->getAppTitle(); - $aFields['DESCRIPTION'] = ''; - $aFields['CREATOR'] = '(USER_DELETED)'; - $aFields['CREATE_DATE'] = $oApp->getAppCreateDate(); - $aFields['UPDATE_DATE'] = $oApp->getAppUpdateDate(); + $fields['TITLE'] = $oApp->getAppTitle(); + $fields['DESCRIPTION'] = ''; + $fields['CREATOR'] = '(USER_DELETED)'; + $fields['CREATE_DATE'] = $oApp->getAppCreateDate(); + $fields['UPDATE_DATE'] = $oApp->getAppUpdateDate(); } if ($iDelIndex > 0) { @@ -513,50 +513,52 @@ class Cases $oAppDel = new AppDelegation(); $oAppDel->Load($sAppUid, $iDelIndex); $aAppDel = $oAppDel->toArray(BasePeer::TYPE_FIELDNAME); - $aFields['TAS_UID'] = $aAppDel['TAS_UID']; - $aFields['DEL_INDEX'] = $aAppDel['DEL_INDEX']; - $aFields['DEL_PREVIOUS'] = $aAppDel['DEL_PREVIOUS']; - $aFields['DEL_TYPE'] = $aAppDel['DEL_TYPE']; - $aFields['DEL_PRIORITY'] = $aAppDel['DEL_PRIORITY']; - $aFields['DEL_THREAD_STATUS'] = $aAppDel['DEL_THREAD_STATUS']; - $aFields['DEL_THREAD'] = $aAppDel['DEL_THREAD']; - $aFields['DEL_DELEGATE_DATE'] = $aAppDel['DEL_DELEGATE_DATE']; - $aFields['DEL_INIT_DATE'] = $aAppDel['DEL_INIT_DATE']; - $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']; + $fields['TAS_UID'] = $aAppDel['TAS_UID']; + $fields['DEL_INDEX'] = $aAppDel['DEL_INDEX']; + $fields['DEL_PREVIOUS'] = $aAppDel['DEL_PREVIOUS']; + $fields['DEL_TYPE'] = $aAppDel['DEL_TYPE']; + $fields['DEL_PRIORITY'] = $aAppDel['DEL_PRIORITY']; + $fields['DEL_THREAD_STATUS'] = $aAppDel['DEL_THREAD_STATUS']; + $fields['DEL_THREAD'] = $aAppDel['DEL_THREAD']; + $fields['DEL_DELEGATE_DATE'] = $aAppDel['DEL_DELEGATE_DATE']; + $fields['DEL_INIT_DATE'] = $aAppDel['DEL_INIT_DATE']; + $fields['DEL_TASK_DUE_DATE'] = $aAppDel['DEL_TASK_DUE_DATE']; + $fields['DEL_FINISH_DATE'] = $aAppDel['DEL_FINISH_DATE']; + $fields['CURRENT_USER_UID'] = $aAppDel['USR_UID']; //Update the global variables - $aFields['TASK'] = $aAppDel['TAS_UID']; - $aFields['INDEX'] = $aAppDel['DEL_INDEX']; - $aFields['TAS_ID'] = $aAppDel['TAS_ID']; - $aFields['PRO_ID'] = $aAppDel['PRO_ID']; + $fields['TASK'] = $aAppDel['TAS_UID']; + $fields['INDEX'] = $aAppDel['DEL_INDEX']; + $fields['TAS_ID'] = $aAppDel['TAS_ID']; + $fields['PRO_ID'] = $aAppDel['PRO_ID']; try { $oCurUser = new Users(); if ($jump != '') { - $aCases = $oAppDel->LoadParallel($sAppUid); - $aFields['TAS_UID'] = ''; - $aFields['CURRENT_USER'] = array(); - foreach ($aCases as $key => $value) { - $oCurUser->load($value['USR_UID']); - $aFields['CURRENT_USER'][] = $oCurUser->getUsrFirstname() . ' ' . $oCurUser->getUsrLastname(); - $aFields['TAS_UID'] .= (($aFields['TAS_UID'] != '') ? '|' : '') . $value['TAS_UID']; + $cases = $oAppDel->LoadParallel($sAppUid); + if (!empty($cases)) { + $fields['TAS_UID'] = ''; } - $aFields['CURRENT_USER'] = implode(" - ", array_values($aFields['CURRENT_USER'])); - $tasksArray = array_filter(explode('|', $aFields['TAS_UID'])); + $fields['CURRENT_USER'] = array(); + foreach ($cases as $key => $value) { + $oCurUser->load($value['USR_UID']); + $fields['CURRENT_USER'][] = $oCurUser->getUsrFirstname() . ' ' . $oCurUser->getUsrLastname(); + $fields['TAS_UID'] .= (($fields['TAS_UID'] != '') ? '|' : '') . $value['TAS_UID']; + } + $fields['CURRENT_USER'] = implode(" - ", array_values($fields['CURRENT_USER'])); + $tasksArray = array_filter(explode('|', $fields['TAS_UID'])); if (count($tasksArray) == 1) { - $aFields['TAS_UID'] = $tasksArray[0]; + $fields['TAS_UID'] = $tasksArray[0]; } } else { $oCurUser->load($aAppDel['USR_UID']); - $aFields['CURRENT_USER'] = $oCurUser->getUsrFirstname() . ' ' . $oCurUser->getUsrLastname(); + $fields['CURRENT_USER'] = $oCurUser->getUsrFirstname() . ' ' . $oCurUser->getUsrLastname(); } } catch (Exception $oError) { - $aFields['CURRENT_USER'] = ''; + $fields['CURRENT_USER'] = ''; } } - return $aFields; + return $fields; } catch (exception $e) { throw ($e); } @@ -963,10 +965,9 @@ class Cases if (isset($Fields['CURRENT_USER_UID'])) { $Fields['USR_UID'] = $Fields['CURRENT_USER_UID']; } - /*----------------------------------********---------------------------------*/ - $completed = new ListCompleted(); - $completed->create(array_merge($Fields, $newTitleOrDescription)); - /*----------------------------------********---------------------------------*/ + //Will be update the status in the list Participated + $listParticipatedLast = new ListParticipatedLast(); + $listParticipatedLast->refreshStatus($Fields['APP_UID'], 'COMPLETED'); } /** Update case*/ @@ -1138,9 +1139,6 @@ class Cases $oCriteria->add(ListParticipatedHistoryPeer::APP_UID, $sAppUid); ListParticipatedHistoryPeer::doDelete($oCriteria); $oCriteria = new Criteria('workflow'); - $oCriteria->add(ListCompletedPeer::APP_UID, $sAppUid); - ListCompletedPeer::doDelete($oCriteria); - $oCriteria = new Criteria('workflow'); $oCriteria->add(ListUnassignedPeer::APP_UID, $sAppUid); ListUnassignedPeer::doDelete($oCriteria); /*----------------------------------********---------------------------------*/ @@ -3538,6 +3536,8 @@ class Cases /** * This section of code its related to the route the case with parallel task in the same time * @link https://processmaker.atlassian.net/browse/PMC-2 + * + * @todo: The solution for ticket HOR-4602 should be restated in another ticket, for now this change was reverted */ if ($oPMScript->executedOn() === $oPMScript::AFTER_ROUTING) { //Get the variables changed with the trigger @@ -3546,11 +3546,6 @@ class Cases //We will be load the last appData because: //Other thread execution can be changed the variables $appUid = !empty($fieldsCase['APPLICATION']) ? $fieldsCase['APPLICATION'] : ''; - if (!empty($appUid)) { - $lastFieldsCase = $this->loadCase($appUid)['APP_DATA']; - //Update $fieldsCase with the last appData - $fieldsCase = array_merge($fieldsCase, $lastFieldsCase); - } //Save the fields changed in the trigger if (!$varInAfterRouting && !empty($fieldsTrigger)) { @@ -5716,7 +5711,7 @@ class Cases '', '', 'pending', - '', + 1, $dataLastEmail['msgError'], true, isset($arrayData['APP_NUMBER']) ? $arrayData['APP_NUMBER'] : 0, diff --git a/workflow/engine/classes/Groups.php b/workflow/engine/classes/Groups.php index b00b776b1..08b393881 100644 --- a/workflow/engine/classes/Groups.php +++ b/workflow/engine/classes/Groups.php @@ -74,6 +74,44 @@ class Groups } } + /** + * Get the IDs of the active groups for an user + * + * @param string $usrUid + * + * @return array + * @throws Exception + */ + public function getActiveGroupsForAnUserById($usrUid) + { + try { + $criteria = new Criteria(); + $criteria->addSelectColumn(GroupUserPeer::GRP_ID); + $criteria->addJoin(GroupUserPeer::GRP_ID, GroupwfPeer::GRP_ID, Criteria::LEFT_JOIN); + //@todo: we need to add a new column GROUP_USER.USR_ID + $criteria->add(GroupUserPeer::USR_UID, $usrUid); + //@todo: we need to add a new column GROUPWF.GRP_STATUS_ID + $criteria->add(GroupwfPeer::GRP_STATUS, 'ACTIVE'); + $dataset = GroupUserPeer::doSelectRS($criteria); + $dataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $dataset->next(); + + //If the user does not relate with any group we will to return a default value for avoiding problems with the IN + $groups = [-1]; + $row = $dataset->getRow(); + while (is_array($row)) { + $groups[] = $row['GRP_ID']; + $dataset->next(); + $row = $dataset->getRow(); + } + + return $groups; + } catch (Exception $error) { + throw ($error); + } + } + + /** * Set a user to group * diff --git a/workflow/engine/classes/Processes.php b/workflow/engine/classes/Processes.php index a5b53da32..43cdc8ce9 100644 --- a/workflow/engine/classes/Processes.php +++ b/workflow/engine/classes/Processes.php @@ -2190,7 +2190,7 @@ class Processes $labels = ['OUT_DOC_TITLE' => $row['OUT_DOC_TITLE'], 'OUT_DOC_DESCRIPTION' => !empty($row['OUT_DOC_DESCRIPTION']) ? $row['OUT_DOC_DESCRIPTION'] : '', 'OUT_DOC_FILENAME' => $row['OUT_DOC_FILENAME'], - 'OUT_DOC_TEMPLATE' => $row['OUT_DOC_TEMPLATE']]; + 'OUT_DOC_TEMPLATE' => !empty($row['OUT_DOC_TEMPLATE']) ? $row['OUT_DOC_TEMPLATE'] : '']; $this->insertToContentTable($con, $labels, $row['OUT_DOC_UID'], SYS_LANG); } $con->commit(); diff --git a/workflow/engine/classes/WorkspaceTools.php b/workflow/engine/classes/WorkspaceTools.php index 3eeb7b9ae..2f37b70d2 100644 --- a/workflow/engine/classes/WorkspaceTools.php +++ b/workflow/engine/classes/WorkspaceTools.php @@ -2398,7 +2398,7 @@ class WorkspaceTools return; } - $arrayTable1 = ['ListInbox', 'ListMyInbox', 'ListCanceled', 'ListParticipatedLast', 'ListParticipatedHistory', 'ListPaused', 'ListCompleted']; + $arrayTable1 = ['ListInbox', 'ListMyInbox', 'ListCanceled', 'ListParticipatedLast', 'ListParticipatedHistory', 'ListPaused']; $arrayTable2 = ['ListUnassigned', 'ListUnassignedGroup']; $arrayTable = array_merge($arrayTable1, $arrayTable2); @@ -2424,7 +2424,6 @@ class WorkspaceTools } if ($flagReinsert || !$flagListAll) { - $this->regenerateListCompleted($lang); $this->regenerateListCanceled($lang); $this->regenerateListMyInbox(); //This list require no translation $this->regenerateListInbox(); //This list require no translation @@ -2509,69 +2508,6 @@ class WorkspaceTools CLI::logging("> Completed table LIST_CANCELED\n"); } - public function regenerateListCompleted($lang = 'en') - { - $this->initPropel(true); - $query = 'INSERT INTO ' . $this->dbName . '.LIST_COMPLETED - (APP_UID, - USR_UID, - TAS_UID, - PRO_UID, - APP_NUMBER, - APP_TITLE, - APP_PRO_TITLE, - APP_TAS_TITLE, - APP_CREATE_DATE, - APP_FINISH_DATE, - DEL_INDEX, - DEL_PREVIOUS_USR_UID, - DEL_CURRENT_USR_USERNAME, - DEL_CURRENT_USR_FIRSTNAME, - DEL_CURRENT_USR_LASTNAME) - - SELECT - ACV.APP_UID, - ACV.USR_UID, - ACV.TAS_UID, - ACV.PRO_UID, - ACV.APP_NUMBER, - C_APP.CON_VALUE AS APP_TITLE, - C_PRO.CON_VALUE AS APP_PRO_TITLE, - C_TAS.CON_VALUE AS APP_TAS_TITLE, - ACV.APP_CREATE_DATE, - ACV.APP_FINISH_DATE, - ACV.DEL_INDEX, - PREV_AD.USR_UID AS DEL_PREVIOUS_USR_UID, - USR.USR_USERNAME AS DEL_CURRENT_USR_USERNAME, - USR.USR_FIRSTNAME AS DEL_CURRENT_USR_FIRSTNAME, - USR.USR_LASTNAME AS DEL_CURRENT_USR_LASTNAME - FROM - (' . $this->dbName . '.APP_CACHE_VIEW ACV - LEFT JOIN ' . $this->dbName . '.CONTENT C_APP ON ACV.APP_UID = C_APP.CON_ID - AND C_APP.CON_CATEGORY = \'APP_TITLE\' - AND C_APP.CON_LANG = \'' . $lang . '\' - LEFT JOIN ' . $this->dbName . '.CONTENT C_PRO ON ACV.PRO_UID = C_PRO.CON_ID - AND C_PRO.CON_CATEGORY = \'PRO_TITLE\' - AND C_PRO.CON_LANG = \'' . $lang . '\' - LEFT JOIN ' . $this->dbName . '.CONTENT C_TAS ON ACV.TAS_UID = C_TAS.CON_ID - AND C_TAS.CON_CATEGORY = \'TAS_TITLE\' - AND C_TAS.CON_LANG = \'' . $lang . '\') - LEFT JOIN - (' . $this->dbName . '.APP_DELEGATION AD - INNER JOIN ' . $this->dbName . '.APP_DELEGATION PREV_AD ON AD.APP_UID = PREV_AD.APP_UID - AND AD.DEL_PREVIOUS = PREV_AD.DEL_INDEX) ON ACV.APP_UID = AD.APP_UID - AND ACV.DEL_INDEX = AD.DEL_INDEX - LEFT JOIN - ' . $this->dbName . '.USERS USR ON ACV.USR_UID = USR.USR_UID - WHERE - ACV.APP_STATUS = \'COMPLETED\' - AND ACV.DEL_LAST_INDEX = 1'; - $con = Propel::getConnection("workflow"); - $stmt = $con->createStatement(); - $stmt->executeQuery($query); - CLI::logging("> Completed table LIST_COMPLETED\n"); - } - public function regenerateListMyInbox() { $this->initPropel(true); diff --git a/workflow/engine/classes/model/AppAssignSelfServiceValue.php b/workflow/engine/classes/model/AppAssignSelfServiceValue.php index b2fea9d9b..07a68e6ab 100644 --- a/workflow/engine/classes/model/AppAssignSelfServiceValue.php +++ b/workflow/engine/classes/model/AppAssignSelfServiceValue.php @@ -64,6 +64,12 @@ class AppAssignSelfServiceValue extends BaseAppAssignSelfServiceValue * * @return void * @throws Exception + * + * @see \Cases->removeCase() + * @see \Cases->setCatchUser() + * @see \Cases->updateCase() + * + * @link https://wiki.processmaker.com/3.2/Tasks#Self_Service_Value_Based_Assignment */ public function remove($applicationUid, $delIndex = 0) { @@ -76,18 +82,7 @@ class AppAssignSelfServiceValue extends BaseAppAssignSelfServiceValue $criteria->add(AppAssignSelfServiceValuePeer::DEL_INDEX, $delIndex, Criteria::EQUAL); } - $result = AppAssignSelfServiceValuePeer::doDelete($criteria); - - // Delete related rows and missing relations, criteria don't execute delete with joins - $cnn = Propel::getConnection(AppAssignSelfServiceValueGroupPeer::DATABASE_NAME); - $cnn->begin(); - $stmt = $cnn->createStatement(); - $rs = $stmt->executeQuery("DELETE " . AppAssignSelfServiceValueGroupPeer::TABLE_NAME . " - FROM " . AppAssignSelfServiceValueGroupPeer::TABLE_NAME . " - LEFT JOIN " . AppAssignSelfServiceValuePeer::TABLE_NAME . " - ON (" . AppAssignSelfServiceValueGroupPeer::ID . " = " . AppAssignSelfServiceValuePeer::ID . ") - WHERE " . AppAssignSelfServiceValuePeer::ID . " IS NULL"); - $cnn->commit(); + AppAssignSelfServiceValuePeer::doDelete($criteria); } catch (Exception $e) { throw $e; } diff --git a/workflow/engine/classes/model/AppMessage.php b/workflow/engine/classes/model/AppMessage.php index 663ade86c..4b2659c56 100644 --- a/workflow/engine/classes/model/AppMessage.php +++ b/workflow/engine/classes/model/AppMessage.php @@ -160,7 +160,7 @@ class AppMessage extends BaseAppMessage * @param string $appMsgTemplate, * @param string $appMsgAttach, * @param string $appMsgStatus, - * @param string $appMsgShowMsg, + * @param integer $appMsgShowMsg, * @param string $appMsgError, * @param boolean $contentTypeIsHtml * @param integer $appNumber, @@ -183,7 +183,7 @@ class AppMessage extends BaseAppMessage $appMsgTemplate = '', $appMsgAttach = '', $appMsgStatus = 'pending', - $appMsgShowMsg = '', + $appMsgShowMsg = 1, $appMsgError = '', $contentTypeIsHtml = true, $appNumber = 0, diff --git a/workflow/engine/classes/model/AppNotes.php b/workflow/engine/classes/model/AppNotes.php index 3885aa6ad..a36b13681 100644 --- a/workflow/engine/classes/model/AppNotes.php +++ b/workflow/engine/classes/model/AppNotes.php @@ -238,7 +238,7 @@ class AppNotes extends BaseAppNotes '', '', 'pending', - '', + 1, $msgError, true, (isset($fieldCase['APP_NUMBER'])) ? $fieldCase['APP_NUMBER'] : 0, diff --git a/workflow/engine/classes/model/Dynaform.php b/workflow/engine/classes/model/Dynaform.php index f1053c0ac..89979a570 100644 --- a/workflow/engine/classes/model/Dynaform.php +++ b/workflow/engine/classes/model/Dynaform.php @@ -223,14 +223,8 @@ class Dynaform extends BaseDynaform $description = "Create from a PM Table: " . $addTabName . ", "; } G::auditLog("CreateDynaform", $description . "Dynaform Title: " . $aData['DYN_TITLE'] . ", Type: " . $aData['DYN_TYPE'] . ", Description: " . $aData['DYN_DESCRIPTION'] . ", Mode: " . $mode); - - $sXml = '' . "\n"; - $sXml .= '' . "\n"; - $sXml .= ''; - G::verifyPath(PATH_DYNAFORM . $this->getProUid(), true); - $oFile = fopen(PATH_DYNAFORM . $this->getProUid() . '/' . $this->getDynUid() . '.xml', 'w'); - fwrite($oFile, $sXml); - fclose($oFile); + + Form::createXMLFile($this->getProUid(), $this->getDynUid(), $this->getDynType(), PATH_DYNAFORM); return $this->getDynUid(); } else { $msg = ''; diff --git a/workflow/engine/classes/model/ListCompleted.php b/workflow/engine/classes/model/ListCompleted.php index d7c145657..d8c88ef5f 100644 --- a/workflow/engine/classes/model/ListCompleted.php +++ b/workflow/engine/classes/model/ListCompleted.php @@ -13,8 +13,8 @@ require_once 'classes/model/om/BaseListCompleted.php'; * long as it does not already exist in the output directory. * * @package classes.model + * @deprecated Method deprecated in Release 3.3.9 */ -// @codingStandardsIgnoreStart class ListCompleted extends BaseListCompleted implements ListInterface { use ListBaseTrait; diff --git a/workflow/engine/classes/model/ListParticipatedLast.php b/workflow/engine/classes/model/ListParticipatedLast.php index 587d4a21a..1df4db269 100644 --- a/workflow/engine/classes/model/ListParticipatedLast.php +++ b/workflow/engine/classes/model/ListParticipatedLast.php @@ -1,6 +1,7 @@ add(ListParticipatedLastPeer::APP_UID, $appUid, Criteria::EQUAL); + //Update - SET + $criteriaSet = new Criteria("workflow"); + $criteriaSet->add(ListParticipatedLastPeer::APP_STATUS, $status); + BasePeer::doUpdate($criteriaWhere, $criteriaSet, Propel::getConnection("workflow")); + } } diff --git a/workflow/engine/classes/model/ListUnassigned.php b/workflow/engine/classes/model/ListUnassigned.php index 7306ad7fe..a073a8c7b 100644 --- a/workflow/engine/classes/model/ListUnassigned.php +++ b/workflow/engine/classes/model/ListUnassigned.php @@ -333,18 +333,16 @@ class ListUnassigned extends BaseListUnassigned implements ListInterface { try { $arrayAppAssignSelfServiceValueData = []; - $criteria = new Criteria("workflow"); + $group = new Groups(); + //Get the GRP_ID related to the $userUid + $arrayId = $group->getActiveGroupsForAnUserById($userUid); + $sql = "(" - . AppAssignSelfServiceValueGroupPeer::ASSIGNEE_ID . " IN (" - . " SELECT " . GroupUserPeer::GRP_ID . " " - . " FROM " . GroupUserPeer::TABLE_NAME . " " - . " LEFT JOIN " . GroupwfPeer::TABLE_NAME . " ON (" . GroupUserPeer::GRP_ID . "=" . GroupwfPeer::GRP_ID . ") " - . " WHERE " . GroupUserPeer::USR_UID . "='" . $userUid . "' AND " . GroupwfPeer::GRP_STATUS . "='ACTIVE'" - . " ) AND " - . " " . AppAssignSelfServiceValueGroupPeer::ASSIGNEE_TYPE . "=2 " - . ")"; + . AppAssignSelfServiceValueGroupPeer::ASSIGNEE_ID . " IN (" . implode(",", $arrayId) . ") AND " + . " " . AppAssignSelfServiceValueGroupPeer::ASSIGNEE_TYPE . " = 2 " + . ")"; $criteria->setDistinct(); $criteria->addSelectColumn(AppAssignSelfServiceValuePeer::APP_UID); diff --git a/workflow/engine/methods/cases/ajaxListener.php b/workflow/engine/methods/cases/ajaxListener.php index 183764b50..6b64382cf 100644 --- a/workflow/engine/methods/cases/ajaxListener.php +++ b/workflow/engine/methods/cases/ajaxListener.php @@ -394,6 +394,12 @@ class Ajax print(G::json_encode($processData)); } + /** + * Get the task information of the current task + * + * @see workflow/engine/templates/cases/open->taskInformation() + * @link https://wiki.processmaker.com/3.3/Cases/Information#Task_Information + */ public function getTaskInformation() { if (!isset($_SESSION['USER_LOGGED'])) { @@ -408,7 +414,15 @@ class Ajax if ($_SESSION['TASK'] == '-1') { $_SESSION['TASK'] = $_SESSION['CURRENT_TASK']; } - $taskData = $task->getDelegatedTaskData($_SESSION['TASK'], $_SESSION['APPLICATION'], $_SESSION['INDEX']); + + $arrayTaskUid = explode('|', $_SESSION['TASK']); + + if (count($arrayTaskUid) > 1) { + $arrayTaskUid = array_unique($arrayTaskUid); + } + $taskUid = $arrayTaskUid[0]; + + $taskData = $task->getDelegatedTaskData($taskUid, $_SESSION['APPLICATION'], $_SESSION['INDEX']); $taskData = \ProcessMaker\Util\DateTime::convertUtcToTimeZone($taskData); diff --git a/workflow/engine/methods/cases/caseMessageHistory_Ajax.php b/workflow/engine/methods/cases/caseMessageHistory_Ajax.php index 6e4c60fee..8f86eb4f6 100644 --- a/workflow/engine/methods/cases/caseMessageHistory_Ajax.php +++ b/workflow/engine/methods/cases/caseMessageHistory_Ajax.php @@ -1,6 +1,7 @@ xssFilterHard($_POST); @@ -85,6 +86,7 @@ switch ($actionAjax) { if ($respMess == 'BLOCK' || $respMess == '') { $appMessageArray[$index]['APP_MSG_BODY'] = ''; } + $appMessageArray[$index]['APP_MSG_DATE'] = DateTime::convertUtcToTimeZone($appMessageArray[$index]['APP_MSG_DATE']); $messageList[] = array_merge($appMessageArray[$index], ['MSGS_HISTORY' => $respMess]); } } diff --git a/workflow/engine/methods/cases/casesListExtJs.php b/workflow/engine/methods/cases/casesListExtJs.php index 559698ee7..30adfce14 100644 --- a/workflow/engine/methods/cases/casesListExtJs.php +++ b/workflow/engine/methods/cases/casesListExtJs.php @@ -196,7 +196,8 @@ $oHeadPublisher->addExtJsScript('app/main', true); $oHeadPublisher->addExtJsScript('cases/casesList', false); //adding a javascript file .js $oHeadPublisher->addContent('cases/casesListExtJs'); //adding a html file .html. $oHeadPublisher->assign('FORMATS', $c->getFormats()); -$oHeadPublisher->assign('extJsViewState', $oHeadPublisher->getExtJsViewState()); +$oHeadPublisher->assign('userUid', $userUid); +$oHeadPublisher->assign('extJsViewState', $oHeadPublisher->getExtJsViewState($userUid)); $oHeadPublisher->assign('isIE', Bootstrap::isIE()); $oHeadPublisher->assign('__OPEN_APPLICATION_UID__', $openApplicationUid); diff --git a/workflow/engine/methods/cases/cases_Ajax.php b/workflow/engine/methods/cases/cases_Ajax.php index 823fa5734..399ab523b 100644 --- a/workflow/engine/methods/cases/cases_Ajax.php +++ b/workflow/engine/methods/cases/cases_Ajax.php @@ -1,6 +1,7 @@ xssFilterHard($_GET); @@ -581,6 +582,7 @@ switch (($_POST['action']) ? $_POST['action'] : $_REQUEST['action']) { while ($rs->next()) { $result = $rs->getRow(); $result["TYPE"] = (array_key_exists($result["TYPE"], $arrayToTranslation)) ? $arrayToTranslation[$result["TYPE"]] : $result["TYPE"]; + $result['CREATE_DATE'] = DateTime::convertUtcToTimeZone($result['CREATE_DATE']); $aProcesses[] = $result; } @@ -622,7 +624,7 @@ switch (($_POST['action']) ? $_POST['action'] : $_REQUEST['action']) { $result["FILEDOCEXIST"] = ($result["FILEDOC"]); $result["FILEPDFEXIST"] = ($result["FILEPDF"]); $result["DELETE_FILE"] = (isset($result['ID_DELETE']) && $result['ID_DELETE'] == 'Delete') ? true : false; - + $result['CREATE_DATE'] = DateTime::convertUtcToTimeZone($result['CREATE_DATE']); $aProcesses[] = $result; $rs->next(); diff --git a/workflow/engine/methods/cases/summary.php b/workflow/engine/methods/cases/summary.php index 1a843ea22..e20b022ea 100644 --- a/workflow/engine/methods/cases/summary.php +++ b/workflow/engine/methods/cases/summary.php @@ -1,26 +1,6 @@ . - * - * For more information, contact Colosa Inc, 2566 Le Jeune Rd., - * Coral Gables, FL, 33134, USA, or email info@colosa.com. - */ + +use ProcessMaker\Util\DateTime; try { global $RBAC; @@ -70,7 +50,7 @@ try { if ($result->next()) { $FieldsPmDynaform = $applicationFields; $FieldsPmDynaform["CURRENT_DYNAFORM"] = $_REQUEST['DYN_UID']; - $a = new PmDynaform(\ProcessMaker\Util\DateTime::convertUtcToTimeZone($FieldsPmDynaform)); + $a = new PmDynaform(DateTime::convertUtcToTimeZone($FieldsPmDynaform)); $a->printView(); } if (file_exists( PATH_DYNAFORM . $applicationFields['PRO_UID'] . PATH_SEP . $_REQUEST['DYN_UID'] . '.xml' )) { diff --git a/workflow/engine/methods/login/authentication.php b/workflow/engine/methods/login/authentication.php index 5058e0950..1fb2c0864 100644 --- a/workflow/engine/methods/login/authentication.php +++ b/workflow/engine/methods/login/authentication.php @@ -1,5 +1,7 @@ loadOrCreateIfNotExists($_SESSION['USER_LOGGED'], array('USR_PASSWORD_HISTORY' => serialize(array(G::encryptOld($pwd))))); + + //change password + if ($changePassword === true) { + $user = new User(); + $currentUser = $user->changePassword($_SESSION['USER_LOGGED'], $_POST['form']['USR_PASSWORD']); + G::header('Location: ' . $currentUser["__REDIRECT_PATH__"]); + return; + } + //Get the errors in the password $errorInPassword = $userProperty->validatePassword( $_POST['form']['USR_PASSWORD'], @@ -345,13 +368,23 @@ try { $G_PUBLISH = new Publisher; $version = explode('.', trim(file_get_contents(PATH_GULLIVER . 'VERSION'))); $version = isset($version[0]) ? intval($version[0]) : 0; + if ($version >= 3) { - $G_PUBLISH->AddContent('xmlform', 'xmlform', 'login/changePasswordpm3', '', $messPassword, - 'changePassword'); + $values = [ + "usrUsername" => $usr, + "usrPassword" => $pwd, + "userEnvironment" => config("system.workspace"), + "browserTimeZoneOffset" => $_POST['form']['BROWSER_TIME_ZONE_OFFSET'] + ]; + $messPassword['__USR_PASSWORD_CHANGE__'] = G::generateUniqueID(); + Cache::put($messPassword['__USR_PASSWORD_CHANGE__'], $values, 2); + $G_PUBLISH->AddContent('xmlform', 'xmlform', 'login/changePasswordpm3', '', $messPassword, 'sysLoginVerify'); + G::RenderPage('publish'); + session_destroy(); } else { $G_PUBLISH->AddContent('xmlform', 'xmlform', 'login/changePassword', '', $messPassword, 'changePassword'); + G::RenderPage('publish'); } - G::RenderPage('publish'); die; } diff --git a/workflow/engine/methods/login/changePassword.php b/workflow/engine/methods/login/changePassword.php index a17e2739d..43f55089b 100644 --- a/workflow/engine/methods/login/changePassword.php +++ b/workflow/engine/methods/login/changePassword.php @@ -1,92 +1,7 @@ load($_SESSION['USER_LOGGED']); -global $RBAC; -$aData['USR_UID'] = $aUser['USR_UID']; -$aData['USR_USERNAME'] = $aUser['USR_USERNAME']; -$aData['USR_PASSWORD'] = Bootstrap::hashPassword($_POST['form']['USR_PASSWORD']); -$aData['USR_FIRSTNAME'] = $aUser['USR_FIRSTNAME']; -$aData['USR_LASTNAME'] = $aUser['USR_LASTNAME']; -$aData['USR_EMAIL'] = $aUser['USR_EMAIL']; -$aData['USR_DUE_DATE'] = $aUser['USR_DUE_DATE']; -$aData['USR_UPDATE_DATE'] = date('Y-m-d H:i:s'); -$RBAC->updateUser($aData, $aUser['USR_ROLE']); -$aData['USR_COUNTRY'] = $aUser['USR_COUNTRY']; -$aData['USR_CITY'] = $aUser['USR_CITY']; -$aData['USR_LOCATION'] = $aUser['USR_LOCATION']; -$aData['USR_ADDRESS'] = $aUser['USR_ADDRESS']; -$aData['USR_PHONE'] = $aUser['USR_PHONE']; -$aData['USR_ZIP_CODE'] = $aUser['USR_ZIP_CODE']; -$aData['USR_POSITION'] = $aUser['USR_POSITION']; -$oUser->update($aData); -require_once 'classes/model/UsersProperties.php'; -$oUserProperty = new UsersProperties(); -$aUserProperty = $oUserProperty->load($_SESSION['USER_LOGGED']); -$aHistory = unserialize($aUserProperty['USR_PASSWORD_HISTORY']); - -if (!is_array($aHistory)) { - $aHistory = array(); -} - -if (!defined('PPP_PASSWORD_HISTORY')) { - define('PPP_PASSWORD_HISTORY', 0); -} - -if (PPP_PASSWORD_HISTORY > 0) { - if (count($aHistory) >= PPP_PASSWORD_HISTORY) { - array_shift($aHistory); - } - $aHistory[] = $_POST['form']['USR_PASSWORD']; -} - -$aUserProperty['USR_LAST_UPDATE_DATE'] = date('Y-m-d H:i:s'); -$aUserProperty['USR_LOGGED_NEXT_TIME'] = 0; -$aUserProperty['USR_PASSWORD_HISTORY'] = serialize($aHistory); -$oUserProperty->update($aUserProperty); - -if (class_exists('redirectDetail')) { - //falta validar... - if (isset($RBAC->aUserInfo['PROCESSMAKER']['ROLE']['ROL_CODE'])) { - $userRole = $RBAC->aUserInfo['PROCESSMAKER']['ROLE']['ROL_CODE']; - } - $oPluginRegistry = PluginRegistry::loadSingleton(); - //$oPluginRegistry->showArrays(); - $aRedirectLogin = $oPluginRegistry->getRedirectLogins(); - if (isset($aRedirectLogin)) { - if (is_array($aRedirectLogin)) { - /** @var \ProcessMaker\Plugins\Interfaces\RedirectDetail $detail */ - foreach ($aRedirectLogin as $detail) { - if (isset($detail->sPathMethod)) { - if ($detail->equalRoleCodeTo($userRole)) { - G::header( - 'location: /sys' . SYS_TEMP . '/' . SYS_LANG . - '/' . SYS_SKIN . '/' . $detail->getPathMethod() - ); - die; - } - } - } - } - } -} -//end plugin - -if (isset($frm['USER_LANG'])) { - if ($frm['USER_LANG'] != '') { - $lang = $frm['USER_LANG']; - } -} else { - if (defined('SYS_LANG')) { - $lang = SYS_LANG; - } else { - $lang = 'en'; - } -} -$sLocation = $oUserProperty->redirectTo($_SESSION['USER_LOGGED'], $lang); -G::header('Location: ' . $sLocation); -die; +use ProcessMaker\BusinessModel\User; +$user = new User(); +$currentUser = $user->changePassword($_SESSION['USER_LOGGED'], $_POST['form']['USR_PASSWORD'], isset($_POST['form']['USER_LANG']) ? $_POST['form']['USER_LANG'] : ""); +G::header('Location: ' . $currentUser["__REDIRECT_PATH__"]); diff --git a/workflow/engine/methods/mails/emailsAjax.php b/workflow/engine/methods/mails/emailsAjax.php index 903c1275e..d83cf5d07 100644 --- a/workflow/engine/methods/mails/emailsAjax.php +++ b/workflow/engine/methods/mails/emailsAjax.php @@ -2,6 +2,7 @@ use ProcessMaker\Plugins\PluginRegistry; use ProcessMaker\Exception\RBACException; +use ProcessMaker\Util\DateTime; $req = (isset($_REQUEST['request']) ? $_REQUEST['request'] : ''); @@ -131,6 +132,7 @@ switch ($req) { while ($result->next()) { $row = $result->getRow(); $row['APP_MSG_STATUS'] = ucfirst($row['APP_MSG_STATUS']); + $row['APP_MSG_DATE'] = DateTime::convertUtcToTimeZone($row['APP_MSG_DATE']); switch ($filterBy) { case 'CASES': diff --git a/workflow/engine/methods/setup/setupSchemas/triggerContentUpdate.sql b/workflow/engine/methods/setup/setupSchemas/triggerContentUpdate.sql index 2c1a28e6a..20844bf0d 100644 --- a/workflow/engine/methods/setup/setupSchemas/triggerContentUpdate.sql +++ b/workflow/engine/methods/setup/setupSchemas/triggerContentUpdate.sql @@ -3,7 +3,7 @@ CREATE TRIGGER CONTENT_UPDATE BEFORE UPDATE ON CONTENT FOR EACH ROW BEGIN - DECLARE str TEXT; + DECLARE str MEDIUMTEXT; IF (NEW.CON_VALUE IS NULL) THEN SET str = ''; diff --git a/workflow/engine/src/ProcessMaker/BusinessModel/ActionsByEmail.php b/workflow/engine/src/ProcessMaker/BusinessModel/ActionsByEmail.php index d5d4f087b..bdd47c37d 100644 --- a/workflow/engine/src/ProcessMaker/BusinessModel/ActionsByEmail.php +++ b/workflow/engine/src/ProcessMaker/BusinessModel/ActionsByEmail.php @@ -411,7 +411,7 @@ class ActionsByEmail '', '', 'pending', - '', + 1, '', false, isset($dataRes['APP_NUMBER']) ? $dataRes['APP_NUMBER'] : 0, diff --git a/workflow/engine/src/ProcessMaker/BusinessModel/User.php b/workflow/engine/src/ProcessMaker/BusinessModel/User.php index ddcaf367b..e5d18ee37 100644 --- a/workflow/engine/src/ProcessMaker/BusinessModel/User.php +++ b/workflow/engine/src/ProcessMaker/BusinessModel/User.php @@ -2005,4 +2005,111 @@ class User return $isSupervisor; } } + + /** + * It changes the password of the user specified by its identifier, optionally + * the value of $userLang can be sent, otherwise the system value is taken. + * In case of success, the updated user returns. + * + * @global object $RBAC + * @param string $usrUid + * @param string $usrPassword + * @param string $userLang + * + * @return string + * + * @see workflow/engine/methods/login/authentication.php + * @see workflow/engine/methods/login/changePassword.php + * @link https://wiki.processmaker.com/3.0/Managing_Users#Creating_New_Users + */ + public function changePassword($usrUid, $usrPassword, $userLang = "") + { + global $RBAC; + + $users = new Users(); + $user = $users->load($usrUid); + + $data = []; + $data['USR_UID'] = $user['USR_UID']; + $data['USR_USERNAME'] = $user['USR_USERNAME']; + $data['USR_PASSWORD'] = Bootstrap::hashPassword($usrPassword); + $data['USR_FIRSTNAME'] = $user['USR_FIRSTNAME']; + $data['USR_LASTNAME'] = $user['USR_LASTNAME']; + $data['USR_EMAIL'] = $user['USR_EMAIL']; + $data['USR_DUE_DATE'] = $user['USR_DUE_DATE']; + $data['USR_UPDATE_DATE'] = date('Y-m-d H:i:s'); + + $RBAC->updateUser($data, $user['USR_ROLE']); + + $data['USR_COUNTRY'] = $user['USR_COUNTRY']; + $data['USR_CITY'] = $user['USR_CITY']; + $data['USR_LOCATION'] = $user['USR_LOCATION']; + $data['USR_ADDRESS'] = $user['USR_ADDRESS']; + $data['USR_PHONE'] = $user['USR_PHONE']; + $data['USR_ZIP_CODE'] = $user['USR_ZIP_CODE']; + $data['USR_POSITION'] = $user['USR_POSITION']; + + $users->update($data); + + $usersProperties = new UsersProperties(); + $userProperty = $usersProperties->load($usrUid); + $history = unserialize($userProperty['USR_PASSWORD_HISTORY']); + + if (!is_array($history)) { + $history = []; + } + + if (!defined('PPP_PASSWORD_HISTORY')) { + define('PPP_PASSWORD_HISTORY', 0); + } + + if (PPP_PASSWORD_HISTORY > 0) { + if (count($history) >= PPP_PASSWORD_HISTORY) { + array_shift($history); + } + $history[] = $usrPassword; + } + + $userProperty['USR_LAST_UPDATE_DATE'] = date('Y-m-d H:i:s'); + $userProperty['USR_LOGGED_NEXT_TIME'] = 0; + $userProperty['USR_PASSWORD_HISTORY'] = serialize($history); + + $usersProperties->update($userProperty); + + if (class_exists('redirectDetail')) { + + if (isset($RBAC->aUserInfo['PROCESSMAKER']['ROLE']['ROL_CODE'])) { + $userRole = $RBAC->aUserInfo['PROCESSMAKER']['ROLE']['ROL_CODE']; + } + $pluginRegistry = PluginRegistry::loadSingleton(); + + $redirectLogin = $pluginRegistry->getRedirectLogins(); + if (isset($redirectLogin)) { + if (is_array($redirectLogin)) { + foreach ($redirectLogin as $detail) { + if (isset($detail->sPathMethod)) { + if ($detail->equalRoleCodeTo($userRole)) { + $user['__REDIRECT_PATH__'] = '/sys' . config('system.workspace') . '/' . SYS_LANG . '/' . SYS_SKIN . '/' . $detail->getPathMethod(); + return $user; + } + } + } + } + } + } + + $lang = ""; + if ($userLang !== "") { + $lang = $userLang; + } else { + if (defined('SYS_LANG')) { + $lang = SYS_LANG; + } else { + $lang = 'en'; + } + } + $location = $usersProperties->redirectTo($usrUid, $lang); + $user['__REDIRECT_PATH__'] = $location; + return $user; + } } diff --git a/workflow/engine/xmlform/cases/cases_Resume_Current_Task.xml b/workflow/engine/xmlform/cases/cases_Resume_Current_Task.xml index f251935e7..4e80eea7a 100644 --- a/workflow/engine/xmlform/cases/cases_Resume_Current_Task.xml +++ b/workflow/engine/xmlform/cases/cases_Resume_Current_Task.xml @@ -1,5 +1,5 @@ - - + + diff --git a/workflow/engine/xmlform/cases/cases_Resume_Current_Task_Title.xml b/workflow/engine/xmlform/cases/cases_Resume_Current_Task_Title.xml index 778e802cb..d6628fb8c 100644 --- a/workflow/engine/xmlform/cases/cases_Resume_Current_Task_Title.xml +++ b/workflow/engine/xmlform/cases/cases_Resume_Current_Task_Title.xml @@ -1,6 +1,6 @@ - - - + + + diff --git a/workflow/engine/xmlform/login/changePasswordpm3.html b/workflow/engine/xmlform/login/changePasswordpm3.html index ecbc54b0a..ae71c164c 100644 --- a/workflow/engine/xmlform/login/changePasswordpm3.html +++ b/workflow/engine/xmlform/login/changePasswordpm3.html @@ -14,6 +14,7 @@ {$form.USR_PASSWORD} {$form.USR_PASSWORD_CONFIRM} + {$form.__USR_PASSWORD_CHANGE__}