|
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 |
|
|
|
|
|
|
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 |
|
|
|
|
|
|
237
|
|
|
* @param int:-1 $limit |
|
|
|
|
|
|
238
|
|
|
* @param string[]:array() $filter_fields |
|
|
|
|
|
|
239
|
|
|
* @param array:array() $params |
|
|
|
|
|
|
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 |
|
|
|
|
|
|
245
|
|
|
* @return array('data'=> row data, 'pageData' => page data information, 'query' => original query string) |
|
|
|
|
|
|
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); |
|
|
|
|
|
|
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); |
|
|
|
|
|
|
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("'", "'"), '\'', $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) { |
|
|
|
|
|
|
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
|
|
|
|
Adding a
@returnannotation 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.