PMC-580: release/3.3.7

This commit is contained in:
Paula Quispe
2019-05-07 14:39:05 -04:00
27 changed files with 874 additions and 551 deletions

View File

@@ -7,7 +7,7 @@ class Applications
/**
* This function return information by searching cases
*
* The query is related to advanced search with diferents filters
* The query is related to advanced search with different filters
* We can search by process, status of case, category of process, users, delegate date from and to
*
* @param string $userUid
@@ -17,11 +17,12 @@ class Applications
* @param integer $process the pro_id
* @param integer $status of the case
* @param string $dir if the order is DESC or ASC
* @param string $sort name of column by sort
* @param string $sort name of column by sort, can be:
* [APP_NUMBER, APP_TITLE, APP_PRO_TITLE, APP_TAS_TITLE, APP_CURRENT_USER, APP_UPDATE_DATE, DEL_DELEGATE_DATE, DEL_TASK_DUE_DATE, APP_STATUS_LABEL]
* @param string $category uid for the process
* @param date $dateFrom
* @param date $dateTo
* @param string $columnSearch name of column for a specific search
* @param string $filterBy name of column for a specific search, can be: [APP_NUMBER, APP_TITLE, TAS_TITLE]
* @return array $result result of the query
*/
public function searchAll(
@@ -36,11 +37,8 @@ class Applications
$category = null,
$dateFrom = null,
$dateTo = null,
$columnSearch = 'APP_TITLE'
$filterBy = 'APP_TITLE'
) {
//Exclude the Task Dummies in the delegations
$arrayTaskTypeToExclude = array("WEBENTRYEVENT", "END-MESSAGE-EVENT", "START-MESSAGE-EVENT", "INTERMEDIATE-THROW-MESSAGE-EVENT", "INTERMEDIATE-CATCH-MESSAGE-EVENT");
//Start the connection to database
$con = Propel::getConnection(AppDelegationPeer::DATABASE_NAME);
@@ -58,7 +56,7 @@ class Applications
$category = $inputFilter->escapeUsingConnection($category, $con);
$dateFrom = $inputFilter->escapeUsingConnection($dateFrom, $con);
$dateTo = $inputFilter->escapeUsingConnection($dateTo, $con);
$columnSearch = $inputFilter->escapeUsingConnection($columnSearch, $con);
$filterBy = $inputFilter->escapeUsingConnection($filterBy, $con);
//Start the transaction
$con->begin();
@@ -101,18 +99,20 @@ class Applications
FROM APP_DELEGATION
";
$sqlData .= " LEFT JOIN APPLICATION ON (APP_DELEGATION.APP_NUMBER = APPLICATION.APP_NUMBER)";
$sqlData .= " LEFT JOIN TASK ON (APP_DELEGATION.TAS_ID = TASK.TAS_ID)";
$sqlData .= " LEFT JOIN TASK ON (APP_DELEGATION.TAS_ID = TASK.TAS_ID ";
//Exclude the Task Dummies in the delegations
$sqlData .= " AND TASK.TAS_TYPE <> 'WEBENTRYEVENT' AND TASK.TAS_TYPE <> 'END-MESSAGE-EVENT' AND TASK.TAS_TYPE <> 'START-MESSAGE-EVENT' AND TASK.TAS_TYPE <> 'INTERMEDIATE-THROW')";
$sqlData .= " LEFT JOIN USERS ON (APP_DELEGATION.USR_ID = USERS.USR_ID)";
$sqlData .= " LEFT JOIN PROCESS ON (APP_DELEGATION.PRO_ID = PROCESS.PRO_ID)";
$sqlData .= " WHERE TASK.TAS_TYPE NOT IN ('" . implode("','", $arrayTaskTypeToExclude) . "')";
$sqlData .= " WHERE 1";
switch ($status) {
case 1: //DRAFT
$sqlData .= " AND APP_DELEGATION.DEL_THREAD_STATUS='OPEN'";
$sqlData .= " AND APP_DELEGATION.DEL_THREAD_STATUS = 'OPEN'";
$sqlData .= " AND APPLICATION.APP_STATUS_ID = 1";
break;
case 2: //TO_DO
$sqlData .= " AND APP_DELEGATION.DEL_THREAD_STATUS='OPEN'";
$sqlData .= " AND APP_DELEGATION.DEL_THREAD_STATUS = 'OPEN'";
$sqlData .= " AND APPLICATION.APP_STATUS_ID = 2";
break;
case 3: //COMPLETED
@@ -148,17 +148,28 @@ class Applications
}
if (!empty($search)) {
//If the filter is related to the APP_DELEGATION table: APP_NUMBER
if ($columnSearch === 'APP_NUMBER') {
$sqlData .= " AND APP_DELEGATION.APP_NUMBER LIKE '%{$search}%' ";
}
//If the filter is related to the APPLICATION table: APP_TITLE
if ($columnSearch === 'APP_TITLE') {
$sqlData .= " AND APPLICATION.APP_TITLE LIKE '%{$search}%' ";
}
//If the filter is related to the TASK table: TAS_TITLE
if ($columnSearch === 'TAS_TITLE') {
$sqlData .= " AND TASK.TAS_TITLE LIKE '%{$search}%' ";
//Search: we need to considerate the filterBy and the sortColumn
$appColumns = ['APP_NUMBER', 'APP_TITLE'];
if (in_array($sort, $appColumns) && in_array($filterBy, $appColumns)) {
$sqlData .= " AND APP_DELEGATION.APP_NUMBER IN (";
//Sub query: get the appNumber(s) that match with the search
$sqlData .= " SELECT APPLICATION.APP_NUMBER FROM APPLICATION WHERE APPLICATION.{$filterBy} LIKE '%{$search}%'";
$sqlData .= " ORDER BY APPLICATION.{$sort} " . $dir;
//End sub query
$sqlData .= " )";
} else {
//If the filter is related to the APP_DELEGATION table: APP_NUMBER
if ($filterBy === 'APP_NUMBER') {
$sqlData .= " AND APP_DELEGATION.APP_NUMBER LIKE '%{$search}%' ";
}
//If the filter is related to the APPLICATION table: APP_TITLE
if ($filterBy === 'APP_TITLE') {
$sqlData .= " AND APPLICATION.APP_TITLE LIKE '%{$search}%' ";
}
//If the filter is related to the TASK table: TAS_TITLE
if ($filterBy === 'TAS_TITLE') {
$sqlData .= " AND TASK.TAS_TITLE LIKE '%{$search}%' ";
}
}
}
@@ -179,6 +190,7 @@ class Applications
$orderBy = 'APP_DELEGATION.APP_NUMBER ' . $dir;
break;
case 'APP_CURRENT_USER':
//@todo: this section needs to use 'User Name Display Format', currently in the extJs is defined this
//The column APP_CURRENT_USER is result of concat those fields
$orderBy = 'USR_LASTNAME ' . $dir . ' ,USR_FIRSTNAME ' . $dir;
break;
@@ -212,6 +224,7 @@ class Applications
if (isset( $row['DEL_PRIORITY'] )) {
$row['DEL_PRIORITY'] = G::LoadTranslation( "ID_PRIORITY_{$priorities[$row['DEL_PRIORITY']]}" );
}
//@todo: this section needs to use 'User Name Display Format', currently in the extJs is defined this
$row["APP_CURRENT_USER"] = $row["USR_LASTNAME"].' '.$row["USR_FIRSTNAME"];
$row["APPDELCR_APP_TAS_TITLE"] = '';
$row["USRCR_USR_UID"] = $row["USR_UID"];

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2,13 +2,14 @@
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\DB;
use ProcessMaker\BusinessModel\Process as BmProcess;
/*----------------------------------********---------------------------------*/
use ProcessMaker\ChangeLog\ChangeLog;
/*----------------------------------********---------------------------------*/
use ProcessMaker\BusinessModel\Process as BmProcess;
use ProcessMaker\Core\Installer;
use ProcessMaker\Core\System;
use ProcessMaker\Plugins\Adapters\PluginAdapter;
use ProcessMaker\Project\Adapter\BpmnWorkflow;
use ProcessMaker\Util\FixReferencePath;
/**
@@ -3739,53 +3740,62 @@ class WorkspaceTools
CLI::logging("|--> Clean data in table " . OauthRefreshTokensPeer::TABLE_NAME . " rows " . $refreshToken . "\n");
}
/**
* Migrate the Intermediate throw Email Event to Dummy task, specify the workspaces.
* The processes in this workspace will be updated.
*
* @param string $workspaceName
* @see workflow/engine/bin/tasks/cliWorkspaces.php::run_migrate_itee_to_dummytask()
* @see workflow/engine/classes/WorkspaceTools.php->upgradeDatabase()
* @link https://wiki.processmaker.com/3.3/processmaker_command#migrate-itee-to-dummytask
*/
public function migrateIteeToDummytask($workspaceName)
{
$this->initPropel(true);
$arraySystemConfiguration = System::getSystemConfiguration('', '', $workspaceName);
$conf = new Configurations();
\G::$sysSys = $workspaceName;
\G::$pathDataSite = PATH_DATA . "sites" . PATH_SEP . \G::$sysSys . PATH_SEP;
\G::$pathDocument = PATH_DATA . 'sites' . DIRECTORY_SEPARATOR . $workspaceName . DIRECTORY_SEPARATOR . 'files';
\G::$memcachedEnabled = $arraySystemConfiguration['memcached'];
\G::$pathDataPublic = \G::$pathDataSite . "public" . PATH_SEP;
\G::$sysSkin = $conf->getConfiguration('SKIN_CRON', '');
if (is_file(\G::$pathDataSite . PATH_SEP . ".server_info")) {
$serverInfo = file_get_contents(\G::$pathDataSite . PATH_SEP . ".server_info");
$config = System::getSystemConfiguration('', '', $workspaceName);
G::$sysSys = $workspaceName;
G::$pathDataSite = PATH_DATA . "sites" . PATH_SEP . G::$sysSys . PATH_SEP;
G::$pathDocument = PATH_DATA . 'sites' . DIRECTORY_SEPARATOR . $workspaceName . DIRECTORY_SEPARATOR . 'files';
G::$memcachedEnabled = $config['memcached'];
G::$pathDataPublic = G::$pathDataSite . "public" . PATH_SEP;
G::$sysSkin = $config['default_skin'];
if (is_file(G::$pathDataSite . PATH_SEP . ".server_info")) {
$serverInfo = file_get_contents(G::$pathDataSite . PATH_SEP . ".server_info");
$serverInfo = unserialize($serverInfo);
$envHost = $serverInfo["SERVER_NAME"];
$envPort = ($serverInfo["SERVER_PORT"] . "" != "80") ? ":" . $serverInfo["SERVER_PORT"] : "";
if (!empty($envPort) && strpos($envHost, $envPort) === false) {
$envHost = $envHost . $envPort;
}
\G::$httpHost = $envHost;
G::$httpHost = $envHost;
}
//Search All process
$oCriteria = new Criteria("workflow");
$oCriteria->addSelectColumn(ProcessPeer::PRO_UID);
$oCriteria->addSelectColumn(ProcessPeer::PRO_ITEE);
$oCriteria->add(ProcessPeer::PRO_ITEE, '0', Criteria::EQUAL);
$rsCriteria = ProcessPeer::doSelectRS($oCriteria);
$rsCriteria->setFetchmode(ResultSet::FETCHMODE_ASSOC);
$criteria = new Criteria("workflow");
$criteria->addSelectColumn(ProcessPeer::PRO_UID);
$criteria->addSelectColumn(ProcessPeer::PRO_ITEE);
$criteria->add(ProcessPeer::PRO_ITEE, '0', Criteria::EQUAL);
$resultSet = ProcessPeer::doSelectRS($criteria);
$resultSet->setFetchmode(ResultSet::FETCHMODE_ASSOC);
$message = "-> Migrating the Intermediate Email Event \n";
CLI::logging($message);
while ($rsCriteria->next()) {
$row = $rsCriteria->getRow();
$prj_uid = $row['PRO_UID'];
$bpmnProcess = new Process();
if ($bpmnProcess->isBpmnProcess($prj_uid)) {
$project = new \ProcessMaker\Project\Adapter\BpmnWorkflow();
$diagram = $project->getStruct($prj_uid);
$res = $project->updateFromStruct($prj_uid, $diagram);
$bpmnProcess->setProUid($prj_uid);
$oProcess = new Process();
$aProcess['PRO_UID'] = $prj_uid;
$aProcess['PRO_ITEE'] = '1';
if ($oProcess->processExists($prj_uid)) {
$oProcess->update($aProcess);
while ($resultSet->next()) {
$row = $resultSet->getRow();
$prjUid = $row['PRO_UID'];
$process = new Process();
if ($process->isBpmnProcess($prjUid)) {
$project = new BpmnWorkflow();
$diagram = $project->getStruct($prjUid);
$project->updateFromStruct($prjUid, $diagram);
$process->setProUid($prjUid);
$updateProcess = new Process();
$updateProcessData = [];
$updateProcessData['PRO_UID'] = $prjUid;
$updateProcessData['PRO_ITEE'] = '1';
if ($updateProcess->processExists($prjUid)) {
$updateProcess->update($updateProcessData);
}
$message = " Process updated " . $bpmnProcess->getProTitle() . "\n";
$message = " Process updated " . $process->getProTitle() . "\n";
CLI::logging($message);
}
}

View File

@@ -28,11 +28,11 @@
//
// License: LGPL, see LICENSE
////////////////////////////////////////////////////
use ProcessMaker\BusinessModel\Cases as BusinessModelCases;
use ProcessMaker\Core\System;
use ProcessMaker\Plugins\PluginRegistry;
use ProcessMaker\Util\ElementTranslation;
/**
* ProcessMaker has made a number of its PHP functions available be used in triggers and conditions.
* Most of these functions are wrappers for internal functions used in Gulliver, which is the development framework
@@ -3470,38 +3470,26 @@ function PMFGetNextDerivationInfo($caseUid, $delIndex)
* @param string | $skin = null | Skin | The skin
*
* @return string | $url | Direct case link | Returns the direct case link, FALSE otherwise
* @link https://wiki.processmaker.com/3.2/Direct_Case_Link
*/
function PMFCaseLink($caseUid, $workspace = null, $language = null, $skin = null)
{
try {
$case = new \ProcessMaker\BusinessModel\Cases();
$case = new BusinessModelCases();
$arrayApplicationData = $case->getApplicationRecordByPk($caseUid, [], false);
if ($arrayApplicationData === false) {
return false;
}
$conf = new Configurations();
$envSkin = defined("SYS_SKIN") ? SYS_SKIN : $conf->getConfiguration('SKIN_CRON', '');
$workspace = (!empty($workspace)) ? $workspace : config("system.workspace");
$language = (!empty($language)) ? $language : SYS_LANG;
$skin = (!empty($skin)) ? $skin : $envSkin;
$workspace = !empty($workspace) ? $workspace : config("system.workspace");
$language = !empty($language) ? $language : SYS_LANG;
if (empty($skin)) {
$config = System::getSystemConfiguration();
$skin = defined("SYS_SKIN") ? SYS_SKIN : $config['default_skin'];
}
$uri = '/sys' . $workspace . '/' . $language . '/' . $skin . '/cases/opencase/' . $caseUid;
$envHost = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : SERVER_NAME;
$envProtocol = defined("REQUEST_SCHEME") && REQUEST_SCHEME === "https";
if (isset($_SERVER['SERVER_PORT'])) {
$envPort = ($_SERVER['SERVER_PORT'] != "80") ? ":" . $_SERVER['SERVER_PORT'] : "";
} else if (defined('SERVER_PORT')) {
$envPort = (SERVER_PORT . "" != "80") ? ":" . SERVER_PORT : "";
} else {
$envPort = "";
}
if (!empty($envPort) && strpos($envHost, $envPort) === false) {
$envHost = $envHost . $envPort;
}
$link = (G::is_https() || $envProtocol ? 'https://' : 'http://') . $envHost . $uri;
$link = System::getServerProtocolHost() . $uri;
return $link;
} catch (Exception $e) {
throw $e;

View File

@@ -223,7 +223,6 @@ class AppDelegation extends BaseAppDelegation
try {
$res = $this->save();
} catch (PropelException $e) {
error_log($e->getMessage());
return;
}
} else {
@@ -1046,4 +1045,45 @@ class AppDelegation extends BaseAppDelegation
return $delIndex;
}
/**
* Update the priority in AppDelegation table, using the defined variable in task
*
* @param integer $delIndex
* @param string $tasUid
* @param string $appUid
* @param array $fieldAppData
*
* @return void
*
* @see Cases->update()
*
*/
public function updatePriority($delIndex, $tasUid, $appUid, $fieldAppData)
{
if (!empty($delIndex) && !empty($tasUid)) {
//Optimized code to avoid load task content row.
$criteria = new Criteria();
$criteria->clearSelectColumns();
$criteria->addSelectColumn(TaskPeer::TAS_PRIORITY_VARIABLE);
$criteria->add(TaskPeer::TAS_UID, $tasUid);
$rs = TaskPeer::doSelectRS($criteria);
$rs->setFetchmode(ResultSet::FETCHMODE_ASSOC);
$rs->next();
$row = $rs->getRow();
$tasPriority = substr($row['TAS_PRIORITY_VARIABLE'], 2);
//End optimized code.
$x = $fieldAppData;
if (!empty($x[$tasPriority])) {
$array = [];
$array['APP_UID'] = $appUid;
$array['DEL_INDEX'] = $delIndex;
$array['TAS_UID'] = $tasUid;
$array['DEL_PRIORITY'] = (isset($x[$tasPriority]) ?
($x[$tasPriority] >= 1 && $x[$tasPriority] <= 5 ? $x[$tasPriority] : '3') : '3');
$this->update($array);
}
}
}
}

View File

@@ -1,7 +1,7 @@
<?php
//require_once 'classes/model/om/BaseAppNotes.php';
use ProcessMaker\Core\System;
use ProcessMaker\Util\DateTime;
/**
* Skeleton subclass for representing a row from the 'APP_NOTES' table.
@@ -14,9 +14,34 @@ use ProcessMaker\Core\System;
*
* @package classes.model
*/
class AppNotes extends BaseAppNotes
{
public function getNotesList (
/**
* Get the existing case notes information from a case
*
* @param string $appUid
* @param string $usrUid
* @param string $start
* @param int $limit
* @param string $sort
* @param string $dir
* @param string $dateFrom
* @param string $dateTo
* @param string $search
*
* @return array
*
* @see \Cases->getCaseNotes()
* @see \AppProxy->getNotesList()
* @see \Home->getAppsData()
* @see workflow/engine/methods/cases/caseNotesAjax.php->getNotesList()
* @see \ProcessMaker\BusinessModel\Cases->getCaseNotes()
* @see \ProcessMaker\Services\Api\Light->doGetCaseNotes()
*
* @link https://wiki.processmaker.com/3.2/Case_Notes#Viewing_Existing_Case_Notes
*/
public function getNotesList(
$appUid,
$usrUid = '',
$start = '',
@@ -25,70 +50,71 @@ class AppNotes extends BaseAppNotes
$dir = 'DESC',
$dateFrom = '',
$dateTo = '',
$search = '')
{
$Criteria = new Criteria( 'workflow' );
$Criteria->clearSelectColumns();
$search = ''
) {
$criteria = new Criteria('workflow');
$criteria->clearSelectColumns();
$Criteria->addSelectColumn( AppNotesPeer::APP_UID );
$Criteria->addSelectColumn( AppNotesPeer::USR_UID );
$Criteria->addSelectColumn( AppNotesPeer::NOTE_DATE );
$Criteria->addSelectColumn( AppNotesPeer::NOTE_CONTENT );
$Criteria->addSelectColumn( AppNotesPeer::NOTE_TYPE );
$Criteria->addSelectColumn( AppNotesPeer::NOTE_AVAILABILITY );
$Criteria->addSelectColumn( AppNotesPeer::NOTE_ORIGIN_OBJ );
$Criteria->addSelectColumn( AppNotesPeer::NOTE_AFFECTED_OBJ1 );
$Criteria->addSelectColumn( AppNotesPeer::NOTE_AFFECTED_OBJ2 );
$Criteria->addSelectColumn( AppNotesPeer::NOTE_RECIPIENTS );
$Criteria->addSelectColumn( UsersPeer::USR_USERNAME );
$Criteria->addSelectColumn( UsersPeer::USR_FIRSTNAME );
$Criteria->addSelectColumn( UsersPeer::USR_LASTNAME );
$Criteria->addSelectColumn( UsersPeer::USR_EMAIL );
$criteria->addSelectColumn(AppNotesPeer::APP_UID);
$criteria->addSelectColumn(AppNotesPeer::USR_UID);
$criteria->addSelectColumn(AppNotesPeer::NOTE_DATE);
$criteria->addSelectColumn(AppNotesPeer::NOTE_CONTENT);
$criteria->addSelectColumn(AppNotesPeer::NOTE_TYPE);
$criteria->addSelectColumn(AppNotesPeer::NOTE_AVAILABILITY);
$criteria->addSelectColumn(AppNotesPeer::NOTE_ORIGIN_OBJ);
$criteria->addSelectColumn(AppNotesPeer::NOTE_AFFECTED_OBJ1);
$criteria->addSelectColumn(AppNotesPeer::NOTE_AFFECTED_OBJ2);
$criteria->addSelectColumn(AppNotesPeer::NOTE_RECIPIENTS);
$criteria->addSelectColumn(UsersPeer::USR_USERNAME);
$criteria->addSelectColumn(UsersPeer::USR_FIRSTNAME);
$criteria->addSelectColumn(UsersPeer::USR_LASTNAME);
$criteria->addSelectColumn(UsersPeer::USR_EMAIL);
$Criteria->addJoin( AppNotesPeer::USR_UID, UsersPeer::USR_UID, Criteria::LEFT_JOIN );
$criteria->addJoin(AppNotesPeer::USR_UID, UsersPeer::USR_UID, Criteria::LEFT_JOIN);
$Criteria->add( AppNotesPeer::APP_UID, $appUid, Criteria::EQUAL );
$criteria->add(AppNotesPeer::APP_UID, $appUid, Criteria::EQUAL);
if ($usrUid != '') {
$Criteria->add( AppNotesPeer::USR_UID, $usrUid, Criteria::EQUAL );
$criteria->add(AppNotesPeer::USR_UID, $usrUid, Criteria::EQUAL);
}
if ($dateFrom != '') {
$Criteria->add( AppNotesPeer::NOTE_DATE, $dateFrom, Criteria::GREATER_EQUAL );
$criteria->add(AppNotesPeer::NOTE_DATE, $dateFrom, Criteria::GREATER_EQUAL);
}
if ($dateTo != '') {
$Criteria->add( AppNotesPeer::NOTE_DATE, $dateTo, Criteria::LESS_EQUAL );
$criteria->add(AppNotesPeer::NOTE_DATE, $dateTo, Criteria::LESS_EQUAL);
}
if ($search != '') {
$Criteria->add( AppNotesPeer::NOTE_CONTENT, '%'.$search.'%', Criteria::LIKE );
$criteria->add(AppNotesPeer::NOTE_CONTENT, '%' . $search . '%', Criteria::LIKE);
}
if ($dir == 'DESC') {
$Criteria->addDescendingOrderByColumn($sort);
$criteria->addDescendingOrderByColumn($sort);
} else {
$Criteria->addAscendingOrderByColumn($sort);
$criteria->addAscendingOrderByColumn($sort);
}
$response = array ();
$totalCount = AppNotesPeer::doCount( $Criteria );
$response = [];
$totalCount = AppNotesPeer::doCount($criteria);
$response['totalCount'] = $totalCount;
$response['notes'] = array ();
$response['notes'] = [];
if ($start != '') {
$Criteria->setLimit( $limit );
$Criteria->setOffset( $start );
$criteria->setLimit($limit);
$criteria->setOffset($start);
}
$oDataset = appNotesPeer::doSelectRS( $Criteria );
$oDataset->setFetchmode( ResultSet::FETCHMODE_ASSOC );
$oDataset->next();
$dataset = AppNotesPeer::doSelectRS($criteria);
$dataset->setFetchmode(ResultSet::FETCHMODE_ASSOC);
$dataset->next();
while ($aRow = $oDataset->getRow()) {
$aRow['NOTE_CONTENT'] = stripslashes($aRow['NOTE_CONTENT']);
$response['notes'][] = $aRow;
$oDataset->next();
while ($row = $dataset->getRow()) {
$row['NOTE_CONTENT'] = stripslashes($row['NOTE_CONTENT']);
$response['notes'][] = $row;
$dataset->next();
}
$result['criteria'] = $Criteria;
$result = [];
$result['criteria'] = $criteria;
$result['array'] = $response;
return $result;