PageRenderTime 34ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/data/CRMEntity.php

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