PageRenderTime 65ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 1ms

/data/CRMEntity.php

https://bitbucket.org/thomashii/vtigercrm-6-for-postgresql
PHP | 2631 lines | 1832 code | 386 blank | 413 comment | 554 complexity | 5663782404bc175a23fa27fc38cd02d8 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-3.0, LGPL-2.1, GPL-2.0, GPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /*********************************************************************************
  3. * The contents of this file are subject to the SugarCRM Public License Version 1.1.2
  4. * ("License"); You may not use this file except in compliance with the
  5. * License. You may obtain a copy of the License at http://www.sugarcrm.com/SPL
  6. * Software distributed under the License is distributed on an "AS IS" basis,
  7. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
  8. * the specific language governing rights and limitations under the License.
  9. * The Original Code is: SugarCRM Open Source
  10. * The Initial Developer of the Original Code is SugarCRM, Inc.
  11. * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.;
  12. * All Rights Reserved.
  13. * Contributor(s): ______________________________________.
  14. ********************************************************************************/
  15. /*********************************************************************************
  16. * $Header: /advent/projects/wesat/vtiger_crm/vtigercrm/data/CRMEntity.php,v 1.16 2005/04/29 04:21:31 mickie Exp $
  17. * Description: Defines the base class for all data entities used throughout the
  18. * application. The base class including its methods and variables is designed to
  19. * be overloaded with module-specific methods and variables particular to the
  20. * module's base entity class.
  21. ********************************************************************************/
  22. include_once('config.php');
  23. require_once('include/logging.php');
  24. require_once('data/Tracker.php');
  25. require_once('include/utils/utils.php');
  26. require_once('include/utils/UserInfoUtil.php');
  27. require_once("include/Zend/Json.php");
  28. class CRMEntity {
  29. var $ownedby;
  30. /**
  31. * Detect if we are in bulk save mode, where some features can be turned-off
  32. * to improve performance.
  33. */
  34. static function isBulkSaveMode() {
  35. global $VTIGER_BULK_SAVE_MODE;
  36. if (isset($VTIGER_BULK_SAVE_MODE) && $VTIGER_BULK_SAVE_MODE) {
  37. return true;
  38. }
  39. return false;
  40. }
  41. static function getInstance($module) {
  42. $modName = $module;
  43. if ($module == 'Calendar' || $module == 'Events') {
  44. $module = 'Calendar';
  45. $modName = 'Activity';
  46. }
  47. // File access security check
  48. if (!class_exists($modName)) {
  49. checkFileAccessForInclusion("modules/$module/$modName.php");
  50. require_once("modules/$module/$modName.php");
  51. }
  52. $focus = new $modName();
  53. return $focus;
  54. }
  55. function saveentity($module, $fileid = '') {
  56. global $current_user, $adb; //$adb added by raju for mass mailing
  57. $insertion_mode = $this->mode;
  58. $columnFields = $this->column_fields;
  59. $anyValue = false;
  60. foreach ($columnFields as $value) {
  61. if(!empty($value)) {
  62. $anyValue = true;
  63. break;
  64. }
  65. }
  66. if(!$anyValue) {
  67. die("<center>" .getTranslatedString('LBL_MANDATORY_FIELD_MISSING')."</center>");
  68. }
  69. $this->db->println("TRANS saveentity starts $module");
  70. $this->db->startTransaction();
  71. foreach ($this->tab_name as $table_name) {
  72. if ($table_name == "vtiger_crmentity") {
  73. $this->insertIntoCrmEntity($module, $fileid);
  74. } else {
  75. $this->insertIntoEntityTable($table_name, $module, $fileid);
  76. }
  77. }
  78. //Calling the Module specific save code
  79. $this->save_module($module);
  80. $this->db->completeTransaction();
  81. $this->db->println("TRANS saveentity ends");
  82. // vtlib customization: Hook provide to enable generic module relation.
  83. if ($_REQUEST['createmode'] == 'link') {
  84. $for_module = vtlib_purify($_REQUEST['return_module']);
  85. $for_crmid = vtlib_purify($_REQUEST['return_id']);
  86. $with_module = $module;
  87. $with_crmid = $this->id;
  88. $on_focus = CRMEntity::getInstance($for_module);
  89. if ($for_module && $for_crmid && $with_module && $with_crmid) {
  90. relateEntities($on_focus, $for_module, $for_crmid, $with_module, $with_crmid);
  91. }
  92. }
  93. // END
  94. }
  95. /**
  96. * This function is used to upload the attachment in the server and save that attachment information in db.
  97. * @param int $id - entity id to which the file to be uploaded
  98. * @param string $module - the current module name
  99. * @param array $file_details - array which contains the file information(name, type, size, tmp_name and error)
  100. * return void
  101. */
  102. function uploadAndSaveFile($id, $module, $file_details) {
  103. global $log;
  104. $log->debug("Entering into uploadAndSaveFile($id,$module,$file_details) method.");
  105. global $adb, $current_user;
  106. global $upload_badext;
  107. $date_var = date("Y-m-d H:i:s");
  108. //to get the owner id
  109. $ownerid = $this->column_fields['assigned_user_id'];
  110. if (!isset($ownerid) || $ownerid == '')
  111. $ownerid = $current_user->id;
  112. if (isset($file_details['original_name']) && $file_details['original_name'] != null) {
  113. $file_name = $file_details['original_name'];
  114. } else {
  115. $file_name = $file_details['name'];
  116. }
  117. $binFile = sanitizeUploadFileName($file_name, $upload_badext);
  118. $current_id = $adb->getUniqueID("vtiger_crmentity");
  119. $filename = ltrim(basename(" " . $binFile)); //allowed filename like UTF-8 characters
  120. $filetype = $file_details['type'];
  121. $filesize = $file_details['size'];
  122. $filetmp_name = $file_details['tmp_name'];
  123. //get the file path inwhich folder we want to upload the file
  124. $upload_file_path = decideFilePath();
  125. //upload the file in server
  126. $upload_status = move_uploaded_file($filetmp_name, $upload_file_path . $current_id . "_" . $binFile);
  127. $save_file = 'true';
  128. //only images are allowed for these modules
  129. if ($module == 'Contacts' || $module == 'Products') {
  130. $save_file = validateImageFile($file_details);
  131. }
  132. if ($save_file == 'true' && $upload_status == 'true') {
  133. //This is only to update the attached filename in the vtiger_notes vtiger_table for the Notes module
  134. if ($module == 'Contacts' || $module == 'Products') {
  135. $sql1 = "insert into vtiger_crmentity (crmid,smcreatorid,smownerid,setype,description,createdtime,modifiedtime) values(?, ?, ?, ?, ?, ?, ?)";
  136. $params1 = array($current_id, $current_user->id, $ownerid, $module . " Image", $this->column_fields['description'], $adb->formatDate($date_var, true), $adb->formatDate($date_var, true));
  137. } else {
  138. $sql1 = "insert into vtiger_crmentity (crmid,smcreatorid,smownerid,setype,description,createdtime,modifiedtime) values(?, ?, ?, ?, ?, ?, ?)";
  139. $params1 = array($current_id, $current_user->id, $ownerid, $module . " Attachment", $this->column_fields['description'], $adb->formatDate($date_var, true), $adb->formatDate($date_var, true));
  140. }
  141. $adb->pquery($sql1, $params1);
  142. $sql2 = "insert into vtiger_attachments(attachmentsid, name, description, type, path) values(?, ?, ?, ?, ?)";
  143. $params2 = array($current_id, $filename, $this->column_fields['description'], $filetype, $upload_file_path);
  144. $result = $adb->pquery($sql2, $params2);
  145. if ($_REQUEST['mode'] == 'edit') {
  146. if ($id != '' && vtlib_purify($_REQUEST['fileid']) != '') {
  147. $delquery = 'delete from vtiger_seattachmentsrel where crmid = ? and attachmentsid = ?';
  148. $delparams = array($id, vtlib_purify($_REQUEST['fileid']));
  149. $adb->pquery($delquery, $delparams);
  150. }
  151. }
  152. if ($module == 'Documents') {
  153. $query = "delete from vtiger_seattachmentsrel where crmid = ?";
  154. $qparams = array($id);
  155. $adb->pquery($query, $qparams);
  156. }
  157. if ($module == 'Contacts') {
  158. $att_sql = "select vtiger_seattachmentsrel.attachmentsid from vtiger_seattachmentsrel inner join vtiger_crmentity on vtiger_crmentity.crmid=vtiger_seattachmentsrel.attachmentsid where vtiger_crmentity.setype='Contacts Image' and vtiger_seattachmentsrel.crmid=?";
  159. $res = $adb->pquery($att_sql, array($id));
  160. $attachmentsid = $adb->query_result($res, 0, 'attachmentsid');
  161. if ($attachmentsid != '') {
  162. $delquery = 'delete from vtiger_seattachmentsrel where crmid=? and attachmentsid=?';
  163. $adb->pquery($delquery, array($id, $attachmentsid));
  164. $crm_delquery = "delete from vtiger_crmentity where crmid=?";
  165. $adb->pquery($crm_delquery, array($attachmentsid));
  166. $sql5 = 'insert into vtiger_seattachmentsrel values(?,?)';
  167. $adb->pquery($sql5, array($id, $current_id));
  168. } else {
  169. $sql3 = 'insert into vtiger_seattachmentsrel values(?,?)';
  170. $adb->pquery($sql3, array($id, $current_id));
  171. }
  172. } else {
  173. $sql3 = 'insert into vtiger_seattachmentsrel values(?,?)';
  174. $adb->pquery($sql3, array($id, $current_id));
  175. }
  176. return true;
  177. } else {
  178. $log->debug("Skip the save attachment process.");
  179. return false;
  180. }
  181. }
  182. /** Function to insert values in the vtiger_crmentity for the specified module
  183. * @param $module -- module:: Type varchar
  184. */
  185. function insertIntoCrmEntity($module, $fileid = '') {
  186. global $adb;
  187. global $current_user;
  188. global $log;
  189. if ($fileid != '') {
  190. $this->id = $fileid;
  191. $this->mode = 'edit';
  192. }
  193. $date_var = date("Y-m-d H:i:s");
  194. $ownerid = $this->column_fields['assigned_user_id'];
  195. if(empty($ownerid)) {
  196. $ownerid = $current_user->id;
  197. }
  198. if ($module == 'Events') {
  199. $module = 'Calendar';
  200. }
  201. if ($this->mode == 'edit') {
  202. $description_val = from_html($this->column_fields['description'], ($insertion_mode == 'edit') ? true : false);
  203. checkFileAccessForInclusion('user_privileges/user_privileges_' . $current_user->id . '.php');
  204. require('user_privileges/user_privileges_' . $current_user->id . '.php');
  205. $tabid = getTabid($module);
  206. if ($is_admin == true || $profileGlobalPermission[1] == 0 || $profileGlobalPermission[2] == 0) {
  207. $sql = "update vtiger_crmentity set smownerid=?,modifiedby=?,description=?, modifiedtime=? where crmid=?";
  208. $params = array($ownerid, $current_user->id, $description_val, $adb->formatDate($date_var, true), $this->id);
  209. } else {
  210. $profileList = getCurrentUserProfileList();
  211. $perm_qry = "SELECT columnname FROM vtiger_field INNER JOIN vtiger_profile2field ON vtiger_profile2field.fieldid = vtiger_field.fieldid INNER JOIN vtiger_def_org_field ON vtiger_def_org_field.fieldid = vtiger_field.fieldid WHERE vtiger_field.tabid = ? AND vtiger_profile2field.visible = 0 AND vtiger_profile2field.readonly = 0 AND vtiger_profile2field.profileid IN (" . generateQuestionMarks($profileList) . ") AND vtiger_def_org_field.visible = 0 and vtiger_field.tablename='vtiger_crmentity' and vtiger_field.displaytype in (1,3) and vtiger_field.presence in (0,2);";
  212. $perm_result = $adb->pquery($perm_qry, array($tabid, $profileList));
  213. $perm_rows = $adb->num_rows($perm_result);
  214. for ($i = 0; $i < $perm_rows; $i++) {
  215. $columname[] = $adb->query_result($perm_result, $i, "columnname");
  216. }
  217. if (is_array($columname) && in_array("description", $columname)) {
  218. $sql = "update vtiger_crmentity set smownerid=?,modifiedby=?,description=?, modifiedtime=? where crmid=?";
  219. $params = array($ownerid, $current_user->id, $description_val, $adb->formatDate($date_var, true), $this->id);
  220. } else {
  221. $sql = "update vtiger_crmentity set smownerid=?,modifiedby=?, modifiedtime=? where crmid=?";
  222. $params = array($ownerid, $current_user->id, $adb->formatDate($date_var, true), $this->id);
  223. }
  224. }
  225. $adb->pquery($sql, $params);
  226. } else {
  227. //if this is the create mode and the group allocation is chosen, then do the following
  228. $current_id = $adb->getUniqueID("vtiger_crmentity");
  229. $_REQUEST['currentid'] = $current_id;
  230. if ($current_user->id == '')
  231. $current_user->id = 0;
  232. // Customization
  233. $created_date_var = $adb->formatDate($date_var, true);
  234. $modified_date_var = $adb->formatDate($date_var, true);
  235. // Preserve the timestamp
  236. if (self::isBulkSaveMode()) {
  237. if (!empty($this->column_fields['createdtime']))
  238. $created_date_var = $adb->formatDate($this->column_fields['createdtime'], true);
  239. //NOTE : modifiedtime ignored to support vtws_sync API track changes.
  240. }
  241. // END
  242. $description_val = from_html($this->column_fields['description'], ($insertion_mode == 'edit') ? true : false);
  243. $sql = "insert into vtiger_crmentity (crmid,smcreatorid,smownerid,setype,description,modifiedby,createdtime,modifiedtime) values(?,?,?,?,?,?,?,?)";
  244. $params = array($current_id, $current_user->id, $ownerid, $module, $description_val, $current_user->id, $created_date_var, $modified_date_var);
  245. $adb->pquery($sql, $params);
  246. $this->id = $current_id;
  247. }
  248. }
  249. // Function which returns the value based on result type (array / ADODB ResultSet)
  250. private function resolve_query_result_value($result, $index, $columnname) {
  251. global $adb;
  252. if (is_array($result))
  253. return $result[$index][$columnname];
  254. else
  255. return $adb->query_result($result, $index, $columnname);
  256. }
  257. /** Function to insert values in the specifed table for the specified module
  258. * @param $table_name -- table name:: Type varchar
  259. * @param $module -- module:: Type varchar
  260. */
  261. function insertIntoEntityTable($table_name, $module, $fileid = '') {
  262. global $log;
  263. global $current_user, $app_strings;
  264. $log->info("function insertIntoEntityTable " . $module . ' vtiger_table name ' . $table_name);
  265. global $adb;
  266. $insertion_mode = $this->mode;
  267. //Checkin whether an entry is already is present in the vtiger_table to update
  268. if ($insertion_mode == 'edit') {
  269. $tablekey = $this->tab_name_index[$table_name];
  270. // Make selection on the primary key of the module table to check.
  271. $check_query = "select $tablekey from $table_name where $tablekey=?";
  272. $check_result = $adb->pquery($check_query, array($this->id));
  273. $num_rows = $adb->num_rows($check_result);
  274. if ($num_rows <= 0) {
  275. $insertion_mode = '';
  276. }
  277. }
  278. $tabid = getTabid($module);
  279. if ($module == 'Calendar' && $this->column_fields["activitytype"] != null && $this->column_fields["activitytype"] != 'Task') {
  280. $tabid = getTabid('Events');
  281. }
  282. if ($insertion_mode == 'edit') {
  283. $update = array();
  284. $update_params = array();
  285. checkFileAccessForInclusion('user_privileges/user_privileges_' . $current_user->id . '.php');
  286. require('user_privileges/user_privileges_' . $current_user->id . '.php');
  287. if ($is_admin == true || $profileGlobalPermission[1] == 0 || $profileGlobalPermission[2] == 0) {
  288. $sql = "select * from vtiger_field where tabid in (" . generateQuestionMarks($tabid) . ") and tablename=? and displaytype in (1,3) and presence in (0,2) group by columnname";
  289. $params = array($tabid, $table_name);
  290. } else {
  291. $profileList = getCurrentUserProfileList();
  292. if (count($profileList) > 0) {
  293. $sql = "SELECT *
  294. FROM vtiger_field
  295. INNER JOIN vtiger_profile2field
  296. ON vtiger_profile2field.fieldid = vtiger_field.fieldid
  297. INNER JOIN vtiger_def_org_field
  298. ON vtiger_def_org_field.fieldid = vtiger_field.fieldid
  299. WHERE vtiger_field.tabid = ?
  300. AND vtiger_profile2field.visible = 0 AND vtiger_profile2field.readonly = 0
  301. AND vtiger_profile2field.profileid IN (" . generateQuestionMarks($profileList) . ")
  302. AND vtiger_def_org_field.visible = 0 and vtiger_field.tablename=? and vtiger_field.displaytype in (1,3) and vtiger_field.presence in (0,2) group by columnname";
  303. $params = array($tabid, $profileList, $table_name);
  304. } else {
  305. $sql = "SELECT *
  306. FROM vtiger_field
  307. INNER JOIN vtiger_profile2field
  308. ON vtiger_profile2field.fieldid = vtiger_field.fieldid
  309. INNER JOIN vtiger_def_org_field
  310. ON vtiger_def_org_field.fieldid = vtiger_field.fieldid
  311. WHERE vtiger_field.tabid = ?
  312. AND vtiger_profile2field.visible = 0 AND vtiger_profile2field.readonly = 0
  313. AND vtiger_def_org_field.visible = 0 and vtiger_field.tablename=? and vtiger_field.displaytype in (1,3) and vtiger_field.presence in (0,2) group by columnname";
  314. $params = array($tabid, $table_name);
  315. }
  316. }
  317. } else {
  318. $table_index_column = $this->tab_name_index[$table_name];
  319. if ($table_index_column == 'id' && $table_name == 'vtiger_users') {
  320. $currentuser_id = $adb->getUniqueID("vtiger_users");
  321. $this->id = $currentuser_id;
  322. }
  323. $column = array($table_index_column);
  324. $value = array($this->id);
  325. $sql = "select * from vtiger_field where tabid=? and tablename=? and displaytype in (1,3,4) and vtiger_field.presence in (0,2)";
  326. $params = array($tabid, $table_name);
  327. }
  328. // Attempt to re-use the quer-result to avoid reading for every save operation
  329. // TODO Need careful analysis on impact ... MEMORY requirement might be more
  330. static $_privatecache = array();
  331. $cachekey = "{$insertion_mode}-" . implode(',', $params);
  332. if (!isset($_privatecache[$cachekey])) {
  333. $result = $adb->pquery($sql, $params);
  334. $noofrows = $adb->num_rows($result);
  335. if (CRMEntity::isBulkSaveMode()) {
  336. $cacheresult = array();
  337. for ($i = 0; $i < $noofrows; ++$i) {
  338. $cacheresult[] = $adb->fetch_array($result);
  339. }
  340. $_privatecache[$cachekey] = $cacheresult;
  341. }
  342. } else { // Useful when doing bulk save
  343. $result = $_privatecache[$cachekey];
  344. $noofrows = count($result);
  345. }
  346. for ($i = 0; $i < $noofrows; $i++) {
  347. $fieldname = $this->resolve_query_result_value($result, $i, "fieldname");
  348. $columname = $this->resolve_query_result_value($result, $i, "columnname");
  349. $uitype = $this->resolve_query_result_value($result, $i, "uitype");
  350. $generatedtype = $this->resolve_query_result_value($result, $i, "generatedtype");
  351. $typeofdata = $this->resolve_query_result_value($result, $i, "typeofdata");
  352. $typeofdata_array = explode("~", $typeofdata);
  353. $datatype = $typeofdata_array[0];
  354. $ajaxSave = false;
  355. if (($_REQUEST['file'] == 'DetailViewAjax' && $_REQUEST['ajxaction'] == 'DETAILVIEW'
  356. && isset($_REQUEST["fldName"]) && $_REQUEST["fldName"] != $fieldname)
  357. || ($_REQUEST['action'] == 'MassEditSave' && !isset($_REQUEST[$fieldname."_mass_edit_check"]))) {
  358. $ajaxSave = true;
  359. }
  360. if ($uitype == 4 && $insertion_mode != 'edit') {
  361. $fldvalue = '';
  362. // Bulk Save Mode: Avoid generation of module sequence number, take care later.
  363. if (!CRMEntity::isBulkSaveMode())
  364. $fldvalue = $this->setModuleSeqNumber("increment", $module);
  365. $this->column_fields[$fieldname] = $fldvalue;
  366. }
  367. if (isset($this->column_fields[$fieldname])) {
  368. if ($uitype == 56) {
  369. if ($this->column_fields[$fieldname] == 'on' || $this->column_fields[$fieldname] == 1) {
  370. $fldvalue = '1';
  371. } else {
  372. $fldvalue = '0';
  373. }
  374. } elseif ($uitype == 15 || $uitype == 16) {
  375. if ($this->column_fields[$fieldname] == $app_strings['LBL_NOT_ACCESSIBLE']) {
  376. //If the value in the request is Not Accessible for a picklist, the existing value will be replaced instead of Not Accessible value.
  377. $sql = "select $columname from $table_name where " . $this->tab_name_index[$table_name] . "=?";
  378. $res = $adb->pquery($sql, array($this->id));
  379. $pick_val = $adb->query_result($res, 0, $columname);
  380. $fldvalue = $pick_val;
  381. } else {
  382. $fldvalue = $this->column_fields[$fieldname];
  383. }
  384. } elseif ($uitype == 33) {
  385. if (is_array($this->column_fields[$fieldname])) {
  386. $field_list = implode(' |##| ', $this->column_fields[$fieldname]);
  387. } else {
  388. $field_list = $this->column_fields[$fieldname];
  389. }
  390. $fldvalue = $field_list;
  391. } elseif ($uitype == 5 || $uitype == 6 || $uitype == 23) {
  392. //Added to avoid function call getDBInsertDateValue in ajax save
  393. if (isset($current_user->date_format) && !$ajaxSave) {
  394. $fldvalue = getValidDBInsertDateValue($this->column_fields[$fieldname]);
  395. } else {
  396. $fldvalue = $this->column_fields[$fieldname];
  397. }
  398. } elseif ($uitype == 7) {
  399. //strip out the spaces and commas in numbers if given ie., in amounts there may be ,
  400. $fldvalue = str_replace(",", "", $this->column_fields[$fieldname]); //trim($this->column_fields[$fieldname],",");
  401. } elseif ($uitype == 26) {
  402. if (empty($this->column_fields[$fieldname])) {
  403. $fldvalue = 1; //the documents will stored in default folder
  404. } else {
  405. $fldvalue = $this->column_fields[$fieldname];
  406. }
  407. } elseif ($uitype == 28) {
  408. if ($this->column_fields[$fieldname] == null) {
  409. $fileQuery = $adb->pquery("SELECT filename from vtiger_notes WHERE notesid = ?", array($this->id));
  410. $fldvalue = null;
  411. if (isset($fileQuery)) {
  412. $rowCount = $adb->num_rows($fileQuery);
  413. if ($rowCount > 0) {
  414. $fldvalue = $adb->query_result($fileQuery, 0, 'filename');
  415. }
  416. }
  417. } else {
  418. $fldvalue = $this->column_fields[$fieldname];
  419. }
  420. } elseif ($uitype == 8) {
  421. $this->column_fields[$fieldname] = rtrim($this->column_fields[$fieldname], ',');
  422. $ids = explode(',', $this->column_fields[$fieldname]);
  423. $json = new Zend_Json();
  424. $fldvalue = $json->encode($ids);
  425. } elseif ($uitype == 12) {
  426. // Bulk Sae Mode: Consider the FROM email address as specified, if not lookup
  427. $fldvalue = $this->column_fields[$fieldname];
  428. if (empty($fldvalue)) {
  429. $query = "SELECT email1 FROM vtiger_users WHERE id = ?";
  430. $res = $adb->pquery($query, array($current_user->id));
  431. $rows = $adb->num_rows($res);
  432. if ($rows > 0) {
  433. $fldvalue = $adb->query_result($res, 0, 'email1');
  434. }
  435. }
  436. // END
  437. } elseif ($uitype == 72 && !$ajaxSave) {
  438. // Some of the currency fields like Unit Price, Totoal , Sub-total - doesn't need currency conversion during save
  439. $fldvalue = CurrencyField::convertToDBFormat($this->column_fields[$fieldname], null, true);
  440. } elseif ($uitype == 71 && !$ajaxSave) {
  441. $fldvalue = CurrencyField::convertToDBFormat($this->column_fields[$fieldname]);
  442. } else {
  443. $fldvalue = $this->column_fields[$fieldname];
  444. }
  445. if ($uitype != 33 && $uitype != 8)
  446. $fldvalue = from_html($fldvalue, ($insertion_mode == 'edit') ? true : false);
  447. }
  448. else {
  449. $fldvalue = '';
  450. }
  451. if ($fldvalue == '') {
  452. $fldvalue = $this->get_column_value($columname, $fldvalue, $fieldname, $uitype, $datatype);
  453. }
  454. if ($insertion_mode == 'edit') {
  455. if ($table_name != 'vtiger_ticketcomments' && $uitype != 4) {
  456. array_push($update, $columname . "=?");
  457. array_push($update_params, $fldvalue);
  458. }
  459. } else {
  460. array_push($column, $columname);
  461. array_push($value, $fldvalue);
  462. }
  463. }
  464. if ($insertion_mode == 'edit') {
  465. if ($module == 'Potentials') {
  466. $dbquery = 'select sales_stage from vtiger_potential where potentialid = ?';
  467. $sales_stage = $adb->query_result($adb->pquery($dbquery, array($this->id)), 0, 'sales_stage');
  468. if ($sales_stage != $_REQUEST['sales_stage'] && $_REQUEST['sales_stage'] != '') {
  469. $date_var = date("Y-m-d H:i:s");
  470. $closingDateField = new DateTimeField($this->column_fields['closingdate']);
  471. $closingdate = ($_REQUEST['ajxaction'] == 'DETAILVIEW') ? $this->column_fields['closingdate'] : $closingDateField->getDBInsertDateValue();
  472. $sql = "insert into vtiger_potstagehistory values(?,?,?,?,?,?,?,?)";
  473. $params = array('', $this->id, $this->column_fields['amount'], decode_html($sales_stage), $this->column_fields['probability'], 0, $adb->formatDate($closingdate, true), $adb->formatDate($date_var, true));
  474. $adb->pquery($sql, $params);
  475. }
  476. } elseif ($module == 'PurchaseOrder' || $module == 'SalesOrder' || $module == 'Quotes' || $module == 'Invoice') {
  477. //added to update the history for PO, SO, Quotes and Invoice
  478. $history_field_array = Array(
  479. "PurchaseOrder" => "postatus",
  480. "SalesOrder" => "sostatus",
  481. "Quotes" => "quotestage",
  482. "Invoice" => "invoicestatus"
  483. );
  484. $inventory_module = $module;
  485. if ($_REQUEST['ajxaction'] == 'DETAILVIEW') {//if we use ajax edit
  486. if ($inventory_module == "PurchaseOrder")
  487. $relatedname = getVendorName($this->column_fields['vendor_id']);
  488. else
  489. $relatedname = getAccountName($this->column_fields['account_id']);
  490. $total = $this->column_fields['hdnGrandTotal'];
  491. }
  492. else {//using edit button and save
  493. if ($inventory_module == "PurchaseOrder")
  494. $relatedname = $_REQUEST["vendor_name"];
  495. else
  496. $relatedname = $_REQUEST["account_name"];
  497. $total = $_REQUEST['total'];
  498. }
  499. if ($this->column_fields["$history_field_array[$inventory_module]"] == $app_strings['LBL_NOT_ACCESSIBLE']) {
  500. //If the value in the request is Not Accessible for a picklist, the existing value will be replaced instead of Not Accessible value.
  501. $his_col = $history_field_array[$inventory_module];
  502. $his_sql = "select $his_col from $this->table_name where " . $this->table_index . "=?";
  503. $his_res = $adb->pquery($his_sql, array($this->id));
  504. $status_value = $adb->query_result($his_res, 0, $his_col);
  505. $stat_value = $status_value;
  506. } else {
  507. $stat_value = $this->column_fields["$history_field_array[$inventory_module]"];
  508. }
  509. $oldvalue = getSingleFieldValue($this->table_name, $history_field_array[$inventory_module], $this->table_index, $this->id);
  510. if ($this->column_fields["$history_field_array[$inventory_module]"] != '' && $oldvalue != $stat_value) {
  511. addInventoryHistory($inventory_module, $this->id, $relatedname, $total, $stat_value);
  512. }
  513. }
  514. //Check done by Don. If update is empty the the query fails
  515. if (count($update) > 0) {
  516. $sql1 = "update $table_name set " . implode(",", $update) . " where " . $this->tab_name_index[$table_name] . "=?";
  517. array_push($update_params, $this->id);
  518. $adb->pquery($sql1, $update_params);
  519. }
  520. } else {
  521. $sql1 = "insert into $table_name(" . implode(",", $column) . ") values(" . generateQuestionMarks($value) . ")";
  522. $adb->pquery($sql1, $value);
  523. }
  524. }
  525. /** Function to delete a record in the specifed table
  526. * @param $table_name -- table name:: Type varchar
  527. * The function will delete a record .The id is obtained from the class variable $this->id and the columnname got from $this->tab_name_index[$table_name]
  528. */
  529. function deleteRelation($table_name) {
  530. global $adb;
  531. $check_query = "select * from $table_name where " . $this->tab_name_index[$table_name] . "=?";
  532. $check_result = $adb->pquery($check_query, array($this->id));
  533. $num_rows = $adb->num_rows($check_result);
  534. if ($num_rows == 1) {
  535. $del_query = "DELETE from $table_name where " . $this->tab_name_index[$table_name] . "=?";
  536. $adb->pquery($del_query, array($this->id));
  537. }
  538. }
  539. /**
  540. * Function returns the column alias for a field
  541. * @param <Array> $fieldinfo - field information
  542. * @return <String> field value
  543. */
  544. protected function createColumnAliasForField($fieldinfo) {
  545. return strtolower($fieldinfo['tablename'] . $fieldinfo['fieldname']);
  546. }
  547. /**
  548. * Retrieve record information of the module
  549. * @param <Integer> $record - crmid of record
  550. * @param <String> $module - module name
  551. */
  552. function retrieve_entity_info($record, $module) {
  553. global $adb, $log, $app_strings;
  554. // INNER JOIN is desirable if all dependent table has entries for the record.
  555. // LEFT JOIN is desired if the dependent tables does not have entry.
  556. $join_type = 'LEFT JOIN';
  557. // Tables which has multiple rows for the same record
  558. // will be skipped in record retrieve - need to be taken care separately.
  559. $multirow_tables = NULL;
  560. if (isset($this->multirow_tables)) {
  561. $multirow_tables = $this->multirow_tables;
  562. } else {
  563. $multirow_tables = array(
  564. 'vtiger_campaignrelstatus',
  565. 'vtiger_attachments',
  566. //'vtiger_inventoryproductrel',
  567. //'vtiger_cntactivityrel',
  568. 'vtiger_email_track'
  569. );
  570. }
  571. // Lookup module field cache
  572. $cachedModuleFields = VTCacheUtils::lookupFieldInfo_Module($module);
  573. if ($cachedModuleFields === false) {
  574. // Pull fields and cache for further use
  575. $tabid = getTabid($module);
  576. $sql0 = "SELECT fieldname, fieldid, fieldlabel, columnname, tablename, uitype, typeofdata,presence FROM vtiger_field WHERE tabid=?";
  577. // NOTE: Need to skip in-active fields which we will be done later.
  578. $result0 = $adb->pquery($sql0, array($tabid));
  579. if ($adb->num_rows($result0)) {
  580. while ($resultrow = $adb->fetch_array($result0)) {
  581. // Update cache
  582. VTCacheUtils::updateFieldInfo(
  583. $tabid, $resultrow['fieldname'], $resultrow['fieldid'], $resultrow['fieldlabel'], $resultrow['columnname'], $resultrow['tablename'], $resultrow['uitype'], $resultrow['typeofdata'], $resultrow['presence']
  584. );
  585. }
  586. // Get only active field information
  587. $cachedModuleFields = VTCacheUtils::lookupFieldInfo_Module($module);
  588. }
  589. }
  590. if ($cachedModuleFields) {
  591. $column_clause = '';
  592. $from_clause = '';
  593. $where_clause = '';
  594. $limit_clause = ' LIMIT 1'; // to eliminate multi-records due to table joins.
  595. $params = array();
  596. $required_tables = $this->tab_name_index; // copies-on-write
  597. foreach ($cachedModuleFields as $fieldinfo) {
  598. if (in_array($fieldinfo['tablename'], $multirow_tables)) {
  599. continue;
  600. }
  601. // Added to avoid picking shipping tax fields for Inventory modules, the shipping tax detail are stored in vtiger_inventoryshippingrel
  602. // table, but in vtiger_field table we have set tablename as vtiger_inventoryproductrel.
  603. if(($module == 'Invoice' || $module == 'Quotes' || $module == 'SalesOrder' || $module == 'PurchaseOrder')
  604. && stripos($fieldinfo['columnname'], 'shtax') !== false) {
  605. continue;
  606. }
  607. // Alias prefixed with tablename+fieldname to avoid duplicate column name across tables
  608. // fieldname are always assumed to be unique for a module
  609. $column_clause .= $fieldinfo['tablename'].'.'.$fieldinfo['columnname'].' AS '.$this->createColumnAliasForField($fieldinfo).',';
  610. }
  611. $column_clause .= 'vtiger_crmentity.deleted';
  612. if (isset($required_tables['vtiger_crmentity'])) {
  613. $from_clause = ' vtiger_crmentity';
  614. unset($required_tables['vtiger_crmentity']);
  615. foreach ($required_tables as $tablename => $tableindex) {
  616. if (in_array($tablename, $multirow_tables)) {
  617. // Avoid multirow table joins.
  618. continue;
  619. }
  620. $from_clause .= sprintf(' %s %s ON %s.%s=%s.%s', $join_type,
  621. $tablename, $tablename, $tableindex, 'vtiger_crmentity', 'crmid');
  622. }
  623. }
  624. $where_clause .= ' vtiger_crmentity.crmid=?';
  625. $params[] = $record;
  626. $sql = sprintf('SELECT %s FROM %s WHERE %s %s', $column_clause, $from_clause, $where_clause, $limit_clause);
  627. $result = $adb->pquery($sql, $params);
  628. if (!$result || $adb->num_rows($result) < 1) {
  629. throw new Exception($app_strings['LBL_RECORD_NOT_FOUND'], -1);
  630. } else {
  631. $resultrow = $adb->query_result_rowdata($result);
  632. if (!empty($resultrow['deleted'])) {
  633. throw new Exception($app_strings['LBL_RECORD_DELETE'], 1);
  634. }
  635. foreach ($cachedModuleFields as $fieldinfo) {
  636. $fieldvalue = '';
  637. $fieldkey = $this->createColumnAliasForField($fieldinfo);
  638. //Note : value is retrieved with a tablename+fieldname as we are using alias while building query
  639. if (isset($resultrow[$fieldkey])) {
  640. $fieldvalue = $resultrow[$fieldkey];
  641. }
  642. $this->column_fields[$fieldinfo['fieldname']] = $fieldvalue;
  643. }
  644. }
  645. }
  646. $this->column_fields['record_id'] = $record;
  647. $this->column_fields['record_module'] = $module;
  648. }
  649. /** Function to saves the values in all the tables mentioned in the class variable $tab_name for the specified module
  650. * @param $module -- module:: Type varchar
  651. */
  652. function save($module_name, $fileid = '') {
  653. global $log;
  654. $log->debug("module name is " . $module_name);
  655. //Event triggering code
  656. require_once("include/events/include.inc");
  657. global $adb;
  658. //In Bulk mode stop triggering events
  659. if(!self::isBulkSaveMode()) {
  660. $em = new VTEventsManager($adb);
  661. // Initialize Event trigger cache
  662. $em->initTriggerCache();
  663. $entityData = VTEntityData::fromCRMEntity($this);
  664. $em->triggerEvent("vtiger.entity.beforesave.modifiable", $entityData);
  665. $em->triggerEvent("vtiger.entity.beforesave", $entityData);
  666. $em->triggerEvent("vtiger.entity.beforesave.final", $entityData);
  667. }
  668. //Event triggering code ends
  669. //GS Save entity being called with the modulename as parameter
  670. $this->saveentity($module_name, $fileid);
  671. if($em) {
  672. //Event triggering code
  673. $em->triggerEvent("vtiger.entity.aftersave", $entityData);
  674. $em->triggerEvent("vtiger.entity.aftersave.final", $entityData);
  675. //Event triggering code ends
  676. }
  677. }
  678. function process_list_query($query, $row_offset, $limit = -1, $max_per_page = -1) {
  679. global $list_max_entries_per_page;
  680. $this->log->debug("process_list_query: " . $query);
  681. if (!empty($limit) && $limit != -1) {
  682. $result = & $this->db->limitQuery($query, $row_offset + 0, $limit, true, "Error retrieving $this->object_name list: ");
  683. } else {
  684. $result = & $this->db->query($query, true, "Error retrieving $this->object_name list: ");
  685. }
  686. $list = Array();
  687. if ($max_per_page == -1) {
  688. $max_per_page = $list_max_entries_per_page;
  689. }
  690. $rows_found = $this->db->getRowCount($result);
  691. $this->log->debug("Found $rows_found " . $this->object_name . "s");
  692. $previous_offset = $row_offset - $max_per_page;
  693. $next_offset = $row_offset + $max_per_page;
  694. if ($rows_found != 0) {
  695. // We have some data.
  696. for ($index = $row_offset, $row = $this->db->fetchByAssoc($result, $index); $row && ($index < $row_offset + $max_per_page || $max_per_page == -99); $index++, $row = $this->db->fetchByAssoc($result, $index)) {
  697. foreach ($this->list_fields as $entry) {
  698. foreach ($entry as $key => $field) { // this will be cycled only once
  699. if (isset($row[$field])) {
  700. $this->column_fields[$this->list_fields_names[$key]] = $row[$field];
  701. $this->log->debug("$this->object_name({$row['id']}): " . $field . " = " . $this->$field);
  702. } else {
  703. $this->column_fields[$this->list_fields_names[$key]] = "";
  704. }
  705. }
  706. }
  707. //$this->db->println("here is the bug");
  708. $list[] = clone($this); //added by Richie to support PHP5
  709. }
  710. }
  711. $response = Array();
  712. $response['list'] = $list;
  713. $response['row_count'] = $rows_found;
  714. $response['next_offset'] = $next_offset;
  715. $response['previous_offset'] = $previous_offset;
  716. return $response;
  717. }
  718. function process_full_list_query($query) {
  719. $this->log->debug("CRMEntity:process_full_list_query");
  720. $result = & $this->db->query($query, false);
  721. //$this->log->debug("CRMEntity:process_full_list_query: result is ".$result);
  722. if ($this->db->getRowCount($result) > 0) {
  723. // $this->db->println("process_full mid=".$this->table_index." mname=".$this->module_name);
  724. // We have some data.
  725. while ($row = $this->db->fetchByAssoc($result)) {
  726. $rowid = $row[$this->table_index];
  727. if (isset($rowid))
  728. $this->retrieve_entity_info($rowid, $this->module_name);
  729. else
  730. $this->db->println("rowid not set unable to retrieve");
  731. //clone function added to resolvoe PHP5 compatibility issue in Dashboards
  732. //If we do not use clone, while using PHP5, the memory address remains fixed but the
  733. //data gets overridden hence all the rows that come in bear the same value. This in turn
  734. //provides a wrong display of the Dashboard graphs. The data is erroneously shown for a specific month alone
  735. //Added by Richie
  736. $list[] = clone($this); //added by Richie to support PHP5
  737. }
  738. }
  739. if (isset($list))
  740. return $list;
  741. else
  742. return null;
  743. }
  744. /** This function should be overridden in each module. It marks an item as deleted.
  745. * If it is not overridden, then marking this type of item is not allowed
  746. * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
  747. * All Rights Reserved..
  748. * Contributor(s): ______________________________________..
  749. */
  750. function mark_deleted($id) {
  751. global $current_user;
  752. $date_var = date("Y-m-d H:i:s");
  753. $query = "UPDATE vtiger_crmentity set deleted=1,modifiedtime=?,modifiedby=? where crmid=?";
  754. $this->db->pquery($query, array($this->db->formatDate($date_var, true), $current_user->id, $id), true, "Error marking record deleted: ");
  755. }
  756. function retrieve_by_string_fields($fields_array, $encode = true) {
  757. $where_clause = $this->get_where($fields_array);
  758. $query = "SELECT * FROM $this->table_name $where_clause";
  759. $this->log->debug("Retrieve $this->object_name: " . $query);
  760. $result = & $this->db->requireSingleResult($query, true, "Retrieving record $where_clause:");
  761. if (empty($result)) {
  762. return null;
  763. }
  764. $row = $this->db->fetchByAssoc($result, -1, $encode);
  765. foreach ($this->column_fields as $field) {
  766. if (isset($row[$field])) {
  767. $this->$field = $row[$field];
  768. }
  769. }
  770. return $this;
  771. }
  772. // this method is called during an import before inserting a bean
  773. // define an associative array called $special_fields
  774. // the keys are user defined, and don't directly map to the bean's vtiger_fields
  775. // the value is the method name within that bean that will do extra
  776. // processing for that vtiger_field. example: 'full_name'=>'get_names_from_full_name'
  777. function process_special_fields() {
  778. foreach ($this->special_functions as $func_name) {
  779. if (method_exists($this, $func_name)) {
  780. $this->$func_name();
  781. }
  782. }
  783. }
  784. /**
  785. * Function to check if the custom vtiger_field vtiger_table exists
  786. * return true or false
  787. */
  788. function checkIfCustomTableExists($tablename) {
  789. global $adb;
  790. $query = "select * from " . $adb->sql_escape_string($tablename);
  791. $result = $this->db->pquery($query, array());
  792. $testrow = $this->db->num_fields($result);
  793. if ($testrow > 1) {
  794. $exists = true;
  795. } else {
  796. $exists = false;
  797. }
  798. return $exists;
  799. }
  800. /**
  801. * function to construct the query to fetch the custom vtiger_fields
  802. * return the query to fetch the custom vtiger_fields
  803. */
  804. function constructCustomQueryAddendum($tablename, $module) {
  805. global $adb;
  806. $tabid = getTabid($module);
  807. $sql1 = "select columnname,fieldlabel from vtiger_field where generatedtype=2 and tabid=? and vtiger_field.presence in (0,2)";
  808. $result = $adb->pquery($sql1, array($tabid));
  809. $numRows = $adb->num_rows($result);
  810. $sql3 = "select ";
  811. for ($i = 0; $i < $numRows; $i++) {
  812. $columnName = $adb->query_result($result, $i, "columnname");
  813. $fieldlabel = $adb->query_result($result, $i, "fieldlabel");
  814. //construct query as below
  815. if ($i == 0) {
  816. $sql3 .= $tablename . "." . $columnName . " '" . $fieldlabel . "'";
  817. } else {
  818. $sql3 .= ", " . $tablename . "." . $columnName . " '" . $fieldlabel . "'";
  819. }
  820. }
  821. if ($numRows > 0) {
  822. $sql3 = $sql3 . ',';
  823. }
  824. return $sql3;
  825. }
  826. /**
  827. * This function returns a full (ie non-paged) list of the current object type.
  828. * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
  829. * All Rights Reserved..
  830. * Contributor(s): ______________________________________..
  831. */
  832. function get_full_list($order_by = "", $where = "") {
  833. $this->log->debug("get_full_list: order_by = '$order_by' and where = '$where'");
  834. $query = $this->create_list_query($order_by, $where);
  835. return $this->process_full_list_query($query);
  836. }
  837. /**
  838. * Track the viewing of a detail record. This leverages get_summary_text() which is object specific
  839. * params $user_id - The user that is viewing the record.
  840. * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
  841. * All Rights Reserved..
  842. * Contributor(s): ______________________________________..
  843. */
  844. function track_view($user_id, $current_module, $id = '') {
  845. $this->log->debug("About to call vtiger_tracker (user_id, module_name, item_id)($user_id, $current_module, $this->id)");
  846. $tracker = new Tracker();
  847. $tracker->track_view($user_id, $current_module, $id, '');
  848. }
  849. /**
  850. * Function to get the column value of a field when the field value is empty ''
  851. * @param $columnname -- Column name for the field
  852. * @param $fldvalue -- Input value for the field taken from the User
  853. * @param $fieldname -- Name of the Field
  854. * @param $uitype -- UI type of the field
  855. * @return Column value of the field.
  856. */
  857. function get_column_value($columnname, $fldvalue, $fieldname, $uitype, $datatype = '') {
  858. global $log;
  859. $log->debug("Entering function get_column_value ($columnname, $fldvalue, $fieldname, $uitype, $datatype='')");
  860. // Added for the fields of uitype '57' which has datatype mismatch in crmentity table and particular entity table
  861. if ($uitype == 57 && $fldvalue == '') {
  862. return 0;
  863. }
  864. if (is_uitype($uitype, "_date_") && $fldvalue == '' || $uitype == '14') {
  865. return null;
  866. }
  867. if ($datatype == 'I' || $datatype == 'N' || $datatype == 'NN') {
  868. return 0;
  869. }
  870. $log->debug("Exiting function get_column_value");
  871. return $fldvalue;
  872. }
  873. /**
  874. * Function to make change to column fields, depending on the current user's accessibility for the fields
  875. */
  876. function apply_field_security($moduleName = '') {
  877. global $current_user, $currentModule;
  878. if($moduleName == '') {
  879. $moduleName = $currentModule;
  880. }
  881. require_once('include/utils/UserInfoUtil.php');
  882. foreach ($this->column_fields as $fieldname => $fieldvalue) {
  883. $reset_value = false;
  884. if (getFieldVisibilityPermission($moduleName, $current_user->id, $fieldname) != '0')
  885. $reset_value = true;
  886. if ($fieldname == "record_id" || $fieldname == "record_module")
  887. $reset_value = false;
  888. /*
  889. if (isset($this->additional_column_fields) && in_array($fieldname, $this->additional_column_fields) == true)
  890. $reset_value = false;
  891. */
  892. if ($reset_value == true)
  893. $this->column_fields[$fieldname] = "";
  894. }
  895. }
  896. /**
  897. * Function invoked during export of module record value.
  898. */
  899. function transform_export_value($key, $value) {
  900. // NOTE: The sub-class can override this function as required.
  901. return $value;
  902. }
  903. /**
  904. * Function to initialize the importable fields array, based on the User's accessibility to the fields
  905. */
  906. function initImportableFields($module) {
  907. global $current_user, $adb;
  908. require_once('include/utils/UserInfoUtil.php');
  909. $skip_uitypes = array('4'); // uitype 4 is for Mod numbers
  910. // Look at cache if the fields information is available.
  911. $cachedModuleFields = VTCacheUtils::lookupFieldInfo_Module($module);
  912. if ($cachedModuleFields === false) {
  913. getColumnFields($module); // This API will initialize the cache as well
  914. // We will succeed now due to above function call
  915. $cachedModuleFields = VTCacheUtils::lookupFieldInfo_Module($module);
  916. }
  917. $colf = Array();
  918. if ($cachedModuleFields) {
  919. foreach ($cachedModuleFields as $fieldinfo) {
  920. // Skip non-supported fields
  921. if (in_array($fieldinfo['uitype'], $skip_uitypes)) {
  922. continue;
  923. } else {
  924. $colf[$fieldinfo['fieldname']] = $fieldinfo['uitype'];
  925. }
  926. }
  927. }
  928. foreach ($colf as $key => $value) {
  929. if (getFieldVisibilityPermission($module, $current_user->id, $key, 'readwrite') == '0')
  930. $this->importable_fields[$key] = $value;
  931. }
  932. }
  933. /** Function to initialize the required fields array for that particular module */
  934. function initRequiredFields($module) {
  935. global $adb;
  936. $tabid = getTabId($module);
  937. $sql = "select * from vtiger_field where tabid= ? and typeofdata like '%M%' and uitype not in ('53','70') and vtiger_field.presence in (0,2)";
  938. $result = $adb->pquery($sql, array($tabid));
  939. $numRows = $adb->num_rows($result);
  940. for ($i = 0; $i < $numRows; $i++) {
  941. $fieldName = $adb->query_result($result, $i, "fieldname");
  942. $this->required_fields[$fieldName] = 1;
  943. }
  944. }
  945. /** Function to delete an entity with given Id */
  946. function trash($module, $id) {
  947. global $log, $current_user, $adb;
  948. if(!self::isBulkSaveMode()) {
  949. require_once("include/events/include.inc");
  950. $em = new VTEventsManager($adb);
  951. // Initialize Event trigger cache
  952. $em->initTriggerCache();
  953. $entityData = VTEntityData::fromEntityId($adb, $id);
  954. $em->triggerEvent("vtiger.entity.beforedelete", $entityData);
  955. }
  956. $this->mark_deleted($id);
  957. $this->unlinkDependencies($module, $id);
  958. require_once('libraries/freetag/freetag.class.php');
  959. $freetag = new freetag();
  960. $freetag->delete_all_object_tags_for_user($current_user->id, $id);
  961. $sql_recentviewed = 'DELETE FROM vtiger_tracker WHERE user_id = ? AND item_id = ?';
  962. $this->db->pquery($sql_recentviewed, array($current_user->id, $id));
  963. if($em){
  964. $em->triggerEvent("vtiger.entity.afterdelete", $entityData);
  965. }
  966. }
  967. /** Function to unlink all the dependent entities of the given Entity by Id */
  968. function unlinkDependencies($module, $id) {
  969. global $log;
  970. $fieldRes = $this->db->pquery('SELECT tabid, tablename, columnname FROM vtiger_field WHERE fieldid IN (
  971. SELECT fieldid FROM vtiger_fieldmodulerel WHERE relmodule=?)', array($module));
  972. $numOfFields = $this->db->num_rows($fieldRes);
  973. for ($i = 0; $i < $numOfFields; $i++) {
  974. $tabId = $this->db->query_result($fieldRes, $i, 'tabid');
  975. $tableName = $this->db->query_result($fieldRes, $i, 'tablename');
  976. $columnName = $this->db->query_result($fieldRes, $i, 'columnname');
  977. $relatedModule = vtlib_getModuleNameById($tabId);
  978. $focusObj = CRMEntity::getInstance($relatedModule);
  979. //Backup Field Relations for the deleted entity
  980. $targetTableColumn = $focusObj->table_index;
  981. //While deleting product record the $targetTableColumn should 'id'.
  982. if ($tableName == 'vtiger_inventoryproductrel') {
  983. $targetTableColumn = 'id';
  984. }
  985. $relQuery = "SELECT $targetTableColumn FROM $tableName WHERE $columnName=?";
  986. $relResult = $this->db->pquery($relQuery, array($id));
  987. $numOfRelRecords = $this->db->num_rows($relResult);
  988. if ($numOfRelRecords > 0) {
  989. $recordIdsList = array();
  990. for ($k = 0; $k < $numOfRelRecords; $k++) {
  991. $recordIdsList[] = $this->db->query_result($relResult, $k, $focusObj->table_index);
  992. }
  993. $params = array($id, RB_RECORD_UPDATED, $tableName, $columnName, $focusObj->table_index, implode(",", $recordIdsList));
  994. $this->db->pquery('INSERT INTO vtiger_relatedlists_rb VALUES (?,?,?,?,?,?)', $params);
  995. }
  996. }
  997. }
  998. /** Function to unlink an entity with given Id from another entity */
  999. function unlinkRelationship($id, $return_module, $return_id) {
  1000. global $log, $currentModule;
  1001. $query = 'DELETE FROM vtiger_crmentityrel WHERE (crmid=? AND relmodule=? AND relcrmid=?) OR (relcrmid=? AND module=? AND crmid=?)';
  1002. $params = array($id, $return_module, $return_id, $id, $return_module, $return_id);
  1003. $this->db->pquery($query, $params);
  1004. $fieldRes = $this->db->pquery('SELECT tabid, tablename, columnname FROM vtiger_field WHERE fieldid IN (
  1005. SELECT fieldid FROM vtiger_fieldmodulerel WHERE module=? AND relmodule=?)', array($currentModule, $return_module));
  1006. $numOfFields = $this->db->num_rows($fieldRes);
  1007. for ($i = 0; $i < $numOfFields; $i++) {
  1008. $tabId = $this->db->query_result($fieldRes, $i, 'tabid');
  1009. $tableName = $this->db->query_result($fieldRes, $i, 'tablename');
  1010. $columnName = $this->db->query_result($fieldRes, $i, 'columnname');
  1011. $relatedModule = vtlib_getModuleNameById($tabId);
  1012. $focusObj = CRMEntity::getInstance($relatedModule);
  1013. $updateQuery = "UPDATE $tableName SET $columnName=? WHERE $columnName=? AND $focusObj->table_index=?";
  1014. $updateParams = array(null, $return_id, $id);
  1015. $this->db->pquery($updateQuery, $updateParams);
  1016. }
  1017. }
  1018. /** Function to restore a deleted record of specified module with given crmid
  1019. * @param $module -- module name:: Type varchar
  1020. * @param $entity_ids -- list of crmids :: Array
  1021. */
  1022. function restore($module, $id) {
  1023. global $current_user, $adb;
  1024. $this->db->println("TRANS restore starts $module");
  1025. $this->db->startTransaction();
  1026. $date_var = date("Y-m-d H:i:s");
  1027. $query = 'UPDATE vtiger_crmentity SET deleted=0,modifiedtime=?,modifiedby=? WHERE crmid = ?';
  1028. $this->db->pquery($query, array($this->db->formatDate($date_var, true), $current_user->id, $id), true, "Error restoring records :");
  1029. //Restore related entities/records
  1030. $this->restoreRelatedRecords($module, $id);
  1031. //Event triggering code
  1032. require_once("include/events/include.inc");
  1033. global $adb;
  1034. $em = new VTEventsManager($adb);
  1035. // Initialize Event trigger cache
  1036. $em->initTriggerCache();
  1037. $this->id = $id;
  1038. $entityData = VTEntityData::fromCRMEntity($this);
  1039. //Event triggering code
  1040. $em->triggerEvent("vtiger.entity.afterrestore", $entityData);
  1041. //Event triggering code ends
  1042. $this->db->completeTransaction();
  1043. $this->db->println("TRANS restore ends");
  1044. }
  1045. /** Function to restore all the related records of a given record by id */
  1046. function restoreRelatedRecords($module, $record) {
  1047. $result = $this->db->pquery('SELECT * FROM vtiger_relatedlists_rb WHERE entityid = ?', array($record));
  1048. $numRows = $this->db->num_rows($result);
  1049. for ($i = 0; $i < $numRows; $i++) {
  1050. $action = $this->db->query_result($result, $i, "action");
  1051. $rel_table = $this->db->query_result($result, $i, "rel_table");
  1052. $rel_column = $this->db->query_result($result, $i, "rel_column");
  1053. $ref_column = $this->db->query_result($result, $i, "ref_column");
  1054. $related_crm_ids = $this->db->query_result($result, $i, "related_crm_ids");
  1055. if (strtoupper($action) == RB_RECORD_UPDATED) {
  1056. $related_ids = explode(",", $related_crm_ids);
  1057. if ($rel_table == 'vtiger_crmentity' && $rel_column == 'deleted') {
  1058. $sql = "UPDATE $rel_table set $rel_column = 0 WHERE $ref_column IN (" . generateQuestionMarks($related_ids) . ")";
  1059. $this->db->pquery($sql, array($related_ids));
  1060. } else {
  1061. $sql = "UPDATE $rel_table set $rel_column = ? WHERE $rel_column = 0 AND $ref_column IN (" . generateQuestionMarks($related_ids) . ")";
  1062. $this->db->pquery($sql, array($record, $related_ids));
  1063. }
  1064. } elseif (strtoupper($action) == RB_RECORD_DELETED) {
  1065. if ($rel_table == 'vtiger_seproductrel') {
  1066. $sql = "INSERT INTO $rel_table($rel_column, $ref_column, 'setype') VALUES (?,?,?)";
  1067. $this->db->pquery($sql, array($record, $related_crm_ids, $module));
  1068. } else {
  1069. $sql = "INSERT INTO $rel_table($rel_column, $ref_column) VALUES (?,?)";
  1070. $this->db->pquery($sql, array($record, $related_crm_ids));
  1071. }
  1072. }
  1073. }
  1074. //Clean up the the backup data also after restoring
  1075. $this->db->pquery('DELETE FROM vtiger_relatedlists_rb WHERE entityid = ?', array($record));
  1076. }
  1077. /**
  1078. * Function to initialize the sortby fields array
  1079. */
  1080. function initSortByField($module) {
  1081. global $adb, $log;
  1082. $log->d

Large files files are truncated, but you can click here to view the full file