PMC-1195: resolve conflict

This commit is contained in:
Paula Quispe
2019-09-16 11:57:49 -04:00
198 changed files with 17219 additions and 5461 deletions

View File

@@ -0,0 +1,369 @@
<?php
namespace ProcessMaker\BusinessModel\ActionsByEmail;
use AbeConfigurationPeer;
use AbeResponses;
use ActionsByEmailCoreClass;
use AppDelegation;
use AppNotes;
use Bootstrap;
use Cases;
use Criteria;
use EmailServerPeer;
use Exception;
use G;
use Illuminate\Support\Facades\Crypt;
use PhpImap\IncomingMail;
use PhpImap\Mailbox;
use PMLicensedFeatures;
use ProcessMaker\BusinessModel\ActionsByEmail;
use ProcessMaker\BusinessModel\EmailServer;
use ProcessMaker\ChangeLog\ChangeLog;
use ResultSet;
use WsBase;
/**
* Class ResponseReader
* @package ProcessMaker\BusinessModel\ActionsByEmail
*/
class ResponseReader
{
/*----------------------------------********---------------------------------*/
private $channel = "ActionsByEmail";
private $case = [];
private $messageResponseError = null;
/**
* @return string
*/
public function getMessageResponseError()
{
return $this->messageResponseError;
}
/**
* @param string $messageResponseError
*/
public function setMessageResponseError($messageResponseError)
{
$this->messageResponseError = $messageResponseError;
}
/**
* Read the Action by Email listener inbox looking for new messages
*/
public function actionsByEmailEmailResponse()
{
try {
if (!extension_loaded('imap')) {
G::outRes(G::LoadTranslation("ID_EXCEPTION_LOG_INTERFAZ", ['php_imap']) . "\n");
exit;
}
if (PMLicensedFeatures
::getSingleton()
->verifyfeature('zLhSk5TeEQrNFI2RXFEVktyUGpnczV1WEJNWVp6cjYxbTU3R29mVXVZNWhZQT0=')) {
$criteriaAbe = new Criteria();
$criteriaAbe->add(AbeConfigurationPeer::ABE_TYPE, "RESPONSE");
$resultAbe = AbeConfigurationPeer::doSelectRS($criteriaAbe);
$resultAbe->setFetchmode(ResultSet::FETCHMODE_ASSOC);
while ($resultAbe->next()) {
$dataAbe = $resultAbe->getRow();
$this->getAllEmails($dataAbe);
}
}
} catch (Exception $e) {
Bootstrap::registerMonolog(
$this->channel,
$e->getCode() != 0 ? $e->getCode() : 300,
$e->getMessage(),
$this->case,
config("system.workspace"),
'processmaker.log'
);
}
}
/**
* Decrypt password of Email Server
* @param array $emailSetup
* @return mixed|string
*/
private function decryptPassword(array $emailSetup)
{
$pass = isset($emailSetup['MESS_PASSWORD']) ? $emailSetup['MESS_PASSWORD'] : '';
$passDec = G::decrypt($pass, 'EMAILENCRYPT');
$auxPass = explode('hash:', $passDec);
if (count($auxPass) > 1) {
if (count($auxPass) == 2) {
$pass = $auxPass[1];
} else {
array_shift($auxPass);
$pass = implode('', $auxPass);
}
}
return $pass;
}
/**
* Get all Email of server listener
* @param array $dataAbe
*/
public function getAllEmails(array $dataAbe)
{
try {
$emailServer = new EmailServer();
$emailSetup = (!is_null(EmailServerPeer::retrieveByPK($dataAbe['ABE_EMAIL_SERVER_RECEIVER_UID']))) ?
$emailServer->getEmailServer($dataAbe['ABE_EMAIL_SERVER_RECEIVER_UID'], true) :
$emailServer->getEmailServerDefault();
if (empty($emailSetup) || (empty($emailSetup['MESS_INCOMING_SERVER']) && $emailSetup['MESS_INCOMING_PORT'] == 0)) {
throw (new Exception(G::LoadTranslation('ID_ABE_LOG_CANNOT_READ'), 500));
}
$mailbox = new Mailbox(
'{'. $emailSetup['MESS_INCOMING_SERVER'] . ':' . $emailSetup['MESS_INCOMING_PORT'] . '/imap/ssl/novalidate-cert}INBOX',
$emailSetup['MESS_ACCOUNT'],
$this->decryptPassword($emailSetup)
);
// Read all messages into an array
$mailsIds = $mailbox->searchMailbox('UNSEEN');
if ($mailsIds) {
// Get the first message and save its attachment(s) to disk:
foreach ($mailsIds as $key => $mailId) {
/** @var IncomingMail $mail */
$mail = $mailbox->getMail($mailId, false);
if (!empty($mail->textPlain)) {
preg_match("/{(.*)}/", $mail->textPlain, $matches);
if ($matches) {
try {
$dataEmail = G::json_decode(Crypt::decryptString($matches[1]), true);
} catch (Exception $e) {
Bootstrap::registerMonolog(
$this->channel,
300,
G::LoadTranslation('ID_ABE_RESPONSE_CANNOT_BE_IDENTIFIED'),
[],
config("system.workspace"),
'processmaker.log'
);
$mailbox->markMailAsRead($mailId);
continue;
}
$dataAbeReq = loadAbeRequest($dataEmail['ABE_REQ_UID']);
if (config("system.workspace") === $dataEmail['workspace']
&& (array_key_exists('ABE_UID', $dataAbeReq) && $dataAbeReq['ABE_UID'] == $dataAbe['ABE_UID'])) {
$this->case = $dataEmail;
try {
$appDelegate = new AppDelegation();
$alreadyRouted = $appDelegate->alreadyRouted($this->case["appUid"], $this->case["delIndex"]);
//Verify if the current case is already routed.
if ($alreadyRouted) {
$this->setMessageResponseError(G::LoadTranslation('ID_ABE_RESPONSE_ALREADY_ROUTED'));
throw (new Exception(G::LoadTranslation('ID_CASE_DELEGATION_ALREADY_CLOSED'), 400));
}
$this->processABE($this->case, $mail, $dataAbe);
Bootstrap::registerMonolog(
$this->channel,
100, // DEBUG
G::LoadTranslation('ID_ABE_LOG_PROCESSED_OK'),
$this->case,
config("system.workspace"),
'processmaker.log'
);
} catch (Exception $e) {
$this->sendMessageError(
$this->getMessageResponseError() ? $this->getMessageResponseError() : $e->getMessage(),
$this->case,
$mail,
$emailSetup
);
Bootstrap::registerMonolog(
$this->channel,
$e->getCode() != 0 ? $e->getCode() : 400,
$e->getMessage(),
$this->case,
config("system.workspace"),
'processmaker.log'
);
}
$mailbox->markMailAsRead($mailId);
}
}
}
}
}
} catch (Exception $e) {
Bootstrap::registerMonolog(
$this->channel,
$e->getCode() != 0 ? $e->getCode() : 500,
$e->getMessage(),
$this->case,
config("system.workspace"),
'processmaker.log'
);
}
}
/**
* Derivation of the case with the mail information
* @param array $caseInfo
* @param IncomingMail $mail
* @param array $dataAbe
* @throws Exception
*/
public function processABE(array $caseInfo, IncomingMail $mail, array $dataAbe = [])
{
try {
$actionsByEmail = new ActionsByEmail();
$actionsByEmail->verifyLogin($caseInfo['appUid'], $caseInfo['delIndex']);
$case = new Cases();
$caseFieldsABE = $case->loadCase($caseInfo['appUid'], $caseInfo['delIndex']);
$actionsByEmailCore = new ActionsByEmailCoreClass();
$actionField = str_replace(
$actionsByEmailCore->getPrefix(),
'',
$dataAbe['ABE_ACTION_FIELD']
);
$dataField = [];
$dataField[$actionField] = $caseInfo['fieldValue'];
$actionBodyField = str_replace(
$actionsByEmailCore->getPrefix(),
'',
$dataAbe['ABE_ACTION_BODY_FIELD']
);
$textPlain = $mail->textPlain;
$textPlain = substr($textPlain, 0, strpos($textPlain, "/="));
$dataField[$actionBodyField] = $textPlain;
$caseFieldsABE['APP_DATA'] = array_merge($caseFieldsABE['APP_DATA'], $dataField);
$dataResponses = [];
$dataResponses['ABE_REQ_UID'] = $caseInfo['ABE_REQ_UID'];
$dataResponses['ABE_RES_CLIENT_IP'] = 'localhost';
$dataResponses['ABE_RES_DATA'] = serialize($dataField);
$dataResponses['ABE_RES_STATUS'] = 'PENDING';
$dataResponses['ABE_RES_MESSAGE'] = '';
try {
$abeAbeResponsesInstance = new AbeResponses();
$dataResponses['ABE_RES_UID'] = $abeAbeResponsesInstance->createOrUpdate($dataResponses);
} catch (Exception $e) {
Bootstrap::registerMonolog(
$this->channel,
300,
$e->getMessage(),
$this->case,
config("system.workspace"),
'processmaker.log'
);
}
ChangeLog::getChangeLog()
->getUsrIdByUsrUid($caseFieldsABE['CURRENT_USER_UID'], true)
->setSourceId(ChangeLog::FromABE);
$caseFieldsABE['CURRENT_DYNAFORM'] = '';
$caseFieldsABE['USER_UID'] = $caseFieldsABE['CURRENT_USER_UID'];
$caseFieldsABE['OBJECT_TYPE'] = '';
$case->updateCase($caseInfo['appUid'], $caseFieldsABE);
try {
$ws = new WsBase();
$result = $ws->derivateCase(
$caseFieldsABE['CURRENT_USER_UID'],
$caseInfo['appUid'],
$caseInfo['delIndex'],
true
);
$code = (is_array($result)) ? $result['status_code'] : $result->status_code;
if ($code != 0) {
throw new Exception(
"An error occurred while the application was being processed\n" .
"Error code: " . $result->status_code . "\nError message: " . $result->message
);
}
} catch (Exception $e) {
$this->setMessageResponseError(G::LoadTranslation('ID_ABE_RESPONSE_ROUTING_FAILED'));
throw (new Exception(G::LoadTranslation('ID_ABE_LOG_ROUTING_FAILED'), 400));
}
//Update AbeResponses
$dataResponses['ABE_RES_STATUS'] = ($code == 0)? 'SENT' : 'ERROR';
$dataResponses['ABE_RES_MESSAGE'] = ($code == 0)? '-' : $result->message;
try {
$abeAbeResponsesInstance = new AbeResponses();
$abeAbeResponsesInstance->createOrUpdate($dataResponses);
} catch (Exception $e) {
Bootstrap::registerMonolog(
$this->channel,
300,
$e->getMessage(),
$this->case,
config("system.workspace"),
'processmaker.log'
);
}
$dataAbeRequests = loadAbeRequest($caseInfo['ABE_REQ_UID']);
//Save Cases Notes
if ($dataAbe['ABE_CASE_NOTE_IN_RESPONSE'] == 1) {
$customGrid = unserialize($dataAbe['ABE_CUSTOM_GRID']);
$fieldLabel = null;
foreach ($customGrid as $key => $value) {
if ($value['abe_custom_value'] == $caseInfo['fieldValue']) {
$fieldLabel = $value['abe_custom_label'];
break;
}
}
$appNotes = new AppNotes();
$noteText = G::LoadTranslation('ID_ABE_CASE_NOTE_HEADER', ['emailAccount' => $mail->toString]) . "\n\n";
$noteText .= G::LoadTranslation('ID_ABE_CASE_NOTE_ANSWER', ['optionLabel' => $fieldLabel ? $fieldLabel : $caseInfo['fieldValue']]) . "\n\n";
$noteText .= G::LoadTranslation('ID_ABE_CASE_NOTE_COMMENT', ['emailBody' => $textPlain]);
$noteContent = addslashes($noteText);
$appNotes->postNewNote($caseInfo['appUid'], $caseFieldsABE['APP_DATA']['USER_LOGGED'], $noteContent, false);
}
$dataAbeRequests['ABE_REQ_ANSWERED'] = 1;
$code == 0 ? uploadAbeRequest($dataAbeRequests) : '';
} catch (Exception $e) {
if ($e->getCode() == 400) {
throw (new Exception($e->getMessage(), $e->getCode()));
} else {
$this->setMessageResponseError(G::LoadTranslation('ID_ABE_RESPONSE_CANNOT_BE_IDENTIFIED'));
throw (new Exception(G::LoadTranslation('ID_ABE_LOG_CANNOT_BE_IDENTIFIED'), 300));
}
}
}
/**
* Send an error message to the sender
* @param string $msgError
* @param array $caseInf
* @param IncomingMail $mail
* @param array $emailSetup
* @return \ProcessMaker\Util\Response|string|\WsResponse
*/
public function sendMessageError($msgError, array $caseInf, IncomingMail $mail, array $emailSetup)
{
$wsBase = new WsBase();
$result = $wsBase->sendMessage(
$caseInf['appUid'],
$mail->toString,
$mail->fromAddress,
'',
'',
$mail->subject,
'actionsByEmailErrorReply.html',
['ACTIONS_BY_EMAIL_ERROR_MESSAGE' => $msgError],
null,
true,
$caseInf['delIndex'],
$emailSetup,
0,
WsBase::MESSAGE_TYPE_ACTIONS_BY_EMAIL
);
return $result;
}
/*----------------------------------********---------------------------------*/
}

