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