");
+ }
+
+ // Lookup in cache for information
+ $cachedModuleFields = VTCacheUtils::lookupFieldInfo_Module($module);
+
+ if($cachedModuleFields === false) {
+ $tabid = getTabid($module);
+
+ // Let us pick up all the fields first so that we can cache information
+ $sql1 = "SELECT fieldname, fieldid, fieldlabel, columnname, tablename, uitype, typeofdata, presence
+ FROM vtiger_field WHERE tabid=?";
+
+ // NOTE: Need to skip in-active fields which we will be done later.
+ $result1 = $adb->pquery($sql1, array($tabid));
+ $noofrows = $adb->num_rows($result1);
+
+ if($noofrows) {
+ while($resultrow = $adb->fetch_array($result1)) {
+ // Update information to cache for re-use
+ VTCacheUtils::updateFieldInfo(
+ $tabid, $resultrow['fieldname'], $resultrow['fieldid'],
+ $resultrow['fieldlabel'], $resultrow['columnname'], $resultrow['tablename'],
+ $resultrow['uitype'], $resultrow['typeofdata'], $resultrow['presence']
+ );
+ }
+ }
+
+ // Get only active field information
+ $cachedModuleFields = VTCacheUtils::lookupFieldInfo_Module($module);
+ }
+
+ if($cachedModuleFields) {
+ foreach($cachedModuleFields as $fieldname=>$fieldinfo) {
+ $fieldcolname = $fieldinfo['columnname'];
+ $tablename = $fieldinfo['tablename'];
+ $fieldname = $fieldinfo['fieldname'];
+
+ // To avoid ADODB execption pick the entries that are in $tablename
+ // (ex. when we don't have attachment for troubletickets, $result[vtiger_attachments]
+ // will not be set so here we should not retrieve)
+ if(isset($result[$tablename])) {
+ $fld_value = $adb->query_result($result[$tablename],0,$fieldcolname);
+ } else {
+ $adb->println("There is no entry for this entity $record ($module) in the table $tablename");
+ $fld_value = "";
+ }
+ $this->column_fields[$fieldname] = $fld_value;
+ }
+ }
+ if($module == 'Users')
+ {
+ for($i=0; $i<$noofrows; $i++)
+ {
+ $fieldcolname = $adb->query_result($result1,$i,"columnname");
+ $tablename = $adb->query_result($result1,$i,"tablename");
+ $fieldname = $adb->query_result($result1,$i,"fieldname");
+ $fld_value = $adb->query_result($result[$tablename],0,$fieldcolname);
+ $this->$fieldname = $fld_value;
+
+ }
+ }
+
+ $this->column_fields["record_id"] = $record;
+ $this->column_fields["record_module"] = $module;
+ }
+
+ /** Function to saves the values in all the tables mentioned in the class variable $tab_name for the specified module
+ * @param $module -- module:: Type varchar
+ */
+ function save($module_name,$fileid='')
+ {
+ global $log;
+ $log->debug("module name is ".$module_name);
+
+ //Event triggering code
+ require_once("include/events/include.inc");
+ global $adb;
+ $em = new VTEventsManager($adb);
+
+ // Initialize Event trigger cache
+ $em->initTriggerCache();
+
+ $entityData = VTEntityData::fromCRMEntity($this);
+ $em->triggerEvent("vtiger.entity.beforesave.modifiable", $entityData);
+ $em->triggerEvent("vtiger.entity.beforesave", $entityData);
+ $em->triggerEvent("vtiger.entity.beforesave.final", $entityData);
+ //Event triggering code ends
+
+ //GS Save entity being called with the modulename as parameter
+ $this->saveentity($module_name,$fileid);
+
+ //Event triggering code
+ $em->triggerEvent("vtiger.entity.aftersave", $entityData);
+ //Event triggering code ends
+ }
+
+ function process_list_query($query, $row_offset, $limit= -1, $max_per_page = -1)
+ {
+ global $list_max_entries_per_page;
+ $this->log->debug("process_list_query: ".$query);
+ if(!empty($limit) && $limit != -1){
+ $result =& $this->db->limitQuery($query, $row_offset + 0, $limit,true,"Error retrieving $this->object_name list: ");
+ }else{
+ $result =& $this->db->query($query,true,"Error retrieving $this->object_name list: ");
+ }
+
+ $list = Array();
+ if($max_per_page == -1){
+ $max_per_page = $list_max_entries_per_page;
+ }
+ $rows_found = $this->db->getRowCount($result);
+
+ $this->log->debug("Found $rows_found ".$this->object_name."s");
+
+ $previous_offset = $row_offset - $max_per_page;
+ $next_offset = $row_offset + $max_per_page;
+
+ if($rows_found != 0)
+ {
+
+ // We have some data.
+
+ 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)){
+
+
+ foreach($this->list_fields as $entry)
+ {
+
+ foreach($entry as $key=>$field) // this will be cycled only once
+ {
+ if (isset($row[$field])) {
+ $this->column_fields[$this->list_fields_names[$key]] = $row[$field];
+
+
+ $this->log->debug("$this->object_name({$row['id']}): ".$field." = ".$this->$field);
+ }
+ else
+ {
+ $this->column_fields[$this->list_fields_names[$key]] = "";
+ }
+ }
+ }
+
+
+ //$this->db->println("here is the bug");
+
+
+ $list[] = clone($this);//added by Richie to support PHP5
+ }
+ }
+
+ $response = Array();
+ $response['list'] = $list;
+ $response['row_count'] = $rows_found;
+ $response['next_offset'] = $next_offset;
+ $response['previous_offset'] = $previous_offset;
+
+ return $response;
+ }
+
+ function process_full_list_query($query)
+ {
+ $this->log->debug("CRMEntity:process_full_list_query");
+ $result =& $this->db->query($query, false);
+ //$this->log->debug("CRMEntity:process_full_list_query: result is ".$result);
+
+
+ if($this->db->getRowCount($result) > 0){
+
+ // $this->db->println("process_full mid=".$this->table_index." mname=".$this->module_name);
+ // We have some data.
+ while ($row = $this->db->fetchByAssoc($result)) {
+ $rowid=$row[$this->table_index];
+
+ if(isset($rowid))
+ $this->retrieve_entity_info($rowid,$this->module_name);
+ else
+ $this->db->println("rowid not set unable to retrieve");
+
+
+
+ //clone function added to resolvoe PHP5 compatibility issue in Dashboards
+ //If we do not use clone, while using PHP5, the memory address remains fixed but the
+ //data gets overridden hence all the rows that come in bear the same value. This in turn
+//provides a wrong display of the Dashboard graphs. The data is erroneously shown for a specific month alone
+//Added by Richie
+ $list[] = clone($this);//added by Richie to support PHP5
+ }
+ }
+
+ if (isset($list)) return $list;
+ else return null;
+ }
+
+ /** This function should be overridden in each module. It marks an item as deleted.
+ * If it is not overridden, then marking this type of item is not allowed
+ * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
+ * All Rights Reserved..
+ * Contributor(s): ______________________________________..
+ */
+ function mark_deleted($id) {
+ $date_var = date('Y-m-d H:i:s');
+ $query = "UPDATE vtiger_crmentity set deleted=1,modifiedtime=? where crmid=?";
+ $this->db->pquery($query, array($this->db->formatDate($date_var, true),$id), true,"Error marking record deleted: ");
+ }
+
+ function retrieve_by_string_fields($fields_array, $encode=true)
+ {
+ $where_clause = $this->get_where($fields_array);
+
+ $query = "SELECT * FROM $this->table_name $where_clause";
+ $this->log->debug("Retrieve $this->object_name: ".$query);
+ $result =& $this->db->requireSingleResult($query, true, "Retrieving record $where_clause:");
+ if( empty($result))
+ {
+ return null;
+ }
+
+ $row = $this->db->fetchByAssoc($result,-1, $encode);
+
+ foreach($this->column_fields as $field)
+ {
+ if(isset($row[$field]))
+ {
+ $this->$field = $row[$field];
+ }
+ }
+ return $this;
+ }
+
+ // this method is called during an import before inserting a bean
+ // define an associative array called $special_fields
+ // the keys are user defined, and don't directly map to the bean's vtiger_fields
+ // the value is the method name within that bean that will do extra
+ // processing for that vtiger_field. example: 'full_name'=>'get_names_from_full_name'
+
+ function process_special_fields()
+ {
+ foreach ($this->special_functions as $func_name)
+ {
+ if ( method_exists($this,$func_name) )
+ {
+ $this->$func_name();
+ }
+ }
+ }
+
+ /**
+ * Function to check if the custom vtiger_field vtiger_table exists
+ * return true or false
+ */
+ function checkIfCustomTableExists($tablename) {
+ global $adb;
+ $query = "select * from ". $adb->sql_escape_string($tablename);
+ $result = $this->db->pquery($query, array());
+ $testrow = $this->db->num_fields($result);
+ if($testrow > 1) {
+ $exists=true;
+ } else {
+ $exists=false;
+ }
+ return $exists;
+ }
+
+ /**
+ * function to construct the query to fetch the custom vtiger_fields
+ * return the query to fetch the custom vtiger_fields
+ */
+ function constructCustomQueryAddendum($tablename,$module)
+ {
+ global $adb;
+ $tabid=getTabid($module);
+ $sql1 = "select columnname,fieldlabel from vtiger_field where generatedtype=2 and tabid=? and vtiger_field.presence in (0,2)";
+ $result = $adb->pquery($sql1, array($tabid));
+ $numRows = $adb->num_rows($result);
+ $sql3 = "select ";
+ for($i=0; $i < $numRows;$i++)
+ {
+ $columnName = $adb->query_result($result,$i,"columnname");
+ $fieldlabel = $adb->query_result($result,$i,"fieldlabel");
+ //construct query as below
+ if($i == 0)
+ {
+ $sql3 .= $tablename.".".$columnName. " '" .$fieldlabel."'";
+ }
+ else
+ {
+ $sql3 .= ", ".$tablename.".".$columnName. " '" .$fieldlabel."'";
+ }
+
+ }
+ if($numRows>0)
+ {
+ $sql3=$sql3.',';
+ }
+ return $sql3;
+
+ }
+
+
+ /**
+ * This function returns a full (ie non-paged) list of the current object type.
+ * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
+ * All Rights Reserved..
+ * Contributor(s): ______________________________________..
+ */
+ function get_full_list($order_by = "", $where = "") {
+ $this->log->debug("get_full_list: order_by = '$order_by' and where = '$where'");
+ $query = $this->create_list_query($order_by, $where);
+ return $this->process_full_list_query($query);
+ }
+
+ /**
+ * Track the viewing of a detail record. This leverages get_summary_text() which is object specific
+ * params $user_id - The user that is viewing the record.
+ * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
+ * All Rights Reserved..
+ * Contributor(s): ______________________________________..
+ */
+ function track_view($user_id, $current_module,$id='')
+ {
+ $this->log->debug("About to call vtiger_tracker (user_id, module_name, item_id)($user_id, $current_module, $this->id)");
+
+ $tracker = new Tracker();
+ $tracker->track_view($user_id, $current_module, $id, '');
+ }
+
+ /**
+ * Function to get the column value of a field when the field value is empty ''
+ * @param $columnname -- Column name for the field
+ * @param $fldvalue -- Input value for the field taken from the User
+ * @param $fieldname -- Name of the Field
+ * @param $uitype -- UI type of the field
+ * @return Column value of the field.
+ */
+ function get_column_value($columnname, $fldvalue, $fieldname, $uitype, $datatype='') {
+ global $log;
+ $log->debug("Entering function get_column_value ($columnname, $fldvalue, $fieldname, $uitype, $datatype='')");
+
+ // Added for the fields of uitype '57' which has datatype mismatch in crmentity table and particular entity table
+ if ($uitype == 57 && $fldvalue == '') {
+ return 0;
+ }
+ if (is_uitype($uitype, "_date_") && $fldvalue == '') {
+ return null;
+ }
+ if ($datatype == 'I' || $datatype == 'N' || $datatype == 'NN'){
+ return 0;
+ }
+ $log->debug("Exiting function get_column_value");
+ return $fldvalue;
+ }
+
+ /**
+ * Function to make change to column fields, depending on the current user's accessibility for the fields
+ */
+ function apply_field_security() {
+ global $current_user, $currentModule;
+
+ require_once('include/utils/UserInfoUtil.php');
+ foreach($this->column_fields as $fieldname=>$fieldvalue) {
+ $reset_value = false;
+ if (getFieldVisibilityPermission($currentModule, $current_user->id, $fieldname) != '0')
+ $reset_value = true;
+
+ if ($fieldname == "record_id" || $fieldname == "record_module")
+ $reset_value = false;
+
+ /*
+ if (isset($this->additional_column_fields) && in_array($fieldname, $this->additional_column_fields) == true)
+ $reset_value = false;
+ */
+
+ if ($reset_value == true)
+ $this->column_fields[$fieldname] = "";
+ }
+ }
+
+ /**
+ * Function invoked during export of module record value.
+ */
+ function transform_export_value($key, $value) {
+ // NOTE: The sub-class can override this function as required.
+ return $value;
+ }
+
+ /**
+ * Function to initialize the importable fields array, based on the User's accessibility to the fields
+ */
+ function initImportableFields($module) {
+ global $current_user, $adb;
+ require_once('include/utils/UserInfoUtil.php');
+
+ $skip_uitypes = array('4'); // uitype 4 is for Mod numbers
+
+ // Look at cache if the fields information is available.
+ $cachedModuleFields = VTCacheUtils::lookupFieldInfo_Module($module);
+
+ if($cachedModuleFields === false) {
+ getColumnFields($module); // This API will initialize the cache as well
+
+ // We will succeed now due to above function call
+ $cachedModuleFields = VTCacheUtils::lookupFieldInfo_Module($module);
+ }
+
+ $colf = Array();
+
+ if($cachedModuleFields) {
+ foreach($cachedModuleFields as $fieldinfo) {
+ // Skip non-supported fields
+ if(in_array($fieldinfo['uitype'], $skip_uitypes)) {
+ continue;
+ } else {
+ $colf[$fieldinfo['fieldname']] = $fieldinfo['uitype'];
+ }
+ }
+ }
+
+ foreach($colf as $key=>$value) {
+ if (getFieldVisibilityPermission($module, $current_user->id, $key) == '0')
+ $this->importable_fields[$key] = $value;
+ }
+ }
+
+
+ /** Function to initialize the required fields array for that particular module */
+ function initRequiredFields($module) {
+ global $adb;
+
+ $tabid = getTabId($module);
+ $sql = "select * from vtiger_field where tabid= ? and typeofdata like '%M%' and uitype not in ('53','70') and vtiger_field.presence in (0,2)";
+ $result = $adb->pquery($sql,array($tabid));
+ $numRows = $adb->num_rows($result);
+ for($i=0; $i < $numRows;$i++)
+ {
+ $fieldName = $adb->query_result($result,$i,"fieldname");
+ $this->required_fields[$fieldName] = 1;
+ }
+ }
+
+ /** Function to delete an entity with given Id */
+ function trash($module, $id) {
+ global $log, $current_user;
+
+ $this->mark_deleted($id);
+ $this->unlinkDependencies($module, $id);
+
+ require_once('include/freetag/freetag.class.php');
+ $freetag=new freetag();
+ $freetag->delete_all_object_tags_for_user($current_user->id,$id);
+
+ $sql_recentviewed ='DELETE FROM vtiger_tracker WHERE user_id = ? AND item_id = ?';
+ $this->db->pquery($sql_recentviewed, array($current_user->id, $id));
+ }
+
+
+ /** Function to unlink all the dependent entities of the given Entity by Id */
+ function unlinkDependencies($module, $id) {
+ global $log;
+
+ $fieldRes = $this->db->pquery('SELECT tabid, tablename, columnname FROM vtiger_field WHERE fieldid IN (
+ SELECT fieldid FROM vtiger_fieldmodulerel WHERE relmodule=?)', array($module));
+ $numOfFields = $this->db->num_rows($fieldRes);
+ for ($i=0; $i<$numOfFields; $i++) {
+ $tabId = $this->db->query_result($fieldRes, $i, 'tabid');
+ $tableName = $this->db->query_result($fieldRes, $i, 'tablename');
+ $columnName = $this->db->query_result($fieldRes, $i, 'columnname');
+
+ $relatedModule = vtlib_getModuleNameById($tabId);
+ $focusObj = CRMEntity::getInstance($relatedModule);
+
+ //Backup Field Relations for the deleted entity
+ $relQuery = "SELECT $focusObj->table_index FROM $tableName WHERE $columnName=?";
+ $relResult = $this->db->pquery($relQuery, array($id));
+ $numOfRelRecords = $this->db->num_rows($relResult);
+ if ($numOfRelRecords > 0) {
+ $recordIdsList = array();
+ for($k=0;$k < $numOfRelRecords;$k++)
+ {
+ $recordIdsList[] = $this->db->query_result($relResult,$k,$focusObj->table_index);
+ }
+ $params = array($id, RB_RECORD_UPDATED, $tableName, $columnName, $focusObj->table_index, implode(",", $recordIdsList));
+ $this->db->pquery('INSERT INTO vtiger_relatedlists_rb VALUES (?,?,?,?,?,?)', $params);
+ }
+
+ }
+ }
+
+ /** Function to unlink an entity with given Id from another entity */
+ function unlinkRelationship($id, $return_module, $return_id) {
+ global $log, $currentModule;
+
+ $query = 'DELETE FROM vtiger_crmentityrel WHERE (crmid=? AND relmodule=? AND relcrmid=?) OR (relcrmid=? AND module=? AND crmid=?)';
+ $params = array($id, $return_module, $return_id, $id, $return_module, $return_id);
+ $this->db->pquery($query, $params);
+
+ $fieldRes = $this->db->pquery('SELECT tabid, tablename, columnname FROM vtiger_field WHERE fieldid IN (
+ SELECT fieldid FROM vtiger_fieldmodulerel WHERE module=? AND relmodule=?)', array($currentModule, $return_module));
+ $numOfFields = $this->db->num_rows($fieldRes);
+ for ($i=0; $i<$numOfFields; $i++) {
+ $tabId = $this->db->query_result($fieldRes, $i, 'tabid');
+ $tableName = $this->db->query_result($fieldRes, $i, 'tablename');
+ $columnName = $this->db->query_result($fieldRes, $i, 'columnname');
+
+ $relatedModule = vtlib_getModuleNameById($tabId);
+ $focusObj = CRMEntity::getInstance($relatedModule);
+
+ $updateQuery = "UPDATE $tableName SET $columnName=0 WHERE $columnName=? AND $focusObj->table_index=?";
+ $updateParams = array($return_id, $id);
+ $this->db->pquery($updateQuery, $updateParams);
+ }
+ }
+
+ /** Function to restore a deleted record of specified module with given crmid
+ * @param $module -- module name:: Type varchar
+ * @param $entity_ids -- list of crmids :: Array
+ */
+ function restore($module, $id) {
+ global $current_user;
+
+ $this->db->println("TRANS restore starts $module");
+ $this->db->startTransaction();
+
+ $this->db->pquery('UPDATE vtiger_crmentity SET deleted=0 WHERE crmid = ?', array($id));
+ //Restore related entities/records
+ $this->restoreRelatedRecords($module,$id);
+
+ $this->db->completeTransaction();
+ $this->db->println("TRANS restore ends");
+ }
+
+ /** Function to restore all the related records of a given record by id */
+ function restoreRelatedRecords($module,$record) {
+
+ $result = $this->db->pquery('SELECT * FROM vtiger_relatedlists_rb WHERE entityid = ?', array($record));
+ $numRows = $this->db->num_rows($result);
+ for($i=0; $i < $numRows;$i++)
+ {
+ $action = $this->db->query_result($result,$i,"action");
+ $rel_table = $this->db->query_result($result,$i,"rel_table");
+ $rel_column = $this->db->query_result($result,$i,"rel_column");
+ $ref_column = $this->db->query_result($result,$i,"ref_column");
+ $related_crm_ids = $this->db->query_result($result,$i,"related_crm_ids");
+
+ if(strtoupper($action) == RB_RECORD_UPDATED) {
+ $related_ids = explode(",", $related_crm_ids);
+ if($rel_table == 'vtiger_crmentity' && $rel_column == 'deleted') {
+ $sql = "UPDATE $rel_table set $rel_column = 0 WHERE $ref_column IN (". generateQuestionMarks($related_ids) . ")";
+ $this->db->pquery($sql, array($related_ids));
+ } else {
+ $sql = "UPDATE $rel_table set $rel_column = ? WHERE $rel_column = 0 AND $ref_column IN (". generateQuestionMarks($related_ids) . ")";
+ $this->db->pquery($sql, array($record, $related_ids));
+ }
+ } elseif (strtoupper($action) == RB_RECORD_DELETED) {
+ if ($rel_table == 'vtiger_seproductrel') {
+ $sql = "INSERT INTO $rel_table($rel_column, $ref_column, 'setype') VALUES (?,?,?)";
+ $this->db->pquery($sql, array($record, $related_crm_ids, $module));
+ } else {
+ $sql = "INSERT INTO $rel_table($rel_column, $ref_column) VALUES (?,?)";
+ $this->db->pquery($sql, array($record, $related_crm_ids));
+ }
+ }
+ }
+
+ //Clean up the the backup data also after restoring
+ $this->db->pquery('DELETE FROM vtiger_relatedlists_rb WHERE entityid = ?', array($record));
+ }
+
+ /**
+ * Function to initialize the sortby fields array
+ */
+ function initSortByField($module) {
+ global $adb, $log;
+ $log->debug("Entering function initSortByField ($module)");
+ // Define the columnname's and uitype's which needs to be excluded
+ $exclude_columns = Array ('parent_id','quoteid','vendorid','access_count');
+ $exclude_uitypes = Array ();
+
+ $tabid = getTabId($module);
+ if($module == 'Calendar') {
+ $tabid = array('9','16');
+ }
+ $sql = "SELECT columnname FROM vtiger_field ".
+ " WHERE (fieldname not like '%\_id' OR fieldname in ('assigned_user_id'))".
+ " AND tabid in (". generateQuestionMarks($tabid) .") and vtiger_field.presence in (0,2)";
+ $params = array($tabid);
+ if (count($exclude_columns) > 0) {
+ $sql .= " AND columnname NOT IN (". generateQuestionMarks($exclude_columns) .")";
+ array_push($params, $exclude_columns);
+ }
+ if (count($exclude_uitypes) > 0) {
+ $sql .= " AND uitype NOT IN (". generateQuestionMarks($exclude_uitypes) . ")";
+ array_push($params, $exclude_uitypes);
+ }
+ $result = $adb->pquery($sql,$params);
+ $num_rows = $adb->num_rows($result);
+ for($i=0; $i<$num_rows; $i++) {
+ $columnname = $adb->query_result($result,$i,'columnname');
+ if(in_array($columnname, $this->sortby_fields)) continue;
+ else $this->sortby_fields[] = $columnname;
+ }
+ if($tabid == 21 or $tabid == 22)
+ $this->sortby_fields[] = 'crmid';
+ $log->debug("Exiting initSortByField");
+ }
+
+ /* Function to set the Sequence string and sequence number starting value */
+ function setModuleSeqNumber($mode, $module, $req_str='', $req_no='')
+ {
+ global $adb;
+ //when we configure the invoice number in Settings this will be used
+ if ($mode == "configure" && $req_no != '') {
+ $check = $adb->pquery("select cur_id from vtiger_modentity_num where semodule=? and prefix = ?", array($module, $req_str));
+ if($adb->num_rows($check)== 0) {
+ $numid = $adb->getUniqueId("vtiger_modentity_num");
+ $active = $adb->pquery("select num_id from vtiger_modentity_num where semodule=? and active=1", array($module));
+ $adb->pquery("UPDATE vtiger_modentity_num SET active=0 where num_id=?", array($adb->query_result($active,0,'num_id')));
+
+ $adb->pquery("INSERT into vtiger_modentity_num values(?,?,?,?,?,?)", array($numid,$module,$req_str,$req_no,$req_no,1));
+ return true;
+ }
+ else if($adb->num_rows($check)!=0) {
+ $num_check = $adb->query_result($check,0,'cur_id');
+ if($req_no < $num_check) {
+ return false;
+ }
+ else {
+ $adb->pquery("UPDATE vtiger_modentity_num SET active=0 where active=1 and semodule=?", array($module));
+ $adb->pquery("UPDATE vtiger_modentity_num SET cur_id=?, active = 1 where prefix=? and semodule=?", array($req_no,$req_str,$module));
+ return true;
+ }
+ }
+ }
+ else if ($mode == "increment") {
+ //when we save new invoice we will increment the invoice id and write
+ $check = $adb->pquery("select cur_id,prefix from vtiger_modentity_num where semodule=? and active = 1", array($module));
+ $prefix = $adb->query_result($check,0,'prefix');
+ $curid = $adb->query_result($check,0,'cur_id');
+ $prev_inv_no=$prefix.$curid;
+ $strip=strlen($curid)-strlen($curid+1);
+ if($strip<0)$strip=0;
+ $temp = str_repeat("0",$strip);
+ $req_no.= $temp.($curid+1);
+ $adb->pquery("UPDATE vtiger_modentity_num SET cur_id=? where cur_id=? and active=1 AND semodule=?", array($req_no,$curid,$module));
+ return decode_html($prev_inv_no);
+ }
+ }
+ // END
+
+ /* Function to get the next module sequence number for a given module */
+ function getModuleSeqInfo($module) {
+ global $adb;
+ $check = $adb->pquery("select cur_id,prefix from vtiger_modentity_num where semodule=? and active = 1", array($module));
+ $prefix = $adb->query_result($check,0,'prefix');
+ $curid = $adb->query_result($check,0,'cur_id');
+ return array($prefix, $curid);
+ }
+ // END
+
+ /* Function to check if the mod number already exits */
+ function checkModuleSeqNumber($table, $column, $no)
+ {
+ global $adb;
+ $result=$adb->pquery("select ".$adb->sql_escape_string($column).
+ " from ".$adb->sql_escape_string($table).
+ " where ".$adb->sql_escape_string($column)." = ?", array($no));
+
+ $num_rows = $adb->num_rows($result);
+
+ if($num_rows > 0)
+ return true;
+ else
+ return false;
+ }
+ // END
+
+ function updateMissingSeqNumber($module) {
+ global $log, $adb;
+ $log->debug("Entered updateMissingSeqNumber function");
+
+ vtlib_setup_modulevars($module, $this);
+
+ $tabid = getTabid($module);
+ $fieldinfo = $adb->pquery("SELECT * FROM vtiger_field WHERE tabid = ? AND uitype = 4", Array($tabid));
+
+ $returninfo = Array();
+
+ if($fieldinfo && $adb->num_rows($fieldinfo)) {
+ // TODO: We assume the following for module sequencing field
+ // 1. There will be only field per module
+ // 2. This field is linked to module base table column
+ $fld_table = $adb->query_result($fieldinfo, 0, 'tablename');
+ $fld_column = $adb->query_result($fieldinfo, 0, 'columnname');
+
+ if($fld_table == $this->table_name) {
+ $records = $adb->query("SELECT $this->table_index AS recordid FROM $this->table_name " .
+ "WHERE $fld_column = '' OR $fld_column is NULL");
+
+ if($records && $adb->num_rows($records)) {
+ $returninfo['totalrecords'] = $adb->num_rows($records);
+ $returninfo['updatedrecords'] = 0;
+
+ $modseqinfo = $this->getModuleSeqInfo($module);
+ $prefix = $modseqinfo[0];
+ $cur_id = $modseqinfo[1];
+
+ $old_cur_id = $cur_id;
+ while($recordinfo = $adb->fetch_array($records)) {
+ $value = "$prefix"."$cur_id";
+ $adb->pquery("UPDATE $fld_table SET $fld_column = ? WHERE $this->table_index = ?", Array($value, $recordinfo['recordid']));
+ $cur_id += 1;
+ $returninfo['updatedrecords'] = $returninfo['updatedrecords'] + 1;
+ }
+ if($old_cur_id != $cur_id) {
+ $adb->pquery("UPDATE vtiger_modentity_num set cur_id=? where semodule=? and active=1", Array($cur_id, $module));
+ }
+ }
+ } else {
+ $log->fatal("Updating Missing Sequence Number FAILED! REASON: Field table and module table mismatching.");
+ }
+ }
+ return $returninfo;
+ }
+
+ /* Generic function to get attachments in the related list of a given module */
+ function get_attachments($id, $cur_tab_id, $rel_tab_id, $actions=false) {
+
+ global $currentModule, $app_strings,$singlepane_view;
+ $this_module = $currentModule;
+ $parenttab = getParentTab();
+
+ $related_module = vtlib_getModuleNameById($rel_tab_id);
+ $other = CRMEntity::getInstance($related_module);
+
+ // Some standard module class doesn't have required variables
+ // that are used in the query, they are defined in this generic API
+ vtlib_setup_modulevars($related_module, $other);
+
+ $singular_modname = vtlib_toSingular($related_module);
+ $button = '';
+ if($actions) {
+ if(is_string($actions)) $actions = explode(',', strtoupper($actions));
+ if(in_array('SELECT', $actions) && isPermitted($related_module,4, '') == 'yes') {
+ $button .= " ";
+ }
+ if(in_array('ADD', $actions) && isPermitted($related_module,1, '') == 'yes') {
+ $button .= " ";
+ }
+ }
+
+ // To make the edit or del link actions to return back to same view.
+ if($singlepane_view == 'true') $returnset = "&return_module=$this_module&return_action=DetailView&return_id=$id";
+ else $returnset = "&return_module=$this_module&return_action=CallRelatedList&return_id=$id";
+
+ $query = "select case when (vtiger_users.user_name not like '') then vtiger_users.user_name else vtiger_groups.groupname end as user_name," .
+ "'Documents' ActivityType,vtiger_attachments.type FileType,crm2.modifiedtime lastmodified,
+ vtiger_seattachmentsrel.attachmentsid attachmentsid, vtiger_notes.notesid crmid,
+ vtiger_notes.notecontent description,vtiger_notes.*
+ from vtiger_notes
+ inner join vtiger_senotesrel on vtiger_senotesrel.notesid= vtiger_notes.notesid
+ inner join vtiger_crmentity on vtiger_crmentity.crmid= vtiger_notes.notesid and vtiger_crmentity.deleted=0
+ inner join vtiger_crmentity crm2 on crm2.crmid=vtiger_senotesrel.crmid
+ LEFT JOIN vtiger_groups
+ ON vtiger_groups.groupid = vtiger_crmentity.smownerid
+ left join vtiger_seattachmentsrel on vtiger_seattachmentsrel.crmid =vtiger_notes.notesid
+ left join vtiger_attachments on vtiger_seattachmentsrel.attachmentsid = vtiger_attachments.attachmentsid
+ left join vtiger_users on vtiger_crmentity.smownerid= vtiger_users.id
+ where crm2.crmid=".$id;
+
+ $return_value = GetRelatedList($this_module, $related_module, $other, $query, $button, $returnset);
+
+ if($return_value == null) $return_value = Array();
+ $return_value['CUSTOM_BUTTON'] = $button;
+ return $return_value;
+ }
+
+ /**
+ * For Record View Notification
+ */
+ function isViewed($crmid=false) {
+ if(!$crmid) { $crmid = $this->id; }
+ if($crmid) {
+ global $adb;
+ $result = $adb->pquery("SELECT viewedtime,modifiedtime,smcreatorid,smownerid,modifiedby FROM vtiger_crmentity WHERE crmid=?", Array($crmid));
+ $resinfo = $adb->fetch_array($result);
+
+ $lastviewed = $resinfo['viewedtime'];
+ $modifiedon = $resinfo['modifiedtime'];
+ $smownerid = $resinfo['smownerid'];
+ $smcreatorid = $resinfo['smcreatorid'];
+ $modifiedby = $resinfo['modifiedby'];
+
+ if($modifiedby == '0' && ($smownerid == $smcreatorid)) {
+ /** When module record is created **/
+ return true;
+ } else if($smownerid == $modifiedby) {
+ /** Owner and Modifier as same. **/
+ return true;
+ } else if($lastviewed && $modifiedon) {
+ /** Lastviewed and Modified time is available. */
+ if($this->__timediff($modifiedon, $lastviewed) > 0) return true;
+ }
+ }
+ return false;
+ }
+
+ function __timediff($d1, $d2) {
+ list($t1_1, $t1_2) = explode(' ', $d1);
+ list($t1_y, $t1_m, $t1_d) = explode('-', $t1_1);
+ list($t1_h, $t1_i, $t1_s) = explode(':', $t1_2);
+
+ $t1 = mktime($t1_h, $t1_i, $t1_s, $t1_m, $t1_d, $t1_y);
+
+ list($t2_1, $t2_2) = explode(' ', $d2);
+ list($t2_y, $t2_m, $t2_d) = explode('-', $t2_1);
+ list($t2_h, $t2_i, $t2_s) = explode(':', $t2_2);
+
+ $t2 = mktime($t2_h, $t2_i, $t2_s, $t2_m, $t2_d, $t2_y);
+
+ if( $t1 == $t2 ) return 0;
+ return $t2 - $t1;
+ }
+
+ function markAsViewed($userid) {
+ global $adb;
+ $adb->pquery("UPDATE vtiger_crmentity set viewedtime=? WHERE crmid=? AND smownerid=?",
+ Array( date('Y-m-d H:i:s', time()), $this->id, $userid));
+ }
+
+ /**
+ * Save the related module record information. Triggered from CRMEntity->saveentity method or updateRelations.php
+ * @param String This module name
+ * @param Integer This module record number
+ * @param String Related module name
+ * @param mixed Integer or Array of related module record number
+ */
+ function save_related_module($module, $crmid, $with_module, $with_crmid) {
+ global $adb;
+ if(!is_array($with_crmid)) $with_crmid = Array($with_crmid);
+ foreach($with_crmid as $relcrmid) {
+
+ if($with_module == 'Documents') {
+ $checkpresence = $adb->pquery("SELECT crmid FROM vtiger_senotesrel WHERE crmid = ? AND notesid = ?", Array($crmid, $relcrmid));
+ // Relation already exists? No need to add again
+ if($checkpresence && $adb->num_rows($checkpresence)) continue;
+
+ $adb->pquery("INSERT INTO vtiger_senotesrel(crmid, notesid) VALUES(?,?)", array($crmid, $relcrmid));
+ } else {
+ $checkpresence = $adb->pquery("SELECT crmid FROM vtiger_crmentityrel WHERE
+ crmid = ? AND module = ? AND relcrmid = ? AND relmodule = ?", Array($crmid, $module, $relcrmid, $with_module));
+ // Relation already exists? No need to add again
+ if($checkpresence && $adb->num_rows($checkpresence)) continue;
+
+ $adb->pquery("INSERT INTO vtiger_crmentityrel(crmid, module, relcrmid, relmodule) VALUES(?,?,?,?)",
+ Array($crmid, $module, $relcrmid, $with_module));
+ }
+ }
+ }
+
+ /**
+ * Delete the related module record information. Triggered from updateRelations.php
+ * @param String This module name
+ * @param Integer This module record number
+ * @param String Related module name
+ * @param mixed Integer or Array of related module record number
+ */
+ function delete_related_module($module, $crmid, $with_module, $with_crmid) {
+ global $adb;
+ if(!is_array($with_crmid)) $with_crmid = Array($with_crmid);
+ foreach($with_crmid as $relcrmid) {
+
+ if($with_module == 'Documents') {
+ $adb->pquery("DELETE FROM vtiger_senotesrel WHERE crmid=? AND notesid=?",
+ Array($crmid, $relcrmid));
+ } else {
+ $adb->pquery("DELETE FROM vtiger_crmentityrel WHERE crmid=? AND module=? AND relcrmid=? AND relmodule=?",
+ Array($crmid, $module, $relcrmid, $with_module));
+ }
+ }
+ }
+
+ /**
+ * Default (generic) function to handle the related list for the module.
+ * NOTE: Vtiger_Module::setRelatedList sets reference to this function in vtiger_relatedlists table
+ * if function name is not explicitly specified.
+ */
+ function get_related_list($id, $cur_tab_id, $rel_tab_id, $actions=false) {
+
+ global $currentModule, $app_strings, $singlepane_view;
+
+ $parenttab = getParentTab();
+
+ $related_module = vtlib_getModuleNameById($rel_tab_id);
+ $other = CRMEntity::getInstance($related_module);
+
+ // Some standard module class doesn't have required variables
+ // that are used in the query, they are defined in this generic API
+ vtlib_setup_modulevars($currentModule, $this);
+ vtlib_setup_modulevars($related_module, $other);
+
+ $singular_modname = vtlib_toSingular($related_module);
+
+ $button = '';
+ if($actions) {
+ if(is_string($actions)) $actions = explode(',', strtoupper($actions));
+ if(in_array('SELECT', $actions) && isPermitted($related_module,4, '') == 'yes') {
+ $button .= " ";
+ }
+ if(in_array('ADD', $actions) && isPermitted($related_module,1, '') == 'yes') {
+ $button .= " ";
+ }
+ }
+
+ // To make the edit or del link actions to return back to same view.
+ if($singlepane_view == 'true') $returnset = "&return_module=$currentModule&return_action=DetailView&return_id=$id";
+ else $returnset = "&return_module=$currentModule&return_action=CallRelatedList&return_id=$id";
+
+ $query = "SELECT vtiger_crmentity.*, $other->table_name.*";
+
+ $query .= ", CASE WHEN (vtiger_users.user_name NOT LIKE '') THEN vtiger_users.user_name ELSE vtiger_groups.groupname END AS user_name";
+
+ $more_relation = '';
+ if(!empty($other->related_tables)) {
+ foreach($other->related_tables as $tname=>$relmap) {
+ $query .= ", $tname.*";
+
+ // Setup the default JOIN conditions if not specified
+ if(empty($relmap[1])) $relmap[1] = $other->table_name;
+ if(empty($relmap[2])) $relmap[2] = $relmap[0];
+ $more_relation .= " LEFT JOIN $tname ON $tname.$relmap[0] = $relmap[1].$relmap[2]";
+ }
+ }
+
+ $query .= " FROM $other->table_name";
+ $query .= " INNER JOIN vtiger_crmentity ON vtiger_crmentity.crmid = $other->table_name.$other->table_index";
+ $query .= " INNER JOIN vtiger_crmentityrel ON (vtiger_crmentityrel.relcrmid = vtiger_crmentity.crmid OR vtiger_crmentityrel.crmid = vtiger_crmentity.crmid)";
+ $query .= " LEFT JOIN $this->table_name ON $this->table_name.$this->table_index = $other->table_name.$other->table_index";
+ $query .= $more_relation;
+ $query .= " LEFT JOIN vtiger_users ON vtiger_users.id = vtiger_crmentity.smownerid";
+ $query .= " LEFT JOIN vtiger_groups ON vtiger_groups.groupid = vtiger_crmentity.smownerid";
+
+ $query .= " WHERE vtiger_crmentity.deleted = 0 AND (vtiger_crmentityrel.crmid = $id OR vtiger_crmentityrel.relcrmid = $id)";
+
+ $return_value = GetRelatedList($currentModule, $related_module, $other, $query, $button, $returnset);
+
+ if($return_value == null) $return_value = Array();
+ $return_value['CUSTOM_BUTTON'] = $button;
+
+ return $return_value;
+ }
+
+ /**
+ * Default (generic) function to handle the dependents list for the module.
+ * NOTE: UI type '10' is used to stored the references to other modules for a given record.
+ * These dependent records can be retrieved through this function.
+ * For eg: A trouble ticket can be related to an Account or a Contact.
+ * From a given Contact/Account if we need to fetch all such dependent trouble tickets, get_dependents_list function can be used.
+ */
+ function get_dependents_list($id, $cur_tab_id, $rel_tab_id, $actions=false) {
+
+ global $currentModule, $app_strings, $singlepane_view, $current_user;
+
+ $parenttab = getParentTab();
+
+ $related_module = vtlib_getModuleNameById($rel_tab_id);
+ $other = CRMEntity::getInstance($related_module);
+
+ // Some standard module class doesn't have required variables
+ // that are used in the query, they are defined in this generic API
+ vtlib_setup_modulevars($currentModule, $this);
+ vtlib_setup_modulevars($related_module, $other);
+
+ $singular_modname = vtlib_toSingular($related_module);
+
+ $button = '';
+
+ // To make the edit or del link actions to return back to same view.
+ if($singlepane_view == 'true') $returnset = "&return_module=$currentModule&return_action=DetailView&return_id=$id";
+ else $returnset = "&return_module=$currentModule&return_action=CallRelatedList&return_id=$id";
+
+ $return_value = null;
+ $dependentFieldSql = $this->db->pquery("SELECT tabid, fieldname, columnname FROM vtiger_field WHERE uitype='10' AND" .
+ " fieldid IN (SELECT fieldid FROM vtiger_fieldmodulerel WHERE relmodule=? AND module=?)", array($currentModule, $related_module));
+ $numOfFields = $this->db->num_rows($dependentFieldSql);
+
+ if($numOfFields > 0) {
+ $dependentColumn = $this->db->query_result($dependentFieldSql, 0, 'columnname');
+ $dependentField = $this->db->query_result($dependentFieldSql, 0, 'fieldname');
+
+ $button .= '';
+ $button .= '';
+ if($actions) {
+ if(is_string($actions)) $actions = explode(',', strtoupper($actions));
+ if(in_array('ADD', $actions) && isPermitted($related_module,1, '') == 'yes'
+ && getFieldVisibilityPermission($related_module,$current_user->id,$dependentField) == '0') {
+ $button .= " ";
+ }
+ }
+
+ $query = "SELECT vtiger_crmentity.*, $other->table_name.*";
+
+ $query .= ", CASE WHEN (vtiger_users.user_name NOT LIKE '') THEN vtiger_users.user_name ELSE vtiger_groups.groupname END AS user_name";
+
+ $more_relation = '';
+ if(!empty($other->related_tables)) {
+ foreach($other->related_tables as $tname=>$relmap) {
+ $query .= ", $tname.*";
+
+ // Setup the default JOIN conditions if not specified
+ if(empty($relmap[1])) $relmap[1] = $other->table_name;
+ if(empty($relmap[2])) $relmap[2] = $relmap[0];
+ $more_relation .= " LEFT JOIN $tname ON $tname.$relmap[0] = $relmap[1].$relmap[2]";
+ }
+ }
+
+ $query .= " FROM $other->table_name";
+ $query .= " INNER JOIN vtiger_crmentity ON vtiger_crmentity.crmid = $other->table_name.$other->table_index";
+ $query .= " INNER JOIN $this->table_name ON $this->table_name.$this->table_index = $other->table_name.$dependentColumn";
+ $query .= $more_relation;
+ $query .= " LEFT JOIN vtiger_users ON vtiger_users.id = vtiger_crmentity.smownerid";
+ $query .= " LEFT JOIN vtiger_groups ON vtiger_groups.groupid = vtiger_crmentity.smownerid";
+
+ $query .= " WHERE vtiger_crmentity.deleted = 0 AND $this->table_name.$this->table_index = $id";
+
+ $return_value = GetRelatedList($currentModule, $related_module, $other, $query, $button, $returnset);
+ }
+ if($return_value == null) $return_value = Array();
+ $return_value['CUSTOM_BUTTON'] = $button;
+
+ return $return_value;
+ }
+
+ /**
+ * Move the related records of the specified list of id's to the given record.
+ * @param String This module name
+ * @param Array List of Entity Id's from which related records need to be transfered
+ * @param Integer Id of the the Record to which the related records are to be moved
+ */
+ function transferRelatedRecords($module, $transferEntityIds, $entityId) {
+ global $adb,$log;
+ $log->debug("Entering function transferRelatedRecords ($module, $transferEntityIds, $entityId)");
+ foreach($transferEntityIds as $transferId){
+
+ // Pick the records related to the entity to be transfered, but do not pick the once which are already related to the current entity.
+ $relatedRecords = $adb->pquery("SELECT relcrmid, relmodule FROM vtiger_crmentityrel WHERE crmid=? AND module=?" .
+ " AND relcrmid NOT IN (SELECT relcrmid FROM vtiger_crmentityrel WHERE crmid=? AND module=?)",
+ array($transferId, $module, $entityId, $module));
+ $numOfRecords = $adb->num_rows($relatedRecords);
+ for($i=0;$i<$numOfRecords;$i++) {
+ $relcrmid = $adb->query_result($relatedRecords,$i,'relcrmid');
+ $relmodule = $adb->query_result($relatedRecords,$i,'relmodule');
+ $adb->pquery("UPDATE vtiger_crmentityrel SET crmid=? WHERE relcrmid=? AND relmodule=? AND crmid=? AND module=?",
+ array($entityId, $relcrmid, $relmodule, $transferId, $module));
+ }
+
+ // 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.
+ $parentRecords = $adb->pquery("SELECT crmid, module FROM vtiger_crmentityrel WHERE relcrmid=? AND relmodule=?" .
+ " AND crmid NOT IN (SELECT crmid FROM vtiger_crmentityrel WHERE relcrmid=? AND relmodule=?)",
+ array($transferId, $module, $entityId, $module));
+ $numOfRecords = $adb->num_rows($parentRecords);
+ for($i=0;$i<$numOfRecords;$i++) {
+ $parcrmid = $adb->query_result($parentRecords,$i,'crmid');
+ $parmodule = $adb->query_result($parentRecords,$i,'module');
+ $adb->pquery("UPDATE vtiger_crmentityrel SET relcrmid=? WHERE crmid=? AND module=? AND relcrmid=? AND relmodule=?",
+ array($entityId, $parcrmid, $parmodule, $transferId, $module));
+ }
+ }
+ $log->debug("Exiting transferRelatedRecords...");
+ }
+
+ /*
+ * Function to get the primary query part of a report for which generateReportsQuery Doesnt exist in module
+ * @param - $module Primary module name
+ * returns the query string formed on fetching the related data for report for primary module
+ */
+ function generateReportsQuery($module){
+ global $adb;
+ $primary = CRMEntity::getInstance($module);
+
+ vtlib_setup_modulevars($module, $primary);
+ $moduletable = $primary->table_name;
+ $moduleindex = $primary->table_index;
+ $modulecftable = $primary->customFieldTable[0];
+ $modulecfindex = $primary->customFieldTable[1];
+
+ if(isset($modulecftable)){
+ $cfquery = "inner join $modulecftable as $modulecftable on $modulecftable.$modulecfindex=$moduletable.$moduleindex";
+ } else {
+ $cfquery = '';
+ }
+ $query = "from $moduletable $cfquery
+ inner join vtiger_crmentity on vtiger_crmentity.crmid=$moduletable.$moduleindex
+ left join vtiger_groups as vtiger_groups".$module." on vtiger_groups".$module.".groupid = vtiger_crmentity.smownerid
+ left join vtiger_users as vtiger_users".$module." on vtiger_users".$module.".id = vtiger_crmentity.smownerid
+ left join vtiger_groups on vtiger_groups.groupid = vtiger_crmentity.smownerid
+ left join vtiger_users on vtiger_users.id = vtiger_crmentity.smownerid";
+
+ $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));
+
+ if($adb->num_rows($fields_query)>0){
+ for($i=0;$i<$adb->num_rows($fields_query);$i++){
+ $field_name = $adb->query_result($fields_query,$i,'fieldname');
+ $field_id = $adb->query_result($fields_query,$i,'fieldid');
+ $tab_name = $adb->query_result($fields_query,$i,'tablename');
+ $ui10_modules_query = $adb->pquery("SELECT relmodule FROM vtiger_fieldmodulerel WHERE fieldid=?",array($field_id));
+
+ if($adb->num_rows($ui10_modules_query)>0){
+ $query.= " left join vtiger_crmentity as vtiger_crmentityRel$module on vtiger_crmentityRel$module.crmid = $tab_name.$field_name and vtiger_crmentityRel$module.deleted=0";
+ for($j=0;$j<$adb->num_rows($ui10_modules_query);$j++){
+ $rel_mod = $adb->query_result($ui10_modules_query,$j,'relmodule');
+ $rel_obj = CRMEntity::getInstance($rel_mod);
+ vtlib_setup_modulevars($rel_mod, $rel_obj);
+
+ $rel_tab_name = $rel_obj->table_name;
+ $rel_tab_index = $rel_obj->table_index;
+ $query.= " left join $rel_tab_name as ".$rel_tab_name."Rel$module on ".$rel_tab_name."Rel$module.$rel_tab_index = vtiger_crmentityRel$module.crmid";
+ }
+ }
+ }
+ }
+ return $query;
+
+ }
+
+ /*
+ * Function to get the secondary query part of a report for which generateReportsSecQuery Doesnt exist in module
+ * @param - $module primary module name
+ * @param - $secmodule secondary module name
+ * returns the query string formed on fetching the related data for report for secondary module
+ */
+ function generateReportsSecQuery($module,$secmodule){
+ global $adb;
+ $secondary = CRMEntity::getInstance($secmodule);
+
+ vtlib_setup_modulevars($secmodule, $secondary);
+
+ $tablename = $secondary->table_name;
+ $tableindex = $secondary->table_index;
+ $modulecftable = $secondary->customFieldTable[0];
+ $modulecfindex = $secondary->customFieldTable[1];
+
+ if(isset($modulecftable)){
+ $cfquery = "left join $modulecftable as $modulecftable on $modulecftable.$modulecfindex=$tablename.$tableindex";
+ } else {
+ $cfquery = '';
+ }
+
+ $query = $this->getRelationQuery($module,$secmodule,"$tablename","$tableindex");
+ $query .=" left join vtiger_crmentity as vtiger_crmentity$secmodule on vtiger_crmentity$secmodule.crmid = $tablename.$tableindex AND vtiger_crmentity$secmodule.deleted=0
+ $cfquery
+ left join vtiger_groups as vtiger_groups".$secmodule." on vtiger_groups".$secmodule.".groupid = vtiger_crmentity$secmodule.smownerid
+ left join vtiger_users as vtiger_users".$secmodule." on vtiger_users".$secmodule.".id = vtiger_crmentity$secmodule.smownerid";
+
+ $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));
+
+ if($adb->num_rows($fields_query)>0){
+ for($i=0;$i<$adb->num_rows($fields_query);$i++){
+ $field_name = $adb->query_result($fields_query,$i,'fieldname');
+ $field_id = $adb->query_result($fields_query,$i,'fieldid');
+ $tab_name = $adb->query_result($fields_query,$i,'tablename');
+ $ui10_modules_query = $adb->pquery("SELECT relmodule FROM vtiger_fieldmodulerel WHERE fieldid=?",array($field_id));
+
+ if($adb->num_rows($ui10_modules_query)>0){
+ $query.= " left join vtiger_crmentity as vtiger_crmentityRel$secmodule on vtiger_crmentityRel$secmodule.crmid = $tab_name.$field_name and vtiger_crmentityRel$secmodule.deleted=0";
+ for($j=0;$j<$adb->num_rows($ui10_modules_query);$j++){
+ $rel_mod = $adb->query_result($ui10_modules_query,$j,'relmodule');
+ $rel_obj = CRMEntity::getInstance($rel_mod);
+ vtlib_setup_modulevars($rel_mod, $rel_obj);
+
+ $rel_tab_name = $rel_obj->table_name;
+ $rel_tab_index = $rel_obj->table_index;
+ $query.= " left join $rel_tab_name as ".$rel_tab_name."Rel$secmodule on ".$rel_tab_name."Rel$secmodule.$rel_tab_index = vtiger_crmentityRel$secmodule.crmid";
+ }
+ }
+ }
+ }
+
+ return $query;
+ }
+
+ /*
+ * Function to get the security query part of a report
+ * @param - $module primary module name
+ * returns the query string formed on fetching the related data for report for security of the module
+ */
+ function getListViewSecurityParameter($module){
+ $tabid=getTabid($module);
+ global $current_user;
+ if($current_user)
+ {
+ require('user_privileges/user_privileges_'.$current_user->id.'.php');
+ require('user_privileges/sharing_privileges_'.$current_user->id.'.php');
+ }
+ $sec_query .= " and (vtiger_crmentity.smownerid in($current_user->id) or vtiger_crmentity.smownerid in(select vtiger_user2role.userid from vtiger_user2role inner join vtiger_users on vtiger_users.id=vtiger_user2role.userid inner join vtiger_role on vtiger_role.roleid=vtiger_user2role.roleid where vtiger_role.parentrole like '".$current_user_parent_role_seq."::%') or vtiger_crmentity.smownerid in(select shareduserid from vtiger_tmp_read_user_sharing_per where userid=".$current_user->id." and tabid=".$tabid.") or (";
+
+ if(sizeof($current_user_groups) > 0)
+ {
+ $sec_query .= " vtiger_groups.groupid in (". implode(",", $current_user_groups) .") or ";
+ }
+ $sec_query .= " vtiger_groups.groupid in(select vtiger_tmp_read_group_sharing_per.sharedgroupid from vtiger_tmp_read_group_sharing_per where userid=".$current_user->id." and tabid=".$tabid."))) ";
+ }
+
+ /*
+ * Function to get the security query part of a report
+ * @param - $module primary module name
+ * returns the query string formed on fetching the related data for report for security of the module
+ */
+ function getSecListViewSecurityParameter($module){
+ $tabid=getTabid($module);
+ global $current_user;
+ if($current_user)
+ {
+ require('user_privileges/user_privileges_'.$current_user->id.'.php');
+ require('user_privileges/sharing_privileges_'.$current_user->id.'.php');
+ }
+ $sec_query .= " and (vtiger_crmentity$module.smownerid in($current_user->id) or vtiger_crmentity$module.smownerid in(select vtiger_user2role.userid from vtiger_user2role inner join vtiger_users on vtiger_users.id=vtiger_user2role.userid inner join vtiger_role on vtiger_role.roleid=vtiger_user2role.roleid where vtiger_role.parentrole like '".$current_user_parent_role_seq."::%') or vtiger_crmentity$module.smownerid in(select shareduserid from vtiger_tmp_read_user_sharing_per where userid=".$current_user->id." and tabid=".$tabid.") or (";
+
+ if(sizeof($current_user_groups) > 0)
+ {
+ $sec_query .= " vtiger_groups$module.groupid in (". implode(",", $current_user_groups) .") or ";
+ }
+ $sec_query .= " vtiger_groups$module.groupid in(select vtiger_tmp_read_group_sharing_per.sharedgroupid from vtiger_tmp_read_group_sharing_per where userid=".$current_user->id." and tabid=".$tabid."))) ";
+ }
+
+ /*
+ * Function to get the relation query part of a report
+ * @param - $module primary module name
+ * @param - $secmodule secondary module name
+ * returns the query string formed on relating the primary module and secondary module
+ */
+ function getRelationQuery($module,$secmodule,$table_name,$column_name){
+ $tab = getRelationTables($module,$secmodule);
+
+ foreach($tab as $key=>$value){
+ $tables[]=$key;
+ $fields[] = $value;
+ }
+ $tabname = $tables[0];
+ $prifieldname = $fields[0][0];
+ $secfieldname = $fields[0][1];
+ $tmpname = $tabname."tmp".$secmodule;
+ $condition = "";
+ if(!empty($tables[1]) && !empty($fields[1])){
+ $condvalue = $tables[1].".".$fields[1];
+ } else {
+ $condvalue = $tabname.".".$prifieldname;
+ }
+ $condition = " {$tmpname}.{$prifieldname} = {$condvalue} ";
+ $entity_check_query = " {$tmpname}.{$secfieldname} IN (SELECT crmid FROM vtiger_crmentity WHERE vtiger_crmentity.deleted=0 AND vtiger_crmentity.setype='{$secmodule}')";
+ $condition_secmod_table = " {$table_name}.{$column_name} = {$tmpname}.{$secfieldname} ";
+ if($tabname=='vtiger_crmentityrel'){
+ $condition = " ($condition OR {$tmpname}.{$secfieldname} = $condvalue) and";
+ $entity_check_query = "({$entity_check_query} OR {$tmpname}.{$prifieldname} IN (SELECT crmid FROM vtiger_crmentity WHERE vtiger_crmentity.deleted=0 AND vtiger_crmentity.setype='{$secmodule}')) ";
+ $condition_secmod_table = "({$condition_secmod_table} OR {$table_name}.{$column_name} = {$tmpname}.{$prifieldname})";
+ } else {
+ $condition .= " and ";
+ }
+
+ $query = " left join {$tabname} as {$tmpname} on {$condition} {$entity_check_query}";
+ $query .= " LEFT JOIN {$table_name} ON {$condition_secmod_table}";
+
+ return $query;
+ }
+ /** END **/
+
+ /**
+ * This function handles the import for uitype 10 fieldtype
+ * @param string $module - the current module name
+ * @param string fieldname - the related to field name
+ */
+ function add_related_to($module, $fieldname){
+ global $adb, $imported_ids, $current_user;
+
+ $related_to = $this->column_fields[$fieldname];
+
+ if(empty($related_to)){
+ return false;
+ }
+
+ //check if the field has module information; if not get the first module
+ if(!strpos($related_to, "::::")){
+ $module = getFirstModule($module, $fieldname);
+ $value = $related_to;
+ }else{
+ //check the module of the field
+ $arr = array();
+ $arr = explode("::::", $related_to);
+ $module = $arr[0];
+ $value = $arr[1];
+ }
+
+ $focus1 = CRMEntity::getInstance($module);
+
+ $entityNameArr = getEntityField($module);
+ $entityName = $entityNameArr['fieldname'];
+ $query = "SELECT vtiger_crmentity.deleted, $focus1->table_name.*
+ FROM $focus1->table_name
+ INNER JOIN vtiger_crmentity ON vtiger_crmentity.crmid=$focus1->table_name.$focus1->table_index
+ where $entityName=? and vtiger_crmentity.deleted=0";
+ $result = $adb->pquery($query, array($value));
+
+ if(!isset($this->checkFlagArr[$module])){
+ $this->checkFlagArr[$module] = (isPermitted($module,'EditView','') == 'yes');
+ }
+
+ if($adb->num_rows($result)>0){
+ //record found
+ $focus1->id = $adb->query_result($result, 0, $focus1->table_index);
+ }elseif($this->checkFlagArr[$module]){
+ //record not found; create it
+ $focus1->column_fields[$focus1->list_link_field] = $value;
+ $focus1->column_fields['assigned_user_id'] = $current_user->id;
+ $focus1->column_fields['modified_user_id'] = $current_user->id;
+ $focus1->save($module);
+
+ $last_import = new UsersLastImport();
+ $last_import->assigned_user_id = $current_user->id;
+ $last_import->bean_type = $module;
+ $last_import->bean_id = $focus1->id;
+ $last_import->save();
+ }else{
+ //record not found and cannot create
+ $this->column_fields[$fieldname] = "";
+ return false;
+ }
+ if(!empty($focus1->id)){
+ $this->column_fields[$fieldname] = $focus1->id;
+ return true;
+ }else{
+ $this->column_fields[$fieldname] = "";
+ return false;
+ }
+ }
+
+ /**
+ * To keep track of action of field filtering and avoiding doing more than once.
+ *
+ * @var Array
+ */
+ protected $__inactive_fields_filtered = false;
+
+ /**
+ * Filter in-active fields based on type
+ *
+ * @param String $module
+ */
+ function filterInactiveFields($module) {
+ if($this->__inactive_fields_filtered) {
+ return;
+ }
+
+ global $adb, $mod_strings;
+
+ // Look for fields that has presence value NOT IN (0,2)
+ $cachedModuleFields = VTCacheUtils::lookupFieldInfo_Module($module, array('1'));
+ if($cachedModuleFields === false) {
+ // Initialize the fields calling suitable API
+ getColumnFields($module);
+ $cachedModuleFields = VTCacheUtils::lookupFieldInfo_Module($module, array('1'));
+ }
+
+ $hiddenFields = array();
+
+ if($cachedModuleFields) {
+ foreach($cachedModuleFields as $fieldinfo) {
+ $fieldLabel= $fieldinfo['fieldlabel'];
+ // NOTE: We should not translate the label to enable field diff based on it down
+ $fieldName = $fieldinfo['fieldname'];
+ $tableName = str_replace("vtiger_","",$fieldinfo['tablename']);
+ $hiddenFields[$fieldLabel] = array($tableName=>$fieldName);
+ }
+ }
+
+ if(isset($this->list_fields)) {
+ $this->list_fields = array_diff_assoc($this->list_fields, $hiddenFields);
+ }
+
+ if(isset($this->search_fields)) {
+ $this->search_fields = array_diff_assoc($this->search_fields, $hiddenFields);
+ }
+
+ // To avoid re-initializing everytime.
+ $this->__inactive_fields_filtered = true;
+ }
+ /** END **/
+}
+?>
diff --git a/oss/vtiger/trunk/data/SugarBean.php b/oss/vtiger/trunk/data/SugarBean.php
new file mode 100644
index 00000000..404a4e88
--- /dev/null
+++ b/oss/vtiger/trunk/data/SugarBean.php
@@ -0,0 +1,456 @@
+id) || $this->id == "")
+ {
+ $isUpdate = false;
+ }
+
+ if ( $this->new_with_id == true )
+ {
+ $isUpdate = false;
+ }
+
+ //$this->date_modified = $this->db->formatDate(date('YmdHis'));
+ $this->date_modified = date('Y-m-d H:i:s');
+ if (isset($current_user)) $this->modified_user_id = $current_user->id;
+
+ if($isUpdate)
+ {
+ $query = "Update ".$this->table_name." set ";
+ }
+ else
+ {
+ //$this->date_entered = $this->db->formatDate(date('YmdHis'));
+ $this->date_entered = date('Y-m-d H:i:s');
+
+ if($this->new_schema &&
+ $this->new_with_id == false)
+ {
+ $this->id = $this->db->getUniqueID("vtiger_users");
+ }
+
+ $query = "INSERT into ".$this->table_name;
+ }
+ // todo - add date modified to the list.
+
+ // write out the SQL statement.
+ //$query .= $this->table_name." set ";
+
+ $firstPass = 0;
+ $insKeys = '(';
+ $insValues = '(';
+ $insParams = array();
+ $updKeyValues='';
+ $updParams = array();
+ foreach($this->column_fields as $field)
+ {
+ // Do not write out the id vtiger_field on the update statement.
+ // We are not allowed to change ids.
+ if($isUpdate && ('id' == $field))
+ continue;
+
+ // Only assign variables that have been set.
+ if(isset($this->$field))
+ {
+ // Try comparing this element with the head element.
+ if(0 == $firstPass)
+ {
+ $firstPass = 1;
+ }
+ else
+ {
+ if($isUpdate)
+ {
+ $updKeyValues = $updKeyValues.", ";
+ }
+ else
+ {
+ $insKeys = $insKeys.", ";
+ $insValues = $insValues.", ";
+ }
+ }
+ /*else
+ $query = $query.", ";
+
+ $query = $query.$field."='".$adb->quote(from_html($this->$field,$isUpdate))."'";
+ */
+ if($isUpdate)
+ {
+ $updKeyValues = $updKeyValues.$field."=?";
+ array_push($updParams, from_html($this->$field,$isUpdate));
+ }
+ else
+ {
+ $insKeys = $insKeys.$field;
+ $insValues = $insValues.'?';
+ array_push($insParams, from_html($this->$field,$isUpdate));
+ }
+ }
+ }
+
+ if($isUpdate)
+ {
+ $query = $query.$updKeyValues." WHERE ID = ?";
+ array_push($updParams, $this->id);
+ $this->log->info("Update $this->object_name: ".$query);
+ $this->db->pquery($query, $updParams, true);
+ }
+ else
+ {
+ $query = $query.$insKeys.") VALUES ".$insValues.")";
+ $this->log->info("Insert: ".$query);
+ $this->db->pquery($query, $insParams, true);
+ }
+
+ // If this is not an update then store the id for later.
+ if(!$isUpdate && !$this->new_schema && !$this->new_with_id)
+ {
+ $this->db->println("Illegal Access - SugarBean");
+ //this is mysql specific
+ $this->id = $this->db->getOne("SELECT LAST_INSERT_ID()" );
+ }
+
+ return $this->id;
+ }
+
+
+ /**
+ * This function retrieves a record of the appropriate type from the DB.
+ * It fills in all of the vtiger_fields from the DB into the object it was called on.
+ * param $id - If ID is specified, it overrides the current value of $this->id. If not specified the current value of $this->id will be used.
+ * returns this - The object that it was called apon or null if exactly 1 record was not found.
+ * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________..
+ function retrieve($id = -1, $encodeThis=true) {
+ if ($id == -1) {
+ $id = $this->id;
+ }
+ if($id == '') {
+ return null;
+ }
+// GS porting vtiger_crmentity
+$query = "SELECT * FROM $this->table_name WHERE $this->table_index = '$id'";
+// $query = "SELECT * FROM $this->table_name WHERE ID = '$id'";
+ $this->log->debug("Retrieve $this->object_name: ".$query);
+
+ $result =& $this->db->requireSingleResult($query, true, "Retrieving record by id $this->table_name:$id found ");
+
+ if(empty($result))
+ {
+ return null;
+ }
+
+ $row = $this->db->fetchByAssoc($result, -1, $encodeThis);
+
+ foreach($this->column_fields as $field)
+ {
+ if(isset($row[$field]))
+ {
+ $this->$field = $row[$field];
+ }
+ }
+ return $this;
+ }
+ */
+
+ function get_list($order_by = "", $where = "", $row_offset = 0, $limit=-1, $max=-1) {
+ $this->log->debug("get_list: order_by = '$order_by' and where = '$where' and limit = '$limit'");
+
+ $query = $this->create_list_query($order_by, $where);
+
+ return $this->process_list_query($query, $row_offset, $limit, $max);
+ }
+
+ /**
+ * This function returns a full (ie non-paged) list of the current object type.
+ * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
+ * All Rights Reserved..
+ * Contributor(s): ______________________________________..
+ */
+ function get_full_list($order_by = "", $where = "") {
+ $this->log->debug("get_full_list: order_by = '$order_by' and where = '$where'");
+ $query = "SELECT * FROM $this->table_name ";
+
+ if($where != "")
+ $query .= " where ($where) AND deleted=0";
+ else
+ $query .= " where deleted=0";
+
+ if(!empty($order_by))
+ $query .= " ORDER BY $order_by";
+
+ $result =& $this->db->query($query, false);
+
+ if($this->db->getRowCount($result) > 0){
+
+ // We have some data.
+ while ($row = $this->db->fetchByAssoc($result)) {
+ foreach($this->list_fields as $field)
+ {
+ if (isset($row[$field])) {
+ $this->$field = $row[$field];
+
+ $this->log->debug("process_full_list: $this->object_name({$row['id']}): ".$field." = ".$this->$field);
+ }
+ else {
+ $this->$field = '';
+ }
+ }
+
+
+ $list[] = clone($this); //added clone tosupport PHP5
+ }
+ }
+
+ if (isset($list)) return $list;
+ else return null;
+
+ }
+
+ function create_list_query($order_by, $where)
+ {
+ $query = "SELECT * FROM $this->table_name ";
+
+ if($where != "")
+ $query .= " where ($where) AND deleted=0";
+ else
+ $query .= " where deleted=0";
+
+ if(!empty($order_by))
+ $query .= " ORDER BY $order_by";
+
+ return $query;
+ }
+
+
+ function process_list_query($query, $row_offset, $limit= -1, $max_per_page = -1)
+ {
+ global $list_max_entries_per_page;
+ $this->log->debug("process_list_query: ".$query);
+ if(!empty($limit) && $limit != -1){
+ $result =& $this->db->limitQuery($query, $row_offset + 0, $limit,true,"Error retrieving $this->object_name list: ");
+ }else{
+ $result =& $this->db->query($query,true,"Error retrieving $this->object_name list: ");
+ }
+
+ $list = Array();
+ if($max_per_page == -1){
+ $max_per_page = $list_max_entries_per_page;
+ }
+ $rows_found = $this->db->getRowCount($result);
+
+ $this->log->debug("Found $rows_found ".$this->object_name."s");
+
+ $previous_offset = $row_offset - $max_per_page;
+ $next_offset = $row_offset + $max_per_page;
+
+ if($rows_found != 0)
+ {
+
+ // We have some data.
+
+ 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)){
+ foreach($this->list_fields as $field)
+ {
+ if (isset($row[$field])) {
+ $this->$field = $row[$field];
+
+
+ $this->log->debug("$this->object_name({$row['id']}): ".$field." = ".$this->$field);
+ }
+ else
+ {
+ $this->$field = "";
+ }
+ }
+
+
+ $list[] = clone($this); //added clone to support PHP5
+ }
+ }
+
+ $response = Array();
+ $response['list'] = $list;
+ $response['row_count'] = $rows_found;
+ $response['next_offset'] = $next_offset;
+ $response['previous_offset'] = $previous_offset;
+
+ return $response;
+ }
+
+
+ /**
+ * Track the viewing of a detail record. This leverages get_summary_text() which is object specific
+ * params $user_id - The user that is viewing the record.
+ * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
+ * All Rights Reserved..
+ * Contributor(s): ______________________________________..
+ */
+ function track_view($user_id, $current_module,$id='')
+ {
+ $this->log->debug("About to call vtiger_tracker (user_id, module_name, item_id)($user_id, $current_module, $this->id)");
+
+ $tracker = new Tracker();
+ $tracker->track_view($user_id, $current_module, $id, '');
+ }
+
+
+ /** This function should be overridden in each module. It marks an item as deleted.
+ * If it is not overridden, then marking this type of item is not allowed
+ * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
+ * All Rights Reserved..
+ * Contributor(s): ______________________________________..
+ */
+ function mark_deleted($id)
+ {
+ $query = "UPDATE $this->table_name set deleted=1 where id=?";
+ $this->db->pquery($query, array($id), true,"Error marking record deleted: ");
+
+ $this->mark_relationships_deleted($id);
+
+ // Take the item off of the recently viewed lists.
+ $tracker = new Tracker();
+ $tracker->delete_item_history($id);
+
+ }
+
+
+ /* This is to allow subclasses to fill in row specific columns of a list view form
+ function list_view_parse_additional_sections(&$list_form)
+ {
+ }
+ */
+ /* This function assigns all of the values into the template for the list view
+ function get_list_view_array(){
+ $return_array = Array();
+
+ foreach($this->list_fields as $field)
+ {
+ $return_array[strtoupper($field)] = $this->$field;
+ }
+
+ return $return_array;
+ }
+ function get_list_view_data()
+ {
+
+ return $this->get_list_view_array();
+ }
+
+ function get_where(&$fields_array)
+ {
+ $where_clause = "WHERE ";
+ $first = 1;
+ foreach ($fields_array as $name=>$value)
+ {
+ if ($first)
+ {
+ $first = 0;
+ }
+ else
+ {
+ $where_clause .= " AND ";
+ }
+
+ $where_clause .= "$name = ".$adb->quote($value)."";
+ }
+
+ $where_clause .= " AND deleted=0";
+ return $where_clause;
+ }
+
+
+ function retrieve_by_string_fields($fields_array, $encode=true)
+ {
+ $where_clause = $this->get_where($fields_array);
+
+ $query = "SELECT * FROM $this->table_name $where_clause";
+ $this->log->debug("Retrieve $this->object_name: ".$query);
+ $result =& $this->db->requireSingleResult($query, true, "Retrieving record $where_clause:");
+ if( empty($result))
+ {
+ return null;
+ }
+
+ $row = $this->db->fetchByAssoc($result,-1, $encode);
+
+ foreach($this->column_fields as $field)
+ {
+ if(isset($row[$field]))
+ {
+ $this->$field = $row[$field];
+ }
+ }
+ return $this;
+ }
+
+ // this method is called during an import before inserting a bean
+ // define an associative array called $special_fields
+ // the keys are user defined, and don't directly map to the bean's vtiger_fields
+ // the value is the method name within that bean that will do extra
+ // processing for that vtiger_field. example: 'full_name'=>'get_names_from_full_name'
+
+ function process_special_fields()
+ {
+ foreach ($this->special_functions as $func_name)
+ {
+ if ( method_exists($this,$func_name) )
+ {
+ $this->$func_name();
+ }
+ }
+ }
+
+ */
+}
+
+
+?>
diff --git a/oss/vtiger/trunk/data/Tracker.php b/oss/vtiger/trunk/data/Tracker.php
new file mode 100644
index 00000000..cc2e9623
--- /dev/null
+++ b/oss/vtiger/trunk/data/Tracker.php
@@ -0,0 +1,239 @@
+log = LoggerManager::getLogger('Tracker');
+ // $this->db = PearDatabase::getInstance();
+ global $adb;
+ $this->db = $adb;
+ }
+
+ /**
+ * Add this new item to the vtiger_tracker vtiger_table. If there are too many items (global config for now)
+ * then remove the oldest item. If there is more than one extra item, log an error.
+ * If the new item is the same as the most recent item then do not change the list
+ * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________..
+ */
+ function track_view($user_id, $current_module, $item_id, $item_summary)
+ {
+ global $adb;
+ $this->delete_history($user_id, $item_id);
+ global $log;
+$log->info("in track view method ".$current_module);
+
+//No genius required. Just add an if case and change the query so that it puts the tracker entry whenever you touch on the DetailView of the required entity
+ //get the first name and last name from the respective modules
+ if($current_module != '')
+ {
+ $query = "select fieldname,tablename,entityidfield from vtiger_entityname where modulename = ?";
+ $result = $adb->pquery($query, array($current_module));
+ $fieldsname = $adb->query_result($result,0,'fieldname');
+ $tablename = $adb->query_result($result,0,'tablename');
+ $entityidfield = $adb->query_result($result,0,'entityidfield');
+ if(!(strpos($fieldsname,',') === false))
+ {
+ // concatenate multiple fields with an whitespace between them
+ $fieldlists = explode(',',$fieldsname);
+ $fl = array();
+ foreach($fieldlists as $w => $c)
+ {
+ if (count($fl))
+ $fl[] = "' '";
+ $fl[] = $c;
+ }
+ $fieldsname = $adb->sql_concat($fl);
+ }
+ $query1 = "select $fieldsname as entityname from $tablename where $entityidfield = ?";
+ $result = $adb->pquery($query1, array($item_id));
+ $item_summary = $adb->query_result($result,0,'entityname');
+ if(strlen($item_summary) > 30)
+ {
+ $item_summary=substr($item_summary,0,30).'...';
+ }
+ }
+
+ #if condition added to skip vtiger_faq in last viewed history
+ $query = "INSERT into $this->table_name (user_id, module_name, item_id, item_summary) values (?,?,?,?)";
+ $qparams = array($user_id, $current_module, $item_id, $item_summary);
+
+ $this->log->info("Track Item View: ".$query);
+
+ $this->db->pquery($query, $qparams, true);
+
+
+ $this->prune_history($user_id);
+ }
+
+ /**
+ * param $user_id - The id of the user to retrive the history for
+ * param $module_name - Filter the history to only return records from the specified module. If not specified all records are returned
+ * return - return the array of result set rows from the query. All of the vtiger_table vtiger_fields are included
+ * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________..
+ */
+ function get_recently_viewed($user_id, $module_name = "")
+ {
+ if (empty($user_id)) {
+ return;
+ }
+
+// $query = "SELECT * from $this->table_name WHERE user_id='$user_id' ORDER BY id DESC";
+ $query = "SELECT * from $this->table_name inner join vtiger_crmentity on vtiger_crmentity.crmid=vtiger_tracker.item_id WHERE user_id=? and vtiger_crmentity.deleted=0 ORDER BY id DESC";
+ $this->log->debug("About to retrieve list: $query");
+ $result = $this->db->pquery($query, array($user_id), true);
+ $list = Array();
+ while($row = $this->db->fetchByAssoc($result, -1, false))
+ {
+ //echo "while loppp";
+ //echo ' ';
+
+
+ // If the module was not specified or the module matches the module of the row, add the row to the list
+ if($module_name == "" || $row[module_name] == $module_name)
+ {
+ //Adding Security check
+ require_once('include/utils/utils.php');
+ require_once('include/utils/UserInfoUtil.php');
+ $entity_id = $row['item_id'];
+ $module = $row['module_name'];
+ //echo "module is ".$module." id is ".$entity_id;
+ //echo ' ';
+ if($module == "Users")
+ {
+ global $current_user;
+ if(is_admin($current_user))
+ {
+ $per = 'yes';
+ }
+ }
+ else
+ {
+
+ $per = isPermitted($module,'DetailView',$entity_id);
+
+ }
+ if($per == 'yes')
+ {
+ $list[] = $row;
+ }
+ }
+ }
+ return $list;
+ }
+
+
+
+ /**
+ * INTERNAL -- This method cleans out any entry for a record for a user.
+ * It is used to remove old occurances of previously viewed items.
+ * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________..
+ */
+ function delete_history( $user_id, $item_id)
+ {
+ $query = "DELETE from $this->table_name WHERE user_id=? and item_id=?";
+ $this->db->pquery($query, array($user_id, $item_id), true);
+ }
+
+ /**
+ * INTERNAL -- This method cleans out any entry for a record.
+ * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________..
+ */
+ function delete_item_history($item_id)
+ {
+ $query = "DELETE from $this->table_name WHERE item_id=?";
+ $this->db->pquery($query, array($item_id), true);
+
+ }
+
+ /**
+ * INTERNAL -- This function will clean out old history records for this user if necessary.
+ * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________..
+ */
+ function prune_history($user_id)
+ {
+ global $history_max_viewed;
+
+ // Check to see if the number of items in the list is now greater than the config max.
+ $query = "SELECT count(*) from $this->table_name WHERE user_id='$user_id'";
+
+ $this->log->debug("About to verify history size: $query");
+
+ $count = $this->db->getOne($query);
+
+
+ $this->log->debug("history size: (current, max)($count, $history_max_viewed)");
+ while($count > $history_max_viewed)
+ {
+ // delete the last one. This assumes that entries are added one at a time.
+ // we should never add a bunch of entries
+ $query = "SELECT * from $this->table_name WHERE user_id='$user_id' ORDER BY id ASC";
+ $this->log->debug("About to try and find oldest item: $query");
+ $result = $this->db->limitQuery($query,0,1);
+
+ $oldest_item = $this->db->fetchByAssoc($result, -1, false);
+ $query = "DELETE from $this->table_name WHERE id=?";
+ $this->log->debug("About to delete oldest item: ");
+
+ $result = $this->db->pquery($query, array($oldest_item['id']), true);
+
+
+ $count--;
+ }
+ }
+
+}
+?>