View File

@@ -54,13 +54,71 @@ trait SuggestTrait
$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"];
$qf = str_replace("'", "''", $json->queryFilter);
$where = $isWhere ? "WHERE " . $col . " LIKE '%" . $qf . "%'" : $where . " AND " . $col . " LIKE '%" . $qf . "%'";
if (isset($json->querySearch) && is_array($json->querySearch) && !empty($json->querySearch)) {
$dataSearch = $json->querySearch;
$sqlWildcard = "";
//We will to search term in the query
if (isset($dataSearch['term'])) {
$value = isset($dataSearch['term']['value']) ? $dataSearch['term']['value'] : '';
$label = isset($dataSearch['term']['text']) ? $dataSearch['term']['text'] : '';
$sqlWildcard = "%";
}
//The match has priority
//We will to search match in the query
if (isset($dataSearch['match'])) {
$value = isset($dataSearch['match']['value']) ? $dataSearch['match']['value'] : '';
$label = isset($dataSearch['match']['text']) ? $dataSearch['match']['text'] : '';
$sqlWildcard = "";
}
if (!empty($value) && !empty($label)){
//We need to search in the firstColumn and secondColumn
//Ex: SELECT COL1, COL2 FROM TABLE WHERE COL1 LIKE 'querySearch' OR COL2 LIKE 'querySearch'
//Ex: SELECT COL1, COL2 FROM TABLE WHERE COL1 LIKE '%querySearch%' OR COL2 LIKE '%querySearch%'
$col1 = $dt[0]["base_expr"];
$col2 = isset($dt[1]["base_expr"]) ? $dt[1]["base_expr"] : $dt[0]["base_expr"];
$qfValue = str_replace("'", "''", $value);
$qfLabel = str_replace("'", "''", $label);
$search = $col1 . " LIKE '" . $sqlWildcard . $qfValue . $sqlWildcard . "' OR " . $col2 . " LIKE '" . $sqlWildcard . $qfLabel . $sqlWildcard . "'";
$where = $isWhere ? "WHERE " . $search : $where . " AND (" . $search . ")";
} else {
$valueOrLabel = '';
$column = $dt[0]["base_expr"];
if (!empty($value)) {
//We need to search in the firstColumn
//Ex: SELECT COL1, COL2 FROM TABLE WHERE COL1 LIKE 'querySearch'
//Ex: SELECT COL1, COL2 FROM TABLE WHERE COL1 LIKE '%querySearch%'
$valueOrLabel = $value;
}
if (!empty($label)) {
//We need to search in the secondColumn
//Ex: SELECT COL1, COL2 FROM TABLE WHERE COL2 LIKE 'querySearch'
//Ex: SELECT COL1, COL2 FROM TABLE WHERE COL2 LIKE '%querySearch%'
$column = isset($dt[1]["base_expr"]) ? $dt[1]["base_expr"] : $column;
$valueOrLabel = $label;
}
$where = $this->buildWhere(
$column,
$valueOrLabel,
$sqlWildcard,
$isWhere,
$where
);
}
} else {
//If the property querySearch does not exist we need to search in the secondColumn
//Ex: SELECT COL1, COL2 FROM TABLE WHERE COL2 LIKE '%queryFilter%'
if (isset($json->queryField) && isset($dt[0]["base_expr"])) {
$where = $this->buildWhere(
isset($dt[1]["base_expr"]) ? $dt[1]["base_expr"] : $dt[0]["base_expr"],
$json->queryFilter,
"%",
$isWhere,
$where
);
}
}
if ($optionsLimit > 0) {
if ($optionsLimit >= 0) {
$this->addSuggestLimit($json, $select, $limit, $where);
} else {
$this->addSuggestWhere($json, $parsed, $select, $where, $having);
@@ -69,6 +127,26 @@ trait SuggestTrait
);
}
/**
* This function will be define the WHERE clause
*
* @param string $col, name of column
* @param string $value, value to search in the column
* @param string $sqlWildcard, if we to search term or correct match
* @param boolean $isWhere, if the we need to concat other condition
* @param string $where, initial where to add the concat
*
* @return string
*
*/
private function buildWhere($col, $value, $sqlWildcard = "", $isWhere = false, $where = "")
{
$qf = str_replace("'", "''", $value);
$searchValue = $col . " LIKE '" . $sqlWildcard . $qf . $sqlWildcard;
$where = ($isWhere) ? "WHERE " . $searchValue . "'" : $where . " AND " . $searchValue . "'";
return $where;
}
/**
* Add the limit sentence to the suggest query.
*

View File

@@ -14,9 +14,11 @@ class EmailServer
{
private $arrayFieldDefinition = array(
"MESS_UID" => array("type" => "string", "required" => false, "empty" => false, "defaultValues" => array(), "fieldNameAux" => "emailServerUid"),
"MESS_ENGINE" => array("type" => "string", "required" => true, "empty" => false, "defaultValues" => array("PHPMAILER", "MAIL"), "fieldNameAux" => "emailServerEngine"),
"MESS_ENGINE" => array("type" => "string", "required" => true, "empty" => false, "defaultValues" => array("PHPMAILER", "MAIL", "IMAP"), "fieldNameAux" => "emailServerEngine"),
"MESS_SERVER" => array("type" => "string", "required" => false, "empty" => true, "defaultValues" => array(), "fieldNameAux" => "emailServerServer"),
"MESS_PORT" => array("type" => "int", "required" => false, "empty" => true, "defaultValues" => array(), "fieldNameAux" => "emailServerPort"),
"MESS_INCOMING_SERVER" => array("type" => "string", "required" => false, "empty" => true, "defaultValues" => array(), "fieldNameAux" => "emailServerIncomingServer"),
"MESS_INCOMING_PORT" => array("type" => "int", "required" => false, "empty" => true, "defaultValues" => array(), "fieldNameAux" => "emailServerIncomingPort"),
"MESS_RAUTH" => array("type" => "int", "required" => false, "empty" => false, "defaultValues" => array(0, 1), "fieldNameAux" => "emailServerRauth"),
"MESS_ACCOUNT" => array("type" => "string", "required" => false, "empty" => true, "defaultValues" => array(), "fieldNameAux" => "emailServerUserName"),
"MESS_PASSWORD" => array("type" => "string", "required" => false, "empty" => true, "defaultValues" => array(), "fieldNameAux" => "emailServerPassword"),
@@ -52,10 +54,10 @@ class EmailServer
throw $e;
}
}
/**
* Get the default information from the context.
*
*
* @global type $RBAC
* @return void
*/
@@ -527,6 +529,7 @@ class EmailServer
}
break;
case "PHPMAILER":
case "IMAP":
$numSteps = ($arrayData['MAIL_TO'] != '') ? count($arrayPhpMailerTestName) :
count($arrayPhpMailerTestName) - 1;
for ($step = 1; $step <= $numSteps; $step++) {
@@ -831,6 +834,8 @@ class EmailServer
'engine'=> $arrayData["MESS_ENGINE"],
'server' => $arrayData["MESS_SERVER"],
'port' => $arrayData["MESS_PORT"],
'incomingServer' => $arrayData["MESS_INCOMING_SERVER"],
'incomingPort' => $arrayData["MESS_INCOMING_PORT"],
'requireAuthentication' => $arrayData["MESS_RAUTH"],
'account' => $arrayData["MESS_ACCOUNT"],
'senderEmail' => $arrayData["MESS_FROM_MAIL"],
@@ -1002,6 +1007,8 @@ class EmailServer
'engine' => $arrayData["MESS_ENGINE"],
'server' => $arrayData["MESS_SERVER"],
'port' => $arrayData["MESS_PORT"],
'incomingServer' => $arrayData["MESS_INCOMING_SERVER"],
'incomingPort' => $arrayData["MESS_INCOMING_PORT"],
'requireAuthentication' => $arrayData["MESS_RAUTH"],
'account' => $arrayData["MESS_ACCOUNT"],
'senderEmail' => $arrayData["MESS_FROM_MAIL"],
@@ -1088,6 +1095,8 @@ class EmailServer
$criteria->addSelectColumn(\EmailServerPeer::MESS_ENGINE);
$criteria->addSelectColumn(\EmailServerPeer::MESS_SERVER);
$criteria->addSelectColumn(\EmailServerPeer::MESS_PORT);
$criteria->addSelectColumn(\EmailServerPeer::MESS_INCOMING_SERVER);
$criteria->addSelectColumn(\EmailServerPeer::MESS_INCOMING_PORT);
$criteria->addSelectColumn(\EmailServerPeer::MESS_RAUTH);
$criteria->addSelectColumn(\EmailServerPeer::MESS_ACCOUNT);
$criteria->addSelectColumn(\EmailServerPeer::MESS_PASSWORD);
@@ -1120,6 +1129,8 @@ class EmailServer
$this->getFieldNameByFormatFieldName("MESS_ENGINE") => $record["MESS_ENGINE"],
$this->getFieldNameByFormatFieldName("MESS_SERVER") => $record["MESS_SERVER"],
$this->getFieldNameByFormatFieldName("MESS_PORT") => $record["MESS_PORT"],
$this->getFieldNameByFormatFieldName("MESS_INCOMING_SERVER") => $record["MESS_INCOMING_SERVER"],
$this->getFieldNameByFormatFieldName("MESS_INCOMING_PORT") => $record["MESS_INCOMING_PORT"],
$this->getFieldNameByFormatFieldName("MESS_RAUTH") => $record["MESS_RAUTH"],
$this->getFieldNameByFormatFieldName("MESS_ACCOUNT") => $record["MESS_ACCOUNT"],
$this->getFieldNameByFormatFieldName("MESS_PASSWORD") => $record["MESS_PASSWORD"],
@@ -1165,6 +1176,8 @@ class EmailServer
$arrayData["MESS_ENGINE"] = $row["MESS_ENGINE"];
$arrayData["MESS_SERVER"] = $row["MESS_SERVER"];
$arrayData["MESS_PORT"] = (int)($row["MESS_PORT"]);
$arrayData["MESS_INCOMING_SERVER"] = $row["MESS_INCOMING_SERVER"];
$arrayData["MESS_INCOMING_PORT"] = (int)($row["MESS_INCOMING_PORT"]);
$arrayData["MESS_RAUTH"] = (int)($row["MESS_RAUTH"]);
$arrayData["MESS_ACCOUNT"] = $row["MESS_ACCOUNT"];
$arrayData["MESS_PASSWORD"] = $row["MESS_PASSWORD"];
@@ -1221,6 +1234,7 @@ class EmailServer
$criteria->add(
$criteria->getNewCriterion(\EmailServerPeer::MESS_ENGINE, "%" . $arrayFilterData["filter"] . "%", \Criteria::LIKE)->addOr(
$criteria->getNewCriterion(\EmailServerPeer::MESS_SERVER, "%" . $arrayFilterData["filter"] . "%", \Criteria::LIKE))->addOr(
$criteria->getNewCriterion(\EmailServerPeer::MESS_INCOMING_SERVER,"%" . $arrayFilterData["filter"] . "%", \Criteria::LIKE))->addOr(
$criteria->getNewCriterion(\EmailServerPeer::MESS_ACCOUNT, "%" . $arrayFilterData["filter"] . "%", \Criteria::LIKE))->addOr(
$criteria->getNewCriterion(\EmailServerPeer::MESS_FROM_NAME, "%" . $arrayFilterData["filter"] . "%", \Criteria::LIKE))->addOr(
$criteria->getNewCriterion(\EmailServerPeer::SMTPSECURE, "%" . $arrayFilterData["filter"] . "%", \Criteria::LIKE))
@@ -1245,7 +1259,7 @@ class EmailServer
if (!is_null($sortField) && trim($sortField) != "") {
$sortField = strtoupper($sortField);
if (in_array($sortField, array("MESS_ENGINE", "MESS_SERVER", "MESS_ACCOUNT", "MESS_FROM_NAME", "SMTPSECURE"))) {
if (in_array($sortField, array("MESS_ENGINE", "MESS_SERVER", "MESS_INCOMING_SERVER", "MESS_ACCOUNT", "MESS_FROM_NAME", "SMTPSECURE"))) {
$sortField = \EmailServerPeer::TABLE_NAME . "." . $sortField;
} else {
$sortField = \EmailServerPeer::MESS_ENGINE;
@@ -1318,6 +1332,7 @@ class EmailServer
$row = $rsCriteria->getRow();
$row["MESS_PORT"] = (int)($row["MESS_PORT"]);
$row["MESS_INCOMING_PORT"] = (int)($row["MESS_INCOMING_PORT"]);
$row["MESS_RAUTH"] = (int)($row["MESS_RAUTH"]);
$row["MESS_TRY_SEND_INMEDIATLY"] = (int)($row["MESS_TRY_SEND_INMEDIATLY"]);
$row["MESS_DEFAULT"] = (int)($row["MESS_DEFAULT"]);

View File

@@ -0,0 +1,43 @@
<?php
namespace ProcessMaker\BusinessModel\Factories;
use Closure;
use Exception;
class Jobs
{
const CLASS_NAMESPACE = "App\\Jobs\\";
/**
* Gets the full name of the class, if the class does not exist, an exception is thrown.
* @param string $name
* @return string
* @throws Exception
*/
public static function getClassName($name)
{
$className = self::CLASS_NAMESPACE . $name;
if (!class_exists($className)) {
throw new Exception("{$className} not exists.");
}
return $className;
}
/**
* This gets an instance of some Job defined in App\Jobs and dispatch this job.
* @param string $name
* @param Closure $closure
* @return object
*/
public static function create($name, Closure $closure)
{
$jobName = self::getClassName($name);
$instance = $jobName::dispatch($closure);
return $instance;
}
}

View File

@@ -30,6 +30,7 @@ use ProcessMaker\ChangeLog\ChangeLog;
/*----------------------------------********---------------------------------*/
use ProcessMaker\Core\RoutingScreen;
use ProcessMaker\Core\System;
use ProcessMaker\Model\Process as ProcessEloquent;
use ProcessMaker\Services\Api\Project\Activity\Step as ActivityStep;
use ProcessMaker\Util\DateTime;
use ProcessMaker\Validation\ExceptionRestApi;
@@ -1237,109 +1238,29 @@ class Light
}
/**
* @param $action
* @param $categoryUid
* @param $userUid
* Return the list of processes
*
* @param string $action
* @param string $categoryUid
* @param string $userUid
*
* @see ProcessMaker\Services\Api\Light::getProcessList();
*
* @return array
* @throws PropelException
*/
public function getProcessList($action, $categoryUid, $userUid)
{
//$action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : null;
//$categoryUid = isset( $_REQUEST['CATEGORY_UID'] ) ? $_REQUEST['CATEGORY_UID'] : null;
//$userUid = (isset( $_SESSION['USER_LOGGED'] ) && $_SESSION['USER_LOGGED'] != '') ? $_SESSION['USER_LOGGED'] : null;
$processes = [];
$processes[] = ['', G::LoadTranslation('ID_ALL_PROCESS')];
// global $oAppCache;
$oAppCache = new AppCacheView();
$processes = array();
$processes[] = array('', G::LoadTranslation('ID_ALL_PROCESS'));
$process = new ProcessEloquent();
$processList = $process->getProcessList($categoryUid, $userUid);
//get the list based in the action provided
switch ($action) {
case 'draft':
$cProcess = $oAppCache->getDraftListCriteria($userUid); //fast enough
break;
case 'sent':
$cProcess = $oAppCache->getSentListProcessCriteria($userUid); // fast enough
break;
case 'simple_search':
case 'search':
//in search action, the query to obtain all process is too slow, so we need to query directly to
//process and content tables, and for that reason we need the current language in AppCacheView.
$values = (array_map(function ($x) {
return array_values([$x['PRO_UID'], $x['PRO_TITLE']]);
}, $processList));
$oConf = new Configurations();
$oConf->loadConfig($x, 'APP_CACHE_VIEW_ENGINE', '', '', '', '');
$appCacheViewEngine = $oConf->aConfig;
$lang = isset($appCacheViewEngine['LANG']) ? $appCacheViewEngine['LANG'] : 'en';
$cProcess = new Criteria('workflow');
$cProcess->clearSelectColumns();
$cProcess->addSelectColumn(ProcessPeer::PRO_UID);
$cProcess->addSelectColumn(ProcessPeer::PRO_TITLE);
if ($categoryUid) {
$cProcess->add(ProcessPeer::PRO_CATEGORY, $categoryUid);
}
$cProcess->add(ProcessPeer::PRO_STATUS, 'ACTIVE');
$cProcess->addAscendingOrderByColumn(ProcessPeer::PRO_TITLE);
$oDataset = ProcessPeer::doSelectRS($cProcess);
$oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC);
$oDataset->next();
while ($aRow = $oDataset->getRow()) {
$processes[] = array($aRow['PRO_UID'], $aRow['PRO_TITLE']);
$oDataset->next();
}
return print G::json_encode($processes);
break;
case 'unassigned':
$cProcess = $oAppCache->getUnassignedListCriteria($userUid);
break;
case 'paused':
$cProcess = $oAppCache->getPausedListCriteria($userUid);
break;
case 'to_revise':
$cProcess = $oAppCache->getToReviseListCriteria($userUid);
break;
case 'to_reassign':
$cProcess = $oAppCache->getToReassignListCriteria($userUid);
break;
case 'gral':
$cProcess = $oAppCache->getGeneralListCriteria();
break;
case 'todo':
default:
$cProcess = $oAppCache->getToDoListCriteria($userUid); //fast enough
break;
}
//get the processes for this user in this action
$cProcess->clearSelectColumns();
$cProcess->addSelectColumn(AppCacheViewPeer::PRO_UID);
$cProcess->addSelectColumn(AppCacheViewPeer::APP_PRO_TITLE);
$cProcess->setDistinct(AppCacheViewPeer::PRO_UID);
if ($categoryUid) {
require_once 'classes/model/Process.php';
$cProcess->addAlias('CP', 'PROCESS');
$cProcess->add('CP.PRO_CATEGORY', $categoryUid, Criteria::EQUAL);
$cProcess->addJoin(AppCacheViewPeer::PRO_UID, 'CP.PRO_UID', Criteria::LEFT_JOIN);
$cProcess->addAsColumn('CATEGORY_UID', 'CP.PRO_CATEGORY');
}
$cProcess->addAscendingOrderByColumn(AppCacheViewPeer::APP_PRO_TITLE);
$oDataset = AppCacheViewPeer::doSelectRS($cProcess, Propel::getDbConnection('workflow_ro'));
$oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC);
$oDataset->next();
while ($aRow = $oDataset->getRow()) {
$processes[] = array(
$aRow['PRO_UID'],
$aRow['APP_PRO_TITLE']
);
$oDataset->next();
}
$processes = array_merge($processes, $values);
return $processes;
}

View File

@@ -18,7 +18,7 @@ use ProcessMaker\Core\System;
class PushMessageAndroid
{
private $url = 'https://fcm.googleapis.com/fcm/send';
private $serverApiKey = "AAAAMvip2iU:APA91bHFAvHmCsSh0zbRaC9Xo2EPIbbRYzehkFAKUdXmj_ZVBOOO52npae183LYUONHjNPHaKo1MqT4BWiEuTF7HVEMfwn05XOA-h1LQ_bJ0ezAA35l-wADPq5VtKDiHT1VFGW1oeU7L";
private $serverApiKey = "AAAAshotYCU:APA91bH25JoNzd_mTIwhMraFdWL7Bu4Fugw6kzTeXyS2x4AUM-FkdB-CWUrI4SeTLsTpFRkT3IH68P6E97Wb7E1ZIc0TpBnZXA3Q3tzrLB8mT4SHkrzVpdbaBnNz8_ih2-FcwYwREoEv";
private $devices = [];
private $numberDevices = 0;

View File

@@ -8,6 +8,7 @@ use G;
use PMmemcached;
use ProcessPeer;
use ResultSet;
use UsersPropertiesPeer;
class Process
{
@@ -2160,4 +2161,21 @@ class Process
return $processes;
}
/**
* Set for the first time the user opened the dynaform editor.
*
* @param string $usrUid
* @param string $seen
*/
public function setIfFirstTimeConsumed($usrUid, $seen)
{
if ($seen === '1') {
$userProperties = UsersPropertiesPeer::retrieveByPk($usrUid);
if ($userProperties) {
$userProperties->setPmDynaformFirstTime('1');
$userProperties->save();
}
}
}
}

View File

@@ -749,6 +749,8 @@ class Variable
*
* @return array
* @throws Exception
* @see ProcessMaker\BusinessModel\Variable->executeSql()
* @see ProcessMaker\BusinessModel\Variable->executeSqlSuggest()
*/
public function executeSqlControl($proUid, array $params = [])
{
@@ -758,6 +760,7 @@ class Variable
$dynUid = $params["dyn_uid"];
$fieldId = $params["field_id"];
$filter = isset($params["filter"]) ? $params["filter"] : "";
$query = isset($params["query"]) ? $params["query"] : [];
$start = isset($params["start"]) ? $params["start"] : 0;
$limit = isset($params["limit"]) ? $params["limit"] : 10;
$appUid = empty($params["app_uid"]) ? null : $params["app_uid"];
@@ -767,6 +770,7 @@ class Variable
unset($params["app_uid"]);
unset($params["del_index"]);
unset($params["filter"]);
unset($params["query"]);
unset($params["start"]);
unset($params["limit"]);
@@ -797,6 +801,7 @@ class Variable
$field->queryField = true;
$field->queryInputData = $params;
$field->queryFilter = $filter;
$field->querySearch = $query;
$field->queryStart = $start;
$field->queryLimit = $limit;
//Grids only access the global variables of 'ProcessMaker', other variables are removed.
@@ -809,7 +814,12 @@ class Variable
}
//Populate control data
$pmDynaform->clearLastQueryError();
$pmDynaform->jsonr($field);
$error = $pmDynaform->getLastQueryError();
if (!empty($error) && is_object($error)) {
throw new Exception(G::LoadTranslation("ID_ERROR_IN_THE_QUERY"));
}
$result = [];
if (isset($field->queryOutputData) && is_array($field->queryOutputData)) {
foreach ($field->queryOutputData as $item) {

View File

@@ -0,0 +1,219 @@
<?php
namespace ProcessMaker\Core;
use Exception;
use Illuminate\Support\Facades\Log;
use ProcessMaker\BusinessModel\Factories\Jobs;
use ProcessMaker\Core\System;
use Propel;
class JobsManager
{
/**
* Single object instance to be used in the entire environment.
*
* @var object
*/
private static $jobsManager = null;
/**
* Delayed Dispatching: To delay the execution of a queued job.
* The time is
* in minutes.
* @var int
*/
private $delay;
/**
* Specifying Max Job Attempts: specifying the maximum number of times a job
* may be attempted.
* Number of times by default is 10, It is defined in env.ini file.
* @var int
*/
private $tries;
/**
* Job Expiration: Specifies how many seconds the queue connection should wait
* before retrying a job that is being processed.
* Time is in seconds.
* @var int
*/
private $retryAfter;
/**
* This is a list of the values that are saved from the current session.
* @var array
*/
private $sessionValues = [
'__SYSTEM_UTC_TIME_ZONE__',
'USER_LOGGED',
'USR_USERNAME',
'APPLICATION',
'INDEX',
'PROCESS',
'TASK',
];
/**
* Get delay property.
* @return int
*/
public function getDelay()
{
return $this->delay;
}
/**
* Get tries property.
* @return int
*/
public function getTries()
{
return $this->tries;
}
/**
* Get retryAfter property.
* @return int
*/
public function getRetryAfter()
{
return $this->retryAfter;
}
/**
* It obtains a single object to be used as a record of the whole environment.
*
* @return object
*/
public static function getSingleton()
{
if (self::$jobsManager === null) {
self::$jobsManager = new JobsManager();
}
return self::$jobsManager;
}
/**
* This initialize environment configuration values.
* @return JobsManager
*/
public function init()
{
$envs = System::getSystemConfiguration('', '', config("system.workspace"));
$this->delay = $envs['delay'];
$this->tries = $envs['tries'];
$this->retryAfter = $envs['retry_after'];
config(['queue.connections.database.retry_after' => $this->retryAfter]);
return $this;
}
/**
* This obtains a status of the current values that are running. The status
* of the values will be used by the Job at a future time when the job is
* launched.
* @return array
*/
private function getDataSnapshot()
{
$constants = get_defined_constants(true);
$session = $this->getSessionValues();
return [
'errorReporting' => ini_get('error_reporting'),
'configuration' => Propel::getConfiguration(),
'constants' => $constants['user'],
'session' => $session,
'server' => $_SERVER,
];
}
/**
* This sets the status of the values when the job is launched. Accepts the
* result of the execution of the getDataSnapshot() method.
* @param array $environment
*/
private function recoverDataSnapshot($environment)
{
$this->prepareEnvironment($environment);
$_SESSION = $environment['session'];
$_SERVER = $environment['server'];
Propel::initConfiguration($environment['configuration']);
foreach ($environment['constants'] as $key => $value) {
if (!defined($key)) {
define($key, $value);
}
}
}
/**
* This allows you to configure the PHP environment policies. The parameter
* must contain the correct indices.
* @param array $environment
*/
private function prepareEnvironment($environment)
{
ini_set('error_reporting', $environment['errorReporting']);
}
/**
* This gets the values defined in the $this->sessionValues property from
* the current $_SESSION.
* @return array
*/
private function getSessionValues()
{
$result = [];
foreach ($this->sessionValues as $key) {
if (array_key_exists($key, $_SESSION)) {
$result[$key] = $_SESSION[$key];
}
}
return $result;
}
/**
* Dispatch a job to its appropriate handler.
* @param string $name
* @param Closure $callback
* @return object
*/
public function dispatch($name, $callback)
{
$environment = $this->getDataSnapshot();
$instance = Jobs::create($name, function() use ($callback, $environment) {
try {
$this->recoverDataSnapshot($environment);
$callback($environment);
} catch (Exception $e) {
Log::error($e->getMessage() . ": " . $e->getTraceAsString());
}
});
$instance->delay($this->delay);
return $instance;
}
/**
* This gets the value of the option specified in the second parameter from an
* array that represents the arguments.
* If the option is not found, it returns false.
* @param array $arguments
* @param string $option
* @return string|boolean
*/
public function getOptionValueFromArguments($arguments, $option, $allocationSeparator = "=")
{
$option = $option . $allocationSeparator;
$result = preg_grep("/{$option}/", $arguments);
if (empty($result)) {
return false;
}
$string = array_pop($result);
$value = str_replace($option, "", $string);
return trim($value);
}
}

View File

@@ -0,0 +1,98 @@
<?php
namespace ProcessMaker\Core;
/**
* Class to manage the processes that runs in the shell
*/
class ProcessesManager
{
// Class properties
private $processes;
private $sleepTime = 1;
private $terminated = [];
private $errors = [];
/**
* Class constructor
*
* @param array $processes
*/
public function __construct(array $processes)
{
$this->processes = $processes;
}
/**
* Get the list of terminated processes
*
* @return array
*/
public function getTerminated()
{
return $this->terminated;
}
/**
* Get the list of processes with errors
*
* @return array
*/
public function getErrors()
{
return $this->errors;
}
/**
* Set the sleep time after each statuses revision
*
* @param int $sleepTime
*/
public function setSleepTime($sleepTime)
{
$this->sleepTime = $sleepTime;
}
/**
* Run the processes
*/
public function run()
{
// Start all processes
foreach ($this->processes as $process) {
$process->run();
}
// Manage the processes
$this->manage();
}
/**
* Manage all started processes
*/
private function manage()
{
do {
// Check all remaining processes
foreach ($this->processes as $index => $process) {
// If the process has finished, save the info and destroy it
if ($process->getStatus() === RunProcess::TERMINATED || $process->getStatus() === RunProcess::ERROR) {
$processInfo = ['command' => $process->getCommand(), 'rawAnswer' => $process->getRawAnswer()];
if ($process->getStatus() === RunProcess::TERMINATED) {
// Processes completed successfully
$this->terminated[] = $processInfo;
} else {
// Processes completed with errors
$this->errors[] = $processInfo;
}
// Destroy the process
unset($this->processes[$index]);
}
}
// Waiting...
sleep($this->sleepTime);
} while (!empty($this->processes));
}
}

View File

@@ -0,0 +1,146 @@
<?php
namespace ProcessMaker\Core;
/**
* This class run a command in shell and stores the pointer to him
*/
class RunProcess
{
// Class constants
const TERMINATED = 'terminated';
const RUNNING = 'running';
const NOT_RUNNING = 'not_running';
const ERROR = 'error';
// This constant can be overrides in the child class according to the command response, always should be have a value
const EXPECTED_ANSWER = '1';
// Class properties
private $resource;
private $command;
private $rawAnswer;
private $status;
private $exitCode;
private $pipes;
private $descriptors = [
['pipe', 'r'],
['pipe', 'w'],
['pipe', 'w']
];
/**
* Class constructor
*
* @param string $command
*/
public function __construct($command)
{
$this->command = $command;
}
/**
* Class destructor, the resource created should be closed
*/
public function __destruct()
{
if (is_resource($this->resource)) {
proc_close($this->resource);
}
}
/**
* Get the command
*
* @return string
*/
public function getCommand()
{
return $this->command;
}
/**
* Get the raw response
*
* @return string|null
*/
public function getRawAnswer()
{
return $this->rawAnswer;
}
/**
* Get the status
*
* @return string
*/
public function getStatus()
{
// If already exist a status return this value
if ($this->status !== null) {
return $this->status;
}
// If doesn't exists a resource the process is not running
if (!is_resource($this->resource)) {
return self::NOT_RUNNING;
}
// If the process is running return this value
if ($this->isRunning()) {
return self::RUNNING;
}
// If the process is not running, parse the response to determine the status
$this->rawAnswer = stream_get_contents($this->pipes[1]);
$this->status = $this->parseAnswer();
return $this->status;
}
/**
* Get the exit code
*
* @return string|null
*/
public function getExitCode()
{
return $this->exitCode;
}
/**
* Run the command
*/
public function run()
{
$this->resource = proc_open($this->command, $this->descriptors, $this->pipes);
}
/**
* Process is running?
*
* @return bool
*/
public function isRunning()
{
// Get the process status
$status = proc_get_status($this->resource);
// If process is not running get the exit code
if ($status['running'] === false) {
$this->exitCode = $status['exitcode'];
}
return $status['running'];
}
/**
* Process the raw response and compare with the expected answer in order to determine the status
*
* @return string
*/
public function parseAnswer()
{
return $this->rawAnswer === self::EXPECTED_ANSWER ? self::TERMINATED : self::ERROR;
}
}

View File

@@ -9,6 +9,7 @@ use Faker;
use G;
use GzipFile;
use Illuminate\Database\QueryException;
use Illuminate\Foundation\Http\Kernel;
use Illuminate\Support\Facades\DB;
use InputFilter;
use InstallerModule;
@@ -29,7 +30,7 @@ class System
private static $config = null;
private static $debug = null;
private static $instance;
private static $defaultConfig = array(
private static $defaultConfig = [
'debug' => 0,
'debug_sql' => 0,
'debug_time' => 0,
@@ -68,10 +69,12 @@ class System
'smtp_timeout' => 20,
'google_map_api_key' => '',
'google_map_signature' => '',
'logging_level' => 'INFO',
'upload_attempts_limit_per_user' => '60,1',
'files_white_list' => ''
);
'files_white_list' => '',
'delay' => '0',
'tries' => '10',
'retry_after' => '90'
];
/**
* List currently installed plugins
@@ -243,39 +246,6 @@ class System
return $items;
}
/**
* Review the checksum.txt
*
* @return array $result
*/
public static function verifyChecksum()
{
if (!file_exists(PATH_TRUNK . "checksum.txt")) {
return false;
}
$lines = explode("\n", file_get_contents(PATH_TRUNK . "checksum.txt"));
$result = array("diff" => array(), "missing" => array()
);
foreach ($lines as $line) {
if (empty($line)) {
continue;
}
list ($checksum, $empty, $filename) = explode(" ", $line);
//Skip xmlform because these files always change.
if (strpos($filename, "/xmlform/") !== false) {
continue;
}
if (file_exists(realpath($filename))) {
if (strcmp($checksum, G::encryptFileOld(realpath($filename))) != 0) {
$result['diff'][] = $filename;
}
} else {
$result['missing'][] = $filename;
}
}
return $result;
}
/**
* This function checks files to do updated to pm
*
@@ -742,12 +712,13 @@ class System
/**
* Retrieves a schema array from a file.
*
* @param string $sSchemaFile schema filename
* @return string $sContent
* @param string $schemaFile schema filename
*
* @return array
*/
public static function getSchema($sSchemaFile)
public static function getSchema($schemaFile)
{
/* This is the MySQL mapping that Propel uses (from MysqlPlatform.php) */
// This is the MySQL mapping that Propel uses (from MysqlPlatform.php)
$mysqlTypes = [
'NUMERIC' => 'DECIMAL',
'LONGVARCHAR' => 'MEDIUMTEXT',
@@ -758,32 +729,38 @@ class System
'LONGVARBINARY' => 'LONGBLOB',
'BLOB' => 'LONGBLOB',
'CLOB' => 'LONGTEXT',
/* This is not from Propel, but is required to get INT right */
// This is not from Propel, but is required to get INT right
'INTEGER' => 'INT'
];
$aSchema = [];
$oXml = new DomDocument();
$oXml->load($sSchemaFile);
$aTables = $oXml->getElementsByTagName('table');
foreach ($aTables as $oTable) {
$aPrimaryKeys = [];
$sTableName = $oTable->getAttribute('name');
$aSchema[$sTableName] = [];
$aColumns = $oTable->getElementsByTagName('column');
foreach ($aColumns as $oColumn) {
$sColumName = $oColumn->getAttribute('name');
$schema = [];
/* Get the field type. Propel uses VARCHAR if nothing else is specified */
$type = $oColumn->hasAttribute('type') ? strtoupper($oColumn->getAttribute('type')) : "VARCHAR";
// Parse schema
$xml = new DomDocument();
$xml->load($schemaFile);
/* Convert type to MySQL type according to Propel */
// Build the schema array
$tablesNodes = $xml->getElementsByTagName('table');
foreach ($tablesNodes as $tableNode) {
$primaryKeys = [];
$tableName = $tableNode->getAttribute('name');
$schema[$tableName] = [];
$columnsNodes = $tableNode->getElementsByTagName('column');
foreach ($columnsNodes as $columnNode) {
$columnName = $columnNode->getAttribute('name');
// Get the field type. Propel uses VARCHAR if nothing else is specified
$type = $columnNode->hasAttribute('type') ? strtoupper($columnNode->getAttribute('type')) : "VARCHAR";
// Convert type to MySQL type according to Propel
if (array_key_exists($type, $mysqlTypes)) {
$type = $mysqlTypes[$type];
}
$size = $oColumn->hasAttribute('size') ? $oColumn->getAttribute('size') : null;
/* Add default sizes from MySQL */
// Get "size" attribute
$size = $columnNode->hasAttribute('size') ? $columnNode->getAttribute('size') : null;
// Add default sizes from MySQL
if ($type == "TINYINT" && !$size) {
$size = "4";
}
@@ -795,46 +772,64 @@ class System
$type = "$type($size)";
}
$required = $oColumn->hasAttribute('required') ? $oColumn->getAttribute('required') : null;
/* Convert $required to a bool */
$required = (in_array(strtolower($required), array('1', 'true'
)));
$autoIncrement = $oColumn->hasAttribute('autoIncrement') ? $oColumn->hasAttribute('autoIncrement') : false;
$unique = $oColumn->hasAttribute('unique') ? $oColumn->hasAttribute('unique') : false;
$default = $oColumn->hasAttribute('default') ? $oColumn->getAttribute('default') : null;
// Get "required" attribute
$required = $columnNode->hasAttribute('required') ? $columnNode->getAttribute('required') : null;
$primaryKey = $oColumn->hasAttribute('primaryKey') ? $oColumn->getAttribute('primaryKey') : null;
/* Convert $primaryKey to a bool */
$primaryKey = (in_array(strtolower($primaryKey), array('1', 'true'
)));
// Convert $required to a bool
$required = (in_array(strtolower($required), ['1', 'true']));
$autoIncrement = $columnNode->hasAttribute('autoIncrement') ? $columnNode->hasAttribute('autoIncrement') : false;
$unique = $columnNode->hasAttribute('unique') ? $columnNode->hasAttribute('unique') : false;
$default = $columnNode->hasAttribute('default') ? $columnNode->getAttribute('default') : null;
$primaryKey = $columnNode->hasAttribute('primaryKey') ? $columnNode->getAttribute('primaryKey') : null;
// Convert $primaryKey to a bool
$primaryKey = (in_array(strtolower($primaryKey), ['1', 'true']));
if ($primaryKey) {
$aPrimaryKeys[] = $sColumName;
$primaryKeys[] = $columnName;
}
$aSchema[$sTableName][$sColumName] = array(
'Field' => $sColumName,
// Add the metadata from the column
$schema[$tableName][$columnName] = [
'Field' => $columnName,
'Type' => $type,
'Null' => $required ? "NO" : "YES",
'Default' => $default,
'AutoIncrement' => $autoIncrement,
'Unique' => $unique,
'PrimaryKey' => $primaryKey
);
];
}
if (is_array($aPrimaryKeys) && count($aPrimaryKeys) > 0) {
$aSchema[$sTableName]['INDEXES']['PRIMARY'] = $aPrimaryKeys;
// Add primary keys to "indexes" list
if (is_array($primaryKeys) && count($primaryKeys) > 0) {
$schema[$tableName]['INDEXES']['PRIMARY'] = $primaryKeys;
}
$aIndexes = $oTable->getElementsByTagName('index');
foreach ($aIndexes as $oIndex) {
$aIndex = [];
$aIndexesColumns = $oIndex->getElementsByTagName('index-column');
foreach ($aIndexesColumns as $oIndexColumn) {
$aIndex[] = $oIndexColumn->getAttribute('name');
// Search normal indexes
$indexesNodes = $tableNode->getElementsByTagName('index');
foreach ($indexesNodes as $indexNode) {
$indexes = [];
$indexesColumnsNodes = $indexNode->getElementsByTagName('index-column');
foreach ($indexesColumnsNodes as $indexColumnNode) {
$indexes[] = $indexColumnNode->getAttribute('name');
}
$aSchema[$sTableName]['INDEXES'][$oIndex->getAttribute('name')] = $aIndex;
$schema[$tableName]['INDEXES'][$indexNode->getAttribute('name')] = $indexes;
}
// Search fulltext indexes
$fulltextNodes = $tableNode->getElementsByTagName('fulltext');
foreach ($fulltextNodes as $fulltextNode) {
$fulltextIndexes = [];
$indexColumnsNodes = $fulltextNode->getElementsByTagName('index-column');
foreach ($indexColumnsNodes as $indexColumnsNode) {
$fulltextIndexes[] = $indexColumnsNode->getAttribute('name');
}
$schema[$tableName]['FULLTEXT'][$fulltextNode->getAttribute('name')] = $fulltextIndexes;
}
}
return $aSchema;
return $schema;
}
/**
@@ -857,63 +852,63 @@ class System
}
/**
* Returns the difference between two schema arrays
* Returns the difference between two schemas
*
* @param array $aOldSchema original schema array
* @param array $aNewSchema new schema array
* @return array with tablesToAdd, tablesToAlter, tablesWithNewIndex and tablesToAlterIndex
* @param array $oldSchema original schema
* @param array $newSchema new schema
*
* @return array with tablesToAdd, tablesToAlter, tablesWithNewIndex, tablesToAlterIndex, tablesWithNewFulltext and tablesToAlterFulltext
*/
public static function compareSchema($aOldSchema, $aNewSchema)
public static function compareSchema($oldSchema, $newSchema)
{
$aChanges = array(
'tablesToAdd' => array(),
'tablesToAlter' => array(),
'tablesWithNewIndex' => array(),
'tablesToAlterIndex' => array()
);
$changes = [
'tablesToAdd' => [],
'tablesToAlter' => [],
'tablesWithNewIndex' => [],
'tablesToAlterIndex' => [],
'tablesWithNewFulltext' => [],
'tablesToAlterFulltext' => []
];
//new tables to create and alter
foreach ($aNewSchema as $sTableName => $aColumns) {
if (!isset($aOldSchema[$sTableName])) {
$aChanges['tablesToAdd'][$sTableName] = $aColumns;
// New tables to create and alter
foreach ($newSchema as $tableName => $columns) {
if (!isset($oldSchema[$tableName])) {
$changes['tablesToAdd'][$tableName] = $columns;
} else {
//drop old columns
foreach ($aOldSchema[$sTableName] as $sColumName => $aParameters) {
if (!isset($aNewSchema[$sTableName][$sColumName])) {
if (!isset($aChanges['tablesToAlter'][$sTableName])) {
$aChanges['tablesToAlter'][$sTableName] = array('DROP' => array(), 'ADD' => array(), 'CHANGE' => array()
);
// Drop old columns
foreach ($oldSchema[$tableName] as $columnName => $parameters) {
if (!isset($newSchema[$tableName][$columnName])) {
if (!isset($changes['tablesToAlter'][$tableName])) {
$changes['tablesToAlter'][$tableName] = ['DROP' => [], 'ADD' => [], 'CHANGE' => []];
}
$aChanges['tablesToAlter'][$sTableName]['DROP'][$sColumName] = $sColumName;
$changes['tablesToAlter'][$tableName]['DROP'][$columnName] = $columnName;
}
}
//create new columns
//foreach ($aNewSchema[$sTableName] as $sColumName => $aParameters) {
foreach ($aColumns as $sColumName => $aParameters) {
if ($sColumName != 'INDEXES') {
if (!isset($aOldSchema[$sTableName][$sColumName])) {
//this column doesnt exist in oldschema
if (!isset($aChanges['tablesToAlter'][$sTableName])) {
$aChanges['tablesToAlter'][$sTableName] = array('DROP' => array(), 'ADD' => array(), 'CHANGE' => array()
);
// Create new columns
foreach ($columns as $columnName => $parameters) {
if ($columnName != 'INDEXES' && $columnName != 'FULLTEXT') {
if (!isset($oldSchema[$tableName][$columnName])) {
// This column doesn't exist in old schema
if (!isset($changes['tablesToAlter'][$tableName])) {
$changes['tablesToAlter'][$tableName] = ['DROP' => [], 'ADD' => [], 'CHANGE' => []];
}
$aChanges['tablesToAlter'][$sTableName]['ADD'][$sColumName] = $aParameters;
$changes['tablesToAlter'][$tableName]['ADD'][$columnName] = $parameters;
} else {
//the column exists
$newField = $aNewSchema[$sTableName][$sColumName];
$oldField = $aOldSchema[$sTableName][$sColumName];
//both are null, no change is required
// The column exists
$newField = $newSchema[$tableName][$columnName];
$oldField = $oldSchema[$tableName][$columnName];
// Both are null, no change is required
if (!isset($newField['Default']) && !isset($oldField['Default'])) {
$changeDefaultAttr = false;
//one of them is null, change IS required
// One of them is null, change is required
}
if (!isset($newField['Default']) && isset($oldField['Default']) && $oldField['Default'] != '') {
$changeDefaultAttr = true;
}
if (isset($newField['Default']) && !isset($oldField['Default'])) {
$changeDefaultAttr = true;
//both are defined and they are different.
// Both are defined and they are different.
}
if (isset($newField['Default']) && isset($oldField['Default'])) {
if ($newField['Default'] != $oldField['Default']) {
@@ -922,63 +917,78 @@ class System
$changeDefaultAttr = false;
}
}
//special cases
// BLOB and TEXT columns cannot have DEFAULT values. http://dev.mysql.com/doc/refman/5.0/en/blob.html
if (in_array(strtolower($newField['Type']), array('text', 'mediumtext'))) {
// Special cases, BLOB and TEXT columns cannot have DEFAULT values. http://dev.mysql.com/doc/refman/5.0/en/blob.html
if (in_array(strtolower($newField['Type']), ['text', 'mediumtext'])) {
$changeDefaultAttr = false;
}
//#1067 - Invalid default value for datetime field
if (in_array($newField['Type'], array('datetime')) && isset($newField['Default']) && $newField['Default'] == '') {
// #1067 - Invalid default value for datetime field
if (in_array($newField['Type'], ['datetime']) && isset($newField['Default']) && $newField['Default'] == '') {
$changeDefaultAttr = false;
}
//#1067 - Invalid default value for int field
// #1067 - Invalid default value for int field
if (substr($newField['Type'], 0, 3) == "INT" && isset($newField['Default']) && $newField['Default'] == '') {
$changeDefaultAttr = false;
}
//if any difference exists, then insert the difference in aChanges
// If any difference exists, then insert the difference in "changes" variable
if (strcasecmp($newField['Field'], $oldField['Field']) !== 0 || strcasecmp($newField['Type'], $oldField['Type']) !== 0 || strcasecmp($newField['Null'], $oldField['Null']) !== 0 || $changeDefaultAttr) {
if (!isset($aChanges['tablesToAlter'][$sTableName])) {
$aChanges['tablesToAlter'][$sTableName] = array('DROP' => array(), 'ADD' => array(), 'CHANGE' => array());
if (!isset($changes['tablesToAlter'][$tableName])) {
$changes['tablesToAlter'][$tableName] = ['DROP' => [], 'ADD' => [], 'CHANGE' => []];
}
$aChanges['tablesToAlter'][$sTableName]['CHANGE'][$sColumName]['Field'] = $newField['Field'];
$aChanges['tablesToAlter'][$sTableName]['CHANGE'][$sColumName]['Type'] = $newField['Type'];
$aChanges['tablesToAlter'][$sTableName]['CHANGE'][$sColumName]['Null'] = $newField['Null'];
$changes['tablesToAlter'][$tableName]['CHANGE'][$columnName]['Field'] = $newField['Field'];
$changes['tablesToAlter'][$tableName]['CHANGE'][$columnName]['Type'] = $newField['Type'];
$changes['tablesToAlter'][$tableName]['CHANGE'][$columnName]['Null'] = $newField['Null'];
if (isset($newField['Default'])) {
$aChanges['tablesToAlter'][$sTableName]['CHANGE'][$sColumName]['Default'] = $newField['Default'];
$changes['tablesToAlter'][$tableName]['CHANGE'][$columnName]['Default'] = $newField['Default'];
} else {
$aChanges['tablesToAlter'][$sTableName]['CHANGE'][$sColumName]['Default'] = null;
$changes['tablesToAlter'][$tableName]['CHANGE'][$columnName]['Default'] = null;
}
}
}
}
//only columns, no the indexes column
// Only columns, no the indexes column
}
//foreach $aColumns
//now check the indexes of table
if (isset($aNewSchema[$sTableName]['INDEXES'])) {
foreach ($aNewSchema[$sTableName]['INDEXES'] as $indexName => $indexFields) {
if (!isset($aOldSchema[$sTableName]['INDEXES'][$indexName])) {
if (!isset($aChanges['tablesWithNewIndex'][$sTableName])) {
$aChanges['tablesWithNewIndex'][$sTableName] = [];
// Now check the normal indexes of the table
if (isset($newSchema[$tableName]['INDEXES'])) {
foreach ($newSchema[$tableName]['INDEXES'] as $indexName => $indexFields) {
if (!isset($oldSchema[$tableName]['INDEXES'][$indexName])) {
if (!isset($changes['tablesWithNewIndex'][$tableName])) {
$changes['tablesWithNewIndex'][$tableName] = [];
}
$aChanges['tablesWithNewIndex'][$sTableName][$indexName] = $indexFields;
$changes['tablesWithNewIndex'][$tableName][$indexName] = $indexFields;
} else {
if ($aOldSchema[$sTableName]['INDEXES'][$indexName] != $indexFields) {
if (!isset($aChanges['tablesToAlterIndex'][$sTableName])) {
$aChanges['tablesToAlterIndex'][$sTableName] = [];
if ($oldSchema[$tableName]['INDEXES'][$indexName] != $indexFields) {
if (!isset($changes['tablesToAlterIndex'][$tableName])) {
$changes['tablesToAlterIndex'][$tableName] = [];
}
$aChanges['tablesToAlterIndex'][$sTableName][$indexName] = $indexFields;
$changes['tablesToAlterIndex'][$tableName][$indexName] = $indexFields;
}
}
}
}
// Now check the "fulltext" indexes of the table
if (isset($newSchema[$tableName]['FULLTEXT'])) {
foreach ($newSchema[$tableName]['FULLTEXT'] as $indexName => $indexFields) {
if (!isset($oldSchema[$tableName]['FULLTEXT'][$indexName])) {
if (!isset($changes['tablesWithNewFulltext'][$tableName])) {
$changes['tablesWithNewFulltext'][$tableName] = [];
}
$changes['tablesWithNewFulltext'][$tableName][$indexName] = $indexFields;
} else {
if ($oldSchema[$tableName]['FULLTEXT'][$indexName] != $indexFields) {
if (!isset($changes['tablesToAlterFulltext'][$tableName])) {
$changes['tablesToAlterFulltext'][$tableName] = [];
}
$changes['tablesToAlterFulltext'][$tableName][$indexName] = $indexFields;
}
}
}
}
}
//for-else table exists
}
//for new schema
return $aChanges;
return $changes;
}
public static function getEmailConfiguration()
@@ -1630,5 +1640,46 @@ class System
{
return !empty(self::getServerHostname()) ? self::getServerHostname() : 'processmaker.com';
}
/**
* Initialize laravel database configuration
* @see workflow/engine/bin/tasks/cliWorkspaces.php->check_queries_incompatibilities()
*/
public static function initLaravel()
{
config(['database.connections.workflow.host' => DB_HOST]);
config(['database.connections.workflow.database' => DB_NAME]);
config(['database.connections.workflow.username' => DB_USER]);
config(['database.connections.workflow.password' => DB_PASS]);
app()->useStoragePath(realpath(PATH_DATA));
app()->make(Kernel::class)->bootstrap();
restore_error_handler();
}
/**
* If the installation file exists it returns the defined values.
* @return object
*/
public static function getPathsInstalled()
{
//default values
$result = [
'pathData' => getcwd() . '/shared',
'pathCompiled' => getcwd() . '/shared/compiled',
];
$pathsInstalled = getcwd() . "/workflow/engine/config/paths_installed.php";
if (file_exists($pathsInstalled)) {
$script = "require_once '{$pathsInstalled}';"
. "return ["
. "'pathData' => PATH_DATA,"
. "'pathCompiled' => PATH_C,"
. "'hashInstallation' => HASH_INSTALLATION,"
. "'systemHash' => SYSTEM_HASH,"
. "];";
$result = eval($script);
}
return (object) $result;
}
}
// end System class

View File

@@ -0,0 +1,17 @@
<?php
namespace ProcessMaker\Model;
use Illuminate\Database\Eloquent\Model;
class Configuration extends Model
{
// Set our table name
protected $table = 'CONFIGURATION';
// Set the PK
protected $primaryKey = ['CFG_UID', 'OBJ_UID', 'PRO_UID', 'USR_UID', 'APP_UID'];
// No timestamps
public $timestamps = false;
public $incrementing = false;
}

View File

@@ -225,7 +225,14 @@ class Delegation extends Model
$query->join('APPLICATION', function ($join) use ($filterBy, $search, $status, $query) {
$join->on('APP_DELEGATION.APP_NUMBER', '=', 'APPLICATION.APP_NUMBER');
if ($filterBy == 'APP_TITLE' && $search) {
$join->where('APPLICATION.APP_TITLE', 'LIKE', "%${search}%");
// Cleaning "fulltext" operators in order to avoid unexpected results
$search = str_replace(['-', '+', '<', '>', '(', ')', '~', '*', '"'], ['', '', '', '', '', '', '', '', ''], $search);
// Build the "fulltext" expression
$search = '+"' . preg_replace('/\s+/', '" +"', addslashes($search)) . '"';
// Searching using "fulltext" index
$join->whereRaw("MATCH(APPLICATION.APP_TITLE) AGAINST('{$search}' IN BOOLEAN MODE)");
}
// Based on the below, we can further limit the join so that we have a smaller data set based on join criteria
switch ($status) {
@@ -278,7 +285,7 @@ class Delegation extends Model
// Search for an app/case number
if ($filterBy == 'APP_NUMBER' && $search) {
$query->where('APP_DELEGATION.APP_NUMBER', 'LIKE', "%${search}%");
$query->where('APP_DELEGATION.APP_NUMBER', '=', $search);
}
// Date range filter
@@ -505,4 +512,55 @@ class Delegation extends Model
return $query->count();
}
/**
* This function get the current user related to the specific case and index
*
* @param integer $appNumber, Case number
* @param integer $index, Index to review
* @param string $status, The status of the thread
*
* @return string
*/
public static function getCurrentUser($appNumber, $index, $status = 'OPEN')
{
$query = Delegation::query()->select('USR_UID');
$query->where('APP_NUMBER', $appNumber);
$query->where('DEL_INDEX', $index);
$query->where('DEL_THREAD_STATUS', $status);
$query->first();
$results = $query->get();
$userUid = '';
$results->each(function ($item, $key) use (&$userUid) {
$userUid = $item->USR_UID;
});
return $userUid;
}
/**
* Return the open thread related to the task
*
* @param integer $appNumber, Case number
* @param string $tasUid, The task uid
*
* @return array
*/
public static function getOpenThreads($appNumber, $tasUid)
{
$query = Delegation::query()->select();
$query->where('DEL_THREAD_STATUS', 'OPEN');
$query->where('DEL_FINISH_DATE', null);
$query->where('APP_NUMBER', $appNumber);
$query->where('TAS_UID', $tasUid);
$results = $query->get();
$arrayOpenThreads = [];
$results->each(function ($item, $key) use (&$arrayOpenThreads) {
$arrayOpenThreads = $item->toArray();
});
return $arrayOpenThreads;
}
}

View File

@@ -66,4 +66,16 @@ class Dynaform extends Model
->where('DYNAFORM.DYN_UID', '!=', $dynUid)
->get();
}
/**
* Scope a query to filter an specific process
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $columns
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeProcess($query, string $proUID)
{
return $query->where('PRO_UID', $proUID);
}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace ProcessMaker\Model;
use Illuminate\Database\Eloquent\Model;
class EmailServer extends Model
{
protected $table = 'EMAIL_SERVER';
protected $primaryKey = 'MESS_UID';
public $timestamps = false;
}

View File

@@ -39,4 +39,28 @@ class Process extends Model
{
return $this->hasOne(ProcessCategory::class, 'PRO_CATEGORY', 'CATEGORY_UID');
}
/**
* Obtains the process list for an specific user and/or for the specific category
*
* @param string $categoryUid
* @param string $userUid
* @return array
*
* @see ProcessMaker\BusinessModel\Light::getProcessList()
*/
public function getProcessList($categoryUid, $userUid)
{
$selectedColumns = ['PRO_UID', 'PRO_TITLE'];
$query = Process::query()
->select($selectedColumns)
->where('PRO_STATUS', 'ACTIVE')
->where('PRO_CREATE_USER', $userUid);
if (!empty($categoryUid)) {
$query->where('PRO_CATEGORY', $categoryUid);
}
return ($query->get()->values()->toArray());
}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace ProcessMaker\Model;
use Illuminate\Database\Eloquent\Model;
class ProcessFiles extends Model
{
protected $table = 'PROCESS_FILES';
protected $primaryKey = 'PRF_UID';
public $timestamps = false;
}

View File

@@ -0,0 +1,27 @@
<?php
namespace ProcessMaker\Model;
use Illuminate\Database\Eloquent\Model;
class ProcessVariables extends Model
{
// Set our table name
protected $table = 'PROCESS_VARIABLES';
// No timestamps
public $timestamps = false;
//primary key
protected $primaryKey = 'VAR_UID';
/**
* Scope a query to filter an specific process
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $columns
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeProcess($query, string $proUID)
{
return $query->where('PRJ_UID', $proUID);
}
}

View File

@@ -39,7 +39,7 @@ class TaskUser extends Model
$groups = GroupUser::getGroups($usrUid, 'GRP_UID');
// Build query
$query = Task::query()->select('TAS_ID');
$query = Task::query()->select('TASK.TAS_ID');
//Add Join with process filtering only the active process
$query->join('PROCESS', function ($join) {
$join->on('PROCESS.PRO_UID', '=', 'TASK.PRO_UID')

View File

@@ -0,0 +1,27 @@
<?php
namespace ProcessMaker\Model;
use Illuminate\Database\Eloquent\Model;
class Triggers extends Model
{
// Set our table name
protected $table = 'TRIGGERS';
// No timestamps
public $timestamps = false;
//primary key
protected $primaryKey = 'TRI_UID';
/**
* Scope a query to filter an specific process
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $columns
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeProcess($query, string $proUID)
{
return $query->where('PRO_UID', $proUID);
}
}

View File

@@ -154,6 +154,13 @@ class ActionsByEmail extends Api
$arrayData = $filesManager->addProcessFilesManager($proId, $userUid, $data);
@copy(PATH_TPL . 'actionsByEmail' . PATH_SEP . 'actionsByEmail.html', $path . 'actionsByEmail.html');
}
/*----------------------------------********---------------------------------*/
if (!file_exists($path . 'actionsByEmailErrorReply.html')) {
$data = array('prf_content' => '', 'prf_filename' => 'actionsByEmailErrorReply.html', 'prf_path' => 'templates');
$arrayData = $filesManager->addProcessFilesManager($proId, $userUid, $data);
@copy(PATH_TPL . 'actionsByEmail' . PATH_SEP . 'actionsByEmailErrorReply.html', $path . 'actionsByEmailErrorReply.html');
}
/*----------------------------------********---------------------------------*/
}
$directory = dir($path);

View File

@@ -366,8 +366,9 @@ class Project extends Api
*
* @url GET /:prj_uid/dynaforms
* @param string $prj_uid {@min 32}{@max 32}
* @param string $seen
*/
public function doGetDynaForms($prj_uid)
public function doGetDynaForms($prj_uid, $seen = '0')
{
try {
$process = new \ProcessMaker\BusinessModel\Process();
@@ -375,7 +376,7 @@ class Project extends Api
$process->setArrayFieldNameForException(array("processUid" => "prj_uid"));
$response = $process->getDynaForms($prj_uid);
$process->setIfFirstTimeConsumed($this->getUserId(), $seen);
return DateTime::convertUtcToIso8601($response, $this->arrayFieldIso8601);
} catch (Exception $e) {
throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage()));

View File

@@ -0,0 +1,61 @@
<?php
namespace ProcessMaker\Upgrade;
use ProcessMaker\Core\RunProcess;
/**
* Extended class to manage the processes that executes a queries in the upgrade process
*/
class RunProcessUpgradeQuery extends RunProcess
{
// Class constants
const SUCCESS = 'success';
const CMD = PHP_BINARY . ' processmaker upgrade-query %s %s %s';
const RBAC = '1';
const NO_RBAC = '0';
// Class properties
private $workspace;
private $sql;
private $isRbac;
/**
* Class constructor
*
* @param string $workspace
* @param string $sql
* @param bool $isRbac
*/
public function __construct($workspace, $sql, $isRbac = false)
{
// Set properties values
$this->workspace = $workspace;
$this->sql = $sql;
$this->isRbac = $isRbac;
// Build the command and send to the parent class
parent::__construct($this->buildCommand());
}
/**
* Override the parent method in order to compare the raw response with the SUCCESS value
*
* @return string
*/
public function parseAnswer()
{
return $this->getRawAnswer() === self::SUCCESS ? parent::TERMINATED : parent::ERROR;
}
/**
* Build the command to execute a query for the upgrade process
*
* @return string
*/
private function buildCommand()
{
return sprintf(self::CMD, $this->workspace, base64_encode($this->sql),
($this->isRbac ? self::RBAC : self::NO_RBAC));
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace ProcessMaker\Util;
use WsResponse;
class WsMessageResponse extends WsResponse
{
private $appMessUid = null;
/**
* Get the appMessUid
*
* @return array
*/
public function getAppMessUid()
{
return $this->appMessUid;
}
/**
* Set the appMessUid
*
* @param string $v
* @return void
*/
public function setAppMessUid($v)
{
$this->appMessUid = $v;
}
}

0
workflow/engine/src/ProcessMaker/Util/helpers.php Executable file → Normal file
View File

View File

@@ -0,0 +1,110 @@
<?php
namespace ProcessMaker\Validation;
use ProcessMaker\Model\Dynaform;
use ProcessMaker\Model\Process;
use ProcessMaker\Model\ProcessVariables;
use ProcessMaker\Model\Triggers;
class MySQL57
{
const REGEX = '/(?i)(select|\$).*?UNION.*?(select|\$).*?/ms';
/**
* Checks the queries inside triggers that could have possible incompatibilities with MySQL 5.7
*
* @see workflow/engine/bin/tasks/cliWorkspaces.php->check_queries_incompatibilities()
* @param array $processes
* @return array
*/
public function checkIncompatibilityTriggers($processes)
{
$result = [];
foreach ($processes as $process) {
$triggerQuery = Triggers::query()->select();
//Call the scope method to filter by process
$triggerQuery->process($process['PRO_UID']);
$triggers = $triggerQuery->get()->values()->toArray();
foreach ($triggers as $trigger) {
$resultIncompatibility = $this->analyzeQuery($trigger['TRI_WEBBOT']);
if ($resultIncompatibility) {
$aux = array_merge($process, $trigger);
array_push($result, $aux);
}
}
}
return $result;
}
/**
* Checks the queries inside dynaforms that could have possible incompatibilities with MySQL 5.7
*
* @see workflow/engine/bin/tasks/cliWorkspaces.php->check_queries_incompatibilities()
* @param array $processes
* @return array
*/
public function checkIncompatibilityDynaforms($processes)
{
$result = [];
foreach ($processes as $process) {
$dynaformQuery = Dynaform::query()->select();
//Call the scope method to filter by process
$dynaformQuery->process($process['PRO_UID']);
$dynaforms = $dynaformQuery->get()->values()->toArray();
foreach ($dynaforms as $dynaform) {
$resultIncompatibility = $this->analyzeQuery($dynaform['DYN_CONTENT']);
if ($resultIncompatibility) {
$aux = array_merge($process, $dynaform);
array_push($result, $aux);
}
}
}
return $result;
}
/**
* Checks the queries inside variables that could have possible incompatibilities with MySQL 5.7
*
* @see workflow/engine/bin/tasks/cliWorkspaces.php->check_queries_incompatibilities()
* @param array $processes
* @return array
*/
public function checkIncompatibilityVariables($processes)
{
$result = [];
foreach ($processes as $process) {
$variablesQuery = ProcessVariables::query()->select();
//Call the scope method to filter by process
$variablesQuery->process($process['PRO_UID']);
$variables = $variablesQuery->get()->values()->toArray();
foreach ($variables as $variable) {
$resultIncompatibility = $this->analyzeQuery($variable['VAR_SQL']);
if ($resultIncompatibility) {
$aux = array_merge($process, $variable);
array_push($result, $aux);
}
}
}
return $result;
}
/**
* Analyze the query using the regular expression
*
* @param string $query
* @return bool
*/
public function analyzeQuery($query)
{
preg_match_all($this::REGEX, $query, $matches, PREG_SET_ORDER, 0);
return !empty($matches);
}
}