Issues (4069)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

include/ListView/ListViewData.php (10 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2 1
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3
/*********************************************************************************
4
 * SugarCRM Community Edition is a customer relationship management program developed by
5
 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
6
7
 * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd.
8
 * Copyright (C) 2011 - 2014 Salesagility Ltd.
9
 *
10
 * This program is free software; you can redistribute it and/or modify it under
11
 * the terms of the GNU Affero General Public License version 3 as published by the
12
 * Free Software Foundation with the addition of the following permission added
13
 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
14
 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
15
 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
16
 *
17
 * This program is distributed in the hope that it will be useful, but WITHOUT
18
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19
 * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
20
 * details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License along with
23
 * this program; if not, see http://www.gnu.org/licenses or write to the Free
24
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25
 * 02110-1301 USA.
26
 *
27
 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
28
 * SW2-130, Cupertino, CA 95014, USA. or at email address [email protected].
29
 *
30
 * The interactive user interfaces in modified source and object code versions
31
 * of this program must display Appropriate Legal Notices, as required under
32
 * Section 5 of the GNU Affero General Public License version 3.
33
 *
34
 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
35
 * these Appropriate Legal Notices must retain the display of the "Powered by
36
 * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not
37
 * reasonably feasible for  technical reasons, the Appropriate Legal Notices must
38
 * display the words  "Powered by SugarCRM" and "Supercharged by SuiteCRM".
39
 ********************************************************************************/
40
41
42 1
require_once('include/EditView/SugarVCR.php');
43
/**
44
 * Data set for ListView
45
 * @api
46
 */
47
class ListViewData {
48
49
	var $additionalDetails = true;
50
    var $listviewName = null;
51
	var $additionalDetailsAllow = null;
52
    var $additionalDetailsAjax = true; // leave this true when using filter fields
53
    var $additionalDetailsFieldToAdd = 'NAME'; // where the span will be attached to
54
    var $base_url = null;
55
    /*
56
     * If you want overwrite the query for the count of the listview set this to your query
57
     * otherwise leave it empty and it will use SugarBean::create_list_count_query
58
     */
59
    var $count_query = '';
60
61
	/**
62
	 * Constructor sets the limitName to look up the limit in $sugar_config
63
	 *
64
	 * @return ListViewData
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
65
	 */
66 5
	public function __construct() {
67 5
		$this->limitName = 'list_max_entries_per_page';
68 5
		$this->db = DBManagerFactory::getInstance('listviews');
69 5
	}
70
71
    /**
72
     * @deprecated deprecated since version 7.6, PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code, use __construct instead
73
     */
74
    public function ListViewData(){
75
        $deprecatedMessage = 'PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code';
76
        if(isset($GLOBALS['log'])) {
77
            $GLOBALS['log']->deprecated($deprecatedMessage);
78
        }
79
        else {
80
            trigger_error($deprecatedMessage, E_USER_DEPRECATED);
81
        }
82
        self::__construct();
83
    }
84
85
86
	/**
87
	 * checks the request for the order by and if that is not set then it checks the session for it
88
	 *
89
	 * @return array containing the keys orderBy => field being ordered off of and sortOrder => the sort order of that field
90
	 */
91 4
	function getOrderBy($orderBy = '', $direction = '') {
92 4
		if (!empty($orderBy) || !empty($_REQUEST[$this->var_order_by])) {
93
            if(!empty($_REQUEST[$this->var_order_by])) {
94
    			$direction = 'ASC';
95
    			$orderBy = $_REQUEST[$this->var_order_by];
96
    			if(!empty($_REQUEST['lvso']) && (empty($_SESSION['lvd']['last_ob']) || strcmp($orderBy, $_SESSION['lvd']['last_ob']) == 0) ){
97
    				$direction = $_REQUEST['lvso'];
98
    			}
99
            }
100
            $_SESSION[$this->var_order_by] = array('orderBy'=>$orderBy, 'direction'=> $direction);
101
            $_SESSION['lvd']['last_ob'] = $orderBy;
102
        }
103
		else {
104 4
            $userPreferenceOrder = $GLOBALS['current_user']->getPreference('listviewOrder', $this->var_name);
105 4
			if(!empty($_SESSION[$this->var_order_by])) {
106
				$orderBy = $_SESSION[$this->var_order_by]['orderBy'];
107
				$direction = $_SESSION[$this->var_order_by]['direction'];
108 4
            } elseif (!empty($userPreferenceOrder)) {
109
                $orderBy = $userPreferenceOrder['orderBy'];
110
                $direction = $userPreferenceOrder['sortOrder'];
111
            } else {
112 4
				$orderBy = 'date_entered';
113 4
				$direction = 'DESC';
114
			}
115
		}
116 4
		if(!empty($direction)) {
117 4
    		if(strtolower($direction) == "desc") {
118 4
    		    $direction = 'DESC';
119
    		} else {
120
    		    $direction = 'ASC';
121
    		}
122
		}
123 4
		return array('orderBy' => $orderBy, 'sortOrder' => $direction);
124
	}
125
126
	/**
127
	 * gets the reverse of the sort order for use on links to reverse a sort order from what is currently used
128
	 *
129
	 * @param STRING (ASC or DESC) $current_order
130
	 * @return  STRING (ASC or DESC)
131
	 */
132 4
	function getReverseSortOrder($current_order){
133 4
		return (strcmp(strtolower($current_order), 'asc') == 0)?'DESC':'ASC';
134
	}
135
	/**
136
	 * gets the limit of how many rows to show per page
137
	 *
138
	 * @return INT (the limit)
139
	 */
140 3
	function getLimit() {
141 3
		return $GLOBALS['sugar_config'][$this->limitName];
142
	}
143
144
	/**
145
	 * returns the current offset
146
	 *
147
	 * @return INT (current offset)
148
	 */
149 4
	function getOffset() {
150 4
		return (!empty($_REQUEST[$this->var_offset])) ? $_REQUEST[$this->var_offset] : 0;
151
	}
152
153
    /**
154
     * generates the base url without
155
     * any files in the block variables will not be part of the url
156
     *
157
     * @return Array (the base url as an array)
158
     */
159 4
    protected function getBaseQuery()
160
    {
161 4
        global $beanList;
162
163 4
        $blockVariables = array('mass', 'uid', 'massupdate', 'delete', 'merge', 'selectCount',$this->var_order_by, $this->var_offset, 'lvso', 'sortOrder', 'orderBy', 'request_data', 'current_query_by_page');
164 4
        foreach($beanList as $bean)
165
        {
166 4
            $blockVariables[] = 'Home2_'.strtoupper($bean).'_ORDER_BY';
167
        }
168 4
        $blockVariables[] = 'Home2_CASE_ORDER_BY';
169
170
        // Added mostly for the unit test runners, which may not have these superglobals defined
171 4
        $params = array_merge($_POST, $_GET);
172 4
        $params = array_diff_key($params, array_flip($blockVariables));
173
174 4
        return $params;
175
    }
176
177
	/**
178
	 * based off of a base name it sets base, offset, and order by variable names to retrieve them from requests and sessions
179
	 *
180
	 * @param unknown_type $baseName
181
	 */
182 4
	function setVariableName($baseName, $where, $listviewName = null){
183 4
        global $timedate;
184 4
        $module = (!empty($listviewName)) ? $listviewName: $_REQUEST['module'];
185 4
        $this->var_name = $module .'2_'. strtoupper($baseName);
186
187 4
		$this->var_order_by = $this->var_name .'_ORDER_BY';
188 4
		$this->var_offset = $this->var_name . '_offset';
189 4
        $timestamp = sugar_microtime();
190 4
        $this->stamp = $timestamp;
191
192 4
        $_SESSION[$module .'2_QUERY_QUERY'] = $where;
193
194 4
        $_SESSION[strtoupper($baseName) . "_FROM_LIST_VIEW"] = $timestamp;
195 4
        $_SESSION[strtoupper($baseName) . "_DETAIL_NAV_HISTORY"] = false;
196 4
	}
197
198
	function getTotalCount($main_query){
199
		if(!empty($this->count_query)){
200
		    $count_query = $this->count_query;
201
		}else{
202
	        $count_query = $this->seed->create_list_count_query($main_query);
203
	    }
204
		$result = $this->db->query($count_query);
205
		if($row = $this->db->fetchByAssoc($result)){
206
			return $row['c'];
207
		}
208
		return 0;
209
	}
210
211
	/**
212
	 * takes in a seed and creates the list view query based off of that seed
213
	 * if the $limit value is set to -1 then it will use the default limit and offset values
214
	 *
215
	 * it will return an array with two key values
216
	 * 	1. 'data'=> this is an array of row data
217
	 *  2. 'pageData'=> this is an array containg three values
218
	 * 			a.'ordering'=> array('orderBy'=> the field being ordered by , 'sortOrder'=> 'ASC' or 'DESC')
219
	 * 			b.'urls'=>array('baseURL'=>url used to generate other urls ,
220
	 * 							'orderBy'=> the base url for order by
221
	 * 							//the following may not be set (so check empty to see if they are set)
222
	 * 							'nextPage'=> the url for the next group of results,
223
	 * 							'prevPage'=> the url for the prev group of results,
224
	 * 							'startPage'=> the url for the start of the group,
225
	 * 							'endPage'=> the url for the last set of results in the group
226
	 * 			c.'offsets'=>array(
227
	 * 								'current'=>current offset
228
	 * 								'next'=> next group offset
229
	 * 								'prev'=> prev group offset
230
	 * 								'end'=> the offset of the last group
231
	 * 								'total'=> the total count (only accurate if totalCounted = true otherwise it is either the total count if less than the limit or the total count + 1 )
232
	 * 								'totalCounted'=> if a count query was used to get the total count
233
	 *
234
	 * @param SugarBean $seed
235
	 * @param string $where
236
	 * @param int:0 $offset
0 ignored issues
show
The doc-type int:0 could not be parsed: Unknown type name "int:0" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
237
	 * @param int:-1 $limit
0 ignored issues
show
The doc-type int:-1 could not be parsed: Unknown type name "int:-1" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
238
	 * @param string[]:array() $filter_fields
0 ignored issues
show
The doc-type string[]:array() could not be parsed: Expected "|" or "end of type", but got ":array" at position 8. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
239
	 * @param array:array() $params
0 ignored issues
show
The doc-type array:array() could not be parsed: Unknown type name "array:array" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
240
	 * 	Potential $params are
241
		$params['distinct'] = use distinct key word
242
		$params['include_custom_fields'] = (on by default)
243
        $params['custom_XXXX'] = append custom statements to query
244
	 * @param string:'id' $id_field
0 ignored issues
show
The doc-type string:'id' could not be parsed: Unknown type name "string:'id'" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
245
	 * @return array('data'=> row data, 'pageData' => page data information, 'query' => original query string)
0 ignored issues
show
The doc-type array('data'=> could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
246
	 */
247 4
	function getListViewData($seed, $where, $offset=-1, $limit = -1, $filter_fields=array(),$params=array(),$id_field = 'id',$singleSelect=true) {
248 4
        global $current_user;
249 4
        SugarVCR::erase($seed->module_dir);
250 4
        $this->seed =& $seed;
251 4
        $totalCounted = empty($GLOBALS['sugar_config']['disable_count_query']);
252 4
        $_SESSION['MAILMERGE_MODULE_FROM_LISTVIEW'] = $seed->module_dir;
253 4
        if(empty($_REQUEST['action']) || $_REQUEST['action'] != 'Popup'){
254 4
            $_SESSION['MAILMERGE_MODULE'] = $seed->module_dir;
255
        }
256
257 4
        $this->setVariableName($seed->object_name, $where, $this->listviewName);
258
259 4
		$this->seed->id = '[SELECT_ID_LIST]';
260
261
        // if $params tell us to override all ordering
262 4
        if(!empty($params['overrideOrder']) && !empty($params['orderBy'])) {
263
            $order = $this->getOrderBy(strtolower($params['orderBy']), (empty($params['sortOrder']) ? '' : $params['sortOrder'])); // retreive from $_REQUEST
264
        }
265
        else {
266 4
            $order = $this->getOrderBy(); // retreive from $_REQUEST
267
        }
268
269
        // still empty? try to use settings passed in $param
270 4
        if(empty($order['orderBy']) && !empty($params['orderBy'])) {
271
            $order['orderBy'] = $params['orderBy'];
272
            $order['sortOrder'] =  (empty($params['sortOrder']) ? '' : $params['sortOrder']);
273
        }
274
275
        //rrs - bug: 21788. Do not use Order by stmts with fields that are not in the query.
276
        // Bug 22740 - Tweak this check to strip off the table name off the order by parameter.
277
        // Samir Gandhi : Do not remove the report_cache.date_modified condition as the report list view is broken
278 4
        $orderby = $order['orderBy'];
279 4
        if (strpos($order['orderBy'],'.') && ($order['orderBy'] != "report_cache.date_modified")) {
280
            $orderby = substr($order['orderBy'],strpos($order['orderBy'],'.')+1);
281
        }
282 4
        if ($orderby != 'date_entered' && !in_array($orderby, array_keys($filter_fields))) {
283
        	$order['orderBy'] = '';
284
        	$order['sortOrder'] = '';
285
        }
286
287 4
		if (empty($order['orderBy'])) {
288
            $orderBy = '';
289
        } else {
290 4
            $orderBy = $order['orderBy'] . ' ' . $order['sortOrder'];
291
            //wdong, Bug 25476, fix the sorting problem of Oracle.
292 4
            if (isset($params['custom_order_by_override']['ori_code']) && $order['orderBy'] == $params['custom_order_by_override']['ori_code'])
293
                $orderBy = $params['custom_order_by_override']['custom_code'] . ' ' . $order['sortOrder'];
294
        }
295
296 4
        if (empty($params['skipOrderSave'])) { // don't save preferences if told so
297 4
            $current_user->setPreference('listviewOrder', $order, 0, $this->var_name); // save preference
298
        }
299
300
		// If $params tells us to override for the special last_name, first_name sorting
301 4
		if (!empty($params['overrideLastNameOrder']) && $order['orderBy'] == 'last_name') {
302
			$orderBy = 'last_name '.$order['sortOrder'].', first_name '.$order['sortOrder'];
303
		}
304
305 4
		$ret_array = $seed->create_new_list_query($orderBy, $where, $filter_fields, $params, 0, '', true, $seed, $singleSelect);
306 4
        $ret_array['inner_join'] = '';
307 4
        if (!empty($this->seed->listview_inner_join)) {
308 1
            $ret_array['inner_join'] = ' ' . implode(' ', $this->seed->listview_inner_join) . ' ';
309
        }
310
311 4
		if(!is_array($params)) $params = array();
312 4
        if(!isset($params['custom_select'])) $params['custom_select'] = '';
313 4
        if(!isset($params['custom_from'])) $params['custom_from'] = '';
314 4
        if(!isset($params['custom_where'])) $params['custom_where'] = '';
315 4
        if(!isset($params['custom_order_by'])) $params['custom_order_by'] = '';
316 4
		$main_query = $ret_array['select'] . $params['custom_select'] . $ret_array['from'] . $params['custom_from'] . $ret_array['inner_join']. $ret_array['where'] . $params['custom_where'] . $ret_array['order_by'] . $params['custom_order_by'];
317
		//C.L. - Fix for 23461
318 4
		if(empty($_REQUEST['action']) || $_REQUEST['action'] != 'Popup') {
319 4
          	   $_SESSION['export_where'] = $ret_array['where'];
320
		}
321 4
   		if($limit < -1) {
322
			$result = $this->db->query($main_query);
323
		}
324
		else {
325 4
			if($limit == -1) {
326 3
				$limit = $this->getLimit();
327
            }
328 4
			$dyn_offset = $this->getOffset();
329 4
			if($dyn_offset > 0 || !is_int($dyn_offset))$offset = $dyn_offset;
330
331 4
            if(strcmp($offset, 'end') == 0){
332
            	$totalCount = $this->getTotalCount($main_query);
333
            	$offset = (floor(($totalCount -1) / $limit)) * $limit;
334
            }
335 4
            if($this->seed->ACLAccess('ListView')) {
336 4
                $result = $this->db->limitQuery($main_query, $offset, $limit + 1);
337
            }
338
            else {
339
                $result = array();
340
            }
341
342
		}
343
344 4
		$data = array();
345
346 4
		$temp = clone $seed;
347
348 4
		$rows = array();
349 4
		$count = 0;
350 4
        $idIndex = array();
351 4
        $id_list = '';
352
353 4
   		while(($row = $this->db->fetchByAssoc($result)) != null)
354
        {
355 2
   			if($count < $limit)
356
            {
357 2
   				$id_list .= ',\''.$row[$id_field].'\'';
358 2
   				$idIndex[$row[$id_field]][] = count($rows);
359 2
   				$rows[] = $seed->convertRow($row);
360
   			}
361 2
   			$count++;
362
   		}
363
364 4
        if (!empty($id_list))
365
        {
366 2
            $id_list = '('.substr($id_list, 1).')';
367
        }
368
369 4
        SugarVCR::store($this->seed->module_dir,  $main_query);
370 4
		if($count != 0) {
371
			//NOW HANDLE SECONDARY QUERIES
372 2
			if(!empty($ret_array['secondary_select'])) {
373
				$secondary_query = $ret_array['secondary_select'] . $ret_array['secondary_from'] . ' WHERE '.$this->seed->table_name.'.id IN ' .$id_list;
374
                if(isset($ret_array['order_by']))
375
                {
376
                    $secondary_query .= ' ' . $ret_array['order_by'];
377
                }
378
379
                $secondary_result = $this->db->query($secondary_query);
380
381
                $ref_id_count = array();
382
				while($row = $this->db->fetchByAssoc($secondary_result)) {
383
384
                    $ref_id_count[$row['ref_id']][] = true;
385
					foreach($row as $name=>$value) {
386
						//add it to every row with the given id
387
						foreach($idIndex[$row['ref_id']] as $index){
388
						    $rows[$index][$name]=$value;
389
						}
390
					}
391
				}
392
393
                $rows_keys = array_keys($rows);
394
                foreach($rows_keys as $key)
395
                {
396
                    $rows[$key]['secondary_select_count'] = count($ref_id_count[$rows[$key]['ref_id']]);
397
                }
398
			}
399
400
            // retrieve parent names
401 2
            if(!empty($filter_fields['parent_name']) && !empty($filter_fields['parent_id']) && !empty($filter_fields['parent_type'])) {
402
                foreach($idIndex as $id => $rowIndex) {
403
                    if(!isset($post_retrieve[$rows[$rowIndex[0]]['parent_type']])) {
404
                        $post_retrieve[$rows[$rowIndex[0]]['parent_type']] = array();
405
                    }
406
                    if(!empty($rows[$rowIndex[0]]['parent_id'])) $post_retrieve[$rows[$rowIndex[0]]['parent_type']][] = array('child_id' => $id , 'parent_id'=> $rows[$rowIndex[0]]['parent_id'], 'parent_type' => $rows[$rowIndex[0]]['parent_type'], 'type' => 'parent');
407
                }
408
                if(isset($post_retrieve)) {
409
                    $parent_fields = $seed->retrieve_parent_fields($post_retrieve);
410
                    foreach($parent_fields as $child_id => $parent_data) {
411
                        //add it to every row with the given id
412
						foreach($idIndex[$child_id] as $index){
413
						    $rows[$index]['parent_name']= $parent_data['parent_name'];
414
						}
415
                    }
416
                }
417
            }
418
419 2
			$pageData = array();
420
421 2
			reset($rows);
422 2
			while($row = current($rows)){
423
424 2
                $temp = clone $seed;
425 2
			    $dataIndex = count($data);
426
427 2
			    $temp->setupCustomFields($temp->module_dir);
428 2
				$temp->loadFromRow($row);
429 2
				if (empty($this->seed->assigned_user_id) && !empty($temp->assigned_user_id)) {
430
				    $this->seed->assigned_user_id = $temp->assigned_user_id;
431
				}
432 2
				if($idIndex[$row[$id_field]][0] == $dataIndex){
433 2
				    $pageData['tag'][$dataIndex] = $temp->listviewACLHelper();
434
				}else{
435
				    $pageData['tag'][$dataIndex] = $pageData['tag'][$idIndex[$row[$id_field]][0]];
436
				}
437 2
				$data[$dataIndex] = $temp->get_list_view_data($filter_fields);
0 ignored issues
show
The call to SugarBean::get_list_view_data() has too many arguments starting with $filter_fields.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
438 2
                $detailViewAccess = $temp->ACLAccess('DetailView');
439 2
                $editViewAccess = $temp->ACLAccess('EditView');
440 2
                $pageData['rowAccess'][$dataIndex] = array('view' => $detailViewAccess, 'edit' => $editViewAccess);
441 2
                $additionalDetailsAllow = $this->additionalDetails && $detailViewAccess && (file_exists(
442 2
                         'modules/' . $temp->module_dir . '/metadata/additionalDetails.php'
443 2
                     ) || file_exists('custom/modules/' . $temp->module_dir . '/metadata/additionalDetails.php'));
444 2
                $additionalDetailsEdit = $editViewAccess;
445 2
                if($additionalDetailsAllow) {
446 2
                    if($this->additionalDetailsAjax) {
447 2
					   $ar = $this->getAdditionalDetailsAjax($data[$dataIndex]['ID']);
448
                    }
449
                    else {
450
                        $additionalDetailsFile = 'modules/' . $this->seed->module_dir . '/metadata/additionalDetails.php';
451
                        if(file_exists('custom/modules/' . $this->seed->module_dir . '/metadata/additionalDetails.php')){
452
                        	$additionalDetailsFile = 'custom/modules/' . $this->seed->module_dir . '/metadata/additionalDetails.php';
453
                        }
454
                        require_once($additionalDetailsFile);
455
                        $ar = $this->getAdditionalDetails($data[$dataIndex],
456
                                    (empty($this->additionalDetailsFunction) ? 'additionalDetails' : $this->additionalDetailsFunction) . $this->seed->object_name,
457
                                    $additionalDetailsEdit);
458
                    }
459 2
                    $pageData['additionalDetails'][$dataIndex] = $ar['string'];
460 2
                    $pageData['additionalDetails']['fieldToAddTo'] = $ar['fieldToAddTo'];
461
				}
462 2
				next($rows);
463
			}
464
		}
465 4
		$nextOffset = -1;
466 4
		$prevOffset = -1;
467 4
		$endOffset = -1;
468 4
		if($count > $limit) {
469
			$nextOffset = $offset + $limit;
470
		}
471
472 4
		if($offset > 0) {
473
			$prevOffset = $offset - $limit;
474
			if($prevOffset < 0)$prevOffset = 0;
475
		}
476 4
		$totalCount = $count + $offset;
477
478 4
		if( $count >= $limit && $totalCounted){
479
			$totalCount  = $this->getTotalCount($main_query);
480
		}
481 4
		SugarVCR::recordIDs($this->seed->module_dir, array_keys($idIndex), $offset, $totalCount);
482
        $module_names = array(
483
            'Prospects' => 'Targets'
484 4
        );
485 4
		$endOffset = (floor(($totalCount - 1) / $limit)) * $limit;
486 4
		$pageData['ordering'] = $order;
487 4
		$pageData['ordering']['sortOrder'] = $this->getReverseSortOrder($pageData['ordering']['sortOrder']);
488
        //get url parameters as an array
489 4
        $pageData['queries'] = $this->generateQueries($pageData['ordering']['sortOrder'], $offset, $prevOffset, $nextOffset,  $endOffset, $totalCounted);
490
        //join url parameters from array to a string
491 4
        $pageData['urls'] = $this->generateURLS($pageData['queries']);
492 4
		$pageData['offsets'] = array( 'current'=>$offset, 'next'=>$nextOffset, 'prev'=>$prevOffset, 'end'=>$endOffset, 'total'=>$totalCount, 'totalCounted'=>$totalCounted);
493 4
		$pageData['bean'] = array('objectName' => $seed->object_name, 'moduleDir' => $seed->module_dir, 'moduleName' => strtr($seed->module_dir, $module_names));
494 4
        $pageData['stamp'] = $this->stamp;
495 4
        $pageData['access'] = array('view' => $this->seed->ACLAccess('DetailView'), 'edit' => $this->seed->ACLAccess('EditView'));
496 4
		$pageData['idIndex'] = $idIndex;
497 4
        if(!$this->seed->ACLAccess('ListView')) {
498
            $pageData['error'] = 'ACL restricted access';
499
        }
500
501 4
        $queryString = '';
502
503 4
        if( isset($_REQUEST["searchFormTab"]) && $_REQUEST["searchFormTab"] == "advanced_search" ||
504 4
        	isset($_REQUEST["type_basic"]) && (count($_REQUEST["type_basic"] > 1) || $_REQUEST["type_basic"][0] != "") ||
505 4
        	isset($_REQUEST["module"]) && $_REQUEST["module"] == "MergeRecords")
506
        {
507
            $queryString = "-advanced_search";
508
        }
509 4
        else if (isset($_REQUEST["searchFormTab"]) && $_REQUEST["searchFormTab"] == "basic_search")
510
        {
511
            if($seed->module_dir == "Reports") $searchMetaData = SearchFormReports::retrieveReportsSearchDefs();
512
            else $searchMetaData = SearchForm::retrieveSearchDefs($seed->module_dir);
0 ignored issues
show
The method retrieveSearchDefs() does not seem to exist on object<SearchForm>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
513
514
            $basicSearchFields = array();
515
516
            if( isset($searchMetaData['searchdefs']) && isset($searchMetaData['searchdefs'][$seed->module_dir]['layout']['basic_search']) )
517
                $basicSearchFields = $searchMetaData['searchdefs'][$seed->module_dir]['layout']['basic_search'];
518
519
            foreach( $basicSearchFields as $basicSearchField)
520
            {
521
                $field_name = (is_array($basicSearchField) && isset($basicSearchField['name'])) ? $basicSearchField['name'] : $basicSearchField;
522
                $field_name .= "_basic";
523
                if( isset($_REQUEST[$field_name])  && ( !is_array($basicSearchField) || !isset($basicSearchField['type']) || $basicSearchField['type'] == 'text' || $basicSearchField['type'] == 'name') )
524
                {
525
                    // Ensure the encoding is UTF-8
526
                    $queryString = htmlentities($_REQUEST[$field_name], null, 'UTF-8');
527
                    break;
528
                }
529
            }
530
        }
531
532 4
		return array('data'=>$data , 'pageData'=>$pageData, 'query' => $queryString);
533
	}
534
535
536
    /**
537
     * generates urls as a string for use by the display layer
538
     *
539
     * @param array $queries
540
     * @return array of urls orderBy and baseURL are always returned the others are only returned  according to values passed in.
541
     */
542 4
    protected function generateURLS($queries)
543
    {
544 4
        foreach ($queries as $name => $value)
545
        {
546 4
            $queries[$name] = 'index.php?' . http_build_query($value);
547
        }
548 4
        $this->base_url = $queries['baseURL'];
549 4
        return $queries;
550
    }
551
552
    /**
553
     * generates queries for use by the display layer
554
     *
555
     * @param int $sortOrder
556
     * @param int $offset
557
     * @param int $prevOffset
558
     * @param int $nextOffset
559
     * @param int $endOffset
560
     * @param int $totalCounted
561
     * @return array of queries orderBy and baseURL are always returned the others are only returned  according to values passed in.
562
     */
563 4
    protected function generateQueries($sortOrder, $offset, $prevOffset, $nextOffset, $endOffset, $totalCounted)
564
    {
565 4
        $queries = array();
566 4
        $queries['baseURL'] = $this->getBaseQuery();
567 4
        $queries['baseURL']['lvso'] = $sortOrder;
568
569 4
        $queries['orderBy'] = $queries['baseURL'];
570 4
        $queries['orderBy'][$this->var_order_by] = '';
571
572 4
        if($nextOffset > -1)
573
        {
574
            $queries['nextPage'] = $queries['baseURL'];
575
            $queries['nextPage'][$this->var_offset] = $nextOffset;
576
        }
577 4
        if($offset > 0)
578
        {
579
            $queries['startPage'] = $queries['baseURL'];
580
            $queries['startPage'][$this->var_offset] = 0;
581
        }
582 4
        if($prevOffset > -1)
583
        {
584
            $queries['prevPage'] = $queries['baseURL'];
585
            $queries['prevPage'][$this->var_offset] = $prevOffset;
586
        }
587 4
        if($totalCounted)
588
        {
589 4
            $queries['endPage'] = $queries['baseURL'];
590 4
            $queries['endPage'][$this->var_offset] = $endOffset;
591
        }
592
        else
593
        {
594
            $queries['endPage'] = $queries['baseURL'];
595
            $queries['endPage'][$this->var_offset] = 'end';
596
        }
597 4
        return $queries;
598
    }
599
600
	/**
601
	 * generates the additional details span to be retrieved via ajax
602
	 *
603
	 * @param GUID id id of the record
604
	 * @return array string to attach to field
605
	 */
606 2
	function getAdditionalDetailsAjax($id)
607
    {
608 2
        global $app_strings;
609
610 2
        $jscalendarImage = SugarThemeRegistry::current()->getImageURL('info_inline.gif');
611
612 2
        $extra = "<span id='adspan_" . $id . "' "
613 2
                . "onclick=\"lvg_dtails('$id')\" "
614 2
				. " style='position: relative;'><!--not_in_theme!--><img vertical-align='middle' class='info' border='0' alt='".$app_strings['LBL_ADDITIONAL_DETAILS']."' src='$jscalendarImage'></span>";
615
616 2
        return array('fieldToAddTo' => $this->additionalDetailsFieldToAdd, 'string' => $extra);
617
	}
618
619
    /**
620
     * generates the additional details values
621
     *
622
     * @param unknown_type $fields
623
     * @param unknown_type $adFunction
624
     * @param unknown_type $editAccess
625
     * @return array string to attach to field
626
     */
627
    function getAdditionalDetails($fields, $adFunction, $editAccess)
628
    {
629
        global $app_strings;
630
        global $mod_strings;
631
632
        $results = $adFunction($fields);
633
634
        $results['string'] = str_replace(array("&#039", "'"), '\&#039', $results['string']); // no xss!
635
636
        if(trim($results['string']) == '')
637
        {
638
            $results['string'] = $app_strings['LBL_NONE'];
639
        }
640
         	$close = false;
641
            $extra = "<img alt='{$app_strings['LBL_INFOINLINE']}' style='padding: 0px 5px 0px 2px' border='0' onclick=\"SUGAR.util.getStaticAdditionalDetails(this,'";
642
643
            $extra .= str_replace(array("\rn", "\r", "\n"), array('','','<br />'), $results['string']) ;
644
            $extra .= "','<div style=\'float:left\'>{$app_strings['LBL_ADDITIONAL_DETAILS']}</div><div style=\'float: right\'>";
645
646
	        if($editAccess && !empty($results['editLink']))
647
	        {
648
	            $extra .=  "<a title=\'{$app_strings['LBL_EDIT_BUTTON']}\' href={$results['editLink']}><img style=\'margin-left: 2px;\' border=\'0\' src=\'".SugarThemeRegistry::current()->getImageURL('edit_inline.png')."\'></a>";
649
	            $close = true;
650
	        }
651
	        $close = (!empty($results['viewLink'])) ? true : $close;
652
	        $extra .= (!empty($results['viewLink']) ? "<a title=\'{$app_strings['LBL_VIEW_BUTTON']}\' href={$results['viewLink']}><img style=\'margin-left: 2px;\' border=\'0\' src=".SugarThemeRegistry::current()->getImageURL('view_inline.png')."></a>" : '');
653
654
            if($close == true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
655
            	$closeVal = "true";
656
            	$extra .=  "<a title=\'{$app_strings['LBL_ADDITIONAL_DETAILS_CLOSE_TITLE']}\' href=\'javascript: SUGAR.util.closeStaticAdditionalDetails();\'><img style=\'margin-left: 2px;\' border=\'0\' src=\'".SugarThemeRegistry::current()->getImageURL('close.png')."\'></a>";
657
            } else {
658
            	$closeVal = "false";
659
            }
660
            $extra .= "',".$closeVal.")\" src='".SugarThemeRegistry::current()->getImageURL('info_inline.png')."' class='info'>";
661
662
        return array('fieldToAddTo' => $results['fieldToAddTo'], 'string' => $extra);
663
    }
664
665
}
666