[ Index ]

PHP Cross Reference of vtigercrm-6.1.0

title

Body

[close]

/data/ -> CRMEntity.php (source)

   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) . "'>&nbsp;";
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) . "'>&nbsp;";
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) . "'>&nbsp;";
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) . "'>&nbsp;";
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) . "'>&nbsp;";
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  ?>


Generated: Fri Nov 28 20:08:37 2014 Cross-referenced by PHPXref 0.7.1