mirror of
https://github.com/VTECRM/vtenext.git
synced 2026-02-26 16:18:47 +00:00
566 lines
18 KiB
PHP
566 lines
18 KiB
PHP
<?php
|
|
/*************************************
|
|
* SPDX-FileCopyrightText: 2009-2020 Vtenext S.r.l. <info@vtenext.com>
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
************************************/
|
|
/* crmv@57010 - limits */
|
|
|
|
class TouchGetRelatedList extends TouchWSClass {
|
|
|
|
public $defaultPageLimit = 5000; // default value for page size if no specified
|
|
public $longOperation = true;
|
|
public $excludeMods = array('ModComments');
|
|
|
|
function process(&$request) {
|
|
global $adb, $table_prefix;
|
|
global $current_user, $currentModule, $touchInst, $touchUtils;
|
|
|
|
$relationids = Zend_Json::decode($request['relationids']);
|
|
if (!is_array($relationids)) return array('success'=>false, 'error'=>'Invalid list of relations');
|
|
|
|
// limits
|
|
$pageLimit = intval($request['limit']);
|
|
if ($pageLimit <= 0) $pageLimit = $this->defaultPageLimit;
|
|
$page = intval($request['page']);
|
|
if ($page <= 0) $page = 1;
|
|
unset($request['page'], $request['limit'], $request['start']);
|
|
|
|
$result = array();
|
|
$total = 0;
|
|
foreach ($relationids as $relationId) {
|
|
$pmodule = null;
|
|
if ($relationId >= $touchUtils->related_blockids['related_events']) {
|
|
$pmodule = 'Events';
|
|
}
|
|
$list = $this->getIdsForRelation($relationId, $pmodule, $page, $pageLimit);
|
|
if (intval($list['total']) > 0) {
|
|
$result[] = $list;
|
|
$total += intval($list['total']);
|
|
}
|
|
}
|
|
|
|
return array('success'=>true, 'relateds'=>$result, 'total'=>$total);
|
|
}
|
|
|
|
function getIdsForRelation($relationId, $prefModule = null, $page = null, $pageLimit = null) {
|
|
global $adb, $table_prefix, $onlyquery; // crmv@54449
|
|
global $current_user, $currentModule, $touchInst, $touchUtils;
|
|
|
|
if (empty($relationId)) return array();
|
|
if (empty($page)) $page = 1;
|
|
if (empty($pageLimit)) $pageLimit = $this->defaultPageLimit;
|
|
|
|
$excludeMods = array_merge($this->excludeMods, $touchInst->excluded_modules);
|
|
|
|
// relationid used internally by the VTE, might be different from the app's one
|
|
$crmRelationId = $relationId;
|
|
|
|
// check for special relations
|
|
if ($touchUtils->isInviteesRelated($relationId)) {
|
|
// invitees
|
|
return $this->getInvitees($relationId, $page, $pageLimit);
|
|
} elseif ($touchUtils->isProductsRelated($relationId)) {
|
|
// products
|
|
return $this->getProducts($relationId, $page, $pageLimit);
|
|
} elseif ($touchUtils->isNotesRelated($relationId)) {
|
|
// MyNotes
|
|
return $this->getNotes($relationId, $page, $pageLimit);
|
|
} elseif ($prefModule == 'Events') {
|
|
$crmRelationId -= $touchUtils->related_blockids['related_events'];
|
|
}
|
|
|
|
$relinfo = ModuleRelation::createFromRelationId($crmRelationId);
|
|
|
|
if ($relinfo && $relinfo->getType() == ModuleRelation::$TYPE_NTON) {
|
|
if (in_array($relinfo->getFirstModule(), $excludeMods) || in_array($relinfo->getSecondModule(), $excludeMods)) return array();
|
|
return $this->getIdsForRelationN2N($relinfo, true, false, $page, $pageLimit);
|
|
}
|
|
|
|
$relationInfo = getRelatedListInfoById($crmRelationId);
|
|
$primaryModule = vtlib_getModuleNameById($relationInfo['tabid']);
|
|
$relatedModule = vtlib_getModuleNameById($relationInfo['relatedTabId']);
|
|
|
|
if (in_array($relatedModule, $excludeMods) || in_array($primaryModule, $excludeMods)) return array();
|
|
$currentModule = $module = $primaryModule;
|
|
|
|
// crmv@54449
|
|
$modObj = $touchUtils->getModuleInstance(($module == 'Events' ? 'Calendar' : $module));
|
|
if (!$modObj) return array();
|
|
// crmv@54449e
|
|
|
|
$onlyquery = true;
|
|
$fakeRecordId = 1234567;
|
|
$function_name = $relationInfo['functionName'];
|
|
|
|
// crmv@55371
|
|
if ($relatedModule == 'Calendar' || $relatedModule == 'Events') // crmv@54449
|
|
$mod_listquery = "activity_listquery";
|
|
else
|
|
$mod_listquery = strtolower($relatedModule)."_listquery";
|
|
|
|
VteSession::set($mod_listquery, '');
|
|
$relatedListData = $modObj->$function_name($fakeRecordId, getTabid($currentModule),$relationInfo['relatedTabId'], $actions);
|
|
$query = VteSession::get($mod_listquery);
|
|
// crmv@55371e
|
|
|
|
if (empty($query)) return array();
|
|
|
|
// now parse the query
|
|
if (preg_match('/order by\s+(.+)$/i', $query, $matches)) {
|
|
$order_by = explode(',', $matches[1]);
|
|
$order_by = $order_by[0];
|
|
list($order_by, $order_dir) = array_map('trim', explode(' ', $order_by, 2));
|
|
|
|
if (empty($order_dir)) $order_dir = 'ASC';
|
|
|
|
list($order_tab, $order_col) = array_map('trim', explode('.', $order_by, 2));
|
|
|
|
$res = $adb->pquery("select fieldname from {$table_prefix}_field where columnname = ? and tablename = ?", array($order_col, $order_tab));
|
|
|
|
if ($res && $adb->num_rows($res) > 0) {
|
|
$row = $adb->FetchByAssoc($res, -1, false);
|
|
$orderField = $row['fieldname'];
|
|
$orderDir = $order_dir;
|
|
} else {
|
|
$orderField = '';
|
|
$orderDir = '';
|
|
}
|
|
|
|
// remove the order by clause
|
|
$query = preg_replace('/\s*order by.+$/i', '', $query);
|
|
}
|
|
|
|
if (preg_match('/([^\s()]+)\s*=\s*'.$fakeRecordId.'/', $query, $matches)) {
|
|
$relatedIndex = $matches[1];
|
|
$query = preg_replace('/(and|or)\s*[^\s()]+\s*=\s*'.$fakeRecordId.'/i', '', $query);
|
|
$query = preg_replace('/^select .+? from/i', "SELECT {$table_prefix}_crmentity.crmid as relcrmid, $relatedIndex AS crmid FROM", $query);
|
|
// now add a join with crmentity of first module because I have to filter by module
|
|
$query = $this->sql_preg_replace('/\s+where\s+/i', " INNER JOIN {$table_prefix}_crmentity crm1 ON crm1.crmid = $relatedIndex WHERE ", $query, 1);
|
|
//and add the condition
|
|
$query .= " AND crm1.setype = '$primaryModule'";
|
|
}
|
|
|
|
// crmv@54449, really terrible tricks, please please, someone destroys that ugly calendar!!
|
|
if ($relatedModule == 'Calendar') {
|
|
if ($prefModule == 'Events') {
|
|
// only events
|
|
$query = preg_replace("/'Task'/", "'NOTATASK'", $query);
|
|
$relatedModule = 'Events';
|
|
} else {
|
|
// only tasks
|
|
$query = preg_replace("/activitytype in \(.*?\)/i", "activitytype = 'NOTANEVENT'", $query);
|
|
}
|
|
}
|
|
// crmv@54449e
|
|
|
|
// and
|
|
$list = array(
|
|
'list' => array(),
|
|
'module' => $primaryModule,
|
|
'relmodule' => $relatedModule,
|
|
'relationid' => $relationId,
|
|
'extra' => null,
|
|
'total' => 0,
|
|
'totalcount' => 0
|
|
);
|
|
|
|
// total
|
|
$list['totalcount'] = $this->countTotalQuery($query);
|
|
|
|
$start = ($page-1)*$pageLimit;
|
|
$res = $adb->limitQuery($query, $start, $pageLimit);
|
|
if ($res) {
|
|
$total = 0;
|
|
while ($row = $adb->FetchByAssoc($res, -1, false)) {
|
|
$crmid = intval($row['crmid']);
|
|
$relcrmid = intval(($row['relcrmid']));
|
|
if ($crmid > 0 && $relcrmid > 0) {
|
|
$list['list']['crmid'][] = $crmid;
|
|
$list['list']['relcrmid'][] = $relcrmid;
|
|
++$total;
|
|
}
|
|
}
|
|
}
|
|
$list['total'] = $total;
|
|
|
|
return $list;
|
|
}
|
|
|
|
// replaces pieces of a query, without replacing inside subqueries
|
|
// assume subquery starts with "(select"
|
|
protected function sql_preg_replace($regexp, $replace, $sql, $limit = -1) {
|
|
$subQueries = array();
|
|
|
|
// first replace subqueries with safe strings
|
|
while (preg_match('/\(\s*select/i', $sql, $smatches, PREG_OFFSET_CAPTURE)) {
|
|
$rpos1 = $smatches[0][1];
|
|
$rpos2 = 0;
|
|
$bcount = 1;
|
|
// now walk to find the closing bracket
|
|
for ($pos = $smatches[0][1]+1; $pos<strlen($sql); ++$pos) {
|
|
if ($sql[$pos] == '(') ++$bcount;
|
|
elseif ($sql[$pos] == ')') --$bcount;
|
|
if ($bcount == 0) {
|
|
$rpos2 = $pos+1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($rpos2 > $rpos1) {
|
|
$subid = '###SUBQUERY'.count($subQueries).'###';
|
|
$subQueries[$subid] = substr($sql, $rpos1, $rpos2-$rpos1);
|
|
$sql = substr($sql, 0, $rpos1) . $subid . substr($sql, $rpos2);
|
|
} else {
|
|
// if the closing bracket wasn't found
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
// now do the replace
|
|
$sql = preg_replace($regexp, $replace, $sql, $limit);
|
|
|
|
// and restore the subqueries
|
|
if (count($subQueries) > 0) {
|
|
$sql = str_replace(array_keys($subQueries), array_values($subQueries), $sql);
|
|
}
|
|
|
|
return $sql;
|
|
}
|
|
|
|
// TODO: use fetchExtra, TODO: PERMISSIONS!!
|
|
public function getIdsForRelationN2N($relinfo, $fetchExtra = true, $reverse = false, $page = null, $pageLimit = null) {
|
|
global $adb, $table_prefix, $current_user;
|
|
|
|
if (empty($page)) $page = 1;
|
|
if (empty($pageLimit)) $pageLimit = $this->defaultPageLimit;
|
|
$info = $relinfo->relationinfo;
|
|
|
|
$list = array(
|
|
'list' => array(),
|
|
'relationid' => $relinfo->relationid,
|
|
'module' => $relinfo->getFirstModule(),
|
|
'relmodule' => $relinfo->getSecondModule(),
|
|
'extra' => null,
|
|
'total' => 0,
|
|
'totalcount' => 0,
|
|
);
|
|
|
|
if (empty($info['relidx']) || empty($info['reltab']) || empty($info['relidx2'])) return $list;
|
|
|
|
$otherJoins = '';
|
|
|
|
if ($reverse) {
|
|
$firstModule = $relinfo->getSecondModule();
|
|
$secondModule = $relinfo->getFirstModule();
|
|
$firstId = $info['relidx2'];
|
|
$secondId = $info['relidx'];
|
|
} else {
|
|
$firstModule = $relinfo->getFirstModule();
|
|
$secondModule = $relinfo->getSecondModule();
|
|
$firstId = $info['relidx'];
|
|
$secondId = $info['relidx2'];
|
|
}
|
|
|
|
$firstSQLModule = $firstModule;
|
|
$secondSQLModule = $secondModule;
|
|
|
|
|
|
if ($firstModule == 'Events') $firstSQLModule = 'Calendar';
|
|
if ($secondModule == 'Events') $secondSQLModule = 'Calendar';
|
|
|
|
if (in_array($firstModule, array('Calendar', 'Events'))) {
|
|
$otherJoins .= "INNER JOIN {$table_prefix}_activity activity1 on activity1.activityid = crm1.crmid";
|
|
}
|
|
|
|
if (in_array($secondModule, array('Calendar', 'Events'))) {
|
|
$otherJoins .= "INNER JOIN {$table_prefix}_activity activity2 on activity2.activityid = crm2.crmid";
|
|
}
|
|
|
|
if ($firstModule == 'Leads') {
|
|
$otherJoins .= "INNER JOIN {$table_prefix}_leaddetails leads1 on leads1.leadid = crm1.crmid";
|
|
}
|
|
|
|
if ($secondModule == 'Leads') {
|
|
$otherJoins .= "INNER JOIN {$table_prefix}_leaddetails leads2 on leads2.leadid = crm2.crmid";
|
|
}
|
|
|
|
// build the query
|
|
$where = array();
|
|
$params = array();
|
|
$query = "SELECT reltab.$firstId AS crmid, reltab.$secondId AS relcrmid
|
|
FROM {$info['reltab']} reltab
|
|
INNER JOIN {$table_prefix}_crmentity crm1 ON crm1.crmid = reltab.$firstId
|
|
INNER JOIN {$table_prefix}_crmentity crm2 ON crm2.crmid = reltab.$secondId
|
|
$otherJoins
|
|
";
|
|
|
|
if ($firstModule == 'Events') {
|
|
$where[] = "activity1.activitytype not in ('Task', 'Emails')"; // crmv@152701
|
|
} elseif ($firstModule == 'Calendar') {
|
|
$where[] = "activity1.activitytype = 'Task'";
|
|
}
|
|
|
|
if ($secondModule == 'Events') {
|
|
$where[] = "activity2.activitytype not in ('Task', 'Emails')"; // crmv@152701
|
|
} elseif ($secondModule == 'Calendar') {
|
|
$where[] = "activity2.activitytype = 'Task'";
|
|
}
|
|
|
|
$skipSetype1 = false;
|
|
$skipSetype2 = false;
|
|
$deletedTab = 'crm2'; // crmv@177095
|
|
|
|
// special query for messages
|
|
if ($secondModule == 'Messages') {
|
|
|
|
$info['relmod1'] = null;
|
|
$info['relmod2'] = null;
|
|
$query = "SELECT MAX(m.messagesid) AS relcrmid, MAX(reltab.crmid) AS crmid
|
|
FROM {$table_prefix}_messagesrel reltab
|
|
INNER JOIN {$table_prefix}_messages m ON reltab.messagehash = m.messagehash
|
|
INNER JOIN {$table_prefix}_crmentity crm1 ON crm1.crmid = reltab.crmid
|
|
$otherJoins"; // crmv@177095
|
|
$where[] = 'reltab.module = ?';
|
|
$where[] = "m.smownerid = ?"; // crmv@177095
|
|
$params[] = $firstSQLModule;
|
|
$params[] = $current_user->id;
|
|
$skipSetype1 = true;
|
|
$skipSetype2 = true;
|
|
$deletedTab = 'm'; // crmv@177095
|
|
}
|
|
|
|
if (!$skipSetype1) {
|
|
if ($info['relmod1']) {
|
|
$where[] = "reltab.{$info['relmod1']} = ?";
|
|
} else {
|
|
$where[] = "crm1.setype = ?";
|
|
}
|
|
$params[] = $firstSQLModule;
|
|
}
|
|
|
|
|
|
if (!$skipSetype2) {
|
|
if ($info['relmod2']) {
|
|
$where[] = "reltab.{$info['relmod2']} = ?";
|
|
} else {
|
|
$where[] = "crm2.setype = ?";
|
|
}
|
|
$params[] = $secondSQLModule;
|
|
}
|
|
|
|
// add clause for deleted records
|
|
$where[] = "crm1.deleted = 0";
|
|
$where[] = "$deletedTab.deleted = 0"; // crmv@177095
|
|
|
|
if ($firstModule == 'Leads') $where[] = 'leads1.converted = 0';
|
|
if ($secondModule == 'Leads') $where[] = 'leads2.converted = 0';
|
|
|
|
if (count($where) > 0) {
|
|
$query .= " WHERE ".implode(' AND ', $where);
|
|
}
|
|
|
|
if ($secondModule == 'Messages') {
|
|
$query .= " GROUP BY reltab.messagehash";
|
|
}
|
|
|
|
// total
|
|
$list['totalcount'] = $this->countTotalQuery($query, $params);
|
|
|
|
$start = ($page-1)*$pageLimit;
|
|
$res = $adb->limitPQuery($query, $start, $pageLimit, $params);
|
|
if ($res) {
|
|
$total = 0;
|
|
while ($row = $adb->FetchByAssoc($res, -1, false)) {
|
|
$crmid = intval($row['crmid']);
|
|
$relcrmid = intval(($row['relcrmid']));
|
|
if ($crmid > 0 && $relcrmid > 0) {
|
|
$list['list']['crmid'][] = $crmid;
|
|
$list['list']['relcrmid'][] = $relcrmid;
|
|
++$total;
|
|
}
|
|
}
|
|
}
|
|
$list['total'] = $total;
|
|
|
|
return $list;
|
|
}
|
|
|
|
public function getNotes($relationId, $page = null, $pageLimit = null) { // crmv@73256
|
|
global $touchInst, $touchUtils;
|
|
|
|
if (empty($page)) $page = 1;
|
|
if (empty($pageLimit)) $pageLimit = $this->defaultPageLimit;
|
|
$excludeMods = array_merge($this->excludeMods, $touchInst->excluded_modules);
|
|
|
|
$modTabId = $relationId - $touchUtils->related_blockids['notes'];
|
|
$primaryModule = vtlib_getModuleNameById($modTabId);
|
|
$relatedModule = 'MyNotes';
|
|
|
|
if (in_array($relatedModule, $excludeMods) || in_array($primaryModule, $excludeMods)) return array();
|
|
|
|
$RM = RelationManager::getInstance();
|
|
$relations = $RM->getRelations($primaryModule, ModuleRelation::$TYPE_NTON, $relatedModule);
|
|
|
|
if (empty($relations[0])) return array();
|
|
$relinfo = $relations[0];
|
|
|
|
// notes are reversed in crmentityrel
|
|
$list = $this->getIdsForRelationN2N($relinfo, false, true, $page, $pageLimit);
|
|
|
|
// but keep the custom relationid
|
|
if (is_array($list) && $list['relationid']) {
|
|
$list['relationid'] = $relationId;
|
|
}
|
|
return $list;
|
|
}
|
|
|
|
protected function getInvitees($relationId, $page = null, $pageLimit = null) {
|
|
global $adb, $table_prefix, $touchInst;
|
|
|
|
if (empty($page)) $page = 1;
|
|
if (empty($pageLimit)) $pageLimit = $this->defaultPageLimit;
|
|
|
|
if ($relationId == 2700000) {
|
|
$relmod = 'Contacts';
|
|
$table = $table_prefix.'_invitees_con';
|
|
|
|
$query = "select i.* from {$table} i
|
|
inner join {$table_prefix}_crmentity c on c.crmid = i.inviteeid
|
|
where c.deleted = 0 and c.setype = ?";
|
|
$params = array($relmod);
|
|
|
|
} elseif ($relationId == 2700001) {
|
|
$relmod = 'Users';
|
|
$table = $table_prefix.'_invitees';
|
|
|
|
$query = "select i.* from {$table} i
|
|
inner join {$table_prefix}_users u on u.id = i.inviteeid
|
|
where u.deleted = 0";
|
|
$params = array();
|
|
} else {
|
|
return array();
|
|
}
|
|
|
|
$invitees = array(
|
|
'list' => array(),
|
|
'module' => 'Events',
|
|
'relmodule' => $relmod,
|
|
'relationid' => $relationId,
|
|
'total' => 0,
|
|
'totalcount' => 0,
|
|
);
|
|
|
|
// total
|
|
$invitees['totalcount'] = $this->countTotalQuery($query, $params);
|
|
|
|
$start = ($page-1)*$pageLimit;
|
|
$res = $adb->limitPQuery($query, $start, $pageLimit, $params);
|
|
if ($res) {
|
|
$total = 0;
|
|
while ($row = $adb->FetchByAssoc($res, -1, false)) {
|
|
$crmid = intval($row['activityid']);
|
|
$relcrmid = intval($row['inviteeid']);
|
|
$part = intval($row['partecipation']);
|
|
if ($crmid > 0 && $relcrmid > 0) {
|
|
$invitees['list']['crmid'][] = $crmid;
|
|
$invitees['list']['relcrmid'][] = $relcrmid;
|
|
$invitees['list']['extra'][] = array('participation' => $part);
|
|
++$total;
|
|
}
|
|
}
|
|
$invitees['total'] = $total;
|
|
}
|
|
|
|
|
|
return $invitees;
|
|
}
|
|
|
|
protected function getProducts($relationId, $page = null, $pageLimit = null) {
|
|
global $adb, $table_prefix;
|
|
global $touchInst, $touchUtils, $current_user;
|
|
|
|
if (empty($page)) $page = 1;
|
|
if (empty($pageLimit)) $pageLimit = $this->defaultPageLimit;
|
|
|
|
$tabid = $relationId - $touchUtils->related_blockids['products'];
|
|
$module = getTabname($tabid);
|
|
|
|
if (empty($module) || in_array($module, $touchInst->excluded_modules)) return array();
|
|
|
|
$prodList = array(
|
|
'list' => array(),
|
|
'module' => $module,
|
|
'relmodule' => 'Products',
|
|
'relationid' => $relationId,
|
|
'total' => 0,
|
|
'totalcount' => 0,
|
|
);
|
|
|
|
$total = 0;
|
|
|
|
$focus = $touchUtils->getModuleInstance($module);
|
|
$focus->mode = 'edit';
|
|
|
|
$queryGenerator = QueryGenerator::getInstance($module, $current_user);
|
|
$queryGenerator->initForDefaultCustomView();
|
|
|
|
$queryGenerator->appendToFromClause("INNER JOIN {$table_prefix}_inventoryproductrel prel ON prel.id = {$table_prefix}_crmentity.crmid");
|
|
$queryGenerator->addField('crmid');
|
|
|
|
$params = array();
|
|
$query = $queryGenerator->getQuery();
|
|
$query = preg_replace('/^select\s+.*?\s+from/i', "SELECT {$table_prefix}_crmentity.crmid, {$focus->table_name}.taxtype, prel.lineitem_id as lineid, prel.* FROM", $query);
|
|
|
|
// total:
|
|
$prodList['totalcount'] = $this->countTotalQuery($query, $params);
|
|
|
|
$start = ($page-1)*$pageLimit;
|
|
$res = $adb->limitPQuery($query, $start, $pageLimit, $params);
|
|
|
|
if ($res) {
|
|
|
|
$InventoryUtils = InventoryUtils::getInstance();
|
|
$modWsClass = $touchInst->getWSClassInstance('GetAssociatedProducts', $this->requestedVersion);
|
|
|
|
$i = 1;
|
|
while ($prodrow = $adb->FetchByAssoc($res, -1, false)) {
|
|
$prodid = $prodrow['productid'];
|
|
|
|
$prodList['list']['lineid'][] = $prodrow['lineid'];
|
|
$prodList['list']['crmid'][] = $prodrow['crmid'];
|
|
$prodList['list']['relcrmid'][] = $prodid;
|
|
|
|
$focus->id = $prodrow['crmid'];
|
|
$options = array(
|
|
'taxtype' => $prodrow['taxtype'],
|
|
'skip_subproducts' => true,
|
|
);
|
|
$prodrow = $InventoryUtils->processProductSqlRow($prodrow, $i, $options, $module, $focus);
|
|
$prodrow = $modWsClass->processRow($i, $prodrow);
|
|
|
|
$prodList['list']['extra'][] = $prodrow;
|
|
|
|
++$total;
|
|
++$i;
|
|
}
|
|
}
|
|
|
|
$prodList['total'] = $total;
|
|
|
|
return $prodList;
|
|
}
|
|
|
|
protected function countTotalQuery($query, $params = array()) {
|
|
global $adb, $table_prefix;
|
|
|
|
$list_count = 0;
|
|
$count_query = replaceSelectQuery($query,'count(*) as cnt');
|
|
$res = $adb->pquery($count_query, $params);
|
|
if ($res) {
|
|
$list_count = $adb->query_result_no_html($res,0,'cnt');
|
|
}
|
|
return intval($list_count);
|
|
}
|
|
|
|
} |