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