]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/ListView/ListView.php
Release 6.5.16
[Github/sugarcrm.git] / include / ListView / ListView.php
1 <?php
2 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  * This program is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU Affero General Public License version 3 as published by the
9  * Free Software Foundation with the addition of the following permission added
10  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13  * 
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
17  * details.
18  * 
19  * You should have received a copy of the GNU Affero General Public License along with
20  * this program; if not, see http://www.gnu.org/licenses or write to the Free
21  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301 USA.
23  * 
24  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26  * 
27  * The interactive user interfaces in modified source and object code versions
28  * of this program must display Appropriate Legal Notices, as required under
29  * Section 5 of the GNU Affero General Public License version 3.
30  * 
31  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32  * these Appropriate Legal Notices must retain the display of the "Powered by
33  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34  * technical reasons, the Appropriate Legal Notices must display the words
35  * "Powered by SugarCRM".
36  ********************************************************************************/
37
38 require_once('include/EditView/SugarVCR.php');
39 /**
40  * ListView - list of many objects
41  * @api
42  */
43 class ListView
44 {
45     var $local_theme= null;
46     var $local_app_strings= null;
47     var $local_image_path = null;
48     var $local_current_module = null;
49     var $local_mod_strings = null;
50     var $records_per_page = 20;
51     var $xTemplate = null;
52     var $xTemplatePath = null;
53     var $seed_data = null;
54     var $query_where = null;
55     var $query_limit = -1;
56     var $query_orderby = null;
57     var $header_title = '';
58     var $header_text = '';
59     var $initialized = false;
60     var $show_export_button = true;
61     var $show_delete_button = true;
62     var $show_select_menu = true;
63     var $show_paging = true;
64     var $show_mass_update = true;
65     var $show_mass_update_form = true;
66     var $query_where_has_changed = false;
67     var $display_header_and_footer = true;
68     var $baseURL = '';
69     var $is_dynamic = false;
70     var $inline = false;
71     var $start_link_wrapper = '';
72     var $end_link_wrapper = '';
73     var $list_field_defs = array();
74
75     var $shouldProcess = false;
76     var $data_array;
77     var $related_field_name = '';
78     var $child_focus = '';
79     var $layout_manager = null;
80     var $process_for_popups = false;
81     var $multi_select_popup=false;
82     var $_additionalDetails = false;
83     var $additionalDetailsFunction = null;
84     var $sort_order = '';
85     var $force_mass_update=false;
86     var $keep_mass_update_form_open=false;
87     var $ignorePopulateOnly = false;
88
89 function setDataArray($value) {
90     $this->data_array = $value;
91 }
92
93 function processListViewMulti($seed, $xTemplateSection, $html_varName) {
94
95     $this->shouldProcess = true;
96
97     echo "<form name='MassUpdate' method='post' action='index.php'>";
98     $this->processListViewTwo($seed, $xTemplateSection, $html_varName);
99
100     echo "<a href='javascript:" . ((!$this->multi_select_popup) ? 'sListView.' : ''). "check_all(document.MassUpdate, \"mass[]\", true)'>".translate('LBL_CHECKALL')."</a> - <a href='javascript:sListView.check_all(document.MassUpdate, \"mass[]\", false);'>".translate('LBL_CLEARALL')."</a>";
101     echo '<br><br>';
102 }
103
104
105 function processListView($seed, $xTemplateSection, $html_varName)
106 {
107     global $sugar_config;
108
109     $populateOnly = $this->ignorePopulateOnly ? FALSE : (!empty($sugar_config['save_query']) && $sugar_config['save_query'] == 'populate_only');
110     if(isset($seed->module_dir) && $populateOnly) {
111         if(empty($GLOBALS['displayListView']) && strcmp(strtolower($_REQUEST['action']), 'popup') != 0 && (!empty($_REQUEST['clear_query']) || $_REQUEST['module'] == $seed->module_dir && ((empty($_REQUEST['query']) || $_REQUEST['query'] == 'MSI')&& (empty($_SESSION['last_search_mod']) || $_SESSION['last_search_mod'] != $seed->module_dir)))) {
112             $_SESSION['last_search_mod'] = $_REQUEST['module'] ;
113             return;
114         }
115     }
116     if(strcmp(strtolower($_REQUEST['action']), 'popup') != 0){
117         $_SESSION['last_search_mod'] = $_REQUEST['module'] ;
118     }
119     //following session variable will track the detail view navigation history.
120     //needs to the reset after each search.
121     $this->setLocalSessionVariable($html_varName,"DETAIL_NAV_HISTORY",false);
122
123     require_once('include/MassUpdate.php');
124     $mass = new MassUpdate();
125     $add_acl_javascript = false;
126     if(!isset($_REQUEST['action'])) {
127         $this->shouldProcess=false;
128     } else {
129     $this->shouldProcess = is_subclass_of($seed, "SugarBean")
130         && (($_REQUEST['action'] == 'index') || ('ListView' == substr($_REQUEST['action'],0,8)) /* cn: to include all ListViewXXX.php type views */)
131         && ($_REQUEST['module'] == $seed->module_dir);
132     }
133
134     //when processing a multi-select popup.
135     if($this->process_for_popups && $this->multi_select_popup)  $this->shouldProcess =true;
136     //mass update turned off?
137     if(!$this->show_mass_update) $this->shouldProcess = false;
138     if(is_subclass_of($seed, "SugarBean")) {
139         if($seed->bean_implements('ACL')) {
140             if(!ACLController::checkAccess($seed->module_dir,'list',true)) {
141                 if($_REQUEST['module'] != 'Home') {
142                     ACLController::displayNoAccess();
143                 }
144                 return;
145             }
146             if(!ACLController::checkAccess($seed->module_dir,'export',true)) {
147                 $sugar_config['disable_export']= true;
148             }
149
150         }
151     }
152
153     //force mass update form if requested.
154     if($this->force_mass_update) {
155         $this->shouldProcess = true;
156     }
157
158     if($this->shouldProcess) {
159         echo $mass->getDisplayMassUpdateForm(true, $this->multi_select_popup);
160         echo $mass->getMassUpdateFormHeader($this->multi_select_popup);
161         $mass->setSugarBean($seed);
162
163         //C.L. Fix for 10048, do not process handleMassUpdate for multi select popups
164         if(!$this->multi_select_popup) {
165             $mass->handleMassUpdate();
166         }
167     }
168
169     $this->processListViewTwo($seed,$xTemplateSection, $html_varName);
170
171     if($this->shouldProcess && empty($this->process_for_popups)) {
172         //echo "<a href='javascript:sListView.clear_all(document.MassUpdate, \"mass[]\");'>".translate('LBL_CLEARALL')."</a>";
173         // cn: preserves current functionality, exception is InboundEmail
174         if($this->show_mass_update_form) {
175             echo $mass->getMassUpdateForm();
176         }
177         if(!$this->keep_mass_update_form_open) {
178             echo $mass->endMassUpdateForm();
179         }
180     }
181 }
182
183
184 function process_dynamic_listview($source_module, $sugarbean,$subpanel_def)
185 {
186         $this->source_module = $source_module;
187         $this->subpanel_module = $subpanel_def->name;
188         if(!isset($this->xTemplate))
189             $this->createXTemplate();
190
191         $html_var = $this->subpanel_module . "_CELL";
192
193         $list_data = $this->processUnionBeans($sugarbean,$subpanel_def, $html_var);
194
195         $list = $list_data['list'];
196         $parent_data = $list_data['parent_data'];
197
198         if($subpanel_def->isCollection()) {
199             $thepanel=$subpanel_def->get_header_panel_def();
200         } else {
201             $thepanel=$subpanel_def;
202         }
203
204
205
206         $this->process_dynamic_listview_header($thepanel->get_module_name(), $thepanel, $html_var);
207         $this->process_dynamic_listview_rows($list,$parent_data, 'dyn_list_view', $html_var,$subpanel_def);
208
209         if($this->display_header_and_footer)
210         {
211             $this->getAdditionalHeader();
212             if(!empty($this->header_title))
213             {
214                 echo get_form_header($this->header_title, $this->header_text, false);
215             }
216         }
217
218         $this->xTemplate->out('dyn_list_view');
219
220         if(isset($_SESSION['validation']))
221         {
222             print base64_decode('PGEgaHJlZj0naHR0cDovL3d3dy5zdWdhcmNybS5jb20nPlBPV0VSRUQmbmJzcDtCWSZuYnNwO1NVR0FSQ1JNPC9hPg==');
223         }
224         if(isset($list_data['query'])) {
225             return ($list_data['query']);
226         }
227     }
228
229 /**
230  * @return void
231  * @param unknown $data
232  * @param unknown $xTemplateSection
233  * @param unknown $html_varName
234  * @desc INTERNAL FUNCTION handles the rows
235  */
236  function process_dynamic_listview_rows($data,$parent_data, $xtemplateSection, $html_varName, $subpanel_def)
237  {
238     global $subpanel_item_count;
239     global $odd_bg;
240     global $even_bg;
241     global $hilite_bg;
242     global $click_bg;
243
244     $this->xTemplate->assign("BG_HILITE", $hilite_bg);
245     $this->xTemplate->assign('CHECKALL', SugarThemeRegistry::current()->getImage('blank', '', 1, 1, ".gif", ''));
246     //$this->xTemplate->assign("BG_CLICK", $click_bg);
247     $subpanel_item_count = 0;
248     $oddRow = true;
249     $count = 0;
250     reset($data);
251
252     //GETTING OFFSET
253     $offset = $this->getOffset($html_varName);
254     //$totaltime = 0;
255     $processed_ids = array();
256
257     $fill_additional_fields = array();
258     //Either retrieve the is_fill_in_additional_fields property from the lone
259     //subpanel or visit each subpanel's subpanels to retrieve the is_fill_in_addition_fields
260     //property
261     $subpanel_list=array();
262     if($subpanel_def->isCollection()) {
263         $subpanel_list=$subpanel_def->sub_subpanels;
264     } else {
265         $subpanel_list[]= $subpanel_def;
266     }
267
268     foreach($subpanel_list as $this_subpanel)
269     {
270         if($this_subpanel->is_fill_in_additional_fields())
271         {
272             $fill_additional_fields[] = $this_subpanel->bean_name;
273             $fill_additional_fields[$this_subpanel->bean_name] = true;
274         }
275     }
276
277     if ( empty($data) ) {
278         $this->xTemplate->assign("ROW_COLOR", 'oddListRow');
279         $thepanel=$subpanel_def;
280         if($subpanel_def->isCollection())
281             $thepanel=$subpanel_def->get_header_panel_def();
282         $this->xTemplate->assign("COL_COUNT", count($thepanel->get_list_fields()));
283         $this->xTemplate->parse($xtemplateSection.".nodata");
284     }
285     while(list($aVal, $aItem) = each($data))
286     {
287         $subpanel_item_count++;
288         $aItem->check_date_relationships_load();
289         // TODO: expensive and needs to be removed and done better elsewhere
290
291         if(!empty($fill_additional_fields[$aItem->object_name])
292         || ($aItem->object_name == 'Case' && !empty($fill_additional_fields['aCase']))
293         )
294         {
295             $aItem->fill_in_additional_list_fields();
296             //$aItem->fill_in_additional_detail_fields();
297         }
298         //rrs bug: 25343
299         $aItem->call_custom_logic("process_record");
300
301         if(isset($parent_data[$aItem->id])) {
302
303             $aItem->parent_name = $parent_data[$aItem->id]['parent_name'];
304             if(!empty($parent_data[$aItem->id]['parent_name_owner'])) {
305             $aItem->parent_name_owner =  $parent_data[$aItem->id]['parent_name_owner'];
306             $aItem->parent_name_mod =  $parent_data[$aItem->id]['parent_name_mod'];
307         }}
308         $fields = $aItem->get_list_view_data();
309         if(isset($processed_ids[$aItem->id])) {
310             continue;
311
312         } else {
313             $processed_ids[$aItem->id] = 1;
314         }
315
316
317         //ADD OFFSET TO ARRAY
318         $fields['OFFSET'] = ($offset + $count + 1);
319
320         if($this->shouldProcess) {
321             if($aItem->ACLAccess('EditView')) {
322             $this->xTemplate->assign('PREROW', "<input type='checkbox' class='checkbox' name='mass[]' value='". $fields['ID']. "' />");
323             } else {
324                 $this->xTemplate->assign('PREROW', '');
325
326             }
327             if($aItem->ACLAccess('DetailView')) {
328                 $this->xTemplate->assign('TAG_NAME','a');
329             } else {
330                 $this->xTemplate->assign('TAG_NAME','span');
331             }
332             $this->xTemplate->assign('CHECKALL', "<input type='checkbox'  title='".$GLOBALS['app_strings']['LBL_SELECT_ALL_TITLE']."' class='checkbox' name='massall' id='massall' value='' onclick='sListView.check_all(document.MassUpdate, \"mass[]\", this.checked);' />");
333         }
334
335         if($oddRow)
336         {
337             $ROW_COLOR = 'oddListRow';
338             $BG_COLOR =  $odd_bg;
339         }
340         else
341         {
342             $ROW_COLOR = 'evenListRow';
343             $BG_COLOR =  $even_bg;
344         }
345         $oddRow = !$oddRow;
346                 $button_contents = array();
347         $this->xTemplate->assign("ROW_COLOR", $ROW_COLOR);
348         $this->xTemplate->assign("BG_COLOR", $BG_COLOR);
349         $layout_manager = $this->getLayoutManager();
350         $layout_manager->setAttribute('context','List');
351         $layout_manager->setAttribute('image_path',$this->local_image_path);
352         $layout_manager->setAttribute('module_name', $subpanel_def->_instance_properties['module']);
353         if(!empty($this->child_focus))
354             $layout_manager->setAttribute('related_module_name',$this->child_focus->module_dir);
355
356         //AG$subpanel_data = $this->list_field_defs;
357         //$bla = array_pop($subpanel_data);
358         //select which sub-panel to display here, the decision will be made based on the type of
359         //the sub-panel and panel in the bean being processed.
360         if($subpanel_def->isCollection()) {
361             $thepanel=$subpanel_def->sub_subpanels[$aItem->panel_name];
362         } else {
363             $thepanel=$subpanel_def;
364         }
365         //get data source name
366         $linked_field=$thepanel->get_data_source_name();
367         $linked_field_set=$thepanel->get_data_source_name(true);
368         static $count;
369         if(!isset($count))$count = 0;
370
371         $field_acl['DetailView'] = $aItem->ACLAccess('DetailView');
372         $field_acl['ListView'] = $aItem->ACLAccess('ListView');
373         $field_acl['EditView'] = $aItem->ACLAccess('EditView');
374         $field_acl['Delete'] = $aItem->ACLAccess('Delete');
375         foreach($thepanel->get_list_fields() as $field_name=>$list_field)
376         {
377             //add linked field attribute to the array.
378             $list_field['linked_field']=$linked_field;
379             $list_field['linked_field_set']=$linked_field_set;
380
381             $usage = empty($list_field['usage']) ? '' : $list_field['usage'];
382             if($usage == 'query_only' && !empty($list_field['force_query_only_display'])){
383                 //if you are here you have column that is query only but needs to be displayed as blank.  This is helpful
384                 //for collections such as Activities where you have a field in only one object and wish to show it in the subpanel list
385                 $count++;
386                 $widget_contents = '&nbsp;';
387                 $this->xTemplate->assign('CLASS', "");
388                 $this->xTemplate->assign('CELL_COUNT', $count);
389                 $this->xTemplate->assign('CELL', $widget_contents);
390                 $this->xTemplate->parse($xtemplateSection.".row.cell");
391
392             }else if($usage != 'query_only')
393             {
394                 $list_field['name']=$field_name;
395
396                 $module_field = $field_name.'_mod';
397                 $owner_field = $field_name.'_owner';
398                 if(!empty($aItem->$module_field)) {
399
400                     $list_field['owner_id'] = $aItem->$owner_field;
401                     $list_field['owner_module'] = $aItem->$module_field;
402
403                 } else {
404                     $list_field['owner_id'] = false;
405                     $list_field['owner_module'] = false;
406                 }
407                 if(isset($list_field['alias'])) $list_field['name'] = $list_field['alias'];
408                 else $list_field['name']=$field_name;
409                 $list_field['fields'] = $fields;
410                 $list_field['module'] = $aItem->module_dir;
411                 $list_field['start_link_wrapper'] = $this->start_link_wrapper;
412                 $list_field['end_link_wrapper'] = $this->end_link_wrapper;
413                 $list_field['subpanel_id'] = $this->subpanel_id;
414                 $list_field += $field_acl;
415                 if ( isset($aItem->field_defs[strtolower($list_field['name'])])) {
416                     require_once('include/SugarFields/SugarFieldHandler.php');
417                     // We need to see if a sugar field exists for this field type first,
418                     // if it doesn't, toss it at the old sugarWidgets. This is for
419                     // backwards compatibility and will be removed in a future release
420                     $vardef = $aItem->field_defs[strtolower($list_field['name'])];
421                     if ( isset($vardef['type']) ) {
422                         $fieldType = isset($vardef['custom_type'])?$vardef['custom_type']:$vardef['type'];
423                         $tmpField = SugarFieldHandler::getSugarField($fieldType,true);
424                     } else {
425                         $tmpField = NULL;
426                     }
427
428                     if ( $tmpField != NULL ) {
429                         $widget_contents = SugarFieldHandler::displaySmarty($list_field['fields'],$vardef,'ListView',$list_field);
430                     } else {
431                         // No SugarField for this particular type
432                         // Use the old, icky, SugarWidget for now
433                         $widget_contents = $layout_manager->widgetDisplay($list_field);
434                     }
435
436                     if ( isset($list_field['widget_class']) && $list_field['widget_class'] == 'SubPanelDetailViewLink' ) {
437                         // We need to call into the old SugarWidgets for the time being, so it can generate a proper link with all the various corner-cases handled
438                         // So we'll populate the field data with the pre-rendered display for the field
439                         $list_field['fields'][$field_name] = $widget_contents;
440                         if('full_name' == $field_name){//bug #32465
441                            $list_field['fields'][strtoupper($field_name)] = $widget_contents;
442                         }
443
444                         //vardef source is non db, assign the field name to varname for processing of column.
445                         if(!empty($vardef['source']) && $vardef['source']=='non-db'){
446                             $list_field['varname'] = $field_name;
447
448                         }
449                         $widget_contents = $layout_manager->widgetDisplay($list_field);
450                     } else if(isset($list_field['widget_class']) && $list_field['widget_class'] == 'SubPanelEmailLink' ) {
451                         $widget_contents = $layout_manager->widgetDisplay($list_field);
452                     }
453
454                  $count++;
455                 $this->xTemplate->assign('CELL_COUNT', $count);
456                 $this->xTemplate->assign('CLASS', "");
457                 if ( empty($widget_contents) ) $widget_contents = '&nbsp;';
458                 $this->xTemplate->assign('CELL', $widget_contents);
459                 $this->xTemplate->parse($xtemplateSection.".row.cell");
460                 } else {
461                     // This handles the edit and remove buttons and icon widget
462                         if( isset($list_field['widget_class']) && $list_field['widget_class'] == "SubPanelIcon") {
463                                 $count++;
464                                 $widget_contents = $layout_manager->widgetDisplay($list_field);
465                                 $this->xTemplate->assign('CELL_COUNT', $count);
466                                 $this->xTemplate->assign('CLASS', "");
467                                 if ( empty($widget_contents) ) $widget_contents = '&nbsp;';
468                                 $this->xTemplate->assign('CELL', $widget_contents);
469                                 $this->xTemplate->parse($xtemplateSection.".row.cell");
470                         } elseif (preg_match("/button/i", $list_field['name'])) {
471                         if ((($list_field['name'] === 'edit_button' && $field_acl['EditView']) || ($list_field['name'] === 'close_button' && $field_acl['EditView']) || ($list_field['name'] === 'remove_button' && $field_acl['Delete'])) && '' != ($_content = $layout_manager->widgetDisplay($list_field)) )
472                         {
473                             $button_contents[] = $_content;
474                             unset($_content);
475                         }
476                         else
477                         {
478                             $button_contents[] = '';
479                         }
480                         } else {
481                                 $count++;
482                                 $this->xTemplate->assign('CLASS', "");
483                                 $widget_contents = $layout_manager->widgetDisplay($list_field);
484                                 $this->xTemplate->assign('CELL_COUNT', $count);
485                                 if ( empty($widget_contents) ) $widget_contents = '&nbsp;';
486                                 $this->xTemplate->assign('CELL', $widget_contents);
487                                 $this->xTemplate->parse($xtemplateSection.".row.cell");
488                         }
489                 }
490
491             }
492         }
493
494
495         // Make sure we have at least one button before rendering a column for
496         // the action buttons in a list view. Relevant bugs: #51647 and #51640.
497         if(!empty($button_contents))
498         {
499             $button_contents = array_filter($button_contents);
500             if (!empty($button_contents))
501             {
502             // this is for inline buttons on listviews
503             // bug#51275: smarty widget to help provide the action menu functionality as it is currently sprinkled throughout the app with html
504                 require_once('include/Smarty/plugins/function.sugar_action_menu.php');
505                 $tempid = create_guid();
506                 array_unshift($button_contents, "<div style='display: inline' id='$tempid'>" . array_shift($button_contents) . "</div>");
507                 $action_button = smarty_function_sugar_action_menu(array(
508                     'id' => $tempid,
509                     'buttons' => $button_contents,
510                     'class' => 'clickMenu subpanel records fancymenu button',
511                     'flat' => false //assign flat value as false to display dropdown menu at any other preferences.
512                 ), $this->xTemplate);
513             }
514             else
515             {
516                 $action_button = '';
517             }
518             $this->xTemplate->assign('CLASS', "inlineButtons");
519             $this->xTemplate->assign('CELL_COUNT', ++$count);
520             //Bug#51275 for beta3 pre_script is not required any more
521             $this->xTemplate->assign('CELL', $action_button);
522             $this->xTemplate->parse($xtemplateSection . ".row.cell");
523         }
524
525
526         $aItem->setupCustomFields($aItem->module_dir);
527         $aItem->custom_fields->populateAllXTPL($this->xTemplate, 'detail', $html_varName, $fields);
528
529         $count++;
530
531         $this->xTemplate->parse($xtemplateSection.".row");
532     }
533
534     $this->xTemplate->parse($xtemplateSection);
535 }
536
537 /**sets whether or not to display the xtemplate header and footer
538  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
539  * All Rights Reserved.
540  * Contributor(s): ______________________________________.
541 */
542 function setDisplayHeaderAndFooter($bool) {
543         $this->display_header_and_footer = $bool;
544 }
545
546 /**initializes ListView
547  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
548  * All Rights Reserved.
549  * Contributor(s): ______________________________________.
550 */
551  function ListView() {
552
553
554     if(!$this->initialized) {
555         global $sugar_config;
556         $this->records_per_page = $sugar_config['list_max_entries_per_page'] + 0;
557         $this->initialized = true;
558         global $app_strings, $currentModule;
559         $this->local_theme = SugarThemeRegistry::current()->__toString();
560         $this->local_app_strings =$app_strings;
561         $this->local_image_path = SugarThemeRegistry::current()->getImagePath();
562         $this->local_current_module = $currentModule;
563     }
564 }
565 /**sets how many records should be displayed per page in the list view
566  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
567  * All Rights Reserved.
568  * Contributor(s): ______________________________________.
569 */
570  function setRecordsPerPage($count) {
571     $this->records_per_page = $count;
572 }
573 /**sets the header title */
574  function setHeaderTitle($value) {
575     $this->header_title = $value;
576 }
577 /**sets the header text this is text that's appended to the header table and is usually used for the creation of buttons
578  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
579  * All Rights Reserved.
580  * Contributor(s): ______________________________________.
581 */
582  function setHeaderText($value) {
583     $this->header_text = $value;
584 }
585 /**sets the path for the XTemplate HTML file to be used this is only needed to be set if you are allowing ListView to create the XTemplate
586  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
587  * All Rights Reserved.
588  * Contributor(s): ______________________________________.
589 */
590  function setXTemplatePath($value) {
591     $this->xTemplatePath= $value;
592 }
593
594 /**this is a helper function for allowing ListView to create a new XTemplate it groups parameters that should be set into a single function
595  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
596  * All Rights Reserved.
597  * Contributor(s): ______________________________________.
598 */
599  function initNewXTemplate($XTemplatePath, $modString, $imagePath = null) {
600     $this->setXTemplatePath($XTemplatePath);
601     if(isset($modString))
602         $this->setModStrings($modString);
603     if(isset($imagePath))
604         $this->setImagePath($imagePath);
605 }
606
607
608 function getOrderBy($varName, $defaultOrderBy='', $force_sortorder='') {
609     $sortBy = $this->getSessionVariable($varName, "ORDER_BY") ;
610
611     $orderByDirection = $this->getSessionVariableName($varName, "order_by_direction");
612     $orderByColumn = $this->getSessionVariableName($varName, "ORDER_BY");
613     $lastEqualsSortBy = false;
614     $defaultOrder = false; //ascending
615
616     if(empty($sortBy)) {
617         $this->setUserVariable($varName, "ORDER_BY", $defaultOrderBy);
618         $sortBy = $defaultOrderBy;
619     } else {
620         $this->setUserVariable($varName, "ORDER_BY", $sortBy);
621     }
622
623     $desc = $this->getSessionVariable($varName, $sortBy."S");
624
625     if (empty($desc))
626         {
627             $desc = $defaultOrder;
628         }
629         $defaultOrder = $desc ? 'desc' : 'asc';
630         $orderByValue = $defaultOrder;
631         if (isset($_REQUEST[$orderByDirection]))
632         {
633             $possibleRequestOrderBy = $_REQUEST[$orderByDirection];
634             if ($possibleRequestOrderBy == 'asc' || $possibleRequestOrderBy == 'desc')
635             {
636                 $orderByValue = $possibleRequestOrderBy;
637             }
638         }
639
640         if (isset($_REQUEST[$orderByColumn]))
641         {
642             $last = $this->getSessionVariable($varName, "OBL");
643         }
644         if (!empty($last) && $last == $sortBy)
645         {
646             $lastEqualsSortBy = true;
647         } else
648         {
649             $orderByValue = $defaultOrder;
650             $this->setSessionVariable($varName, "OBL", $sortBy);
651         }
652         $desc = $orderByValue == 'desc';
653         $orderByDirectionValue = false;
654         $this->setSessionVariable($varName, $sortBy . "S", $desc);
655         if (!empty($sortBy))
656         {
657             if (empty($force_sortorder))
658             {
659                 if (substr_count(strtolower($sortBy), ' desc') == 0 && substr_count(strtolower($sortBy), ' asc') == 0)
660                 {
661                     if ($sortBy)
662                     {
663                         $orderByDirectionValue = $desc ? 'asc' : 'desc';
664                     }
665                     $this->query_orderby = $sortBy . ' ' . $orderByValue;
666                 }
667             } else
668             {
669                 $this->query_orderby = $sortBy . ' ' . $force_sortorder;
670             }
671             if (!isset($this->appendToBaseUrl))
672             {
673                 $this->appendToBaseUrl = array();
674             }
675             if ($orderByDirectionValue)
676             {
677                 $this->appendToBaseUrl[$orderByDirection] = $orderByDirectionValue;
678             }
679             $offsetVar = $this->getSessionVariableName($varName, "offset");
680             if (isset($_REQUEST[$offsetVar]))
681             {
682                 $this->appendToBaseUrl[$offsetVar] = $_REQUEST[$offsetVar];
683             }
684             //Just clear from url...
685             $this->appendToBaseUrl[$orderByColumn] = false;
686     }else {
687         $this->query_orderby = "";
688     }
689     $this->sortby = $sortBy;
690     return $this->query_orderby;
691
692 }
693
694
695 /**sets the parameters dealing with the db
696  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
697  * All Rights Reserved.
698  * Contributor(s): ______________________________________.
699 */
700  function setQuery($where, $limit, $orderBy, $varName, $allowOrderByOveride=true) {
701     $this->query_where = $where;
702     if($this->getSessionVariable("query", "where") != $where) {
703         $this->query_where_has_changed = true;
704         $this->setSessionVariable("query", "where", $where);
705     }
706
707     $this->query_limit = $limit;
708     if(!$allowOrderByOveride) {
709         $this->query_orderby = $orderBy;
710         return;
711     }
712     $this->getOrderBy($varName, $orderBy);
713
714     $this->setLocalSessionVariable($varName, "QUERY_WHERE", $where);
715
716     //SETTING ORDER_BY FOR USE IN DETAILVIEW
717     $this->setLocalSessionVariable($varName, "ORDER_BY_DETAIL", $this->query_orderby);
718 }
719
720 function displayArrow() {
721
722 }
723
724 /**sets the theme used only use if it is different from the global
725  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
726  * All Rights Reserved.
727  * Contributor(s): ______________________________________.
728 */
729  function setTheme($theme) {
730     $this->local_theme = $theme;
731     if(isset($this->xTemplate))$this->xTemplate->assign("THEME", $this->local_theme);
732 }
733
734 /**sets the AppStrings used only use if it is different from the global
735  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
736  * All Rights Reserved.
737  * Contributor(s): ______________________________________.
738 */
739  function setAppStrings($app_strings) {
740     unset($this->local_app_strings);
741     $this->local_app_strings = $app_strings;
742     if(isset($this->xTemplate))$this->xTemplate->assign("APP", $this->local_app_strings);
743 }
744
745 /**sets the ModStrings used
746  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
747  * All Rights Reserved.
748  * Contributor(s): ______________________________________.
749 */
750  function setModStrings($mod_strings) {
751     unset($this->local_module_strings);
752     $this->local_mod_strings = $mod_strings;
753     if(isset($this->xTemplate))$this->xTemplate->assign("MOD", $this->local_mod_strings);
754 }
755
756 /**sets the ImagePath used
757  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
758  * All Rights Reserved.
759  * Contributor(s): ______________________________________.
760 */
761  function setImagePath($image_path) {
762     $this->local_image_path = $image_path;
763     if(empty($this->local_image_path)) {
764         $this->local_image_path = SugarThemeRegistry::get($this->local_theme)->getImagePath();
765     }
766     if(isset($this->xTemplate))$this->xTemplate->assign("IMAGE_PATH", $this->local_image_path);
767 }
768
769 /**sets the currentModule only use if this is different from the global
770  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
771  * All Rights Reserved.
772  * Contributor(s): ______________________________________.
773 */
774  function setCurrentModule($currentModule) {
775     unset($this->local_current_module);
776     $this->local_current_module = $currentModule;
777     if(isset($this->xTemplate))$this->xTemplate->assign("MODULE_NAME", $this->local_current_module);
778 }
779
780 /**INTERNAL FUNCTION creates an XTemplate DO NOT CALL THIS THIS IS AN INTERNAL FUNCTION
781  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
782  * All Rights Reserved.
783  * Contributor(s): ______________________________________.
784 */
785  function createXTemplate() {
786     if(!isset($this->xTemplate)) {
787         if(isset($this->xTemplatePath)) {
788
789             $this->xTemplate = new XTemplate($this->xTemplatePath);
790             $this->xTemplate->assign("APP", $this->local_app_strings);
791             if(isset($this->local_mod_strings))$this->xTemplate->assign("MOD", $this->local_mod_strings);
792             $this->xTemplate->assign("THEME", $this->local_theme);
793             $this->xTemplate->assign("IMAGE_PATH", $this->local_image_path);
794             $this->xTemplate->assign("MODULE_NAME", $this->local_current_module);
795         } else {
796             $GLOBALS['log']->error("NO XTEMPLATEPATH DEFINED CANNOT CREATE XTEMPLATE");
797         }
798     }
799 }
800
801 /**sets the XTemplate telling ListView to use newXTemplate as its current XTemplate
802  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
803  * All Rights Reserved.
804  * Contributor(s): ______________________________________.
805 */
806  function setXTemplate($newXTemplate) {
807     $this->xTemplate = $newXTemplate;
808 }
809
810 /**returns the XTemplate
811  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
812  * All Rights Reserved.
813  * Contributor(s): ______________________________________.
814 */
815  function getXTemplate() {
816     return $this->xTemplate;
817 }
818
819 /**assigns a name value pair to the XTemplate
820  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
821  * All Rights Reserved.
822  * Contributor(s): ______________________________________.
823 */
824  function xTemplateAssign($name, $value) {
825
826         if(!isset($this->xTemplate)) {
827             $this->createXTemplate();
828         }
829         $this->xTemplate->assign($name, $value);
830
831 }
832
833 /**INTERNAL FUNCTION returns the offset first checking the query then checking the session if the where clause has changed from the last time it returns 0
834  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
835  * All Rights Reserved.
836  * Contributor(s): ______________________________________.
837 */
838  function getOffset($localVarName) {
839         if($this->query_where_has_changed || isset($GLOBALS['record_has_changed'])) {
840                 $this->setSessionVariable($localVarName,"offset", 0);
841         }
842         $offset = $this->getSessionVariable($localVarName,"offset");
843         if(isset($offset)) {
844                 return $offset;
845         }
846         return 0;
847 }
848
849 /**INTERNAL FUNCTION sets the offset in the session
850  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
851  * All Rights Reserved.
852  * Contributor(s): ______________________________________.
853 */
854  function setOffset($localVarName, $value) {
855         $this->setSessionVariable($localVarName, "offset", $value);
856 }
857
858 /**INTERNAL FUNCTION sets a session variable
859  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
860  * All Rights Reserved.
861  * Contributor(s): ______________________________________.
862 */
863  function setSessionVariable($localVarName,$varName, $value) {
864     $_SESSION[$this->local_current_module."_".$localVarName."_".$varName] = $value;
865 }
866
867 function setUserVariable($localVarName,$varName, $value) {
868         if($this->is_dynamic ||  $localVarName == 'CELL')return;
869         global $current_user;
870         $current_user->setPreference($this->local_current_module."_".$localVarName."_".$varName, $value);
871 }
872
873 /**INTERNAL FUNCTION returns a session variable first checking the query for it then checking the session
874  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
875  * All Rights Reserved.
876  * Contributor(s): ______________________________________.
877 */
878  function getSessionVariable($localVarName,$varName) {
879     //Set any variables pass in through request first
880     if(isset($_REQUEST[$this->getSessionVariableName($localVarName, $varName)])) {
881         $this->setSessionVariable($localVarName,$varName,$_REQUEST[$this->getSessionVariableName($localVarName, $varName)]);
882     }
883
884     if(isset($_SESSION[$this->getSessionVariableName($localVarName, $varName)])) {
885         return $_SESSION[$this->getSessionVariableName($localVarName, $varName)];
886     }
887     return "";
888 }
889
890 function getUserVariable($localVarName, $varName) {
891     global $current_user;
892     if($this->is_dynamic ||  $localVarName == 'CELL')return;
893     if(isset($_REQUEST[$this->getSessionVariableName($localVarName, $varName)])) {
894
895             $this->setUserVariable($localVarName,$varName,$_REQUEST[$this->getSessionVariableName($localVarName, $varName)]);
896     }
897     return $current_user->getPreference($this->getSessionVariableName($localVarName, $varName));
898 }
899
900
901     /**
902      * helper method to determine sort order by priority of source
903      * 1. explicit in request object
904      * 2. in session variable
905      * 3. subpaneldefs metadata
906      * 4. default 'asc'
907      * @param array $sortOrderList - contains options
908      * @return string 'asc' | 'desc'
909      */
910     function calculateSortOrder($sortOrderList)
911     {
912         $priority_map = array(
913           'request',
914           'session',
915           'subpaneldefs',
916           'default',
917         );
918
919         foreach($priority_map as $p) {
920             if (key_exists($p, $sortOrderList)) {
921                 $order = strtolower($sortOrderList[$p]);
922                 if (in_array($order, array('asc', 'desc'))) {
923                     return $order;
924                 }
925             }
926         }
927         return 'asc';
928     }
929
930
931     /**
932
933     * @return void
934     * @param unknown $localVarName
935     * @param unknown $varName
936     * @desc INTERNAL FUNCTION returns the session/query variable name
937     * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
938     * All Rights Reserved.
939     * Contributor(s): ______________________________________..
940     */
941     function getSessionVariableName($localVarName,$varName) {
942         return $this->local_current_module."_".$localVarName."_".$varName;
943     }
944
945     /**
946
947     * @return void
948     * @param unknown $seed
949     * @param unknown $xTemplateSection
950     * @param unknown $html_varName
951     * @desc INTERNAL FUNCTION Handles List Views using seeds that extend SugarBean
952         $XTemplateSection is the section in the XTemplate file that should be parsed usually main
953         $html_VarName is the variable name used in the XTemplateFile e.g. TASK
954         $seed is a seed that extends SugarBean
955         * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
956         * All Rights Reserved..
957         * Contributor(s): ______________________________________..
958     */
959     function processSugarBean($xtemplateSection, $html_varName, $seed) {
960         global $list_view_row_count;
961
962         $current_offset = $this->getOffset($html_varName);
963         $response = array();
964
965         //ADDING VCR CONTROL
966         SugarVCR::erase($seed->module_dir);
967         $params = array();
968         //$filter = array('id', 'full_name');
969         $filter=array();
970         $ret_array = $seed->create_new_list_query($this->query_orderby, $this->query_where, $filter, $params, 0, '', true, $seed, true);
971         if(!is_array($params)) $params = array();
972         if(!isset($params['custom_select'])) $params['custom_select'] = '';
973         if(!isset($params['custom_from'])) $params['custom_from'] = '';
974         if(!isset($params['custom_where'])) $params['custom_where'] = '';
975         if(!isset($params['custom_order_by'])) $params['custom_order_by'] = '';
976         $main_query = $ret_array['select'] . $params['custom_select'] . $ret_array['from'] . $params['custom_from'] . $ret_array['where'] . $params['custom_where'] . $ret_array['order_by'] . $params['custom_order_by'];
977         SugarVCR::store($seed->module_dir,  $main_query);
978         //ADDING VCR CONTROL
979
980         if(empty($this->related_field_name)) {
981             $response = $seed->get_list($this->query_orderby, $this->query_where, $current_offset, $this->query_limit);
982         } else {
983             $related_field_name = $this->related_field_name;
984             $response = $seed->get_related_list($this->child_focus,$related_field_name, $this->query_orderby,
985             $this->query_where, $current_offset, $this->query_limit);
986         }
987
988         $list = $response['list'];
989         $row_count = $response['row_count'];
990         $next_offset = $response['next_offset'];
991         $previous_offset = $response['previous_offset'];
992
993         if(!empty($response['current_offset'])) {
994             $current_offset = $response['current_offset'];
995         }
996
997         $list_view_row_count = $row_count;
998         $this->processListNavigation($xtemplateSection,$html_varName, $current_offset, $next_offset, $previous_offset, $row_count, null, null, empty($seed->column_fields) ? null : count($seed->column_fields));
999
1000         return $list;
1001     }
1002
1003
1004
1005     function processUnionBeans($sugarbean, $subpanel_def, $html_var = 'CELL') {
1006
1007                 $last_detailview_record = $this->getSessionVariable("detailview", "record");
1008                 if(!empty($last_detailview_record) && $last_detailview_record != $sugarbean->id){
1009                         $GLOBALS['record_has_changed'] = true;
1010                 }
1011                 $this->setSessionVariable("detailview", "record", $sugarbean->id);
1012
1013                 $current_offset = $this->getOffset($html_var);
1014                 $module = isset($_REQUEST['module']) ? $_REQUEST['module'] : '';
1015                 $response = array();
1016
1017         // choose sort order
1018         $sort_order = array();
1019         $sort_order['default'] = 'asc';
1020
1021         // explicit request parameter gets priority over all
1022         $sort_order['request'] = isset($_REQUEST['sort_order']) ? $_REQUEST['sort_order'] : null;
1023
1024         // see if the session data has a sort order
1025         if (isset($_SESSION['last_sub' . $this->subpanel_module . '_order']))
1026         {
1027             $sort_order['session'] = $_SESSION['last_sub' . $this->subpanel_module . '_order'];
1028
1029             // We swap the order when the request contains an offset (indicating a column sort issued);
1030             // otherwise we do not sort.  If we don't make this check, then the subpanel listview will
1031             // swap ordering each time a new record is entered via quick create forms
1032             if (isset($_REQUEST[$module . '_' . $html_var . '_offset']))
1033             {
1034                 $sort_order['session'] = $sort_order['session'] == 'asc' ? 'desc' : 'asc';
1035             }
1036         }
1037         else
1038         {
1039             $sort_order['session'] = null;
1040         }
1041
1042         // does the metadata have a default sort order?
1043         $sort_order['subpaneldefs'] = isset($subpanel_def->_instance_properties['sort_order']) ?
1044             $subpanel_def->_instance_properties['sort_order'] : null;
1045
1046         $this->sort_order = $this->calculateSortOrder($sort_order);
1047
1048
1049         if (isset($subpanel_def->_instance_properties['sort_by'])) {
1050             $this->query_orderby = $subpanel_def->_instance_properties['sort_by'];
1051         } else {
1052             $this->query_orderby = 'id';
1053         }
1054
1055         $this->getOrderBy($html_var,$this->query_orderby, $this->sort_order);
1056
1057         $_SESSION['last_sub' .$this->subpanel_module. '_order'] = $this->sort_order;
1058         $_SESSION['last_sub' .$this->subpanel_module. '_url'] = $this->getBaseURL($html_var);
1059
1060                 // Bug 8139 - Correct Subpanel sorting on 'name', when subpanel sorting default is 'last_name, first_name'
1061                 if (($this->sortby == 'name' || $this->sortby == 'last_name') &&
1062                         str_replace(' ', '', trim($subpanel_def->_instance_properties['sort_by'])) == 'last_name,first_name') {
1063                         $this->sortby = 'last_name '.$this->sort_order.', first_name ';
1064                 }
1065
1066         if(!empty($this->response)){
1067             $response =& $this->response;
1068             echo 'cached';
1069         }else{
1070             $response = SugarBean::get_union_related_list($sugarbean,$this->sortby, $this->sort_order, $this->query_where, $current_offset, -1, $this->records_per_page,$this->query_limit,$subpanel_def);
1071             $this->response =& $response;
1072         }
1073         $list = $response['list'];
1074         $row_count = $response['row_count'];
1075         $next_offset = $response['next_offset'];
1076         $previous_offset = $response['previous_offset'];
1077         if(!empty($response['current_offset']))$current_offset = $response['current_offset'];
1078         global $list_view_row_count;
1079         $list_view_row_count = $row_count;
1080         $this->processListNavigation('dyn_list_view', $html_var, $current_offset, $next_offset, $previous_offset, $row_count, $sugarbean,$subpanel_def);
1081
1082         return array('list'=>$list, 'parent_data'=>$response['parent_data'], 'query'=>$response['query']);
1083     }
1084
1085     function getBaseURL($html_varName) {
1086         static $cache = array();
1087
1088         if(!empty($cache[$html_varName]))return $cache[$html_varName];
1089         $blockVariables = array('mass', 'uid', 'massupdate', 'delete', 'merge', 'selectCount','current_query_by_page');
1090         if(!empty($this->base_URL)) {
1091             return $this->base_URL;
1092         }
1093
1094             $baseurl = $_SERVER['PHP_SELF'];
1095             if(empty($baseurl)) {
1096                 $baseurl = 'index.php';
1097             }
1098
1099             /*fixes an issue with deletes when doing a search*/
1100             foreach(array_merge($_GET, $_POST) as $name=>$value) {
1101                 //echo ("$name = $value <br/>");
1102                 if(!empty($value) && $name != 'sort_order' //&& $name != ListView::getSessionVariableName($html_varName,"ORDER_BY")
1103                         && $name != ListView::getSessionVariableName($html_varName,"offset")
1104                         /*&& substr_count($name, "ORDER_BY")==0*/ && !in_array($name, $blockVariables))
1105                 {
1106                     if(is_array($value)) {
1107                         foreach($value as $valuename=>$valuevalue) {
1108                             if(substr_count($baseurl, '?') > 0)
1109                                 $baseurl        .= "&{$name}[]=".$valuevalue;
1110                             else
1111                                 $baseurl        .= "?{$name}[]=".$valuevalue;
1112                         }
1113                     } else {
1114                         $value = urlencode($value);
1115                         if(substr_count($baseurl, '?') > 0) {
1116                             $baseurl    .= "&$name=$value";
1117                         } else {
1118                             $baseurl    .= "?$name=$value";
1119                         }
1120                     }
1121                 }
1122             }
1123
1124
1125             if($_SERVER['REQUEST_METHOD'] == 'POST') {
1126                 // at this point it is possible that the above foreach already executed resulting in double ?'s in the url
1127                 if(substr_count($baseurl, '?') == 0) {
1128                     $baseurl .= '?';
1129                 }
1130                 if(isset($_REQUEST['action'])) $baseurl.= '&action='.$_REQUEST['action'];
1131                 if(isset($_REQUEST['record'])) $baseurl .= '&record='.$_REQUEST['record'];
1132                 if(isset($_REQUEST['module'])) $baseurl .= '&module='.$_REQUEST['module'];
1133             }
1134
1135             $baseurl .= "&".ListView::getSessionVariableName($html_varName,"offset")."=";
1136             $cache[$html_varName] = $baseurl;
1137             return $baseurl;
1138     }
1139     /**
1140     * @return void
1141     * @param unknown $data
1142     * @param unknown $xTemplateSection
1143     * @param unknown $html_varName
1144     * @desc INTERNAL FUNCTION process the List Navigation
1145     * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1146     * All Rights Reserved.
1147     * Contributor(s): ______________________________________..
1148     */
1149     function processListNavigation($xtemplateSection, $html_varName, $current_offset, $next_offset, $previous_offset, $row_count, $sugarbean=null, $subpanel_def=null, $col_count = 20) {
1150
1151         global $export_module;
1152         global $sugar_config;
1153         global $current_user;
1154         global $currentModule;
1155         global $app_strings;
1156
1157         $start_record = $current_offset + 1;
1158
1159         if(!is_numeric($col_count))
1160             $col_count = 20;
1161
1162         if($row_count == 0)
1163             $start_record = 0;
1164
1165         $end_record = $start_record + $this->records_per_page;
1166         // back up the the last page.
1167         if($end_record > $row_count+1) {
1168             $end_record = $row_count+1;
1169         }
1170         // Determine the start location of the last page
1171         if($row_count == 0)
1172             $number_pages = 0;
1173         else
1174             $number_pages = floor(($row_count - 1) / $this->records_per_page);
1175
1176         $last_offset = $number_pages * $this->records_per_page;
1177
1178         if(empty($this->query_limit)  || $this->query_limit > $this->records_per_page) {
1179             $this->base_URL = $this->getBaseURL($html_varName);
1180             $dynamic_url = '';
1181
1182             if($this->is_dynamic) {
1183                 $dynamic_url .='&'. $this->getSessionVariableName($html_varName,'ORDER_BY') . '='. $this->getSessionVariable($html_varName,'ORDER_BY').'&sort_order='.$this->sort_order.'&to_pdf=true&action=SubPanelViewer&subpanel=' . $this->subpanel_module;
1184             }
1185
1186             $current_URL = htmlentities($this->base_URL.$current_offset.$dynamic_url);
1187             $start_URL = htmlentities($this->base_URL."0".$dynamic_url);
1188             $previous_URL  = htmlentities($this->base_URL.$previous_offset.$dynamic_url);
1189             $next_URL  = htmlentities($this->base_URL.$next_offset.$dynamic_url);
1190             $end_URL  = htmlentities($this->base_URL.'end'.$dynamic_url);
1191
1192             if(!empty($this->start_link_wrapper)) {
1193                 $current_URL = $this->start_link_wrapper.$current_URL.$this->end_link_wrapper;
1194                 $start_URL = $this->start_link_wrapper.$start_URL.$this->end_link_wrapper;
1195                 $previous_URL = $this->start_link_wrapper.$previous_URL.$this->end_link_wrapper;
1196                 $next_URL = $this->start_link_wrapper.$next_URL.$this->end_link_wrapper;
1197                 $end_URL = $this->start_link_wrapper.$end_URL.$this->end_link_wrapper;
1198             }
1199
1200             $moduleString = "{$currentModule}_{$html_varName}_offset";
1201             $moduleStringOrder = "{$currentModule}_{$html_varName}_ORDER_BY";
1202             if($this->shouldProcess && !$this->multi_select_popup) {
1203                 // check the checkboxes onload
1204                 echo "<script>YAHOO.util.Event.addListener(window, \"load\", sListView.check_boxes);</script>\n";
1205
1206                 $massUpdateRun = isset($_REQUEST['massupdate']) && $_REQUEST['massupdate'] == 'true';
1207                 $uids = empty($_REQUEST['uid']) || $massUpdateRun ? '' : $_REQUEST['uid'];
1208                 $select_entire_list = ($massUpdateRun) ? 0 : (isset($_POST['select_entire_list']) ? $_POST['select_entire_list'] : (isset($_REQUEST['select_entire_list']) ? $_REQUEST['select_entire_list'] : 0));
1209
1210                 echo "<textarea style='display: none' name='uid'>{$uids}</textarea>\n" .
1211                     "<input type='hidden' name='select_entire_list' value='{$select_entire_list}'>\n".
1212                     "<input type='hidden' name='{$moduleString}' value='0'>\n".
1213                     "<input type='hidden' name='{$moduleStringOrder}' value='0'>\n";
1214
1215             }
1216
1217
1218             $GLOBALS['log']->debug("Offsets: (start, previous, next, last)(0, $previous_offset, $next_offset, $last_offset)");
1219
1220             if(0 == $current_offset) {
1221                 $start_link = "<button type='button' name='listViewStartButton' title='{$this->local_app_strings['LNK_LIST_START']}' class='button' disabled>".SugarThemeRegistry::current()->getImage("start_off","aborder='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_START'])."</button>";
1222                 $previous_link = "<button type='button' name='listViewPrevButton' title='{$this->local_app_strings['LNK_LIST_PREVIOUS']}' class='button' disabled>".SugarThemeRegistry::current()->getImage("previous_off","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_PREVIOUS'])."</button>";
1223             } else {
1224                 if($this->multi_select_popup) {// nav links for multiselect popup, submit form to save checks.
1225                     $start_link = "<button type='button' class='button' name='listViewStartButton' title='{$this->local_app_strings['LNK_LIST_START']}' onClick='javascript:save_checks(0, \"{$moduleString}\");'>".SugarThemeRegistry::current()->getImage("start","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_START'])."</button>";
1226                     $previous_link = "<button type='button' class='button' name='listViewPrevButton' title='{$this->local_app_strings['LNK_LIST_PREVIOUS']}' onClick='javascript:save_checks($previous_offset, \"{$moduleString}\");'>".SugarThemeRegistry::current()->getImage("previous","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_PREVIOUS'])."</button>";
1227                 } elseif($this->shouldProcess) {
1228                     $start_link = "<button type='button' class='button' name='listViewStartButton' title='{$this->local_app_strings['LNK_LIST_START']}' onClick='location.href=\"$start_URL\"; sListView.save_checks(0, \"{$moduleString}\");'>".SugarThemeRegistry::current()->getImage("start","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_START'])."</button>";
1229                     $previous_link = "<button type='button' class='button' name='listViewPrevButton' title='{$this->local_app_strings['LNK_LIST_PREVIOUS']}' onClick='location.href=\"$previous_URL\"; sListView.save_checks($previous_offset, \"{$moduleString}\");'>".SugarThemeRegistry::current()->getImage("previous","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_PREVIOUS'])."</button>";
1230                 } else {
1231                     $onClick = '';
1232                     if(0 != preg_match('/javascript.*/', $start_URL)){
1233                         $onClick = "\"$start_URL;\"";
1234                     }else{
1235                         $onClick ="'location.href=\"$start_URL\";'";
1236                     }
1237                     $start_link = "<button type='button' class='button' name='listViewStartButton' title='{$this->local_app_strings['LNK_LIST_START']}' onClick=".$onClick.">".SugarThemeRegistry::current()->getImage("start","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_START'])."</button>";
1238
1239                     $onClick = '';
1240                     if(0 != preg_match('/javascript.*/', $previous_URL)){
1241                         $onClick = "\"$previous_URL;\"";
1242                     }else{
1243                         $onClick = "'location.href=\"$previous_URL\";'";
1244                     }
1245                     $previous_link = "<button type='button' class='button' name='listViewPrevButton' title='{$this->local_app_strings['LNK_LIST_PREVIOUS']}' onClick=".$onClick.">".SugarThemeRegistry::current()->getImage("previous","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_PREVIOUS'])."</button>";
1246                 }
1247             }
1248
1249             if($last_offset <= $current_offset) {
1250                 $end_link = "<button type='button' name='listViewEndButton' title='{$this->local_app_strings['LNK_LIST_END']}' class='button' disabled>".SugarThemeRegistry::current()->getImage("end_off","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_END'])."</button>";
1251                 $next_link = "<button type='button' name='listViewNextButton' title='{$this->local_app_strings['LNK_LIST_NEXT']}' class='button' disabled>".SugarThemeRegistry::current()->getImage("next_off","aborder='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_NEXT'])."</button>";
1252             } else {
1253                 if($this->multi_select_popup) { // nav links for multiselect popup, submit form to save checks.
1254                     $end_link = "<button type='button' name='listViewEndButton' class='button' title='{$this->local_app_strings['LNK_LIST_END']}' onClick='javascript:save_checks($last_offset, \"{$moduleString}\");'>".SugarThemeRegistry::current()->getImage("end","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_END'])."</button>";
1255                     if(!empty($sugar_config['disable_count_query'])) {
1256                         $end_link = '';
1257                     }
1258                     $next_link = "<button type='button' name='listViewNextButton' title='{$this->local_app_strings['LNK_LIST_NEXT']}' class='button' onClick='javascript:save_checks($next_offset, \"{$moduleString}\");'>".SugarThemeRegistry::current()->getImage("next","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_NEXT'])."</button>";
1259                 } elseif($this->shouldProcess) {
1260                     $end_link = "<button type='button' name='listViewEndButton' class='button' title='{$this->local_app_strings['LNK_LIST_END']}' onClick='location.href=\"$end_URL\"; sListView.save_checks(\"end\", \"{$moduleString}\");'>".SugarThemeRegistry::current()->getImage("end","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_END'])."</button>";
1261                     $next_link = "<button type='button' name='listViewNextButton' class='button' title='{$this->local_app_strings['LNK_LIST_NEXT']}' onClick='location.href=\"$next_URL\"; sListView.save_checks($next_offset, \"{$moduleString}\");'>".SugarThemeRegistry::current()->getImage("next","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_NEXT'])."</button>";
1262                 } else {
1263                     $onClick = '';
1264                     if(0 != preg_match('/javascript.*/', $next_URL)){
1265                         $onClick = "\"$next_URL;\"";
1266                     }else{
1267                         $onClick ="'location.href=\"$next_URL\";'";
1268                     }
1269                     $next_link = "<button type='button' name='listViewNextButton' class='button' title='{$this->local_app_strings['LNK_LIST_NEXT']}' onClick=".$onClick.">".SugarThemeRegistry::current()->getImage("next","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_NEXT'])."</button>";
1270
1271                     $onClick = '';
1272                     if(0 != preg_match('/javascript.*/', $end_URL)){
1273                         $onClick = "\"$end_URL;\"";
1274                     }else{
1275                         $onClick = "'location.href=\"$end_URL\";'";
1276                     }
1277                     $end_link = "<button type='button' name='listViewEndButton' class='button' title='{$this->local_app_strings['LNK_LIST_END']}' onClick=".$onClick.">".SugarThemeRegistry::current()->getImage("end","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_END'])."</button>";
1278
1279                 }
1280             }
1281
1282             $GLOBALS['log']->info("Offset (next, current, prev)($next_offset, $current_offset, $previous_offset)");
1283             $GLOBALS['log']->info("Start/end records ($start_record, $end_record)");
1284
1285             $end_record = $end_record-1;
1286
1287 $script_href = "<a style=\'width: 150px\' name=\"thispage\" class=\'menuItem\' onmouseover=\'hiliteItem(this,\"yes\");\' onmouseout=\'unhiliteItem(this);\' onclick=\'if (document.MassUpdate.select_entire_list.value==1){document.MassUpdate.select_entire_list.value=0;sListView.check_all(document.MassUpdate, \"mass[]\", true, $this->records_per_page)}else {sListView.check_all(document.MassUpdate, \"mass[]\", true)};\' href=\'#\'>{$this->local_app_strings['LBL_LISTVIEW_OPTION_CURRENT']}&nbsp;&#x28;{$this->records_per_page}&#x29;&#x200E;</a>"
1288  . "<a style=\'width: 150px\' name=\"selectall\" class=\'menuItem\' onmouseover=\'hiliteItem(this,\"yes\");\' onmouseout=\'unhiliteItem(this);\' onclick=\'sListView.check_entire_list(document.MassUpdate, \"mass[]\",true,{$row_count});\' href=\'#\'>{$this->local_app_strings['LBL_LISTVIEW_OPTION_ENTIRE']}&nbsp;&#x28;{$row_count}&#x29;&#x200E;</a>"
1289  . "<a style=\'width: 150px\' name=\"deselect\" class=\'menuItem\' onmouseover=\'hiliteItem(this,\"yes\");\' onmouseout=\'unhiliteItem(this);\' onclick=\'sListView.clear_all(document.MassUpdate, \"mass[]\", false);\' href=\'#\'>{$this->local_app_strings['LBL_LISTVIEW_NONE']}</a>";
1290
1291 $close_inline_img = SugarThemeRegistry::current()->getImage('close_inline', 'border=0', null, null, ".gif", $app_strings['LBL_CLOSEINLINE']);
1292
1293             echo "<script>
1294                 function select_dialog() {
1295                         var \$dialog = \$('<div></div>')
1296                                         .html('<a style=\'width: 150px\' name=\"thispage\" class=\'menuItem\' onmouseover=\'hiliteItem(this,\"yes\");\' onmouseout=\'unhiliteItem(this);\' onclick=\'if (document.MassUpdate.select_entire_list.value==1){document.MassUpdate.select_entire_list.value=0;sListView.check_all(document.MassUpdate, \"mass[]\", true, $this->records_per_page)}else {sListView.check_all(document.MassUpdate, \"mass[]\", true)};\' href=\'javascript:void(0)\'>{$this->local_app_strings['LBL_LISTVIEW_OPTION_CURRENT']}&nbsp;&#x28;{$this->records_per_page}&#x29;&#x200E;</a>"
1297                 . "<a style=\'width: 150px\' name=\"selectall\" class=\'menuItem\' onmouseover=\'hiliteItem(this,\"yes\");\' onmouseout=\'unhiliteItem(this);\' onclick=\'sListView.check_entire_list(document.MassUpdate, \"mass[]\",true,{$row_count});\' href=\'javascript:void(0)\'>{$this->local_app_strings['LBL_LISTVIEW_OPTION_ENTIRE']}&nbsp;&#x28;{$row_count}&#x29;&#x200E;</a>"
1298                 . "<a style=\'width: 150px\' name=\"deselect\" class=\'menuItem\' onmouseover=\'hiliteItem(this,\"yes\");\' onmouseout=\'unhiliteItem(this);\' onclick=\'sListView.clear_all(document.MassUpdate, \"mass[]\", false);\' href=\'javascript:void(0)\'>{$this->local_app_strings['LBL_LISTVIEW_NONE']}</a>')
1299                                         .dialog({
1300                                                 autoOpen: false,
1301                                                 width: 150
1302                                         });
1303                                         \$dialog.dialog('open');
1304
1305                 }
1306                 </script>";
1307
1308             if($this->show_select_menu)
1309             {
1310                 $total_label = "";
1311                 $total = $row_count;
1312                 $pageTotal = ($row_count > 0) ? $end_record - $start_record + 1 : 0;
1313                 if (!empty($GLOBALS['sugar_config']['disable_count_query']) && $GLOBALS['sugar_config']['disable_count_query'] === true && $total > $pageTotal) {
1314                     $this->show_plus = true;
1315                     $total =  $pageTotal;
1316                     $total_label = $total.'+';
1317                 } else {
1318                     $this->show_plus = false;
1319                     $total_label = $total;
1320                 }
1321                 echo "<input type='hidden' name='show_plus' value='{$this->show_plus}'>\n";
1322
1323                 //Bug#52931: Replace with actionMenu
1324                 //$select_link = "<a id='select_link' onclick='return select_dialog();' href=\"javascript:void(0)\">".$this->local_app_strings['LBL_LINK_SELECT']."&nbsp;".SugarThemeRegistry::current()->getImage('MoreDetail', 'border=0', 11, 7, '.png', $app_strings['LBL_MOREDETAIL'])."</a>";
1325                 $menuItems = array(
1326                     "<input title=\"".$app_strings['LBL_SELECT_ALL_TITLE']."\" type='checkbox' class='checkbox massall' name='massall' id='massall' value='' onclick='sListView.check_all(document.MassUpdate, \"mass[]\", this.checked);' /><a href='javascript: void(0);'></a>",
1327                     "<a  name='thispage' id='button_select_this_page' class='menuItem' onmouseover='hiliteItem(this,\"yes\");' onmouseout='unhiliteItem(this);' onclick='if (document.MassUpdate.select_entire_list.value==1){document.MassUpdate.select_entire_list.value=0;sListView.check_all(document.MassUpdate, \"mass[]\", true, $pageTotal)}else {sListView.check_all(document.MassUpdate, \"mass[]\", true)};' href='#'>{$app_strings['LBL_LISTVIEW_OPTION_CURRENT']}&nbsp;&#x28;{$pageTotal}&#x29;&#x200E;</a>",
1328                     "<a  name='selectall' id='button_select_all' class='menuItem' onmouseover='hiliteItem(this,\"yes\");' onmouseout='unhiliteItem(this);' onclick='sListView.check_entire_list(document.MassUpdate, \"mass[]\",true,{$total});' href='#'>{$app_strings['LBL_LISTVIEW_OPTION_ENTIRE']}&nbsp;&#x28;{$total_label}&#x29;&#x200E;</a>",
1329                     "<a name='deselect' id='button_deselect' class='menuItem' onmouseover='hiliteItem(this,\"yes\");' onmouseout='unhiliteItem(this);' onclick='sListView.clear_all(document.MassUpdate, \"mass[]\", false);' href='#'>{$app_strings['LBL_LISTVIEW_NONE']}</a>",
1330                 );
1331                 require_once('include/Smarty/plugins/function.sugar_action_menu.php');
1332                 $select_link = smarty_function_sugar_action_menu(array(
1333                     'class' => 'clickMenu selectmenu',
1334                     'id' => 'selectLink',
1335                     'buttons' => $menuItems,
1336                     'flat' => false,
1337                 ),$this->xTemplate);
1338
1339             } else {
1340                 $select_link = "&nbsp;";
1341             }
1342
1343             $export_link = '<input class="button" type="button" value="'.$this->local_app_strings['LBL_EXPORT'].'" ' .
1344                     'onclick="return sListView.send_form(true, \''.$_REQUEST['module'].'\', \'index.php?entryPoint=export\',\''.$this->local_app_strings['LBL_LISTVIEW_NO_SELECTED'].'\')">';
1345
1346             if($this->show_delete_button) {
1347                 $delete_link = '<input class="button" type="button" id="delete_button" name="Delete" value="'.$this->local_app_strings['LBL_DELETE_BUTTON_LABEL'].'" onclick="return sListView.send_mass_update(\'selected\',\''.$this->local_app_strings['LBL_LISTVIEW_NO_SELECTED'].'\', 1)">';
1348             } else {
1349                 $delete_link = '&nbsp;';
1350             }
1351
1352             $admin = new Administration();
1353             $admin->retrieveSettings('system');
1354
1355             $user_merge = $current_user->getPreference('mailmerge_on');
1356             if($user_merge == 'on' && isset($admin->settings['system_mailmerge_on']) && $admin->settings['system_mailmerge_on']) {
1357                 echo "<script>
1358                 function mailmerge_dialog(el) {
1359                         var \$dialog = \$('<div></div>')
1360                                         .html('<a style=\'width: 150px\' class=\'menuItem\' onmouseover=\'hiliteItem(this,\"yes\");\' onmouseout=\'unhiliteItem(this);\' onclick=\'return sListView.send_form(true, \"MailMerge\", \"index.php\", \"{$this->local_app_strings['LBL_LISTVIEW_NO_SELECTED']}\")\' href=\'javascript:void(0)\'>{$this->local_app_strings['LBL_LISTVIEW_OPTION_SELECTED']}</a>"
1361                         . "<a style=\'width: 150px\' class=\'menuItem\' onmouseover=\'hiliteItem(this,\"yes\");\' onmouseout=\'unhiliteItem(this);\' href=\'index.php?action=index&module=MailMerge\'>{$this->local_app_strings['LBL_LISTVIEW_OPTION_CURRENT']}</a>"
1362                         . "<a style=\'width: 150px\' class=\'menuItem\' onmouseover=\'hiliteItem(this,\"yes\");\' onmouseout=\'unhiliteItem(this);\' href=\'index.php?action=index&module=MailMerge&entire=true\'>{$this->local_app_strings['LBL_LISTVIEW_OPTION_ENTIRE']}</a>')
1363                                         .dialog({
1364                                                 autoOpen: false,
1365                                                 title: '". $this->local_app_strings['LBL_MAILMERGE']."',
1366                                                 width: 150,
1367                                                 position: {
1368                                                     my: myPos,
1369                                                     at: atPos,
1370                                                     of: \$(el)
1371                                                 }
1372                                         });
1373
1374                 }
1375             </script>";
1376                 $merge_link = "&nbsp;|&nbsp;<a id='mailmerge_link' onclick='return mailmerge_dialog(this)'; href=\"javascript:void(0)\">".$this->local_app_strings['LBL_MAILMERGE']."</a>";
1377             } else {
1378                 $merge_link = "&nbsp;";
1379             }
1380
1381             $selected_objects_span = "&nbsp;|&nbsp;{$this->local_app_strings['LBL_LISTVIEW_SELECTED_OBJECTS']}<input  style='border: 0px; background: transparent; font-size: inherit; color: inherit' type='text' readonly name='selectCount[]' value='" . ((isset($_POST['mass'])) ? count($_POST['mass']): 0) . "' />";
1382
1383             if($_REQUEST['module'] == 'Home' || $this->local_current_module == 'Import'
1384                 || $this->show_export_button == false
1385                 || (!empty($sugar_config['disable_export']))
1386                 || (!empty($sugar_config['admin_export_only'])
1387                 && !(
1388                         is_admin($current_user)
1389                         || (ACLController::moduleSupportsACL($_REQUEST['module'])
1390                             && ACLAction::getUserAccessLevel($current_user->id,$_REQUEST['module'], 'access') == ACL_ALLOW_ENABLED
1391                             && (ACLAction::getUserAccessLevel($current_user->id, $_REQUEST['module'], 'admin') == ACL_ALLOW_ADMIN ||
1392                                 ACLAction::getUserAccessLevel($current_user->id, $_REQUEST['module'], 'admin') == ACL_ALLOW_ADMIN_DEV)))))
1393             {
1394                 if ($_REQUEST['module'] != 'InboundEmail' && $_REQUEST['module'] != 'EmailMan' && $_REQUEST['module'] != 'iFrames') {
1395                     $selected_objects_span = '';
1396                 }
1397                 $export_link = "&nbsp;";
1398                 $merge_link = "&nbsp;";
1399             } elseif($_REQUEST['module'] != "Accounts" && $_REQUEST['module'] != "Cases" && $_REQUEST['module'] != "Contacts" && $_REQUEST['module'] != "Leads" && $_REQUEST['module'] != "Opportunities") {
1400                 $merge_link = "&nbsp;";
1401             }
1402
1403             if($this->show_paging == true) {
1404                 if(!empty($sugar_config['disable_count_query'])) {
1405                     if($row_count > $end_record) {
1406                         $row_count .= '+';
1407                     }
1408                 }
1409
1410                 $html_text = '';
1411                 $html_text .= "<tr class='pagination' role='presentation'>\n";
1412                 $html_text .= "<td COLSPAN=\"$col_count\" align=\"right\">\n";
1413                 //$html_text .= "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"  >$export_link$merge_link$selected_objects_span</td>\n";
1414                 //$html_text .= "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"  >";
1415                 if ($subpanel_def != null) {
1416                     include_once('include/SubPanel/SubPanelTiles.php');
1417                     $subpanelTiles = new SubPanelTiles($sugarbean);
1418                     $html_text .= "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"  >";
1419
1420                     //attempt to get the query to recreate this subpanel
1421                     if(!empty($this->response)){
1422                         $response =& $this->response;
1423                     }else{
1424                         $response = SugarBean::get_union_related_list($sugarbean,$this->sortby, $this->sort_order, $this->query_where, $current_offset, -1, $this->records_per_page,$this->query_limit,$subpanel_def);
1425                         $this->response = $response;
1426                     }
1427                     //if query is present, then pass it in as parameter
1428                     if (isset($response['query']) && !empty($response['query'])){
1429                         $html_text .= $subpanelTiles->get_buttons($subpanel_def, $response['query']);
1430                     }else{
1431                         $html_text .= $subpanelTiles->get_buttons($subpanel_def);
1432                     }
1433                 }
1434                 else {
1435                     $html_text .= "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"  nowrap>$select_link&nbsp;$export_link&nbsp;$delete_link&nbsp;$selected_objects_span";
1436                 }
1437                 $html_text .= "</td>\n<td nowrap align=\"right\">".$start_link."&nbsp;&nbsp;".$previous_link."&nbsp;&nbsp;<span class='pageNumbers'>(".$start_record." - ".$end_record." ".$this->local_app_strings['LBL_LIST_OF']." ".$row_count.")</span>&nbsp;&nbsp;".$next_link."&nbsp;&nbsp;".$end_link."</td></tr></table>\n";
1438                 $html_text .= "</td>\n";
1439                 $html_text .= "</tr>\n";
1440                 $this->xTemplate->assign("PAGINATION",$html_text);
1441             }
1442
1443             //C.L. - Fix for 23461
1444             if(empty($_REQUEST['action']) || $_REQUEST['action'] != 'Popup') {
1445                 $_SESSION['export_where'] = $this->query_where;
1446             }
1447             $this->xTemplate->parse($xtemplateSection.".list_nav_row");
1448         }
1449     } // end processListNavigation
1450
1451     function processOrderBy($html_varName) {
1452
1453         if(!isset($this->base_URL)) {
1454             $this->base_URL = $_SERVER['PHP_SELF'];
1455
1456             if(isset($_SERVER['QUERY_STRING'])) {
1457                 $this->base_URL = preg_replace("/\&".$this->getSessionVariableName($html_varName,"ORDER_BY")."=[0-9a-zA-Z\_\.]*/","",$this->base_URL .'?'.$_SERVER['QUERY_STRING']);
1458                 $this->base_URL = preg_replace("/\&".$this->getSessionVariableName($html_varName,"offset")."=[0-9]*/","",$this->base_URL);
1459             }
1460             if($_SERVER['REQUEST_METHOD'] == 'POST') {
1461                 $this->base_URL .= '?';
1462                 if(isset($_REQUEST['action'])) $this->base_URL .= '&action='.$_REQUEST['action'];
1463                 if(isset($_REQUEST['record'])) $this->base_URL .= '&record='.$_REQUEST['record'];
1464                 if(isset($_REQUEST['module'])) $this->base_URL .= '&module='.$_REQUEST['module'];
1465             }
1466             $this->base_URL .= "&".$this->getSessionVariableName($html_varName,"offset")."=";
1467         }
1468
1469         if($this->is_dynamic) {
1470             $this->base_URL.='&to_pdf=true&action=SubPanelViewer&subpanel=' . $this->source_module;
1471         }
1472
1473         //bug43465 start
1474         if (isset($this->appendToBaseUrl) && is_array($this->appendToBaseUrl))
1475         {
1476             foreach ($this->appendToBaseUrl as $key => $value)
1477             {
1478                 $fullRequestString = $key . '=' . $value;
1479
1480                 if ($this->base_URL == "/index.php")
1481                 {
1482                     $this->base_URL .= "?";
1483                 } else
1484                 {
1485                     if ($fullRequestString == substr($this->baseURL, '-' . strlen($fullRequestString)))
1486                     {
1487                         $this->base_URL = preg_replace("/&" . $key . "\=.*/", "", $this->base_URL);
1488                     } else
1489                     {
1490                         $this->base_URL = preg_replace("/&" . $key . "\=.*?&/", "&", $this->base_URL);
1491                     }
1492                     $this->base_URL .= "&";
1493                 }
1494                 if (!empty($value))
1495                 {
1496                     $this->base_URL .= "{$key}={$value}";
1497                 }
1498             }
1499         }
1500         //bug43465 end
1501
1502         $sort_URL_base = $this->base_URL. "&".$this->getSessionVariableName($html_varName,"ORDER_BY")."=";
1503
1504         if($sort_URL_base !== "")
1505         {
1506             $this->xTemplate->assign("ORDER_BY", $sort_URL_base);
1507             return $sort_URL_base;
1508         } else {
1509             return '';
1510         }
1511     }
1512
1513
1514     function getAdditionalHeader() {
1515
1516     }
1517
1518
1519     /**
1520     * @return void
1521     * @param unknown $data
1522     * @param unknown $xTemplateSection
1523     * @param unknown $html_varName
1524     * @desc INTERNAL FUNCTION handles the rows
1525     * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1526     * All Rights Reserved.
1527     * Contributor(s): ______________________________________..
1528     */
1529     function processListRows($data, $xtemplateSection, $html_varName)
1530     {
1531         global $odd_bg;
1532         global $even_bg;
1533         global $hilite_bg;
1534         global $app_strings, $sugar_version, $sugar_config;
1535         global $currentModule;
1536
1537         $this->xTemplate->assign('BG_HILITE', $hilite_bg);
1538         $this->xTemplate->assign('CHECKALL', SugarThemeRegistry::current()->getImage('blank', '', 1, 1, ".gif", ''));
1539     //$this->xTemplate->assign("BG_CLICK", $click_bg);
1540         $oddRow = true;
1541         $count = 0;
1542         reset($data);
1543
1544         //GETTING OFFSET
1545         $offset = $this->getOffset($html_varName);
1546         $timeStamp = $this->unique_id();
1547         $_SESSION[$html_varName."_FROM_LIST_VIEW"] = $timeStamp;
1548
1549         $associated_row_data = array();
1550
1551         //mail merge list
1552         $mergeList = array();
1553         $module = '';
1554         //todo what is this?  It is using an array as a boolean
1555         while(list($aVal, $aItem) = each($data))
1556         {
1557             if(isset($this->data_array)) {
1558                 $fields = $this->data_array;
1559             } else {
1560                 $aItem->check_date_relationships_load();
1561                 $fields = $aItem->get_list_view_data();
1562             }
1563
1564             if(is_object($aItem)) { // cn: bug 5349
1565                 //add item id to merge list, if the button is clicked
1566                 $mergeList[] = $aItem->id;
1567                 if(empty($module)) {
1568                     $module = $aItem->module_dir;
1569                 }
1570             }
1571             //ADD OFFSET TO ARRAY
1572
1573                 $fields['OFFSET'] = ($offset + $count + 1);
1574
1575             $fields['STAMP'] = $timeStamp;
1576             if($this->shouldProcess) {
1577
1578             $prerow = '';
1579             if(!isset($this->data_array)) {
1580                 $prerow .= "<input onclick='sListView.check_item(this, document.MassUpdate)' type='checkbox' class='checkbox' name='mass[]' value='". $fields['ID']. "'>";
1581             }
1582             $this->xTemplate->assign('PREROW', $prerow);
1583
1584             $this->xTemplate->assign('CHECKALL', "<input type='checkbox' class='checkbox'  title='".$GLOBALS['app_strings']['LBL_SELECT_ALL_TITLE']."'  name='massall' id='massall' value='' onclick='sListView.check_all(document.MassUpdate, \"mass[]\", this.checked)'>");
1585             }
1586             if(!isset($this->data_array)) {
1587                 $tag = $aItem->listviewACLHelper();
1588                 $this->xTemplate->assign('TAG',$tag) ;
1589             }
1590
1591             if($oddRow)
1592             {
1593                 $ROW_COLOR = 'oddListRow';
1594                 $BG_COLOR =  $odd_bg;
1595             }
1596             else
1597             {
1598                 $ROW_COLOR = 'evenListRow';
1599                 $BG_COLOR =  $even_bg;
1600             }
1601             $oddRow = !$oddRow;
1602
1603             $this->xTemplate->assign('ROW_COLOR', $ROW_COLOR);
1604             $this->xTemplate->assign('BG_COLOR', $BG_COLOR);
1605
1606             if(isset($this->data_array))
1607             {
1608                 $this->xTemplate->assign('KEY', $aVal);
1609                 $this->xTemplate->assign('VALUE', $aItem);
1610                 $this->xTemplate->assign('INDEX', $count);
1611
1612             }
1613             else
1614             {
1615     //AED -- some modules do not have their additionalDetails.php established. Add a check to ensure require_once does not fail
1616     // Bug #2786
1617                 if($this->_additionalDetails && $aItem->ACLAccess('DetailView') && (file_exists('modules/' . $aItem->module_dir . '/metadata/additionalDetails.php') || file_exists('custom/modules/' . $aItem->module_dir . '/metadata/additionalDetails.php'))) {
1618
1619                     $additionalDetailsFile = 'modules/' . $aItem->module_dir . '/metadata/additionalDetails.php';
1620                     if(file_exists('custom/modules/' . $aItem->module_dir . '/metadata/additionalDetails.php')){
1621                         $additionalDetailsFile = 'custom/modules/' . $aItem->module_dir . '/metadata/additionalDetails.php';
1622                     }
1623
1624                     require_once($additionalDetailsFile);
1625                     $ad_function = (empty($this->additionalDetailsFunction) ? 'additionalDetails' : $this->additionalDetailsFunction) . $aItem->object_name;
1626                     $results = $ad_function($fields);
1627                     $results['string'] = str_replace(array("&#039", "'"), '\&#039', $results['string']); // no xss!
1628
1629                     if(trim($results['string']) == '') $results['string'] = $app_strings['LBL_NONE'];
1630                     $fields[$results['fieldToAddTo']] = $fields[$results['fieldToAddTo']].'</a>';
1631                 }
1632
1633                 if($aItem->ACLAccess('Delete')) {
1634                     $delete = '<a class="listViewTdToolsS1" onclick="return confirm(\''.$this->local_app_strings['NTC_DELETE_CONFIRMATION'].'\')" href="'.'index.php?action=Delete&module='.$aItem->module_dir.'&record='.$fields['ID'].'&return_module='.$aItem->module_dir.'&return_action=index&return_id=">'.$this->local_app_strings['LBL_DELETE_INLINE'].'</a>';
1635                     require_once('include/Smarty/plugins/function.sugar_action_menu.php');
1636                     $fields['DELETE_BUTTON'] = smarty_function_sugar_action_menu(array(
1637                         'id' => $aItem->module_dir.'_'.$fields['ID'].'_create_button',
1638                         'buttons' => array($delete),
1639                     ), $this);
1640
1641                 }
1642
1643                 $this->xTemplate->assign($html_varName, $fields);
1644                 $aItem->setupCustomFields($aItem->module_dir);
1645                 $aItem->custom_fields->populateAllXTPL($this->xTemplate, 'detail', $html_varName, $fields);
1646             }
1647             if(!isset($this->data_array) && $aItem->ACLAccess('DetailView')) {
1648                 $count++;
1649             }
1650             if(isset($this->data_array)) {
1651                 $count++;
1652             }
1653             if(!isset($this->data_array)) {
1654                 $aItem->list_view_parse_additional_sections($this->xTemplate, $xtemplateSection);
1655
1656                 if($this->xTemplate->exists($xtemplateSection.'.row.pro')) {
1657                     $this->xTemplate->parse($xtemplateSection.'.row.pro');
1658                 }
1659             }
1660             $this->xTemplate->parse($xtemplateSection . '.row');
1661
1662             if(isset($fields['ID'])) {
1663                 $associated_row_data[$fields['ID']] = $fields;
1664                 // Bug 38908: cleanup data for JS to avoid having &nbsp; shuffled around
1665                 foreach($fields as $key => $value) {
1666                     if($value == '&nbsp;') {
1667                         $associated_row_data[$fields['ID']][$key] = '';
1668                     }
1669                 }
1670             }
1671         }
1672
1673         $_SESSION['MAILMERGE_RECORDS'] = $mergeList;
1674         $_SESSION['MAILMERGE_MODULE_FROM_LISTVIEW'] = $module;
1675         if(empty($_REQUEST['action']) || $_REQUEST['action'] != 'Popup') {
1676             $_SESSION['MAILMERGE_MODULE'] = $module;
1677         }
1678
1679         if($this->process_for_popups)
1680         {
1681             $json = getJSONobj();
1682             $is_show_fullname = showFullName() ? 1 : 0;
1683             $associated_javascript_data = '<script type="text/javascript">' . "\n"
1684                 //. '<!-- // associated javascript data generated by ListView' . "\n"
1685                 . 'var associated_javascript_data = '
1686                 . $json->encode($associated_row_data) . ";\n"
1687                 //. '-->' . "\n"
1688                 . 'var is_show_fullname = '
1689                 . $is_show_fullname . ";\n"
1690                 . '</script>';
1691             $this->xTemplate->assign('ASSOCIATED_JAVASCRIPT_DATA', $associated_javascript_data);
1692         }
1693
1694         $this->xTemplate->parse($xtemplateSection);
1695     }
1696
1697
1698     function getLayoutManager()
1699     {
1700         require_once('include/generic/LayoutManager.php');
1701         if($this->layout_manager == null)
1702         {
1703             $this->layout_manager = new LayoutManager();
1704         }
1705         return $this->layout_manager;
1706     }
1707
1708
1709     function process_dynamic_listview_header($source_module, $subpanel_def, $html_var = 'CELL')
1710     {
1711
1712
1713         $layout_manager = $this->getLayoutManager();
1714         $layout_manager->setAttribute('order_by_link',$this->processOrderBy($html_var));
1715         $layout_manager->setAttribute('context','HeaderCell');
1716         $layout_manager->setAttribute('image_path',$this->local_image_path);
1717         $layout_manager->setAttribute('html_varName',$html_var);
1718         $layout_manager->setAttribute('module_name', $source_module);
1719         list($orderBy,$desc) = $this->getOrderByInfo($html_var);
1720
1721         if($orderBy == 'amount*1')
1722         {
1723             $orderBy=  'amount';
1724         }
1725                 $buttons = false;
1726         foreach($subpanel_def->get_list_fields() as $column_name=>$widget_args)
1727         {
1728             $usage = empty($widget_args['usage']) ? '' : $widget_args['usage'];
1729             if($usage != 'query_only' || !empty($widget_args['force_query_only_display']))
1730             {
1731                 $imgArrow = '';
1732
1733                 if($orderBy == $column_name || (isset($widget_args['sort_by']) && str_replace('.','_',$widget_args['sort_by']) == $orderBy))
1734                 {
1735                     $imgArrow = "_down";
1736                     if($this->sort_order == 'asc') {
1737                         $imgArrow = "_up";
1738                     }
1739                 }
1740
1741                 if (!preg_match("/_button/i", $column_name)) {
1742                         $widget_args['name']=$column_name;
1743                         $widget_args['sort'] = $imgArrow;
1744                         $widget_args['start_link_wrapper'] = $this->start_link_wrapper;
1745                         $widget_args['end_link_wrapper'] = $this->end_link_wrapper;
1746                         $widget_args['subpanel_module'] = $this->subpanel_module;
1747
1748                         $widget_contents = $layout_manager->widgetDisplay($widget_args);
1749                         $cell_width = empty($widget_args['width']) ? '' : $widget_args['width'];
1750                         $this->xTemplate->assign('HEADER_CELL', $widget_contents);
1751                         static $count;
1752                     if(!isset($count))$count = 0; else $count++;
1753                         $this->xTemplate->assign('CELL_COUNT', $count);
1754                         $this->xTemplate->assign('CELL_WIDTH', $cell_width);
1755                         $this->xTemplate->parse('dyn_list_view.header_cell');
1756                 } else {
1757                         $buttons = true;
1758                 }
1759             }
1760         }
1761
1762         if($buttons) {
1763                                 $this->xTemplate->assign('HEADER_CELL', "&nbsp;");
1764                                 $this->xTemplate->assign('CELL_COUNT', $count);
1765                         $this->xTemplate->assign('CELL_WIDTH', $cell_width);
1766                         $this->xTemplate->parse('dyn_list_view.header_cell');
1767         }
1768
1769     }
1770
1771
1772     /**
1773     * @return void
1774     * @param unknown $seed
1775     * @param unknown $xTemplateSection
1776     * @param unknown $html_varName
1777     * @desc PUBLIC FUNCTION Handles List Views using seeds that extend SugarBean
1778         $XTemplateSection is the section in the XTemplate file that should be parsed usually main
1779         $html_VarName is the variable name used in the XTemplateFile e.g. TASK
1780         $seed is a seed there are two types of seeds one is a subclass of SugarBean, the other is a list usually created from a sugar bean using get_list
1781         if no XTemplate is set it will create  a new XTemplate
1782         * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
1783         * All Rights Reserved..
1784         * Contributor(s): ______________________________________..
1785     */
1786
1787     function processListViewTwo($seed, $xTemplateSection, $html_varName) {
1788         global $current_user;
1789         if(!isset($this->xTemplate)) {
1790             $this->createXTemplate();
1791         }
1792
1793         $isSugarBean = is_subclass_of($seed, "SugarBean");
1794         $list = null;
1795
1796         if($isSugarBean) {
1797             $list = $this->processSugarBean($xTemplateSection, $html_varName, $seed);
1798         } else {
1799             $list = $seed;
1800         }
1801
1802         if (is_object($seed) && isset($seed->object_name) && $seed->object_name == 'WorkFlow') {
1803             $tab=array();
1804             $access = get_workflow_admin_modules_for_user($current_user);
1805             for ($i = 0; $i < count($list); $i++) {
1806                 if(!empty($access[$list[$i]->base_module])){
1807                     $tab[]=$list[$i];
1808                 }
1809             }
1810             $list = $tab;
1811         }
1812
1813         if($this->is_dynamic) {
1814             $this->processHeaderDynamic($xTemplateSection,$html_varName);
1815             $this->processListRows($list,$xTemplateSection, $html_varName);
1816         } else {
1817             $this->processSortArrows($html_varName);
1818
1819             if($isSugarBean) {
1820                 $seed->parse_additional_headers($this->xTemplate, $xTemplateSection);
1821             }
1822             $this->xTemplateAssign('CHECKALL', SugarThemeRegistry::current()->getImage('blank', '', 1, 1, ".gif", ''));
1823
1824             // Process the  order by before processing the pro_nav.  The pro_nav requires the order by values to be set
1825             $this->processOrderBy($html_varName);
1826
1827
1828             $this->processListRows($list,$xTemplateSection, $html_varName);
1829         }
1830
1831         if($this->display_header_and_footer) {
1832             $this->getAdditionalHeader();
1833             if(!empty($this->header_title)) {
1834                 echo get_form_header($this->header_title, $this->header_text, false);
1835             }
1836         }
1837
1838         $this->xTemplate->out($xTemplateSection);
1839
1840         if(isset($_SESSION['validation'])) {
1841             print base64_decode('PGEgaHJlZj0naHR0cDovL3d3dy5zdWdhcmNybS5jb20nPlBPV0VSRUQmbmJzcDtCWSZuYnNwO1NVR0FSQ1JNPC9hPg==');
1842         }
1843     }
1844
1845     function getArrowStart() {
1846         $imgFileParts = pathinfo(SugarThemeRegistry::current()->getImageURL("arrow.gif"));
1847
1848         return "&nbsp;<!--not_in_theme!--><img border='0' src='".$imgFileParts['dirname']."/".$imgFileParts['filename']."";
1849     }
1850
1851     function getArrowUpDownStart($upDown) {
1852         $ext = ( SugarThemeRegistry::current()->pngSupport ? "png" : "gif" );
1853
1854         if (!isset($upDown) || empty($upDown)) {
1855             $upDown = "";
1856         }
1857         return "&nbsp;<img border='0' src='".SugarThemeRegistry::current()->getImageURL("arrow{$upDown}.{$ext}")."' ";
1858     }
1859
1860         function getArrowEnd() {
1861                 $imgFileParts = pathinfo(SugarThemeRegistry::current()->getImageURL("arrow.gif"));
1862
1863         list($width,$height) = ListView::getArrowImageSize();
1864
1865                 return '.'.$imgFileParts['extension']."' width='$width' height='$height' align='absmiddle' alt=".translate('LBL_SORT').">";
1866     }
1867
1868     function getArrowUpDownEnd($upDown) {
1869         if (!isset($upDown) || empty($upDown)) {
1870             $upDown = "";
1871         }
1872         $imgFileParts = pathinfo(SugarThemeRegistry::current()->getImageURL("arrow{$upDown}.gif"));
1873
1874         list($width,$height) = ListView::getArrowUpDownImageSize($upDown);
1875
1876         //get the right alt tag for the sort
1877         $sortStr = translate('LBL_ALT_SORT');
1878         if($upDown == '_down'){
1879             $sortStr = translate('LBL_ALT_SORT_DESC');
1880         }elseif($upDown == '_up'){
1881             $sortStr = translate('LBL_ALT_SORT_ASC');
1882         }
1883         return " width='$width' height='$height' align='absmiddle' alt='$sortStr'>";
1884     }
1885
1886         function getArrowImageSize() {
1887             // jbasicChartDashletsExpColust get the non-sort image's size.. the up and down have be the same.
1888                 $image = SugarThemeRegistry::current()->getImageURL("arrow.gif",false);
1889
1890         $cache_key = 'arrow_size.'.$image;
1891
1892         // Check the cache
1893         $result = sugar_cache_retrieve($cache_key);
1894         if(!empty($result))
1895         return $result;
1896
1897         // No cache hit.  Calculate the value and return.
1898         $result = getimagesize($image);
1899         sugar_cache_put($cache_key, $result);
1900         return $result;
1901     }
1902
1903     function getArrowUpDownImageSize($upDown) {
1904         // just get the non-sort image's size.. the up and down have be the same.
1905         $image = SugarThemeRegistry::current()->getImageURL("arrow{$upDown}.gif",false);
1906
1907         $cache_key = 'arrowupdown_size.'.$image;
1908
1909         // Check the cache
1910         $result = sugar_cache_retrieve($cache_key);
1911         if(!empty($result))
1912         return $result;
1913
1914         // No cache hit.  Calculate the value and return.
1915         $result = getimagesize($image);
1916         sugar_cache_put($cache_key, $result);
1917         return $result;
1918     }
1919
1920         function getOrderByInfo($html_varName)
1921         {
1922                 $orderBy = $this->getSessionVariable($html_varName, "OBL");
1923                 $desc = $this->getSessionVariable($html_varName, $orderBy.'S');
1924                 $orderBy = str_replace('.', '_', $orderBy);
1925                 return array($orderBy,$desc);
1926         }
1927
1928     function processSortArrows($html_varName)
1929     {
1930
1931         $this->xTemplateAssign("arrow_start", $this->getArrowStart());
1932
1933         list($orderBy,$desc) = $this->getOrderByInfo($html_varName);
1934
1935                 $imgArrow = "_up";
1936                 if($desc) {
1937                         $imgArrow = "_down";
1938                 }
1939                 /**
1940                  * @deprecated only used by legacy opportunites listview, nothing current. Leaving for BC
1941                  */
1942                 if($orderBy == 'amount')
1943                 {
1944                         $this->xTemplateAssign('amount_arrow', $imgArrow);
1945                 }
1946                 else if($orderBy == 'amount_usdollar')
1947                 {
1948                         $this->xTemplateAssign('amount_usdollar_arrow', $imgArrow);
1949                 }
1950                 else
1951                 {
1952                         $this->xTemplateAssign($orderBy.'_arrow', $imgArrow);
1953                 }
1954
1955         $this->xTemplateAssign('arrow_end', $this->getArrowEnd());
1956     }
1957
1958     // this is where translation happens for dynamic list views
1959     function loadListFieldDefs(&$subpanel_fields,&$child_focus)
1960     {
1961         $this->list_field_defs = $subpanel_fields;
1962
1963         for($i=0;$i < count($this->list_field_defs);$i++)
1964         {
1965             $list_field = $this->list_field_defs[$i];
1966             $field_def = null;
1967             $key = '';
1968             if(!empty($list_field['vname']))
1969             {
1970                 $key = $list_field['vname'];
1971             } else if(isset($list_field['name']) &&  isset($child_focus->field_defs[$list_field['name']]))
1972             {
1973                     $field_def = $child_focus->field_defs[$list_field['name']];
1974                     $key = $field_def['vname'];
1975             }
1976             if(!empty($key))
1977             {
1978                 $list_field['label'] = translate($key,$child_focus->module_dir);
1979                 $this->list_field_defs[$i]['label'] = preg_replace('/:$/','',$list_field['label']);
1980             }
1981             else
1982             {
1983                 $this->list_field_defs[$i]['label'] ='&nbsp;';
1984             }
1985         }
1986     }
1987
1988     function unique_id() {
1989         return sugar_microtime();
1990     }
1991
1992      /**INTERNAL FUNCTION sets a session variable keeping it local to the listview
1993      not the current_module
1994      * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1995      * All Rights Reserved.
1996      * Contributor(s): ______________________________________.
1997      */
1998      function setLocalSessionVariable($localVarName,$varName, $value) {
1999         $_SESSION[$localVarName."_".$varName] = $value;
2000      }
2001
2002      /**INTERNAL FUNCTION returns a session variable that is local to the listview,
2003      not the current_module
2004      * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
2005      * All Rights Reserved.
2006      * Contributor(s): ______________________________________.
2007      */
2008  function getLocalSessionVariable($localVarName,$varName) {
2009     if(isset($_SESSION[$localVarName."_".$varName])) {
2010         return $_SESSION[$localVarName."_".$varName];
2011     }
2012     else{
2013         return "";
2014     }
2015  }
2016
2017  /* Set to true if you want Additional Details to appear in the listview
2018   */
2019  function setAdditionalDetails($value = true, $function = '') {
2020     if(!empty($function)) $this->additionalDetailsFunction = $function;
2021     $this->_additionalDetails = $value;
2022  }
2023
2024 }
2025 ?>