PageRenderTime 51ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/include/QueryGenerator/QueryGenerator.php

https://bitbucket.org/thomashii/vtigercrm-5.4-for-postgresql
PHP | 1048 lines | 932 code | 69 blank | 47 comment | 240 complexity | 4366c6f0896ba3d791fc753bfd36ff89 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0
  1. <?php
  2. /*+*******************************************************************************
  3. * The contents of this file are subject to the vtiger CRM Public License Version 1.0
  4. * ("License"); You may not use this file except in compliance with the License
  5. * The Original Code is: vtiger CRM Open Source
  6. * The Initial Developer of the Original Code is vtiger.
  7. * Portions created by vtiger are Copyright (C) vtiger.
  8. * All Rights Reserved.
  9. *
  10. *********************************************************************************/
  11. require_once 'data/CRMEntity.php';
  12. require_once 'modules/CustomView/CustomView.php';
  13. require_once 'include/Webservices/Utils.php';
  14. require_once 'include/Webservices/RelatedModuleMeta.php';
  15. /**
  16. * Description of QueryGenerator
  17. *
  18. * @author MAK
  19. */
  20. class QueryGenerator {
  21. private $module;
  22. private $customViewColumnList;
  23. private $stdFilterList;
  24. private $conditionals;
  25. private $manyToManyRelatedModuleConditions;
  26. private $groupType;
  27. private $whereFields;
  28. /**
  29. *
  30. * @var VtigerCRMObjectMeta
  31. */
  32. private $meta;
  33. /**
  34. *
  35. * @var Users
  36. */
  37. private $user;
  38. private $advFilterList;
  39. private $fields;
  40. private $referenceModuleMetaInfo;
  41. private $moduleNameFields;
  42. private $referenceFieldInfoList;
  43. private $referenceFieldList;
  44. private $ownerFields;
  45. private $columns;
  46. private $fromClause;
  47. private $whereClause;
  48. private $query;
  49. private $groupInfo;
  50. private $conditionInstanceCount;
  51. private $conditionalWhere;
  52. public static $AND = 'AND';
  53. public static $OR = 'OR';
  54. private $customViewFields;
  55. public function __construct($module, $user) {
  56. $db = PearDatabase::getInstance();
  57. $this->module = $module;
  58. $this->customViewColumnList = null;
  59. $this->stdFilterList = null;
  60. $this->conditionals = array();
  61. $this->user = $user;
  62. $this->advFilterList = null;
  63. $this->fields = array();
  64. $this->referenceModuleMetaInfo = array();
  65. $this->moduleNameFields = array();
  66. $this->whereFields = array();
  67. $this->groupType = self::$AND;
  68. $this->meta = $this->getMeta($module);
  69. $this->moduleNameFields[$module] = $this->meta->getNameFields();
  70. $this->referenceFieldInfoList = $this->meta->getReferenceFieldDetails();
  71. $this->referenceFieldList = array_keys($this->referenceFieldInfoList);;
  72. $this->ownerFields = $this->meta->getOwnerFields();
  73. $this->columns = null;
  74. $this->fromClause = null;
  75. $this->whereClause = null;
  76. $this->query = null;
  77. $this->conditionalWhere = null;
  78. $this->groupInfo = '';
  79. $this->manyToManyRelatedModuleConditions = array();
  80. $this->conditionInstanceCount = 0;
  81. $this->customViewFields = array();
  82. }
  83. /**
  84. *
  85. * @param String:ModuleName $module
  86. * @return EntityMeta
  87. */
  88. public function getMeta($module) {
  89. $db = PearDatabase::getInstance();
  90. if (empty($this->referenceModuleMetaInfo[$module])) {
  91. $handler = vtws_getModuleHandlerFromName($module, $this->user);
  92. $meta = $handler->getMeta();
  93. $this->referenceModuleMetaInfo[$module] = $meta;
  94. $this->moduleNameFields[$module] = $meta->getNameFields();
  95. }
  96. return $this->referenceModuleMetaInfo[$module];
  97. }
  98. public function reset() {
  99. $this->fromClause = null;
  100. $this->whereClause = null;
  101. $this->columns = null;
  102. $this->query = null;
  103. }
  104. public function setFields($fields) {
  105. $this->fields = $fields;
  106. }
  107. public function getCustomViewFields() {
  108. return $this->customViewFields;
  109. }
  110. public function getFields() {
  111. return $this->fields;
  112. }
  113. public function getWhereFields() {
  114. return $this->whereFields;
  115. }
  116. public function getOwnerFieldList() {
  117. return $this->ownerFields;
  118. }
  119. public function getModuleNameFields($module) {
  120. return $this->moduleNameFields[$module];
  121. }
  122. public function getReferenceFieldList() {
  123. return $this->referenceFieldList;
  124. }
  125. public function getReferenceFieldInfoList() {
  126. return $this->referenceFieldInfoList;
  127. }
  128. public function getModule () {
  129. return $this->module;
  130. }
  131. public function getConditionalWhere() {
  132. return $this->conditionalWhere;
  133. }
  134. public function getDefaultCustomViewQuery() {
  135. $customView = new CustomView($this->module);
  136. $viewId = $customView->getViewId($this->module);
  137. return $this->getCustomViewQueryById($viewId);
  138. }
  139. public function initForDefaultCustomView() {
  140. $customView = new CustomView($this->module);
  141. $viewId = $customView->getViewId($this->module);
  142. $this->initForCustomViewById($viewId);
  143. }
  144. public function initForCustomViewById($viewId) {
  145. $customView = new CustomView($this->module);
  146. $this->customViewColumnList = $customView->getColumnsListByCvid($viewId);
  147. foreach ($this->customViewColumnList as $customViewColumnInfo) {
  148. $details = explode(':', $customViewColumnInfo);
  149. if(empty($details[2]) && $details[1] == 'crmid' && $details[0] == 'vtiger_crmentity') {
  150. $name = 'id';
  151. $this->customViewFields[] = $name;
  152. } else {
  153. $this->fields[] = $details[2];
  154. $this->customViewFields[] = $details[2];
  155. }
  156. }
  157. if($this->module == 'Calendar' && !in_array('activitytype', $this->fields)) {
  158. $this->fields[] = 'activitytype';
  159. }
  160. if($this->module == 'Documents') {
  161. if(in_array('filename', $this->fields)) {
  162. if(!in_array('filelocationtype', $this->fields)) {
  163. $this->fields[] = 'filelocationtype';
  164. }
  165. if(!in_array('filestatus', $this->fields)) {
  166. $this->fields[] = 'filestatus';
  167. }
  168. }
  169. }
  170. $this->fields[] = 'id';
  171. $this->stdFilterList = $customView->getStdFilterByCvid($viewId);
  172. $this->advFilterList = $customView->getAdvFilterByCvid($viewId);
  173. if(is_array($this->stdFilterList)) {
  174. $value = array();
  175. if(!empty($this->stdFilterList['columnname'])) {
  176. $this->startGroup('');
  177. $name = explode(':',$this->stdFilterList['columnname']);
  178. $name = $name[2];
  179. $value[] = $this->fixDateTimeValue($name, $this->stdFilterList['startdate']);
  180. $value[] = $this->fixDateTimeValue($name, $this->stdFilterList['enddate'], false);
  181. $this->addCondition($name, $value, 'BETWEEN');
  182. }
  183. }
  184. if($this->conditionInstanceCount <= 0 && is_array($this->advFilterList) && count($this->advFilterList) > 0) {
  185. $this->startGroup('');
  186. } elseif($this->conditionInstanceCount > 0 && is_array($this->advFilterList) && count($this->advFilterList) > 0) {
  187. $this->addConditionGlue(self::$AND);
  188. }
  189. if(is_array($this->advFilterList) && count($this->advFilterList) > 0) {
  190. foreach ($this->advFilterList as $groupindex=>$groupcolumns) {
  191. $filtercolumns = $groupcolumns['columns'];
  192. if(count($filtercolumns) > 0) {
  193. $this->startGroup('');
  194. foreach ($filtercolumns as $index=>$filter) {
  195. $name = explode(':',$filter['columnname']);
  196. if(empty($name[2]) && $name[1] == 'crmid' && $name[0] == 'vtiger_crmentity') {
  197. $name = $this->getSQLColumn('id');
  198. } else {
  199. $name = $name[2];
  200. }
  201. $this->addCondition($name, $filter['value'], $filter['comparator']);
  202. $columncondition = $filter['column_condition'];
  203. if(!empty($columncondition)) {
  204. $this->addConditionGlue($columncondition);
  205. }
  206. }
  207. $this->endGroup();
  208. $groupConditionGlue = $groupcolumns['condition'];
  209. if(!empty($groupConditionGlue))
  210. $this->addConditionGlue($groupConditionGlue);
  211. }
  212. }
  213. }
  214. if($this->conditionInstanceCount > 0) {
  215. $this->endGroup();
  216. }
  217. }
  218. public function getCustomViewQueryById($viewId) {
  219. $this->initForCustomViewById($viewId);
  220. return $this->getQuery();
  221. }
  222. public function getQuery() {
  223. if(empty($this->query)) {
  224. $conditionedReferenceFields = array();
  225. $allFields = array_merge($this->whereFields,$this->fields);
  226. foreach ($allFields as $fieldName) {
  227. if(in_array($fieldName,$this->referenceFieldList)) {
  228. $moduleList = $this->referenceFieldInfoList[$fieldName];
  229. foreach ($moduleList as $module) {
  230. if(empty($this->moduleNameFields[$module])) {
  231. $meta = $this->getMeta($module);
  232. }
  233. }
  234. } elseif(in_array($fieldName, $this->ownerFields )) {
  235. $meta = $this->getMeta('Users');
  236. $meta = $this->getMeta('Groups');
  237. }
  238. }
  239. $query = "SELECT ";
  240. $query .= $this->getSelectClauseColumnSQL();
  241. $query .= $this->getFromClause();
  242. $query .= $this->getWhereClause();
  243. $this->query = $query;
  244. return $query;
  245. } else {
  246. return $this->query;
  247. }
  248. }
  249. public function getSQLColumn($name) {
  250. if ($name == 'id') {
  251. $baseTable = $this->meta->getEntityBaseTable();
  252. $moduleTableIndexList = $this->meta->getEntityTableIndexList();
  253. $baseTableIndex = $moduleTableIndexList[$baseTable];
  254. return $baseTable.'.'.$baseTableIndex;
  255. }
  256. $moduleFields = $this->meta->getModuleFields();
  257. $field = $moduleFields[$name];
  258. $sql = '';
  259. //TODO optimization to eliminate one more lookup of name, incase the field refers to only
  260. //one module or is of type owner.
  261. $column = $field->getColumnName();
  262. return $field->getTableName().'.'.$column;
  263. }
  264. public function getSelectClauseColumnSQL(){
  265. $columns = array();
  266. $moduleFields = $this->meta->getModuleFields();
  267. $accessibleFieldList = array_keys($moduleFields);
  268. $accessibleFieldList[] = 'id';
  269. $this->fields = array_intersect($this->fields, $accessibleFieldList);
  270. foreach ($this->fields as $field) {
  271. $sql = $this->getSQLColumn($field);
  272. $columns[] = $sql;
  273. }
  274. $this->columns = implode(', ',$columns);
  275. return $this->columns;
  276. }
  277. public function getFromClause() {
  278. if(!empty($this->query) || !empty($this->fromClause)) {
  279. return $this->fromClause;
  280. }
  281. $moduleFields = $this->meta->getModuleFields();
  282. $tableList = array();
  283. $tableJoinMapping = array();
  284. $tableJoinCondition = array();
  285. foreach ($this->fields as $fieldName) {
  286. if ($fieldName == 'id') {
  287. continue;
  288. }
  289. $field = $moduleFields[$fieldName];
  290. $baseTable = $field->getTableName();
  291. $tableIndexList = $this->meta->getEntityTableIndexList();
  292. $baseTableIndex = $tableIndexList[$baseTable];
  293. if($field->getFieldDataType() == 'reference') {
  294. $moduleList = $this->referenceFieldInfoList[$fieldName];
  295. $tableJoinMapping[$field->getTableName()] = 'INNER JOIN';
  296. foreach($moduleList as $module) {
  297. if($module == 'Users') {
  298. $tableJoinCondition[$fieldName]['vtiger_users'] = $field->getTableName().
  299. ".".$field->getColumnName()." = vtiger_users.id";
  300. $tableJoinCondition[$fieldName]['vtiger_groups'] = $field->getTableName().
  301. ".".$field->getColumnName()." = vtiger_groups.groupid";
  302. $tableJoinMapping['vtiger_users'] = 'LEFT JOIN';
  303. $tableJoinMapping['vtiger_groups'] = 'LEFT JOIN';
  304. }
  305. }
  306. } elseif($field->getFieldDataType() == 'owner') {
  307. $tableList['vtiger_users'] = 'vtiger_users';
  308. $tableList['vtiger_groups'] = 'vtiger_groups';
  309. $tableJoinMapping['vtiger_users'] = 'LEFT JOIN';
  310. $tableJoinMapping['vtiger_groups'] = 'LEFT JOIN';
  311. }
  312. $tableList[$field->getTableName()] = $field->getTableName();
  313. $tableJoinMapping[$field->getTableName()] =
  314. $this->meta->getJoinClause($field->getTableName());
  315. }
  316. $baseTable = $this->meta->getEntityBaseTable();
  317. $moduleTableIndexList = $this->meta->getEntityTableIndexList();
  318. $baseTableIndex = $moduleTableIndexList[$baseTable];
  319. foreach ($this->whereFields as $fieldName) {
  320. if(empty($fieldName)) {
  321. continue;
  322. }
  323. $field = $moduleFields[$fieldName];
  324. if(empty($field)) {
  325. // not accessible field.
  326. continue;
  327. }
  328. $baseTable = $field->getTableName();
  329. // When a field is included in Where Clause, but not is Select Clause, and the field table is not base table,
  330. // The table will not be present in tablesList and hence needs to be added to the list.
  331. if(empty($tableList[$baseTable])) {
  332. $tableList[$baseTable] = $field->getTableName();
  333. $tableJoinMapping[$baseTable] = $this->meta->getJoinClause($field->getTableName());
  334. }
  335. if($field->getFieldDataType() == 'reference') {
  336. $moduleList = $this->referenceFieldInfoList[$fieldName];
  337. $tableJoinMapping[$field->getTableName()] = 'INNER JOIN';
  338. foreach($moduleList as $module) {
  339. $meta = $this->getMeta($module);
  340. $nameFields = $this->moduleNameFields[$module];
  341. $nameFieldList = explode(',',$nameFields);
  342. foreach ($nameFieldList as $index=>$column) {
  343. // for non admin user users module is inaccessible.
  344. // so need hard code the tablename.
  345. if($module == 'Users') {
  346. $instance = CRMEntity::getInstance($module);
  347. $referenceTable = $instance->table_name;
  348. $tableIndexList = $instance->tab_name_index;
  349. $referenceTableIndex = $tableIndexList[$referenceTable];
  350. } else {
  351. $referenceField = $meta->getFieldByColumnName($column);
  352. $referenceTable = $referenceField->getTableName();
  353. $tableIndexList = $meta->getEntityTableIndexList();
  354. $referenceTableIndex = $tableIndexList[$referenceTable];
  355. }
  356. if(isset($moduleTableIndexList[$referenceTable])) {
  357. $referenceTableName = "$referenceTable $referenceTable$fieldName";
  358. $referenceTable = "$referenceTable$fieldName";
  359. } else {
  360. $referenceTableName = $referenceTable;
  361. }
  362. //should always be left join for cases where we are checking for null
  363. //reference field values.
  364. $tableJoinMapping[$referenceTableName] = 'LEFT JOIN';
  365. $tableJoinCondition[$fieldName][$referenceTableName] = $baseTable.'.'.
  366. $field->getColumnName().' = '.$referenceTable.'.'.$referenceTableIndex;
  367. }
  368. }
  369. } elseif($field->getFieldDataType() == 'owner') {
  370. $tableList['vtiger_users'] = 'vtiger_users';
  371. $tableList['vtiger_groups'] = 'vtiger_groups';
  372. $tableJoinMapping['vtiger_users'] = 'LEFT JOIN';
  373. $tableJoinMapping['vtiger_groups'] = 'LEFT JOIN';
  374. } else {
  375. $tableList[$field->getTableName()] = $field->getTableName();
  376. $tableJoinMapping[$field->getTableName()] =
  377. $this->meta->getJoinClause($field->getTableName());
  378. }
  379. }
  380. $defaultTableList = $this->meta->getEntityDefaultTableList();
  381. foreach ($defaultTableList as $table) {
  382. if(!in_array($table, $tableList)) {
  383. $tableList[$table] = $table;
  384. $tableJoinMapping[$table] = 'INNER JOIN';
  385. }
  386. }
  387. $ownerFields = $this->meta->getOwnerFields();
  388. if (count($ownerFields) > 0) {
  389. $ownerField = $ownerFields[0];
  390. }
  391. $baseTable = $this->meta->getEntityBaseTable();
  392. $sql = " FROM $baseTable ";
  393. unset($tableList[$baseTable]);
  394. foreach ($defaultTableList as $tableName) {
  395. $sql .= " $tableJoinMapping[$tableName] $tableName ON $baseTable.".
  396. "$baseTableIndex = $tableName.$moduleTableIndexList[$tableName]";
  397. unset($tableList[$tableName]);
  398. }
  399. foreach ($tableList as $tableName) {
  400. if($tableName == 'vtiger_users') {
  401. $field = $moduleFields[$ownerField];
  402. $sql .= " $tableJoinMapping[$tableName] $tableName ON ".$field->getTableName().".".
  403. $field->getColumnName()." = $tableName.id";
  404. } elseif($tableName == 'vtiger_groups') {
  405. $field = $moduleFields[$ownerField];
  406. $sql .= " $tableJoinMapping[$tableName] $tableName ON ".$field->getTableName().".".
  407. $field->getColumnName()." = $tableName.groupid";
  408. } else {
  409. $sql .= " $tableJoinMapping[$tableName] $tableName ON $baseTable.".
  410. "$baseTableIndex = $tableName.$moduleTableIndexList[$tableName]";
  411. }
  412. }
  413. if( $this->meta->getTabName() == 'Documents') {
  414. $tableJoinCondition['folderid'] = array(
  415. 'vtiger_attachmentsfolder'=>"$baseTable.folderid = vtiger_attachmentsfolder.folderid"
  416. );
  417. $tableJoinMapping['vtiger_attachmentsfolder'] = 'INNER JOIN';
  418. }
  419. foreach ($tableJoinCondition as $fieldName=>$conditionInfo) {
  420. foreach ($conditionInfo as $tableName=>$condition) {
  421. if(!empty($tableList[$tableName])) {
  422. $tableNameAlias = $tableName.'2';
  423. $condition = str_replace($tableName, $tableNameAlias, $condition);
  424. } else {
  425. $tableNameAlias = '';
  426. }
  427. $sql .= " $tableJoinMapping[$tableName] $tableName $tableNameAlias ON $condition";
  428. }
  429. }
  430. foreach ($this->manyToManyRelatedModuleConditions as $conditionInfo) {
  431. $relatedModuleMeta = RelatedModuleMeta::getInstance($this->meta->getTabName(),
  432. $conditionInfo['relatedModule']);
  433. $relationInfo = $relatedModuleMeta->getRelationMeta();
  434. $relatedModule = $this->meta->getTabName();
  435. $sql .= ' INNER JOIN '.$relationInfo['relationTable']." ON ".
  436. $relationInfo['relationTable'].".$relationInfo[$relatedModule]=".
  437. "$baseTable.$baseTableIndex";
  438. }
  439. $sql .= $this->meta->getEntityAccessControlQuery();
  440. $this->fromClause = $sql;
  441. return $sql;
  442. }
  443. public function getWhereClause() {
  444. if(!empty($this->query) || !empty($this->whereClause)) {
  445. return $this->whereClause;
  446. }
  447. $deletedQuery = $this->meta->getEntityDeletedQuery();
  448. $sql = '';
  449. if(!empty($deletedQuery)) {
  450. $sql .= " WHERE $deletedQuery";
  451. }
  452. if($this->conditionInstanceCount > 0) {
  453. $sql .= ' AND ';
  454. } elseif(empty($deletedQuery)) {
  455. $sql .= ' WHERE ';
  456. }
  457. $moduleFieldList = $this->meta->getModuleFields();
  458. $baseTable = $this->meta->getEntityBaseTable();
  459. $moduleTableIndexList = $this->meta->getEntityTableIndexList();
  460. $baseTableIndex = $moduleTableIndexList[$baseTable];
  461. $groupSql = $this->groupInfo;
  462. $fieldSqlList = array();
  463. foreach ($this->conditionals as $index=>$conditionInfo) {
  464. $fieldName = $conditionInfo['name'];
  465. $field = $moduleFieldList[$fieldName];
  466. if(empty($field)) {
  467. continue;
  468. }
  469. $fieldSql = '(';
  470. $fieldGlue = '';
  471. $valueSqlList = $this->getConditionValue($conditionInfo['value'],
  472. $conditionInfo['operator'], $field);
  473. if(!is_array($valueSqlList)) {
  474. $valueSqlList = array($valueSqlList);
  475. }
  476. foreach ($valueSqlList as $valueSql) {
  477. if (in_array($fieldName, $this->referenceFieldList)) {
  478. $moduleList = $this->referenceFieldInfoList[$fieldName];
  479. foreach($moduleList as $module) {
  480. $nameFields = $this->moduleNameFields[$module];
  481. $nameFieldList = explode(',',$nameFields);
  482. $meta = $this->getMeta($module);
  483. $columnList = array();
  484. foreach ($nameFieldList as $column) {
  485. if($module == 'Users') {
  486. $instance = CRMEntity::getInstance($module);
  487. $referenceTable = $instance->table_name;
  488. if(count($this->ownerFields) > 0 ||
  489. $this->getModule() == 'Quotes') {
  490. $referenceTable .= '2';
  491. }
  492. } else {
  493. $referenceField = $meta->getFieldByColumnName($column);
  494. $referenceTable = $referenceField->getTableName();
  495. }
  496. if(isset($moduleTableIndexList[$referenceTable])) {
  497. $referenceTable = "$referenceTable$fieldName";
  498. }
  499. $columnList[] = "$referenceTable.$column";
  500. }
  501. if(count($columnList) > 1) {
  502. $columnSql = getSqlForNameInDisplayFormat(array('first_name'=>$columnList[0],'last_name'=>$columnList[1]),'Users');
  503. } else {
  504. $columnSql = implode('', $columnList);
  505. }
  506. $fieldSql .= "$fieldGlue trim($columnSql) $valueSql";
  507. $fieldGlue = ' OR';
  508. }
  509. } elseif (in_array($fieldName, $this->ownerFields)) {
  510. $concatSql = getSqlForNameInDisplayFormat(array('first_name'=>"vtiger_users.first_name",'last_name'=>"vtiger_users.last_name"), 'Users');
  511. $fieldSql .= "$fieldGlue trim($concatSql) $valueSql or "."vtiger_groups.groupname $valueSql";
  512. } else {
  513. if($fieldName == 'birthday' && !$this->isRelativeSearchOperators(
  514. $conditionInfo['operator'])) {
  515. $fieldSql .= "$fieldGlue DATE_FORMAT(".$field->getTableName().'.'.
  516. $field->getColumnName().",'%m%d') ".$valueSql;
  517. } else {
  518. $fieldSql .= "$fieldGlue ".$field->getTableName().'.'.
  519. $field->getColumnName().' '.$valueSql;
  520. }
  521. }
  522. $fieldGlue = ' OR';
  523. }
  524. $fieldSql .= ')';
  525. $fieldSqlList[$index] = $fieldSql;
  526. }
  527. foreach ($this->manyToManyRelatedModuleConditions as $index=>$conditionInfo) {
  528. $relatedModuleMeta = RelatedModuleMeta::getInstance($this->meta->getTabName(),
  529. $conditionInfo['relatedModule']);
  530. $relationInfo = $relatedModuleMeta->getRelationMeta();
  531. $relatedModule = $this->meta->getTabName();
  532. $fieldSql = "(".$relationInfo['relationTable'].'.'.
  533. $relationInfo[$conditionInfo['column']].$conditionInfo['SQLOperator'].
  534. $conditionInfo['value'].")";
  535. $fieldSqlList[$index] = $fieldSql;
  536. }
  537. $groupSql = $this->makeGroupSqlReplacements($fieldSqlList, $groupSql);
  538. if($this->conditionInstanceCount > 0) {
  539. $this->conditionalWhere = $groupSql;
  540. $sql .= $groupSql;
  541. }
  542. $sql .= " AND $baseTable.$baseTableIndex > 0";
  543. $this->whereClause = $sql;
  544. return $sql;
  545. }
  546. /**
  547. *
  548. * @param mixed $value
  549. * @param String $operator
  550. * @param WebserviceField $field
  551. */
  552. private function getConditionValue($value, $operator, $field) {
  553. $operator = strtolower($operator);
  554. $db = PearDatabase::getInstance();
  555. if(is_string($value)) {
  556. $valueArray = explode(',' , $value);
  557. } elseif(is_array($value)) {
  558. $valueArray = $value;
  559. } else{
  560. $valueArray = array($value);
  561. }
  562. $sql = array();
  563. if($operator == 'between' || $operator == 'bw') {
  564. if($field->getFieldName() == 'birthday') {
  565. $valueArray[0] = getValidDBInsertDateTimeValue($valueArray[0]);
  566. $valueArray[1] = getValidDBInsertDateTimeValue($valueArray[1]);
  567. $sql[] = "BETWEEN DATE_FORMAT(".$db->quote($valueArray[0]).", '%m%d') AND ".
  568. "DATE_FORMAT(".$db->quote($valueArray[1]).", '%m%d')";
  569. } else {
  570. if($this->isDateType($field->getFieldDataType())) {
  571. $valueArray[0] = getValidDBInsertDateTimeValue($valueArray[0]);
  572. $valueArray[1] = getValidDBInsertDateTimeValue($valueArray[1]);
  573. }
  574. $sql[] = "BETWEEN ".$db->quote($valueArray[0])." AND ".
  575. $db->quote($valueArray[1]);
  576. }
  577. return $sql;
  578. }
  579. foreach ($valueArray as $value) {
  580. if(!$this->isStringType($field->getFieldDataType())) {
  581. $value = trim($value);
  582. }
  583. if((strtolower(trim($value)) == 'null') ||
  584. (trim($value) == '' && !$this->isStringType($field->getFieldDataType())) &&
  585. ($operator == 'e' || $operator == 'n')) {
  586. if($operator == 'e'){
  587. $sql[] = "IS NULL";
  588. continue;
  589. }
  590. $sql[] = "IS NOT NULL";
  591. continue;
  592. } elseif($field->getFieldDataType() == 'boolean') {
  593. $value = strtolower($value);
  594. if ($value == 'yes') {
  595. $value = 1;
  596. } elseif($value == 'no') {
  597. $value = 0;
  598. }
  599. } elseif($this->isDateType($field->getFieldDataType())) {
  600. $value = getValidDBInsertDateTimeValue($value);
  601. }
  602. if($field->getFieldName() == 'birthday' && !$this->isRelativeSearchOperators(
  603. $operator)) {
  604. $value = "DATE_FORMAT(".$db->quote($value).", '%m%d')";
  605. } else {
  606. $value = $db->sql_escape_string($value);
  607. }
  608. if(trim($value) == '' && ($operator == 's' || $operator == 'ew' || $operator == 'c')
  609. && ($this->isStringType($field->getFieldDataType()) ||
  610. $field->getFieldDataType() == 'picklist' ||
  611. $field->getFieldDataType() == 'multipicklist')) {
  612. $sql[] = "LIKE ''";
  613. continue;
  614. }
  615. if(trim($value) == '' && ($operator == 'k') &&
  616. $this->isStringType($field->getFieldDataType())) {
  617. $sql[] = "NOT LIKE ''";
  618. continue;
  619. }
  620. switch($operator) {
  621. case 'e': $sqlOperator = "=";
  622. break;
  623. case 'n': $sqlOperator = "<>";
  624. break;
  625. case 's': $sqlOperator = "LIKE";
  626. $value = "$value%";
  627. break;
  628. case 'ew': $sqlOperator = "LIKE";
  629. $value = "%$value";
  630. break;
  631. case 'c': $sqlOperator = "LIKE";
  632. $value = "%$value%";
  633. break;
  634. case 'k': $sqlOperator = "NOT LIKE";
  635. $value = "%$value%";
  636. break;
  637. case 'l': $sqlOperator = "<";
  638. break;
  639. case 'g': $sqlOperator = ">";
  640. break;
  641. case 'm': $sqlOperator = "<=";
  642. break;
  643. case 'h': $sqlOperator = ">=";
  644. break;
  645. case 'a': $sqlOperator = ">";
  646. break;
  647. case 'b': $sqlOperator = "<";
  648. break;
  649. }
  650. if(!$this->isNumericType($field->getFieldDataType()) &&
  651. ($field->getFieldName() != 'birthday' || ($field->getFieldName() == 'birthday'
  652. && $this->isRelativeSearchOperators($operator)))){
  653. $value = "'$value'";
  654. }
  655. if($this->isNumericType($field->getFieldDataType()) && empty($value)) {
  656. $value = '0';
  657. }
  658. $sql[] = "$sqlOperator $value";
  659. }
  660. return $sql;
  661. }
  662. private function makeGroupSqlReplacements($fieldSqlList, $groupSql) {
  663. $pos = 0;
  664. $nextOffset = 0;
  665. foreach ($fieldSqlList as $index => $fieldSql) {
  666. $pos = strpos($groupSql, $index.'', $nextOffset);
  667. if($pos !== false) {
  668. $beforeStr = substr($groupSql,0,$pos);
  669. $afterStr = substr($groupSql, $pos + strlen($index));
  670. $nextOffset = strlen($beforeStr.$fieldSql);
  671. $groupSql = $beforeStr.$fieldSql.$afterStr;
  672. }
  673. }
  674. return $groupSql;
  675. }
  676. private function isRelativeSearchOperators($operator) {
  677. $nonDaySearchOperators = array('l','g','m','h');
  678. return in_array($operator, $nonDaySearchOperators);
  679. }
  680. private function isNumericType($type) {
  681. return ($type == 'integer' || $type == 'double' || $type == 'currency');
  682. }
  683. private function isStringType($type) {
  684. return ($type == 'string' || $type == 'text' || $type == 'email' || $type == 'reference');
  685. }
  686. private function isDateType($type) {
  687. return ($type == 'date' || $type == 'datetime');
  688. }
  689. private function fixDateTimeValue($name, $value, $first = true) {
  690. $moduleFields = $this->meta->getModuleFields();
  691. $field = $moduleFields[$name];
  692. $type = $field->getFieldDataType();
  693. if($type == 'datetime') {
  694. if(strrpos($value, ' ') === false) {
  695. if($first) {
  696. return $value.' 00:00:00';
  697. }else{
  698. return $value.' 23:59:59';
  699. }
  700. }
  701. }
  702. return $value;
  703. }
  704. public function addCondition($fieldname,$value,$operator,$glue= null,$newGroup = false,
  705. $newGroupType = null) {
  706. $conditionNumber = $this->conditionInstanceCount++;
  707. $this->groupInfo .= "$conditionNumber ";
  708. $this->whereFields[] = $fieldname;
  709. $this->reset();
  710. $this->conditionals[$conditionNumber] = $this->getConditionalArray($fieldname,
  711. $value, $operator);
  712. }
  713. public function addRelatedModuleCondition($relatedModule,$column, $value, $SQLOperator) {
  714. $conditionNumber = $this->conditionInstanceCount++;
  715. $this->groupInfo .= "$conditionNumber ";
  716. $this->manyToManyRelatedModuleConditions[$conditionNumber] = array('relatedModule'=>
  717. $relatedModule,'column'=>$column,'value'=>$value,'SQLOperator'=>$SQLOperator);
  718. }
  719. private function getConditionalArray($fieldname,$value,$operator) {
  720. if(is_string($value)) {
  721. $value = trim($value);
  722. } elseif(is_array($value)) {
  723. $value = array_map(trim, $value);
  724. }
  725. return array('name'=>$fieldname,'value'=>$value,'operator'=>$operator);
  726. }
  727. public function startGroup($groupType) {
  728. $this->groupInfo .= " $groupType (";
  729. }
  730. public function endGroup() {
  731. $this->groupInfo .= ')';
  732. }
  733. public function addConditionGlue($glue) {
  734. $this->groupInfo .= " $glue ";
  735. }
  736. public function addUserSearchConditions($input) {
  737. global $log,$default_charset;
  738. if($input['searchtype']=='advance') {
  739. $json = new Zend_Json();
  740. $advft_criteria = $_REQUEST['advft_criteria'];
  741. if(!empty($advft_criteria)) $advft_criteria = $json->decode($advft_criteria);
  742. $advft_criteria_groups = $_REQUEST['advft_criteria_groups'];
  743. if(!empty($advft_criteria_groups)) $advft_criteria_groups = $json->decode($advft_criteria_groups);
  744. if(empty($advft_criteria) || count($advft_criteria) <= 0) {
  745. return ;
  746. }
  747. $advfilterlist = getAdvancedSearchCriteriaList($advft_criteria, $advft_criteria_groups, $this->getModule());
  748. if(empty($advfilterlist) || count($advfilterlist) <= 0) {
  749. return ;
  750. }
  751. if($this->conditionInstanceCount > 0) {
  752. $this->startGroup(self::$AND);
  753. } else {
  754. $this->startGroup('');
  755. }
  756. foreach ($advfilterlist as $groupindex=>$groupcolumns) {
  757. $filtercolumns = $groupcolumns['columns'];
  758. if(count($filtercolumns) > 0) {
  759. $this->startGroup('');
  760. foreach ($filtercolumns as $index=>$filter) {
  761. $name = explode(':',$filter['columnname']);
  762. if(empty($name[2]) && $name[1] == 'crmid' && $name[0] == 'vtiger_crmentity') {
  763. $name = $this->getSQLColumn('id');
  764. } else {
  765. $name = $name[2];
  766. }
  767. $this->addCondition($name, $filter['value'], $filter['comparator']);
  768. $columncondition = $filter['column_condition'];
  769. if(!empty($columncondition)) {
  770. $this->addConditionGlue($columncondition);
  771. }
  772. }
  773. $this->endGroup();
  774. $groupConditionGlue = $groupcolumns['condition'];
  775. if(!empty($groupConditionGlue))
  776. $this->addConditionGlue($groupConditionGlue);
  777. }
  778. }
  779. $this->endGroup();
  780. } elseif($input['type']=='dbrd') {
  781. if($this->conditionInstanceCount > 0) {
  782. $this->startGroup(self::$AND);
  783. } else {
  784. $this->startGroup('');
  785. }
  786. $allConditionsList = $this->getDashBoardConditionList();
  787. $conditionList = $allConditionsList['conditions'];
  788. $relatedConditionList = $allConditionsList['relatedConditions'];
  789. $noOfConditions = count($conditionList);
  790. $noOfRelatedConditions = count($relatedConditionList);
  791. foreach ($conditionList as $index=>$conditionInfo) {
  792. $this->addCondition($conditionInfo['fieldname'], $conditionInfo['value'],
  793. $conditionInfo['operator']);
  794. if($index < $noOfConditions - 1 || $noOfRelatedConditions > 0) {
  795. $this->addConditionGlue(self::$AND);
  796. }
  797. }
  798. foreach ($relatedConditionList as $index => $conditionInfo) {
  799. $this->addRelatedModuleCondition($conditionInfo['relatedModule'],
  800. $conditionInfo['conditionModule'], $conditionInfo['finalValue'],
  801. $conditionInfo['SQLOperator']);
  802. if($index < $noOfRelatedConditions - 1) {
  803. $this->addConditionGlue(self::$AND);
  804. }
  805. }
  806. $this->endGroup();
  807. } else {
  808. if(isset($input['search_field']) && $input['search_field'] !="") {
  809. $fieldName=vtlib_purify($input['search_field']);
  810. } else {
  811. return ;
  812. }
  813. if($this->conditionInstanceCount > 0) {
  814. $this->startGroup(self::$AND);
  815. } else {
  816. $this->startGroup('');
  817. }
  818. $moduleFields = $this->meta->getModuleFields();
  819. $field = $moduleFields[$fieldName];
  820. $type = $field->getFieldDataType();
  821. if(isset($input['search_text']) && $input['search_text']!="") {
  822. // search other characters like "|, ?, ?" by jagi
  823. $value = $input['search_text'];
  824. $stringConvert = function_exists(iconv) ? @iconv("UTF-8",$default_charset,$value)
  825. : $value;
  826. if(!$this->isStringType($type)) {
  827. $value=trim($stringConvert);
  828. }
  829. if($type == 'picklist') {
  830. global $mod_strings;
  831. // Get all the keys for the for the Picklist value
  832. $mod_keys = array_keys($mod_strings, $value);
  833. if(sizeof($mod_keys) >= 1) {
  834. // Iterate on the keys, to get the first key which doesn't start with LBL_ (assuming it is not used in PickList)
  835. foreach($mod_keys as $mod_idx=>$mod_key) {
  836. $stridx = strpos($mod_key, 'LBL_');
  837. // Use strict type comparision, refer strpos for more details
  838. if ($stridx !== 0) {
  839. $value = $mod_key;
  840. break;
  841. }
  842. }
  843. }
  844. }
  845. if($type == 'currency') {
  846. // Some of the currency fields like Unit Price, Total, Sub-total etc of Inventory modules, do not need currency conversion
  847. if($field->getUIType() == '72') {
  848. $value = CurrencyField::convertToDBFormat($value, null, true);
  849. } else {
  850. $currencyField = new CurrencyField($value);
  851. if($this->getModule() == 'Potentials' && $fieldName == 'amount') {
  852. $currencyField->setNumberofDecimals(2);
  853. }
  854. $value = $currencyField->getDBInsertedValue();
  855. }
  856. }
  857. }
  858. if(!empty($input['operator'])) {
  859. $operator = $input['operator'];
  860. } elseif(trim(strtolower($value)) == 'null'){
  861. $operator = 'e';
  862. } else {
  863. if(!$this->isNumericType($type) && !$this->isDateType($type)) {
  864. $operator = 'c';
  865. } else {
  866. $operator = 'h';
  867. }
  868. }
  869. $this->addCondition($fieldName, $value, $operator);
  870. $this->endGroup();
  871. }
  872. }
  873. public function getDashBoardConditionList() {
  874. if(isset($_REQUEST['leadsource'])) {
  875. $leadSource = $_REQUEST['leadsource'];
  876. }
  877. if(isset($_REQUEST['date_closed'])) {
  878. $dateClosed = $_REQUEST['date_closed'];
  879. }
  880. if(isset($_REQUEST['sales_stage'])) {
  881. $salesStage = $_REQUEST['sales_stage'];
  882. }
  883. if(isset($_REQUEST['closingdate_start'])) {
  884. $dateClosedStart = $_REQUEST['closingdate_start'];
  885. }
  886. if(isset($_REQUEST['closingdate_end'])) {
  887. $dateClosedEnd = $_REQUEST['closingdate_end'];
  888. }
  889. if(isset($_REQUEST['owner'])) {
  890. $owner = vtlib_purify($_REQUEST['owner']);
  891. }
  892. if(isset($_REQUEST['campaignid'])) {
  893. $campaignId = vtlib_purify($_REQUEST['campaignid']);
  894. }
  895. if(isset($_REQUEST['quoteid'])) {
  896. $quoteId = vtlib_purify($_REQUEST['quoteid']);
  897. }
  898. if(isset($_REQUEST['invoiceid'])) {
  899. $invoiceId = vtlib_purify($_REQUEST['invoiceid']);
  900. }
  901. if(isset($_REQUEST['purchaseorderid'])) {
  902. $purchaseOrderId = vtlib_purify($_REQUEST['purchaseorderid']);
  903. }
  904. $conditionList = array();
  905. if(!empty($dateClosedStart) && !empty($dateClosedEnd)) {
  906. $conditionList[] = array('fieldname'=>'closingdate', 'value'=>$dateClosedStart,
  907. 'operator'=>'h');
  908. $conditionList[] = array('fieldname'=>'closingdate', 'value'=>$dateClosedEnd,
  909. 'operator'=>'m');
  910. }
  911. if(!empty($salesStage)) {
  912. if($salesStage == 'Other') {
  913. $conditionList[] = array('fieldname'=>'sales_stage', 'value'=>'Closed Won',
  914. 'operator'=>'n');
  915. $conditionList[] = array('fieldname'=>'sales_stage', 'value'=>'Closed Lost',
  916. 'operator'=>'n');
  917. } else {
  918. $conditionList[] = array('fieldname'=>'sales_stage', 'value'=> $salesStage,
  919. 'operator'=>'e');
  920. }
  921. }
  922. if(!empty($leadSource)) {
  923. $conditionList[] = array('fieldname'=>'leadsource', 'value'=>$leadSource,
  924. 'operator'=>'e');
  925. }
  926. if(!empty($dateClosed)) {
  927. $conditionList[] = array('fieldname'=>'closingdate', 'value'=>$dateClosed,
  928. 'operator'=>'h');
  929. }
  930. if(!empty($owner)) {
  931. $conditionList[] = array('fieldname'=>'assigned_user_id', 'value'=>$owner,
  932. 'operator'=>'e');
  933. }
  934. $relatedConditionList = array();
  935. if(!empty($campaignId)) {
  936. $relatedConditionList[] = array('relatedModule'=>'Campaigns','conditionModule'=>
  937. 'Campaigns','finalValue'=>$campaignId, 'SQLOperator'=>'=');
  938. }
  939. if(!empty($quoteId)) {
  940. $relatedConditionList[] = array('relatedModule'=>'Quotes','conditionModule'=>
  941. 'Quotes','finalValue'=>$quoteId, 'SQLOperator'=>'=');
  942. }
  943. if(!empty($invoiceId)) {
  944. $relatedConditionList[] = array('relatedModule'=>'Invoice','conditionModule'=>
  945. 'Invoice','finalValue'=>$invoiceId, 'SQLOperator'=>'=');
  946. }
  947. if(!empty($purchaseOrderId)) {
  948. $relatedConditionList[] = array('relatedModule'=>'PurchaseOrder','conditionModule'=>
  949. 'PurchaseOrder','finalValue'=>$purchaseOrderId, 'SQLOperator'=>'=');
  950. }
  951. return array('conditions'=>$conditionList,'relatedConditions'=>$relatedConditionList);
  952. }
  953. public function initForGlobalSearchByType($type, $value, $operator='s') {
  954. $fieldList = $this->meta->getFieldNameListByType($type);
  955. if($this->conditionInstanceCount <= 0) {
  956. $this->startGroup('');
  957. } else {
  958. $this->startGroup(self::$AND);
  959. }
  960. $nameFieldList = explode(',',$this->getModuleNameFields($this->module));
  961. foreach ($nameFieldList as $nameList) {
  962. $field = $this->meta->getFieldByColumnName($nameList);
  963. $this->fields[] = $field->getFieldName();
  964. }
  965. foreach ($fieldList as $index => $field) {
  966. $fieldName = $this->meta->getFieldByColumnName($field);
  967. $this->fields[] = $fieldName->getFieldName();
  968. if($index > 0) {
  969. $this->addConditionGlue(self::$OR);
  970. }
  971. $this->addCondition($fieldName->getFieldName(), $value, $operator);
  972. }
  973. $this->endGroup();
  974. if(!in_array('id', $this->fields)) {
  975. $this->fields[] = 'id';
  976. }
  977. }
  978. }
  979. ?>