PageRenderTime 132ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 2ms

/data/CRMEntity.php

https://bitbucket.org/thomashii/vtigercrm-6-for-postgresql
PHP | 2631 lines | 1832 code | 386 blank | 413 comment | 554 complexity | 5663782404bc175a23fa27fc38cd02d8 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-3.0, LGPL-2.1, GPL-2.0, GPL-3.0
  1. <?php
  2. /*********************************************************************************
  3. * The contents of this file are subject to the SugarCRM Public License Version 1.1.2
  4. * ("License"); You may not use this file except in compliance with the
  5. * License. You may obtain a copy of the License at http://www.sugarcrm.com/SPL
  6. * Software distributed under the License is distributed on an "AS IS" basis,
  7. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
  8. * the specific language governing rights and limitations under the License.
  9. * The Original Code is: SugarCRM Open Source
  10. * The Initial Developer of the Original Code is SugarCRM, Inc.
  11. * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.;
  12. * All Rights Reserved.
  13. * Contributor(s): ______________________________________.
  14. ********************************************************************************/
  15. /*********************************************************************************
  16. * $Header: /advent/projects/wesat/vtiger_crm/vtigercrm/data/CRMEntity.php,v 1.16 2005/04/29 04:21:31 mickie Exp $
  17. * Description: Defines the base class for all data entities used throughout the
  18. * application. The base class including its methods and variables is designed to
  19. * be overloaded with module-specific methods and variables particular to the
  20. * module's base entity class.
  21. ********************************************************************************/
  22. include_once('config.php');
  23. require_once('include/logging.php');
  24. require_once('data/Tracker.php');
  25. require_once('include/utils/utils.php');
  26. require_once('include/utils/UserInfoUtil.php');
  27. require_once("include/Zend/Json.php");
  28. class CRMEntity {
  29. var $ownedby;
  30. /**
  31. * Detect if we are in bulk save mode, where some features can be turned-off
  32. * to improve performance.
  33. */
  34. static function isBulkSaveMode() {
  35. global $VTIGER_BULK_SAVE_MODE;
  36. if (isset($VTIGER_BULK_SAVE_MODE) && $VTIGER_BULK_SAVE_MODE) {
  37. return true;
  38. }
  39. return false;
  40. }
  41. static function getInstance($module) {
  42. $modName = $module;
  43. if ($module == 'Calendar' || $module == 'Events') {
  44. $module = 'Calendar';
  45. $modName = 'Activity';
  46. }
  47. // File access security check
  48. if (!class_exists($modName)) {
  49. checkFileAccessForInclusion("modules/$module/$modName.php");
  50. require_once("modules/$module/$modName.php");
  51. }
  52. $focus = new $modName();
  53. return $focus;
  54. }
  55. function saveentity($module, $fileid = '') {
  56. global $current_user, $adb; //$adb added by raju for mass mailing
  57. $insertion_mode = $this->mode;
  58. $columnFields = $this->column_fields;
  59. $anyValue = false;
  60. foreach ($columnFields as $value) {
  61. if(!empty($value)) {
  62. $anyValue = true;
  63. break;
  64. }
  65. }
  66. if(!$anyValue) {
  67. die("<center>" .getTranslatedString('LBL_MANDATORY_FIELD_MISSING')."</center>");
  68. }
  69. $this->db->println("TRANS saveentity starts $module");
  70. $this->db->startTransaction();
  71. foreach ($this->tab_name as $table_name) {
  72. if ($table_name == "vtiger_crmentity") {
  73. $this->insertIntoCrmEntity($module, $fileid);
  74. } else {
  75. $this->insertIntoEntityTable($table_name, $module, $fileid);
  76. }
  77. }
  78. //Calling the Module specific save code
  79. $this->save_module($module);
  80. $this->db->completeTransaction();
  81. $this->db->println("TRANS saveentity ends");
  82. // vtlib customization: Hook provide to enable generic module relation.
  83. if ($_REQUEST['createmode'] == 'link') {
  84. $for_module = vtlib_purify($_REQUEST['return_module']);
  85. $for_crmid = vtlib_purify($_REQUEST['return_id']);
  86. $with_module = $module;
  87. $with_crmid = $this->id;
  88. $on_focus = CRMEntity::getInstance($for_module);
  89. if ($for_module && $for_crmid && $with_module && $with_crmid) {
  90. relateEntities($on_focus, $for_module, $for_crmid, $with_module, $with_crmid);
  91. }
  92. }
  93. // END
  94. }
  95. /**
  96. * This function is used to upload the attachment in the server and save that attachment information in db.
  97. * @param int $id - entity id to which the file to be uploaded
  98. * @param string $module - the current module name
  99. * @param array $file_details - array which contains the file information(name, type, size, tmp_name and error)
  100. * return void
  101. */
  102. function uploadAndSaveFile($id, $module, $file_details) {
  103. global $log;
  104. $log->debug("Entering into uploadAndSaveFile($id,$module,$file_details) method.");
  105. global $adb, $current_user;
  106. global $upload_badext;
  107. $date_var = date("Y-m-d H:i:s");
  108. //to get the owner id
  109. $ownerid = $this->column_fields['assigned_user_id'];
  110. if (!isset($ownerid) || $ownerid == '')
  111. $ownerid = $current_user->id;
  112. if (isset($file_details['original_name']) && $file_details['original_name'] != null) {
  113. $file_name = $file_details['original_name'];
  114. } else {
  115. $file_name = $file_details['name'];
  116. }
  117. $binFile = sanitizeUploadFileName($file_name, $upload_badext);
  118. $current_id = $adb->getUniqueID("vtiger_crmentity");
  119. $filename = ltrim(basename(" " . $binFile)); //allowed filename like UTF-8 characters
  120. $filetype = $file_details['type'];
  121. $filesize = $file_details['size'];
  122. $filetmp_name = $file_details['tmp_name'];
  123. //get the file path inwhich folder we want to upload the file
  124. $upload_file_path = decideFilePath();
  125. //upload the file in server
  126. $upload_status = move_uploaded_file($filetmp_name, $upload_file_path . $current_id . "_" . $binFile);
  127. $save_file = 'true';
  128. //only images are allowed for these modules
  129. if ($module == 'Contacts' || $module == 'Products') {
  130. $save_file = validateImageFile($file_details);
  131. }
  132. if ($save_file == 'true' && $upload_status == 'true') {
  133. //This is only to update the attached filename in the vtiger_notes vtiger_table for the Notes module
  134. if ($module == 'Contacts' || $module == 'Products') {
  135. $sql1 = "insert into vtiger_crmentity (crmid,smcreatorid,smownerid,setype,description,createdtime,modifiedtime) values(?, ?, ?, ?, ?, ?, ?)";
  136. $params1 = array($current_id, $current_user->id, $ownerid, $module . " Image", $this->column_fields['description'], $adb->formatDate($date_var, true), $adb->formatDate($date_var, true));
  137. } else {
  138. $sql1 = "insert into vtiger_crmentity (crmid,smcreatorid,smownerid,setype,description,createdtime,modifiedtime) values(?, ?, ?, ?, ?, ?, ?)";
  139. $params1 = array($current_id, $current_user->id, $ownerid, $module . " Attachment", $this->column_fields['description'], $adb->formatDate($date_var, true), $adb->formatDate($date_var, true));
  140. }
  141. $adb->pquery($sql1, $params1);
  142. $sql2 = "insert into vtiger_attachments(attachmentsid, name, description, type, path) values(?, ?, ?, ?, ?)";
  143. $params2 = array($current_id, $filename, $this->column_fields['description'], $filetype, $upload_file_path);
  144. $result = $adb->pquery($sql2, $params2);
  145. if ($_REQUEST['mode'] == 'edit') {
  146. if ($id != '' && vtlib_purify($_REQUEST['fileid']) != '') {
  147. $delquery = 'delete from vtiger_seattachmentsrel where crmid = ? and attachmentsid = ?';
  148. $delparams = array($id, vtlib_purify($_REQUEST['fileid']));
  149. $adb->pquery($delquery, $delparams);
  150. }
  151. }
  152. if ($module == 'Documents') {
  153. $query = "delete from vtiger_seattachmentsrel where crmid = ?";
  154. $qparams = array($id);
  155. $adb->pquery($query, $qparams);
  156. }
  157. if ($module == 'Contacts') {
  158. $att_sql = "select vtiger_seattachmentsrel.attachmentsid from vtiger_seattachmentsrel inner join vtiger_crmentity on vtiger_crmentity.crmid=vtiger_seattachmentsrel.attachmentsid where vtiger_crmentity.setype='Contacts Image' and vtiger_seattachmentsrel.crmid=?";
  159. $res = $adb->pquery($att_sql, array($id));
  160. $attachmentsid = $adb->query_result($res, 0, 'attachmentsid');
  161. if ($attachmentsid != '') {
  162. $delquery = 'delete from vtiger_seattachmentsrel where crmid=? and attachmentsid=?';
  163. $adb->pquery($delquery, array($id, $attachmentsid));
  164. $crm_delquery = "delete from vtiger_crmentity where crmid=?";
  165. $adb->pquery($crm_delquery, array($attachmentsid));
  166. $sql5 = 'insert into vtiger_seattachmentsrel values(?,?)';
  167. $adb->pquery($sql5, array($id, $current_id));
  168. } else {
  169. $sql3 = 'insert into vtiger_seattachmentsrel values(?,?)';
  170. $adb->pquery($sql3, array($id, $current_id));
  171. }
  172. } else {
  173. $sql3 = 'insert into vtiger_seattachmentsrel values(?,?)';
  174. $adb->pquery($sql3, array($id, $current_id));
  175. }
  176. return true;
  177. } else {
  178. $log->debug("Skip the save attachment process.");
  179. return false;
  180. }
  181. }
  182. /** Function to insert values in the vtiger_crmentity for the specified module
  183. * @param $module -- module:: Type varchar
  184. */
  185. function insertIntoCrmEntity($module, $fileid = '') {
  186. global $adb;
  187. global $current_user;
  188. global $log;
  189. if ($fileid != '') {
  190. $this->id = $fileid;
  191. $this->mode = 'edit';
  192. }
  193. $date_var = date("Y-m-d H:i:s");
  194. $ownerid = $this->column_fields['assigned_user_id'];
  195. if(empty($ownerid)) {
  196. $ownerid = $current_user->id;
  197. }
  198. if ($module == 'Events') {
  199. $module = 'Calendar';
  200. }
  201. if ($this->mode == 'edit') {
  202. $description_val = from_html($this->column_fields['description'], ($insertion_mode == 'edit') ? true : false);
  203. checkFileAccessForInclusion('user_privileges/user_privileges_' . $current_user->id . '.php');
  204. require('user_privileges/user_privileges_' . $current_user->id . '.php');
  205. $tabid = getTabid($module);
  206. if ($is_admin == true || $profileGlobalPermission[1] == 0 || $profileGlobalPermission[2] == 0) {
  207. $sql = "update vtiger_crmentity set smownerid=?,modifiedby=?,description=?, modifiedtime=? where crmid=?";
  208. $params = array($ownerid, $current_user->id, $description_val, $adb->formatDate($date_var, true), $this->id);
  209. } else {
  210. $profileList = getCurrentUserProfileList();
  211. $perm_qry = "SELECT columnname FROM vtiger_field INNER JOIN vtiger_profile2field ON vtiger_profile2field.fieldid = vtiger_field.fieldid INNER JOIN vtiger_def_org_field ON vtiger_def_org_field.fieldid = vtiger_field.fieldid WHERE vtiger_field.tabid = ? AND vtiger_profile2field.visible = 0 AND vtiger_profile2field.readonly = 0 AND vtiger_profile2field.profileid IN (" . generateQuestionMarks($profileList) . ") AND vtiger_def_org_field.visible = 0 and vtiger_field.tablename='vtiger_crmentity' and vtiger_field.displaytype in (1,3) and vtiger_field.presence in (0,2);";
  212. $perm_result = $adb->pquery($perm_qry, array($tabid, $profileList));
  213. $perm_rows = $adb->num_rows($perm_result);
  214. for ($i = 0; $i < $perm_rows; $i++) {
  215. $columname[] = $adb->query_result($perm_result, $i, "columnname");
  216. }
  217. if (is_array($columname) && in_array("description", $columname)) {
  218. $sql = "update vtiger_crmentity set smownerid=?,modifiedby=?,description=?, modifiedtime=? where crmid=?";
  219. $params = array($ownerid, $current_user->id, $description_val, $adb->formatDate($date_var, true), $this->id);
  220. } else {
  221. $sql = "update vtiger_crmentity set smownerid=?,modifiedby=?, modifiedtime=? where crmid=?";
  222. $params = array($ownerid, $current_user->id, $adb->formatDate($date_var, true), $this->id);
  223. }
  224. }
  225. $adb->pquery($sql, $params);
  226. } else {
  227. //if this is the create mode and the group allocation is chosen, then do the following
  228. $current_id = $adb->getUniqueID("vtiger_crmentity");
  229. $_REQUEST['currentid'] = $current_id;
  230. if ($current_user->id == '')
  231. $current_user->id = 0;
  232. // Customization
  233. $created_date_var = $adb->formatDate($date_var, true);
  234. $modified_date_var = $adb->formatDate($date_var, true);
  235. // Preserve the timestamp
  236. if (self::isBulkSaveMode()) {
  237. if (!empty($this->column_fields['createdtime']))
  238. $created_date_var = $adb->formatDate($this->column_fields['createdtime'], true);
  239. //NOTE : modifiedtime ignored to support vtws_sync API track changes.
  240. }
  241. // END
  242. $description_val = from_html($this->column_fields['description'], ($insertion_mode == 'edit') ? true : false);
  243. $sql = "insert into vtiger_crmentity (crmid,smcreatorid,smownerid,setype,description,modifiedby,createdtime,modifiedtime) values(?,?,?,?,?,?,?,?)";
  244. $params = array($current_id, $current_user->id, $ownerid, $module, $description_val, $current_user->id, $created_date_var, $modified_date_var);
  245. $adb->pquery($sql, $params);
  246. $this->id = $current_id;
  247. }
  248. }
  249. // Function which returns the value based on result type (array / ADODB ResultSet)
  250. private function resolve_query_result_value($result, $index, $columnname) {
  251. global $adb;
  252. if (is_array($result))
  253. return $result[$index][$columnname];
  254. else
  255. return $adb->query_result($result, $index, $columnname);
  256. }
  257. /** Function to insert values in the specifed table for the specified module
  258. * @param $table_name -- table name:: Type varchar
  259. * @param $module -- module:: Type varchar
  260. */
  261. function insertIntoEntityTable($table_name, $module, $fileid = '') {
  262. global $log;
  263. global $current_user, $app_strings;
  264. $log->info("function insertIntoEntityTable " . $module . ' vtiger_table name ' . $table_name);
  265. global $adb;
  266. $insertion_mode = $this->mode;
  267. //Checkin whether an entry is already is present in the vtiger_table to update
  268. if ($insertion_mode == 'edit') {
  269. $tablekey = $this->tab_name_index[$table_name];
  270. // Make selection on the primary key of the module table to check.
  271. $check_query = "select $tablekey from $table_name where $tablekey=?";
  272. $check_result = $adb->pquery($check_query, array($this->id));
  273. $num_rows = $adb->num_rows($check_result);
  274. if ($num_rows <= 0) {
  275. $insertion_mode = '';
  276. }
  277. }
  278. $tabid = getTabid($module);
  279. if ($module == 'Calendar' && $this->column_fields["activitytype"] != null && $this->column_fields["activitytype"] != 'Task') {
  280. $tabid = getTabid('Events');
  281. }
  282. if ($insertion_mode == 'edit') {
  283. $update = array();
  284. $update_params = array();
  285. checkFileAccessForInclusion('user_privileges/user_privileges_' . $current_user->id . '.php');
  286. require('user_privileges/user_privileges_' . $current_user->id . '.php');
  287. if ($is_admin == true || $profileGlobalPermission[1] == 0 || $profileGlobalPermission[2] == 0) {
  288. $sql = "select * from vtiger_field where tabid in (" . generateQuestionMarks($tabid) . ") and tablename=? and displaytype in (1,3) and presence in (0,2) group by columnname";
  289. $params = array($tabid, $table_name);
  290. } else {
  291. $profileList = getCurrentUserProfileList();
  292. if (count($profileList) > 0) {
  293. $sql = "SELECT *
  294. FROM vtiger_field
  295. INNER JOIN vtiger_profile2field
  296. ON vtiger_profile2field.fieldid = vtiger_field.fieldid
  297. INNER JOIN vtiger_def_org_field
  298. ON vtiger_def_org_field.fieldid = vtiger_field.fieldid
  299. WHERE vtiger_field.tabid = ?
  300. AND vtiger_profile2field.visible = 0 AND vtiger_profile2field.readonly = 0
  301. AND vtiger_profile2field.profileid IN (" . generateQuestionMarks($profileList) . ")
  302. AND vtiger_def_org_field.visible = 0 and vtiger_field.tablename=? and vtiger_field.displaytype in (1,3) and vtiger_field.presence in (0,2) group by columnname";
  303. $params = array($tabid, $profileList, $table_name);
  304. } else {
  305. $sql = "SELECT *
  306. FROM vtiger_field
  307. INNER JOIN vtiger_profile2field
  308. ON vtiger_profile2field.fieldid = vtiger_field.fieldid
  309. INNER JOIN vtiger_def_org_field
  310. ON vtiger_def_org_field.fieldid = vtiger_field.fieldid
  311. WHERE vtiger_field.tabid = ?
  312. AND vtiger_profile2field.visible = 0 AND vtiger_profile2field.readonly = 0
  313. AND vtiger_def_org_field.visible = 0 and vtiger_field.tablename=? and vtiger_field.displaytype in (1,3) and vtiger_field.presence in (0,2) group by columnname";
  314. $params = array($tabid, $table_name);
  315. }
  316. }
  317. } else {
  318. $table_index_column = $this->tab_name_index[$table_name];
  319. if ($table_index_column == 'id' && $table_name == 'vtiger_users') {
  320. $currentuser_id = $adb->getUniqueID("vtiger_users");
  321. $this->id = $currentuser_id;
  322. }
  323. $column = array($table_index_column);
  324. $value = array($this->id);
  325. $sql = "select * from vtiger_field where tabid=? and tablename=? and displaytype in (1,3,4) and vtiger_field.presence in (0,2)";
  326. $params = array($tabid, $table_name);
  327. }
  328. // Attempt to re-use the quer-result to avoid reading for every save operation
  329. // TODO Need careful analysis on impact ... MEMORY requirement might be more
  330. static $_privatecache = array();
  331. $cachekey = "{$insertion_mode}-" . implode(',', $params);
  332. if (!isset($_privatecache[$cachekey])) {
  333. $result = $adb->pquery($sql, $params);
  334. $noofrows = $adb->num_rows($result);
  335. if (CRMEntity::isBulkSaveMode()) {
  336. $cacheresult = array();
  337. for ($i = 0; $i < $noofrows; ++$i) {
  338. $cacheresult[] = $adb->fetch_array($result);
  339. }
  340. $_privatecache[$cachekey] = $cacheresult;
  341. }
  342. } else { // Useful when doing bulk save
  343. $result = $_privatecache[$cachekey];
  344. $noofrows = count($result);
  345. }
  346. for ($i = 0; $i < $noofrows; $i++) {
  347. $fieldname = $this->resolve_query_result_value($result, $i, "fieldname");
  348. $columname = $this->resolve_query_result_value($result, $i, "columnname");
  349. $uitype = $this->resolve_query_result_value($result, $i, "uitype");
  350. $generatedtype = $this->resolve_query_result_value($result, $i, "generatedtype");
  351. $typeofdata = $this->resolve_query_result_value($result, $i, "typeofdata");
  352. $typeofdata_array = explode("~", $typeofdata);
  353. $datatype = $typeofdata_array[0];
  354. $ajaxSave = false;
  355. if (($_REQUEST['file'] == 'DetailViewAjax' && $_REQUEST['ajxaction'] == 'DETAILVIEW'
  356. && isset($_REQUEST["fldName"]) && $_REQUEST["fldName"] != $fieldname)
  357. || ($_REQUEST['action'] == 'MassEditSave' && !isset($_REQUEST[$fieldname."_mass_edit_check"]))) {
  358. $ajaxSave = true;
  359. }
  360. if ($uitype == 4 && $insertion_mode != 'edit') {
  361. $fldvalue = '';
  362. // Bulk Save Mode: Avoid generation of module sequence number, take care later.
  363. if (!CRMEntity::isBulkSaveMode())
  364. $fldvalue = $this->setModuleSeqNumber("increment", $module);
  365. $this->column_fields[$fieldname] = $fldvalue;
  366. }
  367. if (isset($this->column_fields[$fieldname])) {
  368. if ($uitype == 56) {
  369. if ($this->column_fields[$fieldname] == 'on' || $this->column_fields[$fieldname] == 1) {
  370. $fldvalue = '1';
  371. } else {
  372. $fldvalue = '0';
  373. }
  374. } elseif ($uitype == 15 || $uitype == 16) {
  375. if ($this->column_fields[$fieldname] == $app_strings['LBL_NOT_ACCESSIBLE']) {
  376. //If the value in the request is Not Accessible for a picklist, the existing value will be replaced instead of Not Accessible value.
  377. $sql = "select $columname from $table_name where " . $this->tab_name_index[$table_name] . "=?";
  378. $res = $adb->pquery($sql, array($this->id));
  379. $pick_val = $adb->query_result($res, 0, $columname);
  380. $fldvalue = $pick_val;
  381. } else {
  382. $fldvalue = $this->column_fields[$fieldname];
  383. }
  384. } elseif ($uitype == 33) {
  385. if (is_array($this->column_fields[$fieldname])) {
  386. $field_list = implode(' |##| ', $this->column_fields[$fieldname]);
  387. } else {
  388. $field_list = $this->column_fields[$fieldname];
  389. }
  390. $fldvalue = $field_list;
  391. } elseif ($uitype == 5 || $uitype == 6 || $uitype == 23) {
  392. //Added to avoid function call getDBInsertDateValue in ajax save
  393. if (isset($current_user->date_format) && !$ajaxSave) {
  394. $fldvalue = getValidDBInsertDateValue($this->column_fields[$fieldname]);
  395. } else {
  396. $fldvalue = $this->column_fields[$fieldname];
  397. }
  398. } elseif ($uitype == 7) {
  399. //strip out the spaces and commas in numbers if given ie., in amounts there may be ,
  400. $fldvalue = str_replace(",", "", $this->column_fields[$fieldname]); //trim($this->column_fields[$fieldname],",");
  401. } elseif ($uitype == 26) {
  402. if (empty($this->column_fields[$fieldname])) {
  403. $fldvalue = 1; //the documents will stored in default folder
  404. } else {
  405. $fldvalue = $this->column_fields[$fieldname];
  406. }
  407. } elseif ($uitype == 28) {
  408. if ($this->column_fields[$fieldname] == null) {
  409. $fileQuery = $adb->pquery("SELECT filename from vtiger_notes WHERE notesid = ?", array($this->id));
  410. $fldvalue = null;
  411. if (isset($fileQuery)) {
  412. $rowCount = $adb->num_rows($fileQuery);
  413. if ($rowCount > 0) {
  414. $fldvalue = $adb->query_result($fileQuery, 0, 'filename');
  415. }
  416. }
  417. } else {
  418. $fldvalue = $this->column_fields[$fieldname];
  419. }
  420. } elseif ($uitype == 8) {
  421. $this->column_fields[$fieldname] = rtrim($this->column_fields[$fieldname], ',');
  422. $ids = explode(',', $this->column_fields[$fieldname]);
  423. $json = new Zend_Json();
  424. $fldvalue = $json->encode($ids);
  425. } elseif ($uitype == 12) {
  426. // Bulk Sae Mode: Consider the FROM email address as specified, if not lookup
  427. $fldvalue = $this->column_fields[$fieldname];
  428. if (empty($fldvalue)) {
  429. $query = "SELECT email1 FROM vtiger_users WHERE id = ?";
  430. $res = $adb->pquery($query, array($current_user->id));
  431. $rows = $adb->num_rows($res);
  432. if ($rows > 0) {
  433. $fldvalue = $adb->query_result($res, 0, 'email1');
  434. }
  435. }
  436. // END
  437. } elseif ($uitype == 72 && !$ajaxSave) {
  438. // Some of the currency fields like Unit Price, Totoal , Sub-total - doesn't need currency conversion during save
  439. $fldvalue = CurrencyField::convertToDBFormat($this->column_fields[$fieldname], null, true);
  440. } elseif ($uitype == 71 && !$ajaxSave) {
  441. $fldvalue = CurrencyField::convertToDBFormat($this->column_fields[$fieldname]);
  442. } else {
  443. $fldvalue = $this->column_fields[$fieldname];
  444. }
  445. if ($uitype != 33 && $uitype != 8)
  446. $fldvalue = from_html($fldvalue, ($insertion_mode == 'edit') ? true : false);
  447. }
  448. else {
  449. $fldvalue = '';
  450. }
  451. if ($fldvalue == '') {
  452. $fldvalue = $this->get_column_value($columname, $fldvalue, $fieldname, $uitype, $datatype);
  453. }
  454. if ($insertion_mode == 'edit') {
  455. if ($table_name != 'vtiger_ticketcomments' && $uitype != 4) {
  456. array_push($update, $columname . "=?");
  457. array_push($update_params, $fldvalue);
  458. }
  459. } else {
  460. array_push($column, $columname);
  461. array_push($value, $fldvalue);
  462. }
  463. }
  464. if ($insertion_mode == 'edit') {
  465. if ($module == 'Potentials') {
  466. $dbquery = 'select sales_stage from vtiger_potential where potentialid = ?';
  467. $sales_stage = $adb->query_result($adb->pquery($dbquery, array($this->id)), 0, 'sales_stage');
  468. if ($sales_stage != $_REQUEST['sales_stage'] && $_REQUEST['sales_stage'] != '') {
  469. $date_var = date("Y-m-d H:i:s");
  470. $closingDateField = new DateTimeField($this->column_fields['closingdate']);
  471. $closingdate = ($_REQUEST['ajxaction'] == 'DETAILVIEW') ? $this->column_fields['closingdate'] : $closingDateField->getDBInsertDateValue();
  472. $sql = "insert into vtiger_potstagehistory values(?,?,?,?,?,?,?,?)";
  473. $params = array('', $this->id, $this->column_fields['amount'], decode_html($sales_stage), $this->column_fields['probability'], 0, $adb->formatDate($closingdate, true), $adb->formatDate($date_var, true));
  474. $adb->pquery($sql, $params);
  475. }
  476. } elseif ($module == 'PurchaseOrder' || $module == 'SalesOrder' || $module == 'Quotes' || $module == 'Invoice') {
  477. //added to update the history for PO, SO, Quotes and Invoice
  478. $history_field_array = Array(
  479. "PurchaseOrder" => "postatus",
  480. "SalesOrder" => "sostatus",
  481. "Quotes" => "quotestage",
  482. "Invoice" => "invoicestatus"
  483. );
  484. $inventory_module = $module;
  485. if ($_REQUEST['ajxaction'] == 'DETAILVIEW') {//if we use ajax edit
  486. if ($inventory_module == "PurchaseOrder")
  487. $relatedname = getVendorName($this->column_fields['vendor_id']);
  488. else
  489. $relatedname = getAccountName($this->column_fields['account_id']);
  490. $total = $this->column_fields['hdnGrandTotal'];
  491. }
  492. else {//using edit button and save
  493. if ($inventory_module == "PurchaseOrder")
  494. $relatedname = $_REQUEST["vendor_name"];
  495. else
  496. $relatedname = $_REQUEST["account_name"];
  497. $total = $_REQUEST['total'];
  498. }
  499. if ($this->column_fields["$history_field_array[$inventory_module]"] == $app_strings['LBL_NOT_ACCESSIBLE']) {
  500. //If the value in the request is Not Accessible for a picklist, the existing value will be replaced instead of Not Accessible value.
  501. $his_col = $history_field_array[$inventory_module];
  502. $his_sql = "select $his_col from $this->table_name where " . $this->table_index . "=?";
  503. $his_res = $adb->pquery($his_sql, array($this->id));
  504. $status_value = $adb->query_result($his_res, 0, $his_col);
  505. $stat_value = $status_value;
  506. } else {
  507. $stat_value = $this->column_fields["$history_field_array[$inventory_module]"];
  508. }
  509. $oldvalue = getSingleFieldValue($this->table_name, $history_field_array[$inventory_module], $this->table_index, $this->id);
  510. if ($this->column_fields["$history_field_array[$inventory_module]"] != '' && $oldvalue != $stat_value) {
  511. addInventoryHistory($inventory_module, $this->id, $relatedname, $total, $stat_value);
  512. }
  513. }
  514. //Check done by Don. If update is empty the the query fails
  515. if (count($update) > 0) {
  516. $sql1 = "update $table_name set " . implode(",", $update) . " where " . $this->tab_name_index[$table_name] . "=?";
  517. array_push($update_params, $this->id);
  518. $adb->pquery($sql1, $update_params);
  519. }
  520. } else {
  521. $sql1 = "insert into $table_name(" . implode(",", $column) . ") values(" . generateQuestionMarks($value) . ")";
  522. $adb->pquery($sql1, $value);
  523. }
  524. }
  525. /** Function to delete a record in the specifed table
  526. * @param $table_name -- table name:: Type varchar
  527. * The function will delete a record .The id is obtained from the class variable $this->id and the columnname got from $this->tab_name_index[$table_name]
  528. */
  529. function deleteRelation($table_name) {
  530. global $adb;
  531. $check_query = "select * from $table_name where " . $this->tab_name_index[$table_name] . "=?";
  532. $check_result = $adb->pquery($check_query, array($this->id));
  533. $num_rows = $adb->num_rows($check_result);
  534. if ($num_rows == 1) {
  535. $del_query = "DELETE from $table_name where " . $this->tab_name_index[$table_name] . "=?";
  536. $adb->pquery($del_query, array($this->id));
  537. }
  538. }
  539. /**
  540. * Function returns the column alias for a field
  541. * @param <Array> $fieldinfo - field information
  542. * @return <String> field value
  543. */
  544. protected function createColumnAliasForField($fieldinfo) {
  545. return strtolower($fieldinfo['tablename'] . $fieldinfo['fieldname']);
  546. }
  547. /**
  548. * Retrieve record information of the module
  549. * @param <Integer> $record - crmid of record
  550. * @param <String> $module - module name
  551. */
  552. function retrieve_entity_info($record, $module) {
  553. global $adb, $log, $app_strings;
  554. // INNER JOIN is desirable if all dependent table has entries for the record.
  555. // LEFT JOIN is desired if the dependent tables does not have entry.
  556. $join_type = 'LEFT JOIN';
  557. // Tables which has multiple rows for the same record
  558. // will be skipped in record retrieve - need to be taken care separately.
  559. $multirow_tables = NULL;
  560. if (isset($this->multirow_tables)) {
  561. $multirow_tables = $this->multirow_tables;
  562. } else {
  563. $multirow_tables = array(
  564. 'vtiger_campaignrelstatus',
  565. 'vtiger_attachments',
  566. //'vtiger_inventoryproductrel',
  567. //'vtiger_cntactivityrel',
  568. 'vtiger_email_track'
  569. );
  570. }
  571. // Lookup module field cache
  572. $cachedModuleFields = VTCacheUtils::lookupFieldInfo_Module($module);
  573. if ($cachedModuleFields === false) {
  574. // Pull fields and cache for further use
  575. $tabid = getTabid($module);
  576. $sql0 = "SELECT fieldname, fieldid, fieldlabel, columnname, tablename, uitype, typeofdata,presence FROM vtiger_field WHERE tabid=?";
  577. // NOTE: Need to skip in-active fields which we will be done later.
  578. $result0 = $adb->pquery($sql0, array($tabid));
  579. if ($adb->num_rows($result0)) {
  580. while ($resultrow = $adb->fetch_array($result0)) {
  581. // Update cache
  582. VTCacheUtils::updateFieldInfo(
  583. $tabid, $resultrow['fieldname'], $resultrow['fieldid'], $resultrow['fieldlabel'], $resultrow['columnname'], $resultrow['tablename'], $resultrow['uitype'], $resultrow['typeofdata'], $resultrow['presence']
  584. );
  585. }
  586. // Get only active field information
  587. $cachedModuleFields = VTCacheUtils::lookupFieldInfo_Module($module);
  588. }
  589. }
  590. if ($cachedModuleFields) {
  591. $column_clause = '';
  592. $from_clause = '';
  593. $where_clause = '';
  594. $limit_clause = ' LIMIT 1'; // to eliminate multi-records due to table joins.
  595. $params = array();
  596. $required_tables = $this->tab_name_index; // copies-on-write
  597. foreach ($cachedModuleFields as $fieldinfo) {
  598. if (in_array($fieldinfo['tablename'], $multirow_tables)) {
  599. continue;
  600. }
  601. // Added to avoid picking shipping tax fields for Inventory modules, the shipping tax detail are stored in vtiger_inventoryshippingrel
  602. // table, but in vtiger_field table we have set tablename as vtiger_inventoryproductrel.
  603. if(($module == 'Invoice' || $module == 'Quotes' || $module == 'SalesOrder' || $module == 'PurchaseOrder')
  604. && stripos($fieldinfo['columnname'], 'shtax') !== false) {
  605. continue;
  606. }
  607. // Alias prefixed with tablename+fieldname to avoid duplicate column name across tables
  608. // fieldname are always assumed to be unique for a module
  609. $column_clause .= $fieldinfo['tablename'].'.'.$fieldinfo['columnname'].' AS '.$this->createColumnAliasForField($fieldinfo).',';
  610. }
  611. $column_clause .= 'vtiger_crmentity.deleted';
  612. if (isset($required_tables['vtiger_crmentity'])) {
  613. $from_clause = ' vtiger_crmentity';
  614. unset($required_tables['vtiger_crmentity']);
  615. foreach ($required_tables as $tablename => $tableindex) {
  616. if (in_array($tablename, $multirow_tables)) {
  617. // Avoid multirow table joins.
  618. continue;
  619. }
  620. $from_clause .= sprintf(' %s %s ON %s.%s=%s.%s', $join_type,
  621. $tablename, $tablename, $tableindex, 'vtiger_crmentity', 'crmid');
  622. }
  623. }
  624. $where_clause .= ' vtiger_crmentity.crmid=?';
  625. $params[] = $record;
  626. $sql = sprintf('SELECT %s FROM %s WHERE %s %s', $column_clause, $from_clause, $where_clause, $limit_clause);
  627. $result = $adb->pquery($sql, $params);
  628. if (!$result || $adb->num_rows($result) < 1) {
  629. throw new Exception($app_strings['LBL_RECORD_NOT_FOUND'], -1);
  630. } else {
  631. $resultrow = $adb->query_result_rowdata($result);
  632. if (!empty($resultrow['deleted'])) {
  633. throw new Exception($app_strings['LBL_RECORD_DELETE'], 1);
  634. }
  635. foreach ($cachedModuleFields as $fieldinfo) {
  636. $fieldvalue = '';
  637. $fieldkey = $this->createColumnAliasForField($fieldinfo);
  638. //Note : value is retrieved with a tablename+fieldname as we are using alias while building query
  639. if (isset($resultrow[$fieldkey])) {
  640. $fieldvalue = $resultrow[$fieldkey];
  641. }
  642. $this->column_fields[$fieldinfo['fieldname']] = $fieldvalue;
  643. }
  644. }
  645. }
  646. $this->column_fields['record_id'] = $record;
  647. $this->column_fields['record_module'] = $module;
  648. }
  649. /** Function to saves the values in all the tables mentioned in the class variable $tab_name for the specified module
  650. * @param $module -- module:: Type varchar
  651. */
  652. function save($module_name, $fileid = '') {
  653. global $log;
  654. $log->debug("module name is " . $module_name);
  655. //Event triggering code
  656. require_once("include/events/include.inc");
  657. global $adb;
  658. //In Bulk mode stop triggering events
  659. if(!self::isBulkSaveMode()) {
  660. $em = new VTEventsManager($adb);
  661. // Initialize Event trigger cache
  662. $em->initTriggerCache();
  663. $entityData = VTEntityData::fromCRMEntity($this);
  664. $em->triggerEvent("vtiger.entity.beforesave.modifiable", $entityData);
  665. $em->triggerEvent("vtiger.entity.beforesave", $entityData);
  666. $em->triggerEvent("vtiger.entity.beforesave.final", $entityData);
  667. }
  668. //Event triggering code ends
  669. //GS Save entity being called with the modulename as parameter
  670. $this->saveentity($module_name, $fileid);
  671. if($em) {
  672. //Event triggering code
  673. $em->triggerEvent("vtiger.entity.aftersave", $entityData);
  674. $em->triggerEvent("vtiger.entity.aftersave.final", $entityData);
  675. //Event triggering code ends
  676. }
  677. }
  678. function process_list_query($query, $row_offset, $limit = -1, $max_per_page = -1) {
  679. global $list_max_entries_per_page;
  680. $this->log->debug("process_list_query: " . $query);
  681. if (!empty($limit) && $limit != -1) {
  682. $result = & $this->db->limitQuery($query, $row_offset + 0, $limit, true, "Error retrieving $this->object_name list: ");
  683. } else {
  684. $result = & $this->db->query($query, true, "Error retrieving $this->object_name list: ");
  685. }
  686. $list = Array();
  687. if ($max_per_page == -1) {
  688. $max_per_page = $list_max_entries_per_page;
  689. }
  690. $rows_found = $this->db->getRowCount($result);
  691. $this->log->debug("Found $rows_found " . $this->object_name . "s");
  692. $previous_offset = $row_offset - $max_per_page;
  693. $next_offset = $row_offset + $max_per_page;
  694. if ($rows_found != 0) {
  695. // We have some data.
  696. for ($index = $row_offset, $row = $this->db->fetchByAssoc($result, $index); $row && ($index < $row_offset + $max_per_page || $max_per_page == -99); $index++, $row = $this->db->fetchByAssoc($result, $index)) {
  697. foreach ($this->list_fields as $entry) {
  698. foreach ($entry as $key => $field) { // this will be cycled only once
  699. if (isset($row[$field])) {
  700. $this->column_fields[$this->list_fields_names[$key]] = $row[$field];
  701. $this->log->debug("$this->object_name({$row['id']}): " . $field . " = " . $this->$field);
  702. } else {
  703. $this->column_fields[$this->list_fields_names[$key]] = "";
  704. }
  705. }
  706. }
  707. //$this->db->println("here is the bug");
  708. $list[] = clone($this); //added by Richie to support PHP5
  709. }
  710. }
  711. $response = Array();
  712. $response['list'] = $list;
  713. $response['row_count'] = $rows_found;
  714. $response['next_offset'] = $next_offset;
  715. $response['previous_offset'] = $previous_offset;
  716. return $response;
  717. }
  718. function process_full_list_query($query) {
  719. $this->log->debug("CRMEntity:process_full_list_query");
  720. $result = & $this->db->query($query, false);
  721. //$this->log->debug("CRMEntity:process_full_list_query: result is ".$result);
  722. if ($this->db->getRowCount($result) > 0) {
  723. // $this->db->println("process_full mid=".$this->table_index." mname=".$this->module_name);
  724. // We have some data.
  725. while ($row = $this->db->fetchByAssoc($result)) {
  726. $rowid = $row[$this->table_index];
  727. if (isset($rowid))
  728. $this->retrieve_entity_info($rowid, $this->module_name);
  729. else
  730. $this->db->println("rowid not set unable to retrieve");
  731. //clone function added to resolvoe PHP5 compatibility issue in Dashboards
  732. //If we do not use clone, while using PHP5, the memory address remains fixed but the
  733. //data gets overridden hence all the rows that come in bear the same value. This in turn
  734. //provides a wrong display of the Dashboard graphs. The data is erroneously shown for a specific month alone
  735. //Added by Richie
  736. $list[] = clone($this); //added by Richie to support PHP5
  737. }
  738. }
  739. if (isset($list))
  740. return $list;
  741. else
  742. return null;
  743. }
  744. /** This function should be overridden in each module. It marks an item as deleted.
  745. * If it is not overridden, then marking this type of item is not allowed
  746. * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
  747. * All Rights Reserved..
  748. * Contributor(s): ______________________________________..
  749. */
  750. function mark_deleted($id) {
  751. global $current_user;
  752. $date_var = date("Y-m-d H:i:s");
  753. $query = "UPDATE vtiger_crmentity set deleted=1,modifiedtime=?,modifiedby=? where crmid=?";
  754. $this->db->pquery($query, array($this->db->formatDate($date_var, true), $current_user->id, $id), true, "Error marking record deleted: ");
  755. }
  756. function retrieve_by_string_fields($fields_array, $encode = true) {
  757. $where_clause = $this->get_where($fields_array);
  758. $query = "SELECT * FROM $this->table_name $where_clause";
  759. $this->log->debug("Retrieve $this->object_name: " . $query);
  760. $result = & $this->db->requireSingleResult($query, true, "Retrieving record $where_clause:");
  761. if (empty($result)) {
  762. return null;
  763. }
  764. $row = $this->db->fetchByAssoc($result, -1, $encode);
  765. foreach ($this->column_fields as $field) {
  766. if (isset($row[$field])) {
  767. $this->$field = $row[$field];
  768. }
  769. }
  770. return $this;
  771. }
  772. // this method is called during an import before inserting a bean
  773. // define an associative array called $special_fields
  774. // the keys are user defined, and don't directly map to the bean's vtiger_fields
  775. // the value is the method name within that bean that will do extra
  776. // processing for that vtiger_field. example: 'full_name'=>'get_names_from_full_name'
  777. function process_special_fields() {
  778. foreach ($this->special_functions as $func_name) {
  779. if (method_exists($this, $func_name)) {
  780. $this->$func_name();
  781. }
  782. }
  783. }
  784. /**
  785. * Function to check if the custom vtiger_field vtiger_table exists
  786. * return true or false
  787. */
  788. function checkIfCustomTableExists($tablename) {
  789. global $adb;
  790. $query = "select * from " . $adb->sql_escape_string($tablename);
  791. $result = $this->db->pquery($query, array());
  792. $testrow = $this->db->num_fields($result);
  793. if ($testrow > 1) {
  794. $exists = true;
  795. } else {
  796. $exists = false;
  797. }
  798. return $exists;
  799. }
  800. /**
  801. * function to construct the query to fetch the custom vtiger_fields
  802. * return the query to fetch the custom vtiger_fields
  803. */
  804. function constructCustomQueryAddendum($tablename, $module) {
  805. global $adb;
  806. $tabid = getTabid($module);
  807. $sql1 = "select columnname,fieldlabel from vtiger_field where generatedtype=2 and tabid=? and vtiger_field.presence in (0,2)";
  808. $result = $adb->pquery($sql1, array($tabid));
  809. $numRows = $adb->num_rows($result);
  810. $sql3 = "select ";
  811. for ($i = 0; $i < $numRows; $i++) {
  812. $columnName = $adb->query_result($result, $i, "columnname");
  813. $fieldlabel = $adb->query_result($result, $i, "fieldlabel");
  814. //construct query as below
  815. if ($i == 0) {
  816. $sql3 .= $tablename . "." . $columnName . " '" . $fieldlabel . "'";
  817. } else {
  818. $sql3 .= ", " . $tablename . "." . $columnName . " '" . $fieldlabel . "'";
  819. }
  820. }
  821. if ($numRows > 0) {
  822. $sql3 = $sql3 . ',';
  823. }
  824. return $sql3;
  825. }
  826. /**
  827. * This function returns a full (ie non-paged) list of the current object type.
  828. * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
  829. * All Rights Reserved..
  830. * Contributor(s): ______________________________________..
  831. */
  832. function get_full_list($order_by = "", $where = "") {
  833. $this->log->debug("get_full_list: order_by = '$order_by' and where = '$where'");
  834. $query = $this->create_list_query($order_by, $where);
  835. return $this->process_full_list_query($query);
  836. }
  837. /**
  838. * Track the viewing of a detail record. This leverages get_summary_text() which is object specific
  839. * params $user_id - The user that is viewing the record.
  840. * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
  841. * All Rights Reserved..
  842. * Contributor(s): ______________________________________..
  843. */
  844. function track_view($user_id, $current_module, $id = '') {
  845. $this->log->debug("About to call vtiger_tracker (user_id, module_name, item_id)($user_id, $current_module, $this->id)");
  846. $tracker = new Tracker();
  847. $tracker->track_view($user_id, $current_module, $id, '');
  848. }
  849. /**
  850. * Function to get the column value of a field when the field value is empty ''
  851. * @param $columnname -- Column name for the field
  852. * @param $fldvalue -- Input value for the field taken from the User
  853. * @param $fieldname -- Name of the Field
  854. * @param $uitype -- UI type of the field
  855. * @return Column value of the field.
  856. */
  857. function get_column_value($columnname, $fldvalue, $fieldname, $uitype, $datatype = '') {
  858. global $log;
  859. $log->debug("Entering function get_column_value ($columnname, $fldvalue, $fieldname, $uitype, $datatype='')");
  860. // Added for the fields of uitype '57' which has datatype mismatch in crmentity table and particular entity table
  861. if ($uitype == 57 && $fldvalue == '') {
  862. return 0;
  863. }
  864. if (is_uitype($uitype, "_date_") && $fldvalue == '' || $uitype == '14') {
  865. return null;
  866. }
  867. if ($datatype == 'I' || $datatype == 'N' || $datatype == 'NN') {
  868. return 0;
  869. }
  870. $log->debug("Exiting function get_column_value");
  871. return $fldvalue;
  872. }
  873. /**
  874. * Function to make change to column fields, depending on the current user's accessibility for the fields
  875. */
  876. function apply_field_security($moduleName = '') {
  877. global $current_user, $currentModule;
  878. if($moduleName == '') {
  879. $moduleName = $currentModule;
  880. }
  881. require_once('include/utils/UserInfoUtil.php');
  882. foreach ($this->column_fields as $fieldname => $fieldvalue) {
  883. $reset_value = false;
  884. if (getFieldVisibilityPermission($moduleName, $current_user->id, $fieldname) != '0')
  885. $reset_value = true;
  886. if ($fieldname == "record_id" || $fieldname == "record_module")
  887. $reset_value = false;
  888. /*
  889. if (isset($this->additional_column_fields) && in_array($fieldname, $this->additional_column_fields) == true)
  890. $reset_value = false;
  891. */
  892. if ($reset_value == true)
  893. $this->column_fields[$fieldname] = "";
  894. }
  895. }
  896. /**
  897. * Function invoked during export of module record value.
  898. */
  899. function transform_export_value($key, $value) {
  900. // NOTE: The sub-class can override this function as required.
  901. return $value;
  902. }
  903. /**
  904. * Function to initialize the importable fields array, based on the User's accessibility to the fields
  905. */
  906. function initImportableFields($module) {
  907. global $current_user, $adb;
  908. require_once('include/utils/UserInfoUtil.php');
  909. $skip_uitypes = array('4'); // uitype 4 is for Mod numbers
  910. // Look at cache if the fields information is available.
  911. $cachedModuleFields = VTCacheUtils::lookupFieldInfo_Module($module);
  912. if ($cachedModuleFields === false) {
  913. getColumnFields($module); // This API will initialize the cache as well
  914. // We will succeed now due to above function call
  915. $cachedModuleFields = VTCacheUtils::lookupFieldInfo_Module($module);
  916. }
  917. $colf = Array();
  918. if ($cachedModuleFields) {
  919. foreach ($cachedModuleFields as $fieldinfo) {
  920. // Skip non-supported fields
  921. if (in_array($fieldinfo['uitype'], $skip_uitypes)) {
  922. continue;
  923. } else {
  924. $colf[$fieldinfo['fieldname']] = $fieldinfo['uitype'];
  925. }
  926. }
  927. }
  928. foreach ($colf as $key => $value) {
  929. if (getFieldVisibilityPermission($module, $current_user->id, $key, 'readwrite') == '0')
  930. $this->importable_fields[$key] = $value;
  931. }
  932. }
  933. /** Function to initialize the required fields array for that particular module */
  934. function initRequiredFields($module) {
  935. global $adb;
  936. $tabid = getTabId($module);
  937. $sql = "select * from vtiger_field where tabid= ? and typeofdata like '%M%' and uitype not in ('53','70') and vtiger_field.presence in (0,2)";
  938. $result = $adb->pquery($sql, array($tabid));
  939. $numRows = $adb->num_rows($result);
  940. for ($i = 0; $i < $numRows; $i++) {
  941. $fieldName = $adb->query_result($result, $i, "fieldname");
  942. $this->required_fields[$fieldName] = 1;
  943. }
  944. }
  945. /** Function to delete an entity with given Id */
  946. function trash($module, $id) {
  947. global $log, $current_user, $adb;
  948. if(!self::isBulkSaveMode()) {
  949. require_once("include/events/include.inc");
  950. $em = new VTEventsManager($adb);
  951. // Initialize Event trigger cache
  952. $em->initTriggerCache();
  953. $entityData = VTEntityData::fromEntityId($adb, $id);
  954. $em->triggerEvent("vtiger.entity.beforedelete", $entityData);
  955. }
  956. $this->mark_deleted($id);
  957. $this->unlinkDependencies($module, $id);
  958. require_once('libraries/freetag/freetag.class.php');
  959. $freetag = new freetag();
  960. $freetag->delete_all_object_tags_for_user($current_user->id, $id);
  961. $sql_recentviewed = 'DELETE FROM vtiger_tracker WHERE user_id = ? AND item_id = ?';
  962. $this->db->pquery($sql_recentviewed, array($current_user->id, $id));
  963. if($em){
  964. $em->triggerEvent("vtiger.entity.afterdelete", $entityData);
  965. }
  966. }
  967. /** Function to unlink all the dependent entities of the given Entity by Id */
  968. function unlinkDependencies($module, $id) {
  969. global $log;
  970. $fieldRes = $this->db->pquery('SELECT tabid, tablename, columnname FROM vtiger_field WHERE fieldid IN (
  971. SELECT fieldid FROM vtiger_fieldmodulerel WHERE relmodule=?)', array($module));
  972. $numOfFields = $this->db->num_rows($fieldRes);
  973. for ($i = 0; $i < $numOfFields; $i++) {
  974. $tabId = $this->db->query_result($fieldRes, $i, 'tabid');
  975. $tableName = $this->db->query_result($fieldRes, $i, 'tablename');
  976. $columnName = $this->db->query_result($fieldRes, $i, 'columnname');
  977. $relatedModule = vtlib_getModuleNameById($tabId);
  978. $focusObj = CRMEntity::getInstance($relatedModule);
  979. //Backup Field Relations for the deleted entity
  980. $targetTableColumn = $focusObj->table_index;
  981. //While deleting product record the $targetTableColumn should 'id'.
  982. if ($tableName == 'vtiger_inventoryproductrel') {
  983. $targetTableColumn = 'id';
  984. }
  985. $relQuery = "SELECT $targetTableColumn FROM $tableName WHERE $columnName=?";
  986. $relResult = $this->db->pquery($relQuery, array($id));
  987. $numOfRelRecords = $this->db->num_rows($relResult);
  988. if ($numOfRelRecords > 0) {
  989. $recordIdsList = array();
  990. for ($k = 0; $k < $numOfRelRecords; $k++) {
  991. $recordIdsList[] = $this->db->query_result($relResult, $k, $focusObj->table_index);
  992. }
  993. $params = array($id, RB_RECORD_UPDATED, $tableName, $columnName, $focusObj->table_index, implode(",", $recordIdsList));
  994. $this->db->pquery('INSERT INTO vtiger_relatedlists_rb VALUES (?,?,?,?,?,?)', $params);
  995. }
  996. }
  997. }
  998. /** Function to unlink an entity with given Id from another entity */
  999. function unlinkRelationship($id, $return_module, $return_id) {
  1000. global $log, $currentModule;
  1001. $query = 'DELETE FROM vtiger_crmentityrel WHERE (crmid=? AND relmodule=? AND relcrmid=?) OR (relcrmid=? AND module=? AND crmid=?)';
  1002. $params = array($id, $return_module, $return_id, $id, $return_module, $return_id);
  1003. $this->db->pquery($query, $params);
  1004. $fieldRes = $this->db->pquery('SELECT tabid, tablename, columnname FROM vtiger_field WHERE fieldid IN (
  1005. SELECT fieldid FROM vtiger_fieldmodulerel WHERE module=? AND relmodule=?)', array($currentModule, $return_module));
  1006. $numOfFields = $this->db->num_rows($fieldRes);
  1007. for ($i = 0; $i < $numOfFields; $i++) {
  1008. $tabId = $this->db->query_result($fieldRes, $i, 'tabid');
  1009. $tableName = $this->db->query_result($fieldRes, $i, 'tablename');
  1010. $columnName = $this->db->query_result($fieldRes, $i, 'columnname');
  1011. $relatedModule = vtlib_getModuleNameById($tabId);
  1012. $focusObj = CRMEntity::getInstance($relatedModule);
  1013. $updateQuery = "UPDATE $tableName SET $columnName=? WHERE $columnName=? AND $focusObj->table_index=?";
  1014. $updateParams = array(null, $return_id, $id);
  1015. $this->db->pquery($updateQuery, $updateParams);
  1016. }
  1017. }
  1018. /** Function to restore a deleted record of specified module with given crmid
  1019. * @param $module -- module name:: Type varchar
  1020. * @param $entity_ids -- list of crmids :: Array
  1021. */
  1022. function restore($module, $id) {
  1023. global $current_user, $adb;
  1024. $this->db->println("TRANS restore starts $module");
  1025. $this->db->startTransaction();
  1026. $date_var = date("Y-m-d H:i:s");
  1027. $query = 'UPDATE vtiger_crmentity SET deleted=0,modifiedtime=?,modifiedby=? WHERE crmid = ?';
  1028. $this->db->pquery($query, array($this->db->formatDate($date_var, true), $current_user->id, $id), true, "Error restoring records :");
  1029. //Restore related entities/records
  1030. $this->restoreRelatedRecords($module, $id);
  1031. //Event triggering code
  1032. require_once("include/events/include.inc");
  1033. global $adb;
  1034. $em = new VTEventsManager($adb);
  1035. // Initialize Event trigger cache
  1036. $em->initTriggerCache();
  1037. $this->id = $id;
  1038. $entityData = VTEntityData::fromCRMEntity($this);
  1039. //Event triggering code
  1040. $em->triggerEvent("vtiger.entity.afterrestore", $entityData);
  1041. //Event triggering code ends
  1042. $this->db->completeTransaction();
  1043. $this->db->println("TRANS restore ends");
  1044. }
  1045. /** Function to restore all the related records of a given record by id */
  1046. function restoreRelatedRecords($module, $record) {
  1047. $result = $this->db->pquery('SELECT * FROM vtiger_relatedlists_rb WHERE entityid = ?', array($record));
  1048. $numRows = $this->db->num_rows($result);
  1049. for ($i = 0; $i < $numRows; $i++) {
  1050. $action = $this->db->query_result($result, $i, "action");
  1051. $rel_table = $this->db->query_result($result, $i, "rel_table");
  1052. $rel_column = $this->db->query_result($result, $i, "rel_column");
  1053. $ref_column = $this->db->query_result($result, $i, "ref_column");
  1054. $related_crm_ids = $this->db->query_result($result, $i, "related_crm_ids");
  1055. if (strtoupper($action) == RB_RECORD_UPDATED) {
  1056. $related_ids = explode(",", $related_crm_ids);
  1057. if ($rel_table == 'vtiger_crmentity' && $rel_column == 'deleted') {
  1058. $sql = "UPDATE $rel_table set $rel_column = 0 WHERE $ref_column IN (" . generateQuestionMarks($related_ids) . ")";
  1059. $this->db->pquery($sql, array($related_ids));
  1060. } else {
  1061. $sql = "UPDATE $rel_table set $rel_column = ? WHERE $rel_column = 0 AND $ref_column IN (" . generateQuestionMarks($related_ids) . ")";
  1062. $this->db->pquery($sql, array($record, $related_ids));
  1063. }
  1064. } elseif (strtoupper($action) == RB_RECORD_DELETED) {
  1065. if ($rel_table == 'vtiger_seproductrel') {
  1066. $sql = "INSERT INTO $rel_table($rel_column, $ref_column, 'setype') VALUES (?,?,?)";
  1067. $this->db->pquery($sql, array($record, $related_crm_ids, $module));
  1068. } else {
  1069. $sql = "INSERT INTO $rel_table($rel_column, $ref_column) VALUES (?,?)";
  1070. $this->db->pquery($sql, array($record, $related_crm_ids));
  1071. }
  1072. }
  1073. }
  1074. //Clean up the the backup data also after restoring
  1075. $this->db->pquery('DELETE FROM vtiger_relatedlists_rb WHERE entityid = ?', array($record));
  1076. }
  1077. /**
  1078. * Function to initialize the sortby fields array
  1079. */
  1080. function initSortByField($module) {
  1081. global $adb, $log;
  1082. $log->debug("Entering function initSortByField ($module)");
  1083. // Define the columnname's and uitype's which needs to be excluded
  1084. $exclude_columns = Array('parent_id', 'quoteid', 'vendorid', 'access_count');
  1085. $exclude_uitypes = Array();
  1086. $tabid = getTabId($module);
  1087. if ($module == 'Calendar') {
  1088. $tabid = array('9', '16');
  1089. }
  1090. $sql = "SELECT columnname FROM vtiger_field " .
  1091. " WHERE (fieldname not like '%\_id' OR fieldname in ('assigned_user_id'))" .
  1092. " AND tabid in (" . generateQuestionMarks($tabid) . ") and vtiger_field.presence in (0,2)";
  1093. $params = array($tabid);
  1094. if (count($exclude_columns) > 0) {
  1095. $sql .= " AND columnname NOT IN (" . generateQuestionMarks($exclude_columns) . ")";
  1096. array_push($params, $exclude_columns);
  1097. }
  1098. if (count($exclude_uitypes) > 0) {
  1099. $sql .= " AND uitype NOT IN (" . generateQuestionMarks($exclude_uitypes) . ")";
  1100. array_push($params, $exclude_uitypes);
  1101. }
  1102. $result = $adb->pquery($sql, $params);
  1103. $num_rows = $adb->num_rows($result);
  1104. for ($i = 0; $i < $num_rows; $i++) {
  1105. $columnname = $adb->query_result($result, $i, 'columnname');
  1106. if (in_array($columnname, $this->sortby_fields))
  1107. continue;
  1108. else
  1109. $this->sortby_fields[] = $columnname;
  1110. }
  1111. if ($tabid == 21 or $tabid == 22)
  1112. $this->sortby_fields[] = 'crmid';
  1113. $log->debug("Exiting initSortByField");
  1114. }
  1115. /* Function to set the Sequence string and sequence number starting value */
  1116. function setModuleSeqNumber($mode, $module, $req_str = '', $req_no = '') {
  1117. global $adb;
  1118. //when we configure the invoice number in Settings this will be used
  1119. if ($mode == "configure" && $req_no != '') {
  1120. $check = $adb->pquery("select cur_id from vtiger_modentity_num where semodule=? and prefix = ?", array($module, $req_str));
  1121. if ($adb->num_rows($check) == 0) {
  1122. $numid = $adb->getUniqueId("vtiger_modentity_num");
  1123. $active = $adb->pquery("select num_id from vtiger_modentity_num where semodule=? and active=1", array($module));
  1124. $param_num_id = $adb->query_result($active, 0, 'num_id');
  1125. if(!empty($param_num_id)) {
  1126. $adb->pquery("UPDATE vtiger_modentity_num SET active=0 where num_id=?", array($param_num_id));
  1127. }
  1128. $adb->pquery("INSERT into vtiger_modentity_num values(?,?,?,?,?,?)", array($numid, $module, $req_str, $req_no, $req_no, 1));
  1129. return true;
  1130. } else if ($adb->num_rows($check) != 0) {
  1131. $num_check = $adb->query_result($check, 0, 'cur_id');
  1132. if ($req_no < $num_check) {
  1133. return false;
  1134. } else {
  1135. $adb->pquery("UPDATE vtiger_modentity_num SET active=0 where active=1 and semodule=?", array($module));
  1136. $adb->pquery("UPDATE vtiger_modentity_num SET cur_id=?, active = 1 where prefix=? and semodule=?", array($req_no, $req_str, $module));
  1137. return true;
  1138. }
  1139. }
  1140. } else if ($mode == "increment") {
  1141. //when we save new invoice we will increment the invoice id and write
  1142. $check = $adb->pquery("select cur_id,prefix from vtiger_modentity_num where semodule=? and active = 1", array($module));
  1143. $prefix = $adb->query_result($check, 0, 'prefix');
  1144. $curid = $adb->query_result($check, 0, 'cur_id');
  1145. $prev_inv_no = $prefix . $curid;
  1146. $strip = strlen($curid) - strlen($curid + 1);
  1147. if ($strip < 0)
  1148. $strip = 0;
  1149. $temp = str_repeat("0", $strip);
  1150. $req_no.= $temp . ($curid + 1);
  1151. $adb->pquery("UPDATE vtiger_modentity_num SET cur_id=? where cur_id=? and active=1 AND semodule=?", array($req_no, $curid, $module));
  1152. return decode_html($prev_inv_no);
  1153. }
  1154. }
  1155. // END
  1156. /* Function to check if module sequence numbering is configured for the given module or not */
  1157. function isModuleSequenceConfigured($module) {
  1158. $adb = PearDatabase::getInstance();
  1159. $result = $adb->pquery('SELECT 1 FROM vtiger_modentity_num WHERE semodule = ? AND active = 1', array($module));
  1160. if ($result && $adb->num_rows($result) > 0) {
  1161. return true;
  1162. }
  1163. return false;
  1164. }
  1165. /* Function to get the next module sequence number for a given module */
  1166. function getModuleSeqInfo($module) {
  1167. global $adb;
  1168. $check = $adb->pquery("select cur_id,prefix from vtiger_modentity_num where semodule=? and active = 1", array($module));
  1169. $prefix = $adb->query_result($check, 0, 'prefix');
  1170. $curid = $adb->query_result($check, 0, 'cur_id');
  1171. return array($prefix, $curid);
  1172. }
  1173. // END
  1174. /* Function to check if the mod number already exits */
  1175. function checkModuleSeqNumber($table, $column, $no) {
  1176. global $adb;
  1177. $result = $adb->pquery("select " . $adb->sql_escape_string($column) .
  1178. " from " . $adb->sql_escape_string($table) .
  1179. " where " . $adb->sql_escape_string($column) . " = ?", array($no));
  1180. $num_rows = $adb->num_rows($result);
  1181. if ($num_rows > 0)
  1182. return true;
  1183. else
  1184. return false;
  1185. }
  1186. // END
  1187. function updateMissingSeqNumber($module) {
  1188. global $log, $adb;
  1189. $log->debug("Entered updateMissingSeqNumber function");
  1190. vtlib_setup_modulevars($module, $this);
  1191. if (!$this->isModuleSequenceConfigured($module))
  1192. return;
  1193. $tabid = getTabid($module);
  1194. $fieldinfo = $adb->pquery("SELECT * FROM vtiger_field WHERE tabid = ? AND uitype = 4", Array($tabid));
  1195. $returninfo = Array();
  1196. if ($fieldinfo && $adb->num_rows($fieldinfo)) {
  1197. // TODO: We assume the following for module sequencing field
  1198. // 1. There will be only field per module
  1199. // 2. This field is linked to module base table column
  1200. $fld_table = $adb->query_result($fieldinfo, 0, 'tablename');
  1201. $fld_column = $adb->query_result($fieldinfo, 0, 'columnname');
  1202. if ($fld_table == $this->table_name) {
  1203. $records = $adb->query("SELECT $this->table_index AS recordid FROM $this->table_name " .
  1204. "WHERE $fld_column = '' OR $fld_column is NULL");
  1205. if ($records && $adb->num_rows($records)) {
  1206. $returninfo['totalrecords'] = $adb->num_rows($records);
  1207. $returninfo['updatedrecords'] = 0;
  1208. $modseqinfo = $this->getModuleSeqInfo($module);
  1209. $prefix = $modseqinfo[0];
  1210. $cur_id = $modseqinfo[1];
  1211. $old_cur_id = $cur_id;
  1212. while ($recordinfo = $adb->fetch_array($records)) {
  1213. $value = "$prefix" . "$cur_id";
  1214. $adb->pquery("UPDATE $fld_table SET $fld_column = ? WHERE $this->table_index = ?", Array($value, $recordinfo['recordid']));
  1215. $cur_id += 1;
  1216. $returninfo['updatedrecords'] = $returninfo['updatedrecords'] + 1;
  1217. }
  1218. if ($old_cur_id != $cur_id) {
  1219. $adb->pquery("UPDATE vtiger_modentity_num set cur_id=? where semodule=? and active=1", Array($cur_id, $module));
  1220. }
  1221. }
  1222. } else {
  1223. $log->fatal("Updating Missing Sequence Number FAILED! REASON: Field table and module table mismatching.");
  1224. }
  1225. }
  1226. return $returninfo;
  1227. }
  1228. /* Generic function to get attachments in the related list of a given module */
  1229. function get_attachments($id, $cur_tab_id, $rel_tab_id, $actions = false) {
  1230. global $currentModule, $app_strings, $singlepane_view;
  1231. $this_module = $currentModule;
  1232. $parenttab = getParentTab();
  1233. $related_module = vtlib_getModuleNameById($rel_tab_id);
  1234. $other = CRMEntity::getInstance($related_module);
  1235. // Some standard module class doesn't have required variables
  1236. // that are used in the query, they are defined in this generic API
  1237. vtlib_setup_modulevars($related_module, $other);
  1238. $singular_modname = vtlib_toSingular($related_module);
  1239. $button = '';
  1240. if ($actions) {
  1241. if (is_string($actions))
  1242. $actions = explode(',', strtoupper($actions));
  1243. if (in_array('SELECT', $actions) && isPermitted($related_module, 4, '') == 'yes') {
  1244. $button .= "<input title='" . getTranslatedString('LBL_SELECT') . " " . getTranslatedString($related_module) . "' class='crmbutton small edit' type='button' onclick=\"return window.open('index.php?module=$related_module&return_module=$currentModule&action=Popup&popuptype=detailview&select=enable&form=EditView&form_submit=false&recordid=$id&parenttab=$parenttab','test','width=640,height=602,resizable=0,scrollbars=0');\" value='" . getTranslatedString('LBL_SELECT') . " " . getTranslatedString($related_module) . "'>&nbsp;";
  1245. }
  1246. if (in_array('ADD', $actions) && isPermitted($related_module, 1, '') == 'yes') {
  1247. $button .= "<input type='hidden' name='createmode' id='createmode' value='link' />" .
  1248. "<input title='" . getTranslatedString('LBL_ADD_NEW') . " " . getTranslatedString($singular_modname) . "' class='crmbutton small create'" .
  1249. " onclick='this.form.action.value=\"EditView\";this.form.module.value=\"$related_module\"' type='submit' name='button'" .
  1250. " value='" . getTranslatedString('LBL_ADD_NEW') . " " . getTranslatedString($singular_modname) . "'>&nbsp;";
  1251. }
  1252. }
  1253. // To make the edit or del link actions to return back to same view.
  1254. if ($singlepane_view == 'true')
  1255. $returnset = "&return_module=$this_module&return_action=DetailView&return_id=$id";
  1256. else
  1257. $returnset = "&return_module=$this_module&return_action=CallRelatedList&return_id=$id";
  1258. $userNameSql = getSqlForNameInDisplayFormat(array('first_name'=>'vtiger_users.first_name',
  1259. 'last_name' => 'vtiger_users.last_name'), 'Users');
  1260. $query = "select case when (vtiger_users.user_name not like '') then $userNameSql else vtiger_groups.groupname end as user_name," .
  1261. "'Documents' ActivityType,vtiger_attachments.type FileType,crm2.modifiedtime lastmodified,vtiger_crmentity.modifiedtime,
  1262. vtiger_seattachmentsrel.attachmentsid attachmentsid, vtiger_crmentity.smownerid smownerid, vtiger_notes.notesid crmid,
  1263. vtiger_notes.notecontent description,vtiger_notes.*
  1264. from vtiger_notes
  1265. inner join vtiger_senotesrel on vtiger_senotesrel.notesid= vtiger_notes.notesid
  1266. inner join vtiger_crmentity on vtiger_crmentity.crmid= vtiger_notes.notesid and vtiger_crmentity.deleted=0
  1267. inner join vtiger_crmentity crm2 on crm2.crmid=vtiger_senotesrel.crmid
  1268. LEFT JOIN vtiger_groups
  1269. ON vtiger_groups.groupid = vtiger_crmentity.smownerid
  1270. left join vtiger_seattachmentsrel on vtiger_seattachmentsrel.crmid =vtiger_notes.notesid
  1271. left join vtiger_attachments on vtiger_seattachmentsrel.attachmentsid = vtiger_attachments.attachmentsid
  1272. left join vtiger_users on vtiger_crmentity.smownerid= vtiger_users.id
  1273. where crm2.crmid=" . $id;
  1274. $return_value = GetRelatedList($this_module, $related_module, $other, $query, $button, $returnset);
  1275. if ($return_value == null)
  1276. $return_value = Array();
  1277. $return_value['CUSTOM_BUTTON'] = $button;
  1278. return $return_value;
  1279. }
  1280. /**
  1281. * For Record View Notification
  1282. */
  1283. function isViewed($crmid = false) {
  1284. if (!$crmid) {
  1285. $crmid = $this->id;
  1286. }
  1287. if ($crmid) {
  1288. global $adb;
  1289. $result = $adb->pquery("SELECT viewedtime,modifiedtime,smcreatorid,smownerid,modifiedby FROM vtiger_crmentity WHERE crmid=?", Array($crmid));
  1290. $resinfo = $adb->fetch_array($result);
  1291. $lastviewed = $resinfo['viewedtime'];
  1292. $modifiedon = $resinfo['modifiedtime'];
  1293. $smownerid = $resinfo['smownerid'];
  1294. $smcreatorid = $resinfo['smcreatorid'];
  1295. $modifiedby = $resinfo['modifiedby'];
  1296. if ($modifiedby == '0' && ($smownerid == $smcreatorid)) {
  1297. /** When module record is created * */
  1298. return true;
  1299. } else if ($smownerid == $modifiedby) {
  1300. /** Owner and Modifier as same. * */
  1301. return true;
  1302. } else if ($lastviewed && $modifiedon) {
  1303. /** Lastviewed and Modified time is available. */
  1304. if ($this->__timediff($modifiedon, $lastviewed) > 0)
  1305. return true;
  1306. }
  1307. }
  1308. return false;
  1309. }
  1310. function __timediff($d1, $d2) {
  1311. list($t1_1, $t1_2) = explode(' ', $d1);
  1312. list($t1_y, $t1_m, $t1_d) = explode('-', $t1_1);
  1313. list($t1_h, $t1_i, $t1_s) = explode(':', $t1_2);
  1314. $t1 = mktime($t1_h, $t1_i, $t1_s, $t1_m, $t1_d, $t1_y);
  1315. list($t2_1, $t2_2) = explode(' ', $d2);
  1316. list($t2_y, $t2_m, $t2_d) = explode('-', $t2_1);
  1317. list($t2_h, $t2_i, $t2_s) = explode(':', $t2_2);
  1318. $t2 = mktime($t2_h, $t2_i, $t2_s, $t2_m, $t2_d, $t2_y);
  1319. if ($t1 == $t2)
  1320. return 0;
  1321. return $t2 - $t1;
  1322. }
  1323. function markAsViewed($userid) {
  1324. global $adb;
  1325. $adb->pquery("UPDATE vtiger_crmentity set viewedtime=? WHERE crmid=? AND smownerid=?", Array(date('Y-m-d H:i:s', time()), $this->id, $userid));
  1326. }
  1327. /**
  1328. * Save the related module record information. Triggered from CRMEntity->saveentity method or updateRelations.php
  1329. * @param String This module name
  1330. * @param Integer This module record number
  1331. * @param String Related module name
  1332. * @param mixed Integer or Array of related module record number
  1333. */
  1334. function save_related_module($module, $crmid, $with_module, $with_crmid) {
  1335. global $adb;
  1336. if (!is_array($with_crmid))
  1337. $with_crmid = Array($with_crmid);
  1338. foreach ($with_crmid as $relcrmid) {
  1339. if ($with_module == 'Documents') {
  1340. $checkpresence = $adb->pquery("SELECT crmid FROM vtiger_senotesrel WHERE crmid = ? AND notesid = ?", Array($crmid, $relcrmid));
  1341. // Relation already exists? No need to add again
  1342. if ($checkpresence && $adb->num_rows($checkpresence))
  1343. continue;
  1344. $adb->pquery("INSERT INTO vtiger_senotesrel(crmid, notesid) VALUES(?,?)", array($crmid, $relcrmid));
  1345. } else {
  1346. $checkpresence = $adb->pquery("SELECT crmid FROM vtiger_crmentityrel WHERE
  1347. crmid = ? AND module = ? AND relcrmid = ? AND relmodule = ?", Array($crmid, $module, $relcrmid, $with_module));
  1348. // Relation already exists? No need to add again
  1349. if ($checkpresence && $adb->num_rows($checkpresence))
  1350. continue;
  1351. $adb->pquery("INSERT INTO vtiger_crmentityrel(crmid, module, relcrmid, relmodule) VALUES(?,?,?,?)", Array($crmid, $module, $relcrmid, $with_module));
  1352. }
  1353. }
  1354. }
  1355. /**
  1356. * Delete the related module record information. Triggered from updateRelations.php
  1357. * @param String This module name
  1358. * @param Integer This module record number
  1359. * @param String Related module name
  1360. * @param mixed Integer or Array of related module record number
  1361. */
  1362. function delete_related_module($module, $crmid, $with_module, $with_crmid) {
  1363. global $adb;
  1364. if (!is_array($with_crmid))
  1365. $with_crmid = Array($with_crmid);
  1366. foreach ($with_crmid as $relcrmid) {
  1367. if ($with_module == 'Documents') {
  1368. $adb->pquery("DELETE FROM vtiger_senotesrel WHERE crmid=? AND notesid=?", Array($crmid, $relcrmid));
  1369. } else {
  1370. $adb->pquery("DELETE FROM vtiger_crmentityrel WHERE (crmid=? AND module=? AND relcrmid=? AND relmodule=?) OR (relcrmid=? AND relmodule=? AND crmid=? AND module=?)",
  1371. Array($crmid, $module, $relcrmid, $with_module,$crmid, $module, $relcrmid, $with_module));
  1372. }
  1373. }
  1374. }
  1375. /**
  1376. * Default (generic) function to handle the related list for the module.
  1377. * NOTE: Vtiger_Module::setRelatedList sets reference to this function in vtiger_relatedlists table
  1378. * if function name is not explicitly specified.
  1379. */
  1380. function get_related_list($id, $cur_tab_id, $rel_tab_id, $actions = false) {
  1381. global $currentModule, $app_strings, $singlepane_view;
  1382. $parenttab = getParentTab();
  1383. $related_module = vtlib_getModuleNameById($rel_tab_id);
  1384. $other = CRMEntity::getInstance($related_module);
  1385. // Some standard module class doesn't have required variables
  1386. // that are used in the query, they are defined in this generic API
  1387. vtlib_setup_modulevars($currentModule, $this);
  1388. vtlib_setup_modulevars($related_module, $other);
  1389. $singular_modname = 'SINGLE_' . $related_module;
  1390. $button = '';
  1391. if ($actions) {
  1392. if (is_string($actions))
  1393. $actions = explode(',', strtoupper($actions));
  1394. if (in_array('SELECT', $actions) && isPermitted($related_module, 4, '') == 'yes') {
  1395. $button .= "<input title='" . getTranslatedString('LBL_SELECT') . " " . getTranslatedString($related_module) . "' class='crmbutton small edit' " .
  1396. " type='button' onclick=\"return window.open('index.php?module=$related_module&return_module=$currentModule&action=Popup&popuptype=detailview&select=enable&form=EditView&form_submit=false&recordid=$id&parenttab=$parenttab','test','width=640,height=602,resizable=0,scrollbars=0');\"" .
  1397. " value='" . getTranslatedString('LBL_SELECT') . " " . getTranslatedString($related_module, $related_module) . "'>&nbsp;";
  1398. }
  1399. if (in_array('ADD', $actions) && isPermitted($related_module, 1, '') == 'yes') {
  1400. $button .= "<input type='hidden' name='createmode' id='createmode' value='link' />" .
  1401. "<input title='" . getTranslatedString('LBL_ADD_NEW') . " " . getTranslatedString($singular_modname) . "' class='crmbutton small create'" .
  1402. " onclick='this.form.action.value=\"EditView\";this.form.module.value=\"$related_module\"' type='submit' name='button'" .
  1403. " value='" . getTranslatedString('LBL_ADD_NEW') . " " . getTranslatedString($singular_modname, $related_module) . "'>&nbsp;";
  1404. }
  1405. }
  1406. // To make the edit or del link actions to return back to same view.
  1407. if ($singlepane_view == 'true')
  1408. $returnset = "&return_module=$currentModule&return_action=DetailView&return_id=$id";
  1409. else
  1410. $returnset = "&return_module=$currentModule&return_action=CallRelatedList&return_id=$id";
  1411. $query = "SELECT vtiger_crmentity.*, $other->table_name.*";
  1412. $userNameSql = getSqlForNameInDisplayFormat(array('first_name'=>'vtiger_users.first_name',
  1413. 'last_name' => 'vtiger_users.last_name'), 'Users');
  1414. $query .= ", CASE WHEN (vtiger_users.user_name NOT LIKE '') THEN $userNameSql ELSE vtiger_groups.groupname END AS user_name";
  1415. $more_relation = '';
  1416. if (!empty($other->related_tables)) {
  1417. foreach ($other->related_tables as $tname => $relmap) {
  1418. $query .= ", $tname.*";
  1419. // Setup the default JOIN conditions if not specified
  1420. if (empty($relmap[1]))
  1421. $relmap[1] = $other->table_name;
  1422. if (empty($relmap[2]))
  1423. $relmap[2] = $relmap[0];
  1424. $more_relation .= " LEFT JOIN $tname ON $tname.$relmap[0] = $relmap[1].$relmap[2]";
  1425. }
  1426. }
  1427. $query .= " FROM $other->table_name";
  1428. $query .= " INNER JOIN vtiger_crmentity ON vtiger_crmentity.crmid = $other->table_name.$other->table_index";
  1429. $query .= " INNER JOIN vtiger_crmentityrel ON (vtiger_crmentityrel.relcrmid = vtiger_crmentity.crmid OR vtiger_crmentityrel.crmid = vtiger_crmentity.crmid)";
  1430. $query .= $more_relation;
  1431. $query .= " LEFT JOIN vtiger_users ON vtiger_users.id = vtiger_crmentity.smownerid";
  1432. $query .= " LEFT JOIN vtiger_groups ON vtiger_groups.groupid = vtiger_crmentity.smownerid";
  1433. $query .= " WHERE vtiger_crmentity.deleted = 0 AND (vtiger_crmentityrel.crmid = $id OR vtiger_crmentityrel.relcrmid = $id)";
  1434. $return_value = GetRelatedList($currentModule, $related_module, $other, $query, $button, $returnset);
  1435. if ($return_value == null)
  1436. $return_value = Array();
  1437. $return_value['CUSTOM_BUTTON'] = $button;
  1438. return $return_value;
  1439. }
  1440. /**
  1441. * Default (generic) function to handle the dependents list for the module.
  1442. * NOTE: UI type '10' is used to stored the references to other modules for a given record.
  1443. * These dependent records can be retrieved through this function.
  1444. * For eg: A trouble ticket can be related to an Account or a Contact.
  1445. * From a given Contact/Account if we need to fetch all such dependent trouble tickets, get_dependents_list function can be used.
  1446. */
  1447. function get_dependents_list($id, $cur_tab_id, $rel_tab_id, $actions = false) {
  1448. global $currentModule, $app_strings, $singlepane_view, $current_user;
  1449. $parenttab = getParentTab();
  1450. $related_module = vtlib_getModuleNameById($rel_tab_id);
  1451. $other = CRMEntity::getInstance($related_module);
  1452. // Some standard module class doesn't have required variables
  1453. // that are used in the query, they are defined in this generic API
  1454. vtlib_setup_modulevars($currentModule, $this);
  1455. vtlib_setup_modulevars($related_module, $other);
  1456. $singular_modname = 'SINGLE_' . $related_module;
  1457. $button = '';
  1458. // To make the edit or del link actions to return back to same view.
  1459. if ($singlepane_view == 'true')
  1460. $returnset = "&return_module=$currentModule&return_action=DetailView&return_id=$id";
  1461. else
  1462. $returnset = "&return_module=$currentModule&return_action=CallRelatedList&return_id=$id";
  1463. $return_value = null;
  1464. $dependentFieldSql = $this->db->pquery("SELECT tabid, fieldname, columnname FROM vtiger_field WHERE uitype='10' AND" .
  1465. " fieldid IN (SELECT fieldid FROM vtiger_fieldmodulerel WHERE relmodule=? AND module=?)", array($currentModule, $related_module));
  1466. $numOfFields = $this->db->num_rows($dependentFieldSql);
  1467. if ($numOfFields > 0) {
  1468. $dependentColumn = $this->db->query_result($dependentFieldSql, 0, 'columnname');
  1469. $dependentField = $this->db->query_result($dependentFieldSql, 0, 'fieldname');
  1470. $button .= '<input type="hidden" name="' . $dependentColumn . '" id="' . $dependentColumn . '" value="' . $id . '">';
  1471. $button .= '<input type="hidden" name="' . $dependentColumn . '_type" id="' . $dependentColumn . '_type" value="' . $currentModule . '">';
  1472. if ($actions) {
  1473. if (is_string($actions))
  1474. $actions = explode(',', strtoupper($actions));
  1475. if (in_array('ADD', $actions) && isPermitted($related_module, 1, '') == 'yes'
  1476. && getFieldVisibilityPermission($related_module, $current_user->id, $dependentField, 'readwrite') == '0') {
  1477. $button .= "<input title='" . getTranslatedString('LBL_ADD_NEW') . " " . getTranslatedString($singular_modname, $related_module) . "' class='crmbutton small create'" .
  1478. " onclick='this.form.action.value=\"EditView\";this.form.module.value=\"$related_module\"' type='submit' name='button'" .
  1479. " value='" . getTranslatedString('LBL_ADD_NEW') . " " . getTranslatedString($singular_modname, $related_module) . "'>&nbsp;";
  1480. }
  1481. }
  1482. $query = "SELECT vtiger_crmentity.*, $other->table_name.*";
  1483. $userNameSql = getSqlForNameInDisplayFormat(array('first_name'=>'vtiger_users.first_name',
  1484. 'last_name' => 'vtiger_users.last_name'), 'Users');
  1485. $query .= ", CASE WHEN (vtiger_users.user_name NOT LIKE '') THEN $userNameSql ELSE vtiger_groups.groupname END AS user_name";
  1486. $more_relation = '';
  1487. if (!empty($other->related_tables)) {
  1488. foreach ($other->related_tables as $tname => $relmap) {
  1489. $query .= ", $tname.*";
  1490. // Setup the default JOIN conditions if not specified
  1491. if (empty($relmap[1]))
  1492. $relmap[1] = $other->table_name;
  1493. if (empty($relmap[2]))
  1494. $relmap[2] = $relmap[0];
  1495. $more_relation .= " LEFT JOIN $tname ON $tname.$relmap[0] = $relmap[1].$relmap[2]";
  1496. }
  1497. }
  1498. $query .= " FROM $other->table_name";
  1499. $query .= " INNER JOIN vtiger_crmentity ON vtiger_crmentity.crmid = $other->table_name.$other->table_index";
  1500. $query .= " INNER JOIN $this->table_name ON $this->table_name.$this->table_index = $other->table_name.$dependentColumn";
  1501. $query .= $more_relation;
  1502. $query .= " LEFT JOIN vtiger_users ON vtiger_users.id = vtiger_crmentity.smownerid";
  1503. $query .= " LEFT JOIN vtiger_groups ON vtiger_groups.groupid = vtiger_crmentity.smownerid";
  1504. $query .= " WHERE vtiger_crmentity.deleted = 0 AND $this->table_name.$this->table_index = $id";
  1505. $return_value = GetRelatedList($currentModule, $related_module, $other, $query, $button, $returnset);
  1506. }
  1507. if ($return_value == null)
  1508. $return_value = Array();
  1509. $return_value['CUSTOM_BUTTON'] = $button;
  1510. return $return_value;
  1511. }
  1512. /**
  1513. * Move the related records of the specified list of id's to the given record.
  1514. * @param String This module name
  1515. * @param Array List of Entity Id's from which related records need to be transfered
  1516. * @param Integer Id of the the Record to which the related records are to be moved
  1517. */
  1518. function transferRelatedRecords($module, $transferEntityIds, $entityId) {
  1519. global $adb, $log;
  1520. $log->debug("Entering function transferRelatedRecords ($module, $transferEntityIds, $entityId)");
  1521. foreach ($transferEntityIds as $transferId) {
  1522. // Pick the records related to the entity to be transfered, but do not pick the once which are already related to the current entity.
  1523. $relatedRecords = $adb->pquery("SELECT relcrmid, relmodule FROM vtiger_crmentityrel WHERE crmid=? AND module=?" .
  1524. " AND relcrmid NOT IN (SELECT relcrmid FROM vtiger_crmentityrel WHERE crmid=? AND module=?)", array($transferId, $module, $entityId, $module));
  1525. $numOfRecords = $adb->num_rows($relatedRecords);
  1526. for ($i = 0; $i < $numOfRecords; $i++) {
  1527. $relcrmid = $adb->query_result($relatedRecords, $i, 'relcrmid');
  1528. $relmodule = $adb->query_result($relatedRecords, $i, 'relmodule');
  1529. $adb->pquery("UPDATE vtiger_crmentityrel SET crmid=? WHERE relcrmid=? AND relmodule=? AND crmid=? AND module=?", array($entityId, $relcrmid, $relmodule, $transferId, $module));
  1530. }
  1531. // Pick the records to which the entity to be transfered is related, but do not pick the once to which current entity is already related.
  1532. $parentRecords = $adb->pquery("SELECT crmid, module FROM vtiger_crmentityrel WHERE relcrmid=? AND relmodule=?" .
  1533. " AND crmid NOT IN (SELECT crmid FROM vtiger_crmentityrel WHERE relcrmid=? AND relmodule=?)", array($transferId, $module, $entityId, $module));
  1534. $numOfRecords = $adb->num_rows($parentRecords);
  1535. for ($i = 0; $i < $numOfRecords; $i++) {
  1536. $parcrmid = $adb->query_result($parentRecords, $i, 'crmid');
  1537. $parmodule = $adb->query_result($parentRecords, $i, 'module');
  1538. $adb->pquery("UPDATE vtiger_crmentityrel SET relcrmid=? WHERE crmid=? AND module=? AND relcrmid=? AND relmodule=?", array($entityId, $parcrmid, $parmodule, $transferId, $module));
  1539. }
  1540. $adb->pquery("UPDATE vtiger_modcomments SET related_to = ? WHERE related_to = ?", array($entityId, $transferId));
  1541. }
  1542. $log->debug("Exiting transferRelatedRecords...");
  1543. }
  1544. /*
  1545. * Function to get the primary query part of a report for which generateReportsQuery Doesnt exist in module
  1546. * @param - $module Primary module name
  1547. * returns the query string formed on fetching the related data for report for primary module
  1548. */
  1549. function generateReportsQuery($module, $queryPlanner) {
  1550. global $adb;
  1551. $primary = CRMEntity::getInstance($module);
  1552. vtlib_setup_modulevars($module, $primary);
  1553. $moduletable = $primary->table_name;
  1554. $moduleindex = $primary->table_index;
  1555. $modulecftable = $primary->customFieldTable[0];
  1556. $modulecfindex = $primary->customFieldTable[1];
  1557. if (isset($modulecftable) && $queryPlanner->requireTable($modulecftable)) {
  1558. $cfquery = "inner join $modulecftable as $modulecftable on $modulecftable.$modulecfindex=$moduletable.$moduleindex";
  1559. } else {
  1560. $cfquery = '';
  1561. }
  1562. $relquery = '';
  1563. $matrix = $queryPlanner->newDependencyMatrix();
  1564. $fields_query = $adb->pquery("SELECT vtiger_field.fieldname,vtiger_field.tablename,vtiger_field.fieldid from vtiger_field INNER JOIN vtiger_tab on vtiger_tab.name = ? WHERE vtiger_tab.tabid=vtiger_field.tabid AND vtiger_field.uitype IN (10) and vtiger_field.presence in (0,2)", array($module));
  1565. if ($adb->num_rows($fields_query) > 0) {
  1566. for ($i = 0; $i < $adb->num_rows($fields_query); $i++) {
  1567. $field_name = $adb->query_result($fields_query, $i, 'fieldname');
  1568. $field_id = $adb->query_result($fields_query, $i, 'fieldid');
  1569. $tab_name = $adb->query_result($fields_query, $i, 'tablename');
  1570. $ui10_modules_query = $adb->pquery("SELECT relmodule FROM vtiger_fieldmodulerel WHERE fieldid=?", array($field_id));
  1571. if ($adb->num_rows($ui10_modules_query) > 0) {
  1572. // Capture the forward table dependencies due to dynamic related-field
  1573. $crmentityRelModuleFieldTable = "vtiger_crmentityRel$module$field_id";
  1574. $crmentityRelModuleFieldTableDeps = array();
  1575. for ($j = 0; $j < $adb->num_rows($ui10_modules_query); $j++) {
  1576. $rel_mod = $adb->query_result($ui10_modules_query, $j, 'relmodule');
  1577. $rel_obj = CRMEntity::getInstance($rel_mod);
  1578. vtlib_setup_modulevars($rel_mod, $rel_obj);
  1579. $rel_tab_name = $rel_obj->table_name;
  1580. $rel_tab_index = $rel_obj->table_index;
  1581. $crmentityRelModuleFieldTableDeps[] = $rel_tab_name . "Rel$module$field_id";
  1582. }
  1583. $matrix->setDependency($crmentityRelModuleFieldTable, $crmentityRelModuleFieldTableDeps);
  1584. $matrix->addDependency($tab_name, $crmentityRelModuleFieldTable);
  1585. if ($queryPlanner->requireTable($crmentityRelModuleFieldTable, $matrix)) {
  1586. $relquery.= " left join vtiger_crmentity as $crmentityRelModuleFieldTable on $crmentityRelModuleFieldTable.crmid = $tab_name.$field_name and vtiger_crmentityRel$module$field_id.deleted=0";
  1587. }
  1588. for ($j = 0; $j < $adb->num_rows($ui10_modules_query); $j++) {
  1589. $rel_mod = $adb->query_result($ui10_modules_query, $j, 'relmodule');
  1590. $rel_obj = CRMEntity::getInstance($rel_mod);
  1591. vtlib_setup_modulevars($rel_mod, $rel_obj);
  1592. $rel_tab_name = $rel_obj->table_name;
  1593. $rel_tab_index = $rel_obj->table_index;
  1594. $rel_tab_name_rel_module_table_alias = $rel_tab_name . "Rel$module$field_id";
  1595. if ($queryPlanner->requireTable($rel_tab_name_rel_module_table_alias)) {
  1596. $relquery.= " left join $rel_tab_name as $rel_tab_name_rel_module_table_alias on $rel_tab_name_rel_module_table_alias.$rel_tab_index = $crmentityRelModuleFieldTable.crmid";
  1597. }
  1598. }
  1599. }
  1600. }
  1601. }
  1602. $query = "from $moduletable inner join vtiger_crmentity on vtiger_crmentity.crmid=$moduletable.$moduleindex";
  1603. // Add the pre-joined custom table query
  1604. $query .= " "."$cfquery";
  1605. if ($queryPlanner->requireTable('vtiger_groups'.$module)) {
  1606. $query .= " left join vtiger_groups as vtiger_groups" . $module . " on vtiger_groups" . $module . ".groupid = vtiger_crmentity.smownerid";
  1607. }
  1608. if ($queryPlanner->requireTable('vtiger_users'.$module)) {
  1609. $query .= " left join vtiger_users as vtiger_users" . $module . " on vtiger_users" . $module . ".id = vtiger_crmentity.smownerid";
  1610. }
  1611. if ($queryPlanner->requireTable('vtiger_lastModifiedBy'.$module)) {
  1612. $query .= " left join vtiger_users as vtiger_lastModifiedBy" . $module . " on vtiger_lastModifiedBy" . $module . ".id = vtiger_crmentity.modifiedby";
  1613. }
  1614. // TODO Optimize the tables below based on requirement
  1615. $query .= " left join vtiger_groups on vtiger_groups.groupid = vtiger_crmentity.smownerid";
  1616. $query .= " left join vtiger_users on vtiger_users.id = vtiger_crmentity.smownerid";
  1617. // Add the pre-joined relation table query
  1618. $query .= " " . $relquery;
  1619. return $query;
  1620. }
  1621. /*
  1622. * Function to get the secondary query part of a report for which generateReportsSecQuery Doesnt exist in module
  1623. * @param - $module primary module name
  1624. * @param - $secmodule secondary module name
  1625. * returns the query string formed on fetching the related data for report for secondary module
  1626. */
  1627. function generateReportsSecQuery($module, $secmodule,$queryPlanner) {
  1628. global $adb;
  1629. $secondary = CRMEntity::getInstance($secmodule);
  1630. vtlib_setup_modulevars($secmodule, $secondary);
  1631. $tablename = $secondary->table_name;
  1632. $tableindex = $secondary->table_index;
  1633. $modulecftable = $secondary->customFieldTable[0];
  1634. $modulecfindex = $secondary->customFieldTable[1];
  1635. if (isset($modulecftable) && $queryPlanner->requireTable($modulecftable)) {
  1636. $cfquery = "left join $modulecftable as $modulecftable on $modulecftable.$modulecfindex=$tablename.$tableindex";
  1637. } else {
  1638. $cfquery = '';
  1639. }
  1640. $relquery = '';
  1641. $matrix = $queryPlanner->newDependencyMatrix();
  1642. $fields_query = $adb->pquery("SELECT vtiger_field.fieldname,vtiger_field.tablename,vtiger_field.fieldid from vtiger_field INNER JOIN vtiger_tab on vtiger_tab.name = ? WHERE vtiger_tab.tabid=vtiger_field.tabid AND vtiger_field.uitype IN (10) and vtiger_field.presence in (0,2)", array($secmodule));
  1643. if ($adb->num_rows($fields_query) > 0) {
  1644. for ($i = 0; $i < $adb->num_rows($fields_query); $i++) {
  1645. $field_name = $adb->query_result($fields_query, $i, 'fieldname');
  1646. $field_id = $adb->query_result($fields_query, $i, 'fieldid');
  1647. $tab_name = $adb->query_result($fields_query, $i, 'tablename');
  1648. $ui10_modules_query = $adb->pquery("SELECT relmodule FROM vtiger_fieldmodulerel WHERE fieldid=?", array($field_id));
  1649. if ($adb->num_rows($ui10_modules_query) > 0) {
  1650. // Capture the forward table dependencies due to dynamic related-field
  1651. $crmentityRelSecModuleTable = "vtiger_crmentityRel$secmodule$field_id";
  1652. $crmentityRelSecModuleTableDeps = array();
  1653. for ($j = 0; $j < $adb->num_rows($ui10_modules_query); $j++) {
  1654. $rel_mod = $adb->query_result($ui10_modules_query, $j, 'relmodule');
  1655. $rel_obj = CRMEntity::getInstance($rel_mod);
  1656. vtlib_setup_modulevars($rel_mod, $rel_obj);
  1657. $rel_tab_name = $rel_obj->table_name;
  1658. $rel_tab_index = $rel_obj->table_index;
  1659. $crmentityRelSecModuleTableDeps[] = $rel_tab_name . "Rel$secmodule";
  1660. }
  1661. $matrix->setDependency($crmentityRelSecModuleTable, $crmentityRelSecModuleTableDeps);
  1662. $matrix->addDependency($tab_name, $crmentityRelSecModuleTable);
  1663. if ($queryPlanner->requireTable($crmentityRelSecModuleTable, $matrix)) {
  1664. $relquery .= " left join vtiger_crmentity as $crmentityRelSecModuleTable on $crmentityRelSecModuleTable.crmid = $tab_name.$field_name and $crmentityRelSecModuleTable.deleted=0";
  1665. }
  1666. for ($j = 0; $j < $adb->num_rows($ui10_modules_query); $j++) {
  1667. $rel_mod = $adb->query_result($ui10_modules_query, $j, 'relmodule');
  1668. $rel_obj = CRMEntity::getInstance($rel_mod);
  1669. vtlib_setup_modulevars($rel_mod, $rel_obj);
  1670. $rel_tab_name = $rel_obj->table_name;
  1671. $rel_tab_index = $rel_obj->table_index;
  1672. $rel_tab_name_rel_secmodule_table_alias = $rel_tab_name . "Rel$secmodule";
  1673. if ($queryPlanner->requireTable($rel_tab_name_rel_secmodule_table_alias)) {
  1674. $relquery .= " left join $rel_tab_name as $rel_tab_name_rel_secmodule_table_alias on $rel_tab_name_rel_secmodule_table_alias.$rel_tab_index = $crmentityRelSecModuleTable.crmid";
  1675. }
  1676. }
  1677. }
  1678. }
  1679. }
  1680. // Update forward table dependencies
  1681. $matrix->setDependency("vtiger_crmentity$secmodule", array("vtiger_groups$secmodule", "vtiger_users$secmodule", "vtiger_lastModifiedBy$secmodule"));
  1682. $matrix->addDependency($tablename, "vtiger_crmentity$secmodule");
  1683. if (!$queryPlanner->requireTable($tablename, $matrix)) {
  1684. return '';
  1685. }
  1686. $query = $this->getRelationQuery($module, $secmodule, "$tablename", "$tableindex", $queryPlanner);
  1687. if ($queryPlanner->requireTable("vtiger_crmentity$secmodule", $matrix)) {
  1688. $query .= " left join vtiger_crmentity as vtiger_crmentity$secmodule on vtiger_crmentity$secmodule.crmid = $tablename.$tableindex AND vtiger_crmentity$secmodule.deleted=0";
  1689. }
  1690. // Add the pre-joined custom table query
  1691. $query .= " ".$cfquery;
  1692. if ($queryPlanner->requireTable("vtiger_groups$secmodule")) {
  1693. $query .= " left join vtiger_groups as vtiger_groups" . $secmodule . " on vtiger_groups" . $secmodule . ".groupid = vtiger_crmentity$secmodule.smownerid";
  1694. }
  1695. if ($queryPlanner->requireTable("vtiger_users$secmodule")) {
  1696. $query .= " left join vtiger_users as vtiger_users" . $secmodule . " on vtiger_users" . $secmodule . ".id = vtiger_crmentity$secmodule.smownerid";
  1697. }
  1698. if ($queryPlanner->requireTable("vtiger_lastModifiedBy$secmodule")) {
  1699. $query .= " left join vtiger_users as vtiger_lastModifiedBy" . $secmodule . " on vtiger_lastModifiedBy" . $secmodule . ".id = vtiger_crmentity" . $secmodule . ".modifiedby";
  1700. }
  1701. // Add the pre-joined relation table query
  1702. $query .= " " . $relquery;
  1703. return $query;
  1704. }
  1705. /*
  1706. * Function to get the security query part of a report
  1707. * @param - $module primary module name
  1708. * returns the query string formed on fetching the related data for report for security of the module
  1709. */
  1710. function getListViewSecurityParameter($module) {
  1711. $tabid = getTabid($module);
  1712. global $current_user;
  1713. if ($current_user) {
  1714. require('user_privileges/user_privileges_' . $current_user->id . '.php');
  1715. require('user_privileges/sharing_privileges_' . $current_user->id . '.php');
  1716. }
  1717. $sec_query = '';
  1718. if($is_admin==false && $profileGlobalPermission[1] == 1 && $profileGlobalPermission[2] == 1
  1719. && $defaultOrgSharingPermission[$tabid] == 3) {
  1720. $sec_query .= " and (vtiger_crmentity.smownerid in($current_user->id) or vtiger_crmentity.smownerid
  1721. in (select vtiger_user2role.userid from vtiger_user2role
  1722. inner join vtiger_users on vtiger_users.id=vtiger_user2role.userid
  1723. inner join vtiger_role on vtiger_role.roleid=vtiger_user2role.roleid
  1724. where vtiger_role.parentrole like '" . $current_user_parent_role_seq . "::%') or vtiger_crmentity.smownerid
  1725. in(select shareduserid from vtiger_tmp_read_user_sharing_per
  1726. where userid=" . $current_user->id . " and tabid=" . $tabid . ") or (";
  1727. if (sizeof($current_user_groups) > 0) {
  1728. $sec_query .= " vtiger_groups.groupid in (" . implode(",", $current_user_groups) . ") or ";
  1729. }
  1730. $sec_query .= " vtiger_groups.groupid in(select vtiger_tmp_read_group_sharing_per.sharedgroupid
  1731. from vtiger_tmp_read_group_sharing_per where userid=" . $current_user->id . " and tabid=" . $tabid . "))) ";
  1732. }
  1733. return $sec_query;
  1734. }
  1735. /*
  1736. * Function to get the security query part of a report
  1737. * @param - $module primary module name
  1738. * returns the query string formed on fetching the related data for report for security of the module
  1739. */
  1740. function getSecListViewSecurityParameter($module) {
  1741. $tabid = getTabid($module);
  1742. global $current_user;
  1743. if ($current_user) {
  1744. require('user_privileges/user_privileges_' . $current_user->id . '.php');
  1745. require('user_privileges/sharing_privileges_' . $current_user->id . '.php');
  1746. }
  1747. $sec_query .= " and (vtiger_crmentity$module.smownerid in($current_user->id) or vtiger_crmentity$module.smownerid in(select vtiger_user2role.userid from vtiger_user2role inner join vtiger_users on vtiger_users.id=vtiger_user2role.userid inner join vtiger_role on vtiger_role.roleid=vtiger_user2role.roleid where vtiger_role.parentrole like '" . $current_user_parent_role_seq . "::%') or vtiger_crmentity$module.smownerid in(select shareduserid from vtiger_tmp_read_user_sharing_per where userid=" . $current_user->id . " and tabid=" . $tabid . ") or (";
  1748. if (sizeof($current_user_groups) > 0) {
  1749. $sec_query .= " vtiger_groups$module.groupid in (" . implode(",", $current_user_groups) . ") or ";
  1750. }
  1751. $sec_query .= " vtiger_groups$module.groupid in(select vtiger_tmp_read_group_sharing_per.sharedgroupid from vtiger_tmp_read_group_sharing_per where userid=" . $current_user->id . " and tabid=" . $tabid . "))) ";
  1752. return $sec_query;
  1753. }
  1754. /*
  1755. * Function to get the relation query part of a report
  1756. * @param - $module primary module name
  1757. * @param - $secmodule secondary module name
  1758. * returns the query string formed on relating the primary module and secondary module
  1759. */
  1760. function getRelationQuery($module, $secmodule, $table_name, $column_name, $queryPlanner) {
  1761. $tab = getRelationTables($module, $secmodule);
  1762. foreach ($tab as $key => $value) {
  1763. $tables[] = $key;
  1764. $fields[] = $value;
  1765. }
  1766. $pritablename = $tables[0];
  1767. $sectablename = $tables[1];
  1768. $prifieldname = $fields[0][0];
  1769. $secfieldname = $fields[0][1];
  1770. $tmpname = $pritablename . 'tmp' . $secmodule;
  1771. $condition = "";
  1772. if (!empty($tables[1]) && !empty($fields[1])) {
  1773. $condvalue = $tables[1] . "." . $fields[1];
  1774. $condition = "$pritablename.$prifieldname=$condvalue";
  1775. } else {
  1776. $condvalue = $table_name . "." . $column_name;
  1777. $condition = "$pritablename.$secfieldname=$condvalue";
  1778. }
  1779. // Look forward for temporary table usage as defined by the QueryPlanner
  1780. $secQuery = "select $table_name.* from $table_name inner join vtiger_crmentity on " .
  1781. "vtiger_crmentity.crmid=$table_name.$column_name and vtiger_crmentity.deleted=0";
  1782. $secQueryTempTableQuery = $queryPlanner->registerTempTable($secQuery, array($column_name, $fields[1]));
  1783. $query = '';
  1784. if ($pritablename == 'vtiger_crmentityrel') {
  1785. $condition = "($table_name.$column_name={$tmpname}.{$secfieldname} " .
  1786. "OR $table_name.$column_name={$tmpname}.{$prifieldname})";
  1787. $query = " left join vtiger_crmentityrel as $tmpname ON ($condvalue={$tmpname}.{$secfieldname} " .
  1788. "OR $condvalue={$tmpname}.{$prifieldname}) ";
  1789. } elseif (strripos($pritablename, 'rel') === (strlen($pritablename) - 3)) {
  1790. $instance = self::getInstance($module);
  1791. $sectableindex = $instance->tab_name_index[$sectablename];
  1792. $condition = "$table_name.$column_name=$tmpname.$secfieldname";
  1793. $query = " left join $pritablename as $tmpname ON ($sectablename.$sectableindex=$tmpname.$prifieldname)";
  1794. if($secmodule == 'Calendar'){
  1795. $condition .= " AND $table_name.activitytype != 'Emails'";
  1796. }else if($secmodule == 'Leads'){
  1797. $condition .= " AND $table_name.converted = 0";
  1798. }
  1799. }
  1800. $query .= " left join $secQueryTempTableQuery as $table_name on {$condition}";
  1801. return $query;
  1802. }
  1803. /** END * */
  1804. /**
  1805. * This function handles the import for uitype 10 fieldtype
  1806. * @param string $module - the current module name
  1807. * @param string fieldname - the related to field name
  1808. */
  1809. function add_related_to($module, $fieldname) {
  1810. global $adb, $imported_ids, $current_user;
  1811. $related_to = $this->column_fields[$fieldname];
  1812. if (empty($related_to)) {
  1813. return false;
  1814. }
  1815. //check if the field has module information; if not get the first module
  1816. if (!strpos($related_to, "::::")) {
  1817. $module = getFirstModule($module, $fieldname);
  1818. $value = $related_to;
  1819. } else {
  1820. //check the module of the field
  1821. $arr = array();
  1822. $arr = explode("::::", $related_to);
  1823. $module = $arr[0];
  1824. $value = $arr[1];
  1825. }
  1826. $focus1 = CRMEntity::getInstance($module);
  1827. $entityNameArr = getEntityField($module);
  1828. $entityName = $entityNameArr['fieldname'];
  1829. $query = "SELECT vtiger_crmentity.deleted, $focus1->table_name.*
  1830. FROM $focus1->table_name
  1831. INNER JOIN vtiger_crmentity ON vtiger_crmentity.crmid=$focus1->table_name.$focus1->table_index
  1832. where $entityName=? and vtiger_crmentity.deleted=0";
  1833. $result = $adb->pquery($query, array($value));
  1834. if (!isset($this->checkFlagArr[$module])) {
  1835. $this->checkFlagArr[$module] = (isPermitted($module, 'EditView', '') == 'yes');
  1836. }
  1837. if ($adb->num_rows($result) > 0) {
  1838. //record found
  1839. $focus1->id = $adb->query_result($result, 0, $focus1->table_index);
  1840. } elseif ($this->checkFlagArr[$module]) {
  1841. //record not found; create it
  1842. $focus1->column_fields[$focus1->list_link_field] = $value;
  1843. $focus1->column_fields['assigned_user_id'] = $current_user->id;
  1844. $focus1->column_fields['modified_user_id'] = $current_user->id;
  1845. $focus1->save($module);
  1846. $last_import = new UsersLastImport();
  1847. $last_import->assigned_user_id = $current_user->id;
  1848. $last_import->bean_type = $module;
  1849. $last_import->bean_id = $focus1->id;
  1850. $last_import->save();
  1851. } else {
  1852. //record not found and cannot create
  1853. $this->column_fields[$fieldname] = "";
  1854. return false;
  1855. }
  1856. if (!empty($focus1->id)) {
  1857. $this->column_fields[$fieldname] = $focus1->id;
  1858. return true;
  1859. } else {
  1860. $this->column_fields[$fieldname] = "";
  1861. return false;
  1862. }
  1863. }
  1864. /**
  1865. * To keep track of action of field filtering and avoiding doing more than once.
  1866. *
  1867. * @var Array
  1868. */
  1869. protected $__inactive_fields_filtered = false;
  1870. /**
  1871. * Filter in-active fields based on type
  1872. *
  1873. * @param String $module
  1874. */
  1875. function filterInactiveFields($module) {
  1876. if ($this->__inactive_fields_filtered) {
  1877. return;
  1878. }
  1879. global $adb, $mod_strings;
  1880. // Look for fields that has presence value NOT IN (0,2)
  1881. $cachedModuleFields = VTCacheUtils::lookupFieldInfo_Module($module, array('1'));
  1882. if ($cachedModuleFields === false) {
  1883. // Initialize the fields calling suitable API
  1884. getColumnFields($module);
  1885. $cachedModuleFields = VTCacheUtils::lookupFieldInfo_Module($module, array('1'));
  1886. }
  1887. $hiddenFields = array();
  1888. if ($cachedModuleFields) {
  1889. foreach ($cachedModuleFields as $fieldinfo) {
  1890. $fieldLabel = $fieldinfo['fieldlabel'];
  1891. // NOTE: We should not translate the label to enable field diff based on it down
  1892. $fieldName = $fieldinfo['fieldname'];
  1893. $tableName = str_replace("vtiger_", "", $fieldinfo['tablename']);
  1894. $hiddenFields[$fieldLabel] = array($tableName => $fieldName);
  1895. }
  1896. }
  1897. if (isset($this->list_fields)) {
  1898. $this->list_fields = array_diff_assoc($this->list_fields, $hiddenFields);
  1899. }
  1900. if (isset($this->search_fields)) {
  1901. $this->search_fields = array_diff_assoc($this->search_fields, $hiddenFields);
  1902. }
  1903. // To avoid re-initializing everytime.
  1904. $this->__inactive_fields_filtered = true;
  1905. }
  1906. /** END * */
  1907. function buildSearchQueryForFieldTypes($uitypes, $value) {
  1908. global $adb;
  1909. if (!is_array($uitypes))
  1910. $uitypes = array($uitypes);
  1911. $module = get_class($this);
  1912. $cachedModuleFields = VTCacheUtils::lookupFieldInfo_Module($module);
  1913. if ($cachedModuleFields === false) {
  1914. getColumnFields($module); // This API will initialize the cache as well
  1915. // We will succeed now due to above function call
  1916. $cachedModuleFields = VTCacheUtils::lookupFieldInfo_Module($module);
  1917. }
  1918. $lookuptables = array();
  1919. $lookupcolumns = array();
  1920. foreach ($cachedModuleFields as $fieldinfo) {
  1921. if (in_array($fieldinfo['uitype'], $uitypes)) {
  1922. $lookuptables[] = $fieldinfo['tablename'];
  1923. $lookupcolumns[] = $fieldinfo['columnname'];
  1924. }
  1925. }
  1926. $entityfields = getEntityField($module);
  1927. $querycolumnnames = implode(',', $lookupcolumns);
  1928. $entitycolumnnames = $entityfields['fieldname'];
  1929. $query = "select crmid as id, $querycolumnnames, $entitycolumnnames as name ";
  1930. $query .= " FROM $this->table_name ";
  1931. $query .=" INNER JOIN vtiger_crmentity ON $this->table_name.$this->table_index = vtiger_crmentity.crmid AND deleted = 0 ";
  1932. //remove the base table
  1933. $LookupTable = array_unique($lookuptables);
  1934. $indexes = array_keys($LookupTable, $this->table_name);
  1935. if (!empty($indexes)) {
  1936. foreach ($indexes as $index) {
  1937. unset($LookupTable[$index]);
  1938. }
  1939. }
  1940. foreach ($LookupTable as $tablename) {
  1941. $query .= " INNER JOIN $tablename
  1942. on $this->table_name.$this->table_index = $tablename." . $this->tab_name_index[$tablename];
  1943. }
  1944. if (!empty($lookupcolumns)) {
  1945. $query .=" WHERE ";
  1946. $i = 0;
  1947. $columnCount = count($lookupcolumns);
  1948. foreach ($lookupcolumns as $columnname) {
  1949. if (!empty($columnname)) {
  1950. if ($i == 0 || $i == ($columnCount))
  1951. $query .= sprintf("%s = '%s'", $columnname, $value);
  1952. else
  1953. $query .= sprintf(" OR %s = '%s'", $columnname, $value);
  1954. $i++;
  1955. }
  1956. }
  1957. }
  1958. return $query;
  1959. }
  1960. /**
  1961. *
  1962. * @param String $tableName
  1963. * @return String
  1964. */
  1965. public function getJoinClause($tableName) {
  1966. if (strripos($tableName, 'rel') === (strlen($tableName) - 3)) {
  1967. return 'LEFT JOIN';
  1968. } else {
  1969. return 'INNER JOIN';
  1970. }
  1971. }
  1972. /**
  1973. *
  1974. * @param <type> $module
  1975. * @param <type> $user
  1976. * @param <type> $parentRole
  1977. * @param <type> $userGroups
  1978. */
  1979. function getNonAdminAccessQuery($module, $user, $parentRole, $userGroups) {
  1980. $query = $this->getNonAdminUserAccessQuery($user, $parentRole, $userGroups);
  1981. if (!empty($module)) {
  1982. $moduleAccessQuery = $this->getNonAdminModuleAccessQuery($module, $user);
  1983. if (!empty($moduleAccessQuery)) {
  1984. $query .= " UNION $moduleAccessQuery";
  1985. }
  1986. }
  1987. return $query;
  1988. }
  1989. /**
  1990. *
  1991. * @param <type> $user
  1992. * @param <type> $parentRole
  1993. * @param <type> $userGroups
  1994. */
  1995. function getNonAdminUserAccessQuery($user, $parentRole, $userGroups) {
  1996. $query = "(SELECT $user->id as id) UNION (SELECT vtiger_user2role.userid AS userid FROM " .
  1997. "vtiger_user2role INNER JOIN vtiger_users ON vtiger_users.id=vtiger_user2role.userid " .
  1998. "INNER JOIN vtiger_role ON vtiger_role.roleid=vtiger_user2role.roleid WHERE " .
  1999. "vtiger_role.parentrole like '$parentRole::%')";
  2000. if (count($userGroups) > 0) {
  2001. $query .= " UNION (SELECT groupid FROM vtiger_groups where" .
  2002. " groupid in (" . implode(",", $userGroups) . "))";
  2003. }
  2004. return $query;
  2005. }
  2006. /**
  2007. *
  2008. * @param <type> $module
  2009. * @param <type> $user
  2010. */
  2011. function getNonAdminModuleAccessQuery($module, $user) {
  2012. require('user_privileges/sharing_privileges_' . $user->id . '.php');
  2013. $tabId = getTabid($module);
  2014. $sharingRuleInfoVariable = $module . '_share_read_permission';
  2015. $sharingRuleInfo = $$sharingRuleInfoVariable;
  2016. $sharedTabId = null;
  2017. $query = '';
  2018. if (!empty($sharingRuleInfo) && (count($sharingRuleInfo['ROLE']) > 0 ||
  2019. count($sharingRuleInfo['GROUP']) > 0)) {
  2020. $query = " (SELECT shareduserid FROM vtiger_tmp_read_user_sharing_per " .
  2021. "WHERE userid=$user->id AND tabid=$tabId) UNION (SELECT " .
  2022. "vtiger_tmp_read_group_sharing_per.sharedgroupid FROM " .
  2023. "vtiger_tmp_read_group_sharing_per WHERE userid=$user->id AND tabid=$tabId)";
  2024. }
  2025. return $query;
  2026. }
  2027. /**
  2028. *
  2029. * @param <type> $module
  2030. * @param <type> $user
  2031. * @param <type> $parentRole
  2032. * @param <type> $userGroups
  2033. */
  2034. protected function setupTemporaryTable($tableName, $tabId, $user, $parentRole, $userGroups) {
  2035. $module = null;
  2036. if (!empty($tabId)) {
  2037. $module = getTabModuleName($tabId);
  2038. }
  2039. $query = $this->getNonAdminAccessQuery($module, $user, $parentRole, $userGroups);
  2040. $query = "create temporary table IF NOT EXISTS $tableName(id int(11) primary key) ignore " .
  2041. $query;
  2042. $db = PearDatabase::getInstance();
  2043. $result = $db->pquery($query, array());
  2044. if (is_object($result)) {
  2045. return true;
  2046. }
  2047. return false;
  2048. }
  2049. /**
  2050. *
  2051. * @param String $module - module name for which query needs to be generated.
  2052. * @param Users $user - user for which query needs to be generated.
  2053. * @return String Access control Query for the user.
  2054. */
  2055. function getNonAdminAccessControlQuery($module, $user, $scope = '') {
  2056. require('user_privileges/user_privileges_' . $user->id . '.php');
  2057. require('user_privileges/sharing_privileges_' . $user->id . '.php');
  2058. $query = ' ';
  2059. $tabId = getTabid($module);
  2060. if ($is_admin == false && $profileGlobalPermission[1] == 1 && $profileGlobalPermission[2]
  2061. == 1 && $defaultOrgSharingPermission[$tabId] == 3) {
  2062. $tableName = 'vt_tmp_u' . $user->id;
  2063. $sharingRuleInfoVariable = $module . '_share_read_permission';
  2064. $sharingRuleInfo = $$sharingRuleInfoVariable;
  2065. $sharedTabId = null;
  2066. if (!empty($sharingRuleInfo) && (count($sharingRuleInfo['ROLE']) > 0 ||
  2067. count($sharingRuleInfo['GROUP']) > 0)) {
  2068. $tableName = $tableName . '_t' . $tabId;
  2069. $sharedTabId = $tabId;
  2070. } elseif ($module == 'Calendar' || !empty($scope)) {
  2071. $tableName .= '_t' . $tabId;
  2072. }
  2073. $this->setupTemporaryTable($tableName, $sharedTabId, $user, $current_user_parent_role_seq, $current_user_groups);
  2074. $query = " INNER JOIN $tableName $tableName$scope ON $tableName$scope.id = " .
  2075. "vtiger_crmentity$scope.smownerid ";
  2076. }
  2077. return $query;
  2078. }
  2079. public function listQueryNonAdminChange($query, $scope = '') {
  2080. //make the module base table as left hand side table for the joins,
  2081. //as mysql query optimizer puts crmentity on the left side and considerably slow down
  2082. $query = preg_replace('/\s+/', ' ', $query);
  2083. if (strripos($query, ' WHERE ') !== false) {
  2084. vtlib_setup_modulevars($module, $this);
  2085. $query = str_ireplace(' where ', " WHERE $this->table_name.$this->table_index > 0 AND ", $query);
  2086. }
  2087. return $query;
  2088. }
  2089. /*
  2090. * Function to get the relation tables for related modules
  2091. * @param String $secmodule - $secmodule secondary module name
  2092. * @return Array returns the array with table names and fieldnames storing relations
  2093. * between module and this module
  2094. */
  2095. function setRelationTables($secmodule) {
  2096. $rel_tables = array(
  2097. "Documents" => array("vtiger_senotesrel" => array("crmid", "notesid"),
  2098. $this->table_name => $this->table_index),
  2099. );
  2100. return $rel_tables[$secmodule];
  2101. }
  2102. /**
  2103. * Function to clear the fields which needs to be saved only once during the Save of the record
  2104. * For eg: Comments of HelpDesk should be saved only once during one save of a Trouble Ticket
  2105. */
  2106. function clearSingletonSaveFields() {
  2107. return;
  2108. }
  2109. /**
  2110. * Function to track when a new record is linked to a given record
  2111. */
  2112. function trackLinkedInfo($module, $crmid, $with_module, $with_crmid) {
  2113. global $current_user;
  2114. $adb = PearDatabase::getInstance();
  2115. $currentTime = date('Y-m-d H:i:s');
  2116. $adb->pquery('UPDATE vtiger_crmentity SET modifiedtime = ?, modifiedby = ? WHERE crmid = ?', array($currentTime, $current_user->id, $crmid));
  2117. // @Note: We should extend this to event handlers
  2118. if(vtlib_isModuleActive('ModTracker')) {
  2119. // Track the time the relation was added
  2120. require_once 'modules/ModTracker/ModTracker.php';
  2121. ModTracker::linkRelation($module, $crmid, $with_module, $with_crmid);
  2122. }
  2123. }
  2124. /**
  2125. * Function to get sort order
  2126. * return string $sorder - sortorder string either 'ASC' or 'DESC'
  2127. */
  2128. function getSortOrder() {
  2129. global $log,$currentModule;
  2130. $log->debug("Entering getSortOrder() method ...");
  2131. if (isset($_REQUEST['sorder']))
  2132. $sorder = $this->db->sql_escape_string($_REQUEST['sorder']);
  2133. else
  2134. $sorder = (($_SESSION[$currentModule . '_Sort_Order'] != '') ? ($_SESSION[$currentModule . '_Sort_Order']) : ($this->default_sort_order));
  2135. $log->debug("Exiting getSortOrder() method ...");
  2136. return $sorder;
  2137. }
  2138. /**
  2139. * Function to get order by
  2140. * return string $order_by - fieldname(eg: 'accountname')
  2141. */
  2142. function getOrderBy() {
  2143. global $log, $currentModule;
  2144. $log->debug("Entering getOrderBy() method ...");
  2145. $use_default_order_by = '';
  2146. if (PerformancePrefs::getBoolean('LISTVIEW_DEFAULT_SORTING', true)) {
  2147. $use_default_order_by = $this->default_order_by;
  2148. }
  2149. if (isset($_REQUEST['order_by']))
  2150. $order_by = $this->db->sql_escape_string($_REQUEST['order_by']);
  2151. else
  2152. $order_by = (($_SESSION[$currentModule.'_Order_By'] != '') ? ($_SESSION[$currentModule.'_Order_By']) : ($use_default_order_by));
  2153. $log->debug("Exiting getOrderBy method ...");
  2154. return $order_by;
  2155. }
  2156. // Mike Crowe Mod --------------------------------------------------------
  2157. /**
  2158. * Function to Listview buttons
  2159. * return array $list_buttons - for module (eg: 'Accounts')
  2160. */
  2161. function getListButtons($app_strings) {
  2162. $list_buttons = Array();
  2163. if (isPermitted($currentModule, 'Delete', '') == 'yes')
  2164. $list_buttons['del'] = $app_strings[LBL_MASS_DELETE];
  2165. if (isPermitted($currentModule, 'EditView', '') == 'yes') {
  2166. $list_buttons['mass_edit'] = $app_strings[LBL_MASS_EDIT];
  2167. // Mass Edit could be used to change the owner as well!
  2168. //$list_buttons['c_owner'] = $app_strings[LBL_CHANGE_OWNER];
  2169. }
  2170. return $list_buttons;
  2171. }
  2172. /**
  2173. * Function to track when a record is unlinked to a given record
  2174. */
  2175. function trackUnLinkedInfo($module, $crmid, $with_module, $with_crmid) {
  2176. global $current_user;
  2177. $adb = PearDatabase::getInstance();
  2178. $currentTime = date('Y-m-d H:i:s');
  2179. $adb->pquery('UPDATE vtiger_crmentity SET modifiedtime = ?, modifiedby = ? WHERE crmid = ?', array($currentTime, $current_user->id, $crmid));
  2180. // @Note: We should extend this to event handlers
  2181. if(vtlib_isModuleActive('ModTracker')) {
  2182. //Track the time the relation was deleted
  2183. require_once 'modules/ModTracker/ModTracker.php';
  2184. ModTracker::unLinkRelation($module, $crmid, $with_module, $with_crmid);
  2185. }
  2186. }
  2187. /**
  2188. * Function which will give the basic query to find duplicates
  2189. * @param <String> $module
  2190. * @param <String> $tableColumns
  2191. * @param <String> $mergeFields
  2192. * @param <String> $select_cols
  2193. * @return string
  2194. */
  2195. // Note : remove getDuplicatesQuery API once vtiger5 code is removed
  2196. function getQueryForDuplicates($module, $tableColumns, $selectedColumns = '') {
  2197. if(is_array($tableColumns)) {
  2198. $tableColumnsString = implode(',', $tableColumns);
  2199. }
  2200. $selectClause = "SELECT " . $this->table_name . "." . $this->table_index . " AS recordid," . $tableColumnsString;
  2201. // Select Custom Field Table Columns if present
  2202. if (isset($this->customFieldTable))
  2203. $query .= ", " . $this->customFieldTable[0] . ".* ";
  2204. $fromClause = " FROM $this->table_name";
  2205. $fromClause .= " INNER JOIN vtiger_crmentity ON vtiger_crmentity.crmid = $this->table_name.$this->table_index";
  2206. if($this->tab_name) {
  2207. foreach($this->tab_name as $tableName) {
  2208. if($tableName != 'vtiger_crmentity' && $tableName != $this->table_name) {
  2209. if($this->tab_name_index[$tableName]) {
  2210. $fromClause .= " INNER JOIN " . $tableName . " ON " . $tableName . '.' . $this->tab_name_index[$tableName] .
  2211. " = $this->table_name.$this->table_index";
  2212. }
  2213. }
  2214. }
  2215. }
  2216. $fromClause .= " LEFT JOIN vtiger_users ON vtiger_users.id = vtiger_crmentity.smownerid
  2217. LEFT JOIN vtiger_groups ON vtiger_groups.groupid = vtiger_crmentity.smownerid";
  2218. $whereClause = " WHERE vtiger_crmentity.deleted = 0";
  2219. $whereClause .= $this->getListViewSecurityParameter($module);
  2220. if (isset($selectedColumns) && trim($selectedColumns) != '') {
  2221. $sub_query = "SELECT $selectedColumns FROM $this->table_name AS t " .
  2222. " INNER JOIN vtiger_crmentity AS crm ON crm.crmid = t." . $this->table_index;
  2223. // Consider custom table join as well.
  2224. if (isset($this->customFieldTable)) {
  2225. $sub_query .= " LEFT JOIN " . $this->customFieldTable[0] . " tcf ON tcf." . $this->customFieldTable[1] . " = t.$this->table_index";
  2226. }
  2227. $sub_query .= " WHERE crm.deleted=0 GROUP BY $selectedColumns HAVING COUNT(*)>1";
  2228. } else {
  2229. $sub_query = "SELECT $tableColumnsString $fromClause $whereClause GROUP BY $tableColumnsString HAVING COUNT(*)>1";
  2230. }
  2231. $i = 1;
  2232. foreach($tableColumns as $tableColumn){
  2233. $tableInfo = explode('.', $tableColumn);
  2234. $duplicateCheckClause .= " ifnull($tableColumn,'null') = ifnull(temp.$tableInfo[1],'null')";
  2235. if (count($tableColumns) != $i++) $duplicateCheckClause .= " AND ";
  2236. }
  2237. $query = $selectClause . $fromClause .
  2238. " LEFT JOIN vtiger_users_last_import ON vtiger_users_last_import.bean_id=" . $this->table_name . "." . $this->table_index .
  2239. " INNER JOIN (" . $sub_query . ") AS temp ON " . $duplicateCheckClause .
  2240. $whereClause .
  2241. " ORDER BY $tableColumnsString," . $this->table_name . "." . $this->table_index . " ASC";
  2242. return $query;
  2243. }
  2244. }
  2245. ?>