]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/ListView/ListView.php
Release 6.5.0beta1
[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-2012 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 $odd_bg;
239     global $even_bg;
240     global $hilite_bg;
241     global $click_bg;
242
243     $this->xTemplate->assign("BG_HILITE", $hilite_bg);
244     $this->xTemplate->assign('CHECKALL', SugarThemeRegistry::current()->getImage('blank', '', 1, 1, ".gif", ''));
245     //$this->xTemplate->assign("BG_CLICK", $click_bg);
246     $oddRow = true;
247     $count = 0;
248     reset($data);
249
250     //GETTING OFFSET
251     $offset = $this->getOffset($html_varName);
252     //$totaltime = 0;
253     $processed_ids = array();
254
255     $fill_additional_fields = array();
256     //Either retrieve the is_fill_in_additional_fields property from the lone
257     //subpanel or visit each subpanel's subpanels to retrieve the is_fill_in_addition_fields
258     //property
259     $subpanel_list=array();
260     if($subpanel_def->isCollection()) {
261         $subpanel_list=$subpanel_def->sub_subpanels;
262     } else {
263         $subpanel_list[]= $subpanel_def;
264     }
265
266     foreach($subpanel_list as $this_subpanel)
267     {
268         if($this_subpanel->is_fill_in_additional_fields())
269         {
270             $fill_additional_fields[] = $this_subpanel->bean_name;
271             $fill_additional_fields[$this_subpanel->bean_name] = true;
272         }
273     }
274
275     if ( empty($data) ) {
276         $this->xTemplate->assign("ROW_COLOR", 'oddListRow');
277         $thepanel=$subpanel_def;
278         if($subpanel_def->isCollection())
279             $thepanel=$subpanel_def->get_header_panel_def();
280         $this->xTemplate->assign("COL_COUNT", count($thepanel->get_list_fields()));
281         $this->xTemplate->parse($xtemplateSection.".nodata");
282     }
283
284     while(list($aVal, $aItem) = each($data))
285     {
286         $aItem->check_date_relationships_load();
287         // TODO: expensive and needs to be removed and done better elsewhere
288
289         if(!empty($fill_additional_fields[$aItem->object_name])
290         || ($aItem->object_name == 'Case' && !empty($fill_additional_fields['aCase']))
291         )
292         {
293             $aItem->fill_in_additional_list_fields();
294             //$aItem->fill_in_additional_detail_fields();
295         }
296         //rrs bug: 25343
297         $aItem->call_custom_logic("process_record");
298
299         if(isset($parent_data[$aItem->id])) {
300
301             $aItem->parent_name = $parent_data[$aItem->id]['parent_name'];
302             if(!empty($parent_data[$aItem->id]['parent_name_owner'])) {
303             $aItem->parent_name_owner =  $parent_data[$aItem->id]['parent_name_owner'];
304             $aItem->parent_name_mod =  $parent_data[$aItem->id]['parent_name_mod'];
305         }}
306
307         $fields = $aItem->get_list_view_data();
308         if(isset($processed_ids[$aItem->id])) {
309             continue;
310
311         } else {
312             $processed_ids[$aItem->id] = 1;
313         }
314
315
316         //ADD OFFSET TO ARRAY
317         $fields['OFFSET'] = ($offset + $count + 1);
318
319         if($this->shouldProcess) {
320             if($aItem->ACLAccess('EditView')) {
321             $this->xTemplate->assign('PREROW', "<input type='checkbox' class='checkbox' name='mass[]' value='". $fields['ID']. "' />");
322             } else {
323                 $this->xTemplate->assign('PREROW', '');
324
325             }
326             if($aItem->ACLAccess('DetailView')) {
327                 $this->xTemplate->assign('TAG_NAME','a');
328             } else {
329                 $this->xTemplate->assign('TAG_NAME','span');
330             }
331             $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);' />");
332         }
333
334         if($oddRow)
335         {
336             $ROW_COLOR = 'oddListRow';
337             $BG_COLOR =  $odd_bg;
338         }
339         else
340         {
341             $ROW_COLOR = 'evenListRow';
342             $BG_COLOR =  $even_bg;
343         }
344         $oddRow = !$oddRow;
345                 $button_contents = array();
346         $this->xTemplate->assign("ROW_COLOR", $ROW_COLOR);
347         $this->xTemplate->assign("BG_COLOR", $BG_COLOR);
348         $layout_manager = $this->getLayoutManager();
349         $layout_manager->setAttribute('context','List');
350         $layout_manager->setAttribute('image_path',$this->local_image_path);
351         $layout_manager->setAttribute('module_name', $subpanel_def->_instance_properties['module']);
352         if(!empty($this->child_focus))
353             $layout_manager->setAttribute('related_module_name',$this->child_focus->module_dir);
354
355         //AG$subpanel_data = $this->list_field_defs;
356         //$bla = array_pop($subpanel_data);
357         //select which sub-panel to display here, the decision will be made based on the type of
358         //the sub-panel and panel in the bean being processed.
359         if($subpanel_def->isCollection()) {
360             $thepanel=$subpanel_def->sub_subpanels[$aItem->panel_name];
361         } else {
362             $thepanel=$subpanel_def;
363         }
364         //get data source name
365         $linked_field=$thepanel->get_data_source_name();
366         $linked_field_set=$thepanel->get_data_source_name(true);
367         static $count;
368         if(!isset($count))$count = 0;
369
370         foreach($thepanel->get_list_fields() as $field_name=>$list_field)
371         {
372             //add linked field attribute to the array.
373             $list_field['linked_field']=$linked_field;
374             $list_field['linked_field_set']=$linked_field_set;
375
376             $usage = empty($list_field['usage']) ? '' : $list_field['usage'];
377             if($usage != 'query_only')
378             {
379                 $list_field['name']=$field_name;
380
381                 $module_field = $field_name.'_mod';
382                 $owner_field = $field_name.'_owner';
383                 if(!empty($aItem->$module_field)) {
384
385                     $list_field['owner_id'] = $aItem->$owner_field;
386                     $list_field['owner_module'] = $aItem->$module_field;
387
388                 } else {
389                     $list_field['owner_id'] = false;
390                     $list_field['owner_module'] = false;
391                 }
392                 if(isset($list_field['alias'])) $list_field['name'] = $list_field['alias'];
393                 else $list_field['name']=$field_name;
394                 $list_field['fields'] = $fields;
395                 $list_field['module'] = $aItem->module_dir;
396                 $list_field['start_link_wrapper'] = $this->start_link_wrapper;
397                 $list_field['end_link_wrapper'] = $this->end_link_wrapper;
398                 $list_field['subpanel_id'] = $this->subpanel_id;
399                 $list_field['DetailView'] = $aItem->ACLAccess('DetailView');
400                 $list_field['ListView'] = $aItem->ACLAccess('ListView');
401                 $list_field['EditView'] = $aItem->ACLAccess('EditView');
402                 $list_field['Delete'] = $aItem->ACLAccess('Delete');
403                 if ( isset($aItem->field_defs[strtolower($list_field['name'])])) {
404                     require_once('include/SugarFields/SugarFieldHandler.php');
405                     // We need to see if a sugar field exists for this field type first,
406                     // if it doesn't, toss it at the old sugarWidgets. This is for
407                     // backwards compatibility and will be removed in a future release
408                     $vardef = $aItem->field_defs[strtolower($list_field['name'])];
409                     if ( isset($vardef['type']) ) {
410                         $fieldType = isset($vardef['custom_type'])?$vardef['custom_type']:$vardef['type'];
411                         $tmpField = SugarFieldHandler::getSugarField($fieldType,true);
412                     } else {
413                         $tmpField = NULL;
414                     }
415
416                     if ( $tmpField != NULL ) {
417                         $widget_contents = SugarFieldHandler::displaySmarty($list_field['fields'],$vardef,'ListView',$list_field);
418                     } else {
419                         // No SugarField for this particular type
420                         // Use the old, icky, SugarWidget for now
421                         $widget_contents = $layout_manager->widgetDisplay($list_field);
422                     }
423
424                     if ( isset($list_field['widget_class']) && $list_field['widget_class'] == 'SubPanelDetailViewLink' ) {
425                         // 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
426                         // So we'll populate the field data with the pre-rendered display for the field
427                         $list_field['fields'][$field_name] = $widget_contents;
428                         if('full_name' == $field_name){//bug #32465
429                            $list_field['fields'][strtoupper($field_name)] = $widget_contents;
430                         }
431                         $widget_contents = $layout_manager->widgetDisplay($list_field);
432                     } else if(isset($list_field['widget_class']) && $list_field['widget_class'] == 'SubPanelEmailLink' ) {
433                         $widget_contents = $layout_manager->widgetDisplay($list_field);
434                     }
435
436                  $count++;
437                 $this->xTemplate->assign('CELL_COUNT', $count);
438                 $this->xTemplate->assign('CLASS', "");
439                 if ( empty($widget_contents) ) $widget_contents = '&nbsp;';
440                 $this->xTemplate->assign('CELL', $widget_contents);
441                 $this->xTemplate->parse($xtemplateSection.".row.cell");
442                 } else {
443                     // This handles the edit and remove buttons and icon widget
444                         if( isset($list_field['widget_class']) && $list_field['widget_class'] == "SubPanelIcon") {
445                                 $count++;
446                                 $widget_contents = $layout_manager->widgetDisplay($list_field);
447                                 $this->xTemplate->assign('CELL_COUNT', $count);
448                                 $this->xTemplate->assign('CLASS', "");
449                                 if ( empty($widget_contents) ) $widget_contents = '&nbsp;';
450                                 $this->xTemplate->assign('CELL', $widget_contents);
451                                 $this->xTemplate->parse($xtemplateSection.".row.cell");
452                         } elseif (preg_match("/button/i", $list_field['name'])) {
453                                 $button_contents[] = $layout_manager->widgetDisplay($list_field);
454                         } else {
455                                 $count++;
456                                 $this->xTemplate->assign('CLASS', "");
457                                 $widget_contents = $layout_manager->widgetDisplay($list_field);
458                                 $this->xTemplate->assign('CELL_COUNT', $count);
459                                 if ( empty($widget_contents) ) $widget_contents = '&nbsp;';
460                                 $this->xTemplate->assign('CELL', $widget_contents);
461                                 $this->xTemplate->parse($xtemplateSection.".row.cell");
462                         }
463                 }
464
465             }
466         }
467
468                 $button_count = 1;
469                 $widget_contents = "";
470         $first = true;
471         // this is for inline buttons on listviews
472                 foreach ($button_contents as $actions => $action)
473         {
474
475             if ($first && count($button_contents) > 1)
476             {
477                 $hide = " style:'display: none'";
478                 $firstaction = $action;
479                 $button_count++;
480                 $first = false;
481                 continue;
482             }
483             else if ($first && count($button_contents) == 1)
484             {
485                 $firstaction = $action;
486                 $widget_contents .= "<li>&nbsp;</li>";
487             }
488             else
489             {
490                 $widget_contents .= "<li>".$action."</li>";
491             }
492
493
494                         if(sizeof($button_contents) == $button_count)
495             {
496                                 $count++;
497                 $this->xTemplate->assign('CELL_COUNT', $count);
498                 $pre = '<ul class="clickMenu subpanel records fancymenu button">'. "\n";
499                 $this->xTemplate->assign('CLASS', "inlineButtons");
500                 if(sizeof($button_contents) == 1)
501                 {
502                                 $pre .= '<li class="single">'. "\n";
503                 }
504                 else {
505                         $pre .= '<li>'. "\n";
506                 }
507
508                 $tempid = create_guid();
509                 $pre .= '<script type="text/javascript">
510                         var zz = $("#'.$tempid.'").children().first().find("span").remove();
511                     </script>';
512                 $pre .= "<div style='display: inline' id='$tempid'>".$firstaction."</div>";
513
514                         $pre .= '<ul class="subnav';
515                         if(sizeof($button_contents) > 1)
516                 {
517                                 $pre .= " multi";
518                         }
519
520                         $pre .='" id="'.$tempid.'">' . "\n";
521                         $post = ' </ul>' . "\n";
522                         $post .= '</li>' . "\n";
523                         $post .= '</ul>' . "\n";
524
525                 if ( empty($widget_contents) )
526                     $widget_contents = '&nbsp;';
527
528                 $this->xTemplate->assign('CELL', $pre.$widget_contents.$post);
529                 $this->xTemplate->parse($xtemplateSection.".row.cell");
530                         }
531                         $button_count++;
532             $first = false;
533                 }
534
535         $aItem->setupCustomFields($aItem->module_dir);
536         $aItem->custom_fields->populateAllXTPL($this->xTemplate, 'detail', $html_varName, $fields);
537
538         $count++;
539
540         $this->xTemplate->parse($xtemplateSection.".row");
541     }
542
543     $this->xTemplate->parse($xtemplateSection);
544 }
545
546 /**sets whether or not to display the xtemplate header and footer
547  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
548  * All Rights Reserved.
549  * Contributor(s): ______________________________________.
550 */
551 function setDisplayHeaderAndFooter($bool) {
552         $this->display_header_and_footer = $bool;
553 }
554
555 /**initializes ListView
556  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
557  * All Rights Reserved.
558  * Contributor(s): ______________________________________.
559 */
560  function ListView() {
561
562
563     if(!$this->initialized) {
564         global $sugar_config;
565         $this->records_per_page = $sugar_config['list_max_entries_per_page'] + 0;
566         $this->initialized = true;
567         global $app_strings, $currentModule;
568         $this->local_theme = SugarThemeRegistry::current()->__toString();
569         $this->local_app_strings =$app_strings;
570         $this->local_image_path = SugarThemeRegistry::current()->getImagePath();
571         $this->local_current_module = $currentModule;
572     }
573 }
574 /**sets how many records should be displayed per page in the list view
575  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
576  * All Rights Reserved.
577  * Contributor(s): ______________________________________.
578 */
579  function setRecordsPerPage($count) {
580     $this->records_per_page = $count;
581 }
582 /**sets the header title */
583  function setHeaderTitle($value) {
584     $this->header_title = $value;
585 }
586 /**sets the header text this is text that's appended to the header table and is usually used for the creation of buttons
587  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
588  * All Rights Reserved.
589  * Contributor(s): ______________________________________.
590 */
591  function setHeaderText($value) {
592     $this->header_text = $value;
593 }
594 /**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
595  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
596  * All Rights Reserved.
597  * Contributor(s): ______________________________________.
598 */
599  function setXTemplatePath($value) {
600     $this->xTemplatePath= $value;
601 }
602
603 /**this is a helper function for allowing ListView to create a new XTemplate it groups parameters that should be set into a single function
604  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
605  * All Rights Reserved.
606  * Contributor(s): ______________________________________.
607 */
608  function initNewXTemplate($XTemplatePath, $modString, $imagePath = null) {
609     $this->setXTemplatePath($XTemplatePath);
610     if(isset($modString))
611         $this->setModStrings($modString);
612     if(isset($imagePath))
613         $this->setImagePath($imagePath);
614 }
615
616
617 function getOrderBy($varName, $defaultOrderBy='', $force_sortorder='') {
618     $sortBy = $this->getSessionVariable($varName, "ORDER_BY") ;
619
620     if(empty($sortBy)) {
621         $this->setUserVariable($varName, "ORDER_BY", $defaultOrderBy);
622         $sortBy = $defaultOrderBy;
623     } else {
624         $this->setUserVariable($varName, "ORDER_BY", $sortBy);
625     }
626     if($sortBy == 'amount') {
627         $sortBy = 'amount*1';
628     }
629     if($sortBy == 'amount_usdollar') {
630         $sortBy = 'amount_usdollar*1';
631     }
632
633     $desc = $this->getSessionVariable($varName, $sortBy."S");
634
635     if(empty($desc))
636         $desc = false;
637     if(isset($_REQUEST[$this->getSessionVariableName($varName,  "ORDER_BY")]))
638         $last = $this->getSessionVariable($varName, "OBL");
639         if(!empty($last) && $last == $sortBy) {
640             $desc = !$desc;
641         }else {
642             $this->setSessionVariable($varName, "OBL", $sortBy);
643         }
644     $this->setSessionVariable($varName, $sortBy."S", $desc);
645     if(!empty($sortBy)) {
646         if(empty($force_sortorder)) {
647             if(substr_count(strtolower($sortBy), ' desc') == 0 && substr_count(strtolower($sortBy), ' asc') == 0) {
648                 if($desc) {
649                     $this->query_orderby = $sortBy.' desc';
650                 } else {
651                     $this->query_orderby = $sortBy.' asc';
652                 }
653             }
654
655         } else {
656             $this->query_orderby = $sortBy . ' ' . $force_sortorder;
657         }
658     }else {
659         $this->query_orderby = "";
660     }
661     $this->sortby = $sortBy;
662     return $this->query_orderby;
663
664 }
665
666
667 /**sets the parameters dealing with the db
668  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
669  * All Rights Reserved.
670  * Contributor(s): ______________________________________.
671 */
672  function setQuery($where, $limit, $orderBy, $varName, $allowOrderByOveride=true) {
673     $this->query_where = $where;
674     if($this->getSessionVariable("query", "where") != $where) {
675         $this->query_where_has_changed = true;
676         $this->setSessionVariable("query", "where", $where);
677     }
678
679     $this->query_limit = $limit;
680     if(!$allowOrderByOveride) {
681         $this->query_orderby = $orderBy;
682         return;
683     }
684     $this->getOrderBy($varName, $orderBy);
685
686     $this->setLocalSessionVariable($varName, "QUERY_WHERE", $where);
687
688     //SETTING ORDER_BY FOR USE IN DETAILVIEW
689     $this->setLocalSessionVariable($varName, "ORDER_BY_DETAIL", $this->query_orderby);
690 }
691
692 function displayArrow() {
693
694 }
695
696 /**sets the theme used only use if it is different from the global
697  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
698  * All Rights Reserved.
699  * Contributor(s): ______________________________________.
700 */
701  function setTheme($theme) {
702     $this->local_theme = $theme;
703     if(isset($this->xTemplate))$this->xTemplate->assign("THEME", $this->local_theme);
704 }
705
706 /**sets the AppStrings used only use if it is different from the global
707  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
708  * All Rights Reserved.
709  * Contributor(s): ______________________________________.
710 */
711  function setAppStrings($app_strings) {
712     unset($this->local_app_strings);
713     $this->local_app_strings = $app_strings;
714     if(isset($this->xTemplate))$this->xTemplate->assign("APP", $this->local_app_strings);
715 }
716
717 /**sets the ModStrings used
718  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
719  * All Rights Reserved.
720  * Contributor(s): ______________________________________.
721 */
722  function setModStrings($mod_strings) {
723     unset($this->local_module_strings);
724     $this->local_mod_strings = $mod_strings;
725     if(isset($this->xTemplate))$this->xTemplate->assign("MOD", $this->local_mod_strings);
726 }
727
728 /**sets the ImagePath used
729  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
730  * All Rights Reserved.
731  * Contributor(s): ______________________________________.
732 */
733  function setImagePath($image_path) {
734     $this->local_image_path = $image_path;
735     if(empty($this->local_image_path)) {
736         $this->local_image_path = SugarThemeRegistry::get($this->local_theme)->getImagePath();
737     }
738     if(isset($this->xTemplate))$this->xTemplate->assign("IMAGE_PATH", $this->local_image_path);
739 }
740
741 /**sets the currentModule only use if this is different from the global
742  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
743  * All Rights Reserved.
744  * Contributor(s): ______________________________________.
745 */
746  function setCurrentModule($currentModule) {
747     unset($this->local_current_module);
748     $this->local_current_module = $currentModule;
749     if(isset($this->xTemplate))$this->xTemplate->assign("MODULE_NAME", $this->local_current_module);
750 }
751
752 /**INTERNAL FUNCTION creates an XTemplate DO NOT CALL THIS THIS IS AN INTERNAL FUNCTION
753  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
754  * All Rights Reserved.
755  * Contributor(s): ______________________________________.
756 */
757  function createXTemplate() {
758     if(!isset($this->xTemplate)) {
759         if(isset($this->xTemplatePath)) {
760
761             $this->xTemplate = new XTemplate($this->xTemplatePath);
762             $this->xTemplate->assign("APP", $this->local_app_strings);
763             if(isset($this->local_mod_strings))$this->xTemplate->assign("MOD", $this->local_mod_strings);
764             $this->xTemplate->assign("THEME", $this->local_theme);
765             $this->xTemplate->assign("IMAGE_PATH", $this->local_image_path);
766             $this->xTemplate->assign("MODULE_NAME", $this->local_current_module);
767         } else {
768             $GLOBALS['log']->error("NO XTEMPLATEPATH DEFINED CANNOT CREATE XTEMPLATE");
769         }
770     }
771 }
772
773 /**sets the XTemplate telling ListView to use newXTemplate as its current XTemplate
774  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
775  * All Rights Reserved.
776  * Contributor(s): ______________________________________.
777 */
778  function setXTemplate($newXTemplate) {
779     $this->xTemplate = $newXTemplate;
780 }
781
782 /**returns the XTemplate
783  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
784  * All Rights Reserved.
785  * Contributor(s): ______________________________________.
786 */
787  function getXTemplate() {
788     return $this->xTemplate;
789 }
790
791 /**assigns a name value pair to the XTemplate
792  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
793  * All Rights Reserved.
794  * Contributor(s): ______________________________________.
795 */
796  function xTemplateAssign($name, $value) {
797
798         if(!isset($this->xTemplate)) {
799             $this->createXTemplate();
800         }
801         $this->xTemplate->assign($name, $value);
802
803 }
804
805 /**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
806  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
807  * All Rights Reserved.
808  * Contributor(s): ______________________________________.
809 */
810  function getOffset($localVarName) {
811         if($this->query_where_has_changed || isset($GLOBALS['record_has_changed'])) {
812                 $this->setSessionVariable($localVarName,"offset", 0);
813         }
814         $offset = $this->getSessionVariable($localVarName,"offset");
815         if(isset($offset)) {
816                 return $offset;
817         }
818         return 0;
819 }
820
821 /**INTERNAL FUNCTION sets the offset in the session
822  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
823  * All Rights Reserved.
824  * Contributor(s): ______________________________________.
825 */
826  function setOffset($localVarName, $value) {
827         $this->setSessionVariable($localVarName, "offset", $value);
828 }
829
830 /**INTERNAL FUNCTION sets a session variable
831  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
832  * All Rights Reserved.
833  * Contributor(s): ______________________________________.
834 */
835  function setSessionVariable($localVarName,$varName, $value) {
836     $_SESSION[$this->local_current_module."_".$localVarName."_".$varName] = $value;
837 }
838
839 function setUserVariable($localVarName,$varName, $value) {
840         if($this->is_dynamic ||  $localVarName == 'CELL')return;
841         global $current_user;
842         $current_user->setPreference($this->local_current_module."_".$localVarName."_".$varName, $value);
843 }
844
845 /**INTERNAL FUNCTION returns a session variable first checking the query for it then checking the session
846  * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
847  * All Rights Reserved.
848  * Contributor(s): ______________________________________.
849 */
850  function getSessionVariable($localVarName,$varName) {
851     //Set any variables pass in through request first
852     if(isset($_REQUEST[$this->getSessionVariableName($localVarName, $varName)])) {
853         $this->setSessionVariable($localVarName,$varName,$_REQUEST[$this->getSessionVariableName($localVarName, $varName)]);
854     }
855
856     if(isset($_SESSION[$this->getSessionVariableName($localVarName, $varName)])) {
857         return $_SESSION[$this->getSessionVariableName($localVarName, $varName)];
858     }
859     return "";
860 }
861
862 function getUserVariable($localVarName, $varName) {
863     global $current_user;
864     if($this->is_dynamic ||  $localVarName == 'CELL')return;
865     if(isset($_REQUEST[$this->getSessionVariableName($localVarName, $varName)])) {
866
867             $this->setUserVariable($localVarName,$varName,$_REQUEST[$this->getSessionVariableName($localVarName, $varName)]);
868     }
869     return $current_user->getPreference($this->getSessionVariableName($localVarName, $varName));
870 }
871
872
873
874
875
876     /**
877
878     * @return void
879     * @param unknown $localVarName
880     * @param unknown $varName
881     * @desc INTERNAL FUNCTION returns the session/query variable name
882     * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
883     * All Rights Reserved.
884     * Contributor(s): ______________________________________..
885     */
886     function getSessionVariableName($localVarName,$varName) {
887         return $this->local_current_module."_".$localVarName."_".$varName;
888     }
889
890     /**
891
892     * @return void
893     * @param unknown $seed
894     * @param unknown $xTemplateSection
895     * @param unknown $html_varName
896     * @desc INTERNAL FUNCTION Handles List Views using seeds that extend SugarBean
897         $XTemplateSection is the section in the XTemplate file that should be parsed usually main
898         $html_VarName is the variable name used in the XTemplateFile e.g. TASK
899         $seed is a seed that extends SugarBean
900         * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
901         * All Rights Reserved..
902         * Contributor(s): ______________________________________..
903     */
904     function processSugarBean($xtemplateSection, $html_varName, $seed) {
905         global $list_view_row_count;
906
907         $current_offset = $this->getOffset($html_varName);
908         $response = array();
909
910         //ADDING VCR CONTROL
911         SugarVCR::erase($seed->module_dir);
912         $params = array();
913         //$filter = array('id', 'full_name');
914         $filter=array();
915         $ret_array = $seed->create_new_list_query($this->query_orderby, $this->query_where, $filter, $params, 0, '', true, $seed, true);
916         if(!is_array($params)) $params = array();
917         if(!isset($params['custom_select'])) $params['custom_select'] = '';
918         if(!isset($params['custom_from'])) $params['custom_from'] = '';
919         if(!isset($params['custom_where'])) $params['custom_where'] = '';
920         if(!isset($params['custom_order_by'])) $params['custom_order_by'] = '';
921         $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'];
922         SugarVCR::store($seed->module_dir,  $main_query);
923         //ADDING VCR CONTROL
924
925         if(empty($this->related_field_name)) {
926             $response = $seed->get_list($this->query_orderby, $this->query_where, $current_offset, $this->query_limit);
927         } else {
928             $related_field_name = $this->related_field_name;
929             $response = $seed->get_related_list($this->child_focus,$related_field_name, $this->query_orderby,
930             $this->query_where, $current_offset, $this->query_limit);
931         }
932
933         $list = $response['list'];
934         $row_count = $response['row_count'];
935         $next_offset = $response['next_offset'];
936         $previous_offset = $response['previous_offset'];
937
938         if(!empty($response['current_offset'])) {
939             $current_offset = $response['current_offset'];
940         }
941
942         $list_view_row_count = $row_count;
943         $this->processListNavigation($xtemplateSection,$html_varName, $current_offset, $next_offset, $previous_offset, $row_count, null, null, empty($seed->column_fields) ? null : count($seed->column_fields));
944
945         return $list;
946     }
947
948     function processUnionBeans($sugarbean, $subpanel_def, $html_var = 'CELL') {
949
950                 $last_detailview_record = $this->getSessionVariable("detailview", "record");
951                 if(!empty($last_detailview_record) && $last_detailview_record != $sugarbean->id){
952                         $GLOBALS['record_has_changed'] = true;
953                 }
954                 $this->setSessionVariable("detailview", "record", $sugarbean->id);
955
956                 $current_offset = $this->getOffset($html_var);
957                 $module = isset($_REQUEST['module']) ? $_REQUEST['module'] : '';
958                 $response = array();
959
960         $this->sort_order = 'asc';
961         if(isset($_REQUEST['sort_order'])) {
962             $this->sort_order = $_REQUEST['sort_order'];
963         } else {
964             if(isset($subpanel_def->_instance_properties['sort_order'])) {
965                 $sort_order = $subpanel_def->_instance_properties['sort_order'];
966             }
967
968             if(isset($_SESSION['last_sub' .$this->subpanel_module. '_order'])) {
969                 // We swap the order when the request contains an offset (indicating a column sort issued);
970                 // otherwise we do not sort.  If we don't make this check, then the subpanel listview will
971                 // swap ordering each time a new record is entered via quick create forms
972
973                 if(isset($_REQUEST[$module. '_' . $html_var . '_offset'])) {
974                     $this->sort_order = $_SESSION['last_sub' .$this->subpanel_module. '_order'] == 'asc' ? 'desc' : 'asc';
975                 } else {
976                 $this->sort_order = $_SESSION['last_sub' .$this->subpanel_module. '_order'];
977                 }
978             }
979             elseif(isset($sort_order)) {
980                 $this->sort_order = $sort_order;
981             }
982         }
983
984         if (isset($subpanel_def->_instance_properties['sort_by'])) {
985             $this->query_orderby = $subpanel_def->_instance_properties['sort_by'];
986         } else {
987             $this->query_orderby = 'id';
988         }
989
990         $this->getOrderBy($html_var,$this->query_orderby, $this->sort_order);
991
992         $_SESSION['last_sub' .$this->subpanel_module. '_order'] = $this->sort_order;
993         $_SESSION['last_sub' .$this->subpanel_module. '_url'] = $this->getBaseURL($html_var);
994
995                 // Bug 8139 - Correct Subpanel sorting on 'name', when subpanel sorting default is 'last_name, first_name'
996                 if (($this->sortby == 'name' || $this->sortby == 'last_name') &&
997                         str_replace(' ', '', trim($subpanel_def->_instance_properties['sort_by'])) == 'last_name,first_name') {
998                         $this->sortby = 'last_name '.$this->sort_order.', first_name ';
999                 }
1000
1001         if(!empty($this->response)){
1002             $response =& $this->response;
1003             echo 'cached';
1004         }else{
1005             $response = SugarBean::get_union_related_list($sugarbean,$this->sortby, $this->sort_order, $this->query_where, $current_offset, -1,-1,$this->query_limit,$subpanel_def);
1006             $this->response =& $response;
1007         }
1008         $list = $response['list'];
1009         $row_count = $response['row_count'];
1010         $next_offset = $response['next_offset'];
1011         $previous_offset = $response['previous_offset'];
1012         if(!empty($response['current_offset']))$current_offset = $response['current_offset'];
1013         global $list_view_row_count;
1014         $list_view_row_count = $row_count;
1015         $this->processListNavigation('dyn_list_view', $html_var, $current_offset, $next_offset, $previous_offset, $row_count, $sugarbean,$subpanel_def);
1016
1017         return array('list'=>$list, 'parent_data'=>$response['parent_data'], 'query'=>$response['query']);
1018     }
1019
1020     function getBaseURL($html_varName) {
1021         static $cache = array();
1022
1023         if(!empty($cache[$html_varName]))return $cache[$html_varName];
1024         $blockVariables = array('mass', 'uid', 'massupdate', 'delete', 'merge', 'selectCount','current_query_by_page');
1025         if(!empty($this->base_URL)) {
1026             return $this->base_URL;
1027         }
1028
1029             $baseurl = $_SERVER['PHP_SELF'];
1030             if(empty($baseurl)) {
1031                 $baseurl = 'index.php';
1032             }
1033
1034             /*fixes an issue with deletes when doing a search*/
1035             foreach(array_merge($_GET, $_POST) as $name=>$value) {
1036                 //echo ("$name = $value <br/>");
1037                 if(!empty($value) && $name != 'sort_order' //&& $name != ListView::getSessionVariableName($html_varName,"ORDER_BY")
1038                         && $name != ListView::getSessionVariableName($html_varName,"offset")
1039                         /*&& substr_count($name, "ORDER_BY")==0*/ && !in_array($name, $blockVariables))
1040                 {
1041                     if(is_array($value)) {
1042                         foreach($value as $valuename=>$valuevalue) {
1043                             if(substr_count($baseurl, '?') > 0)
1044                                 $baseurl        .= "&{$name}[]=".$valuevalue;
1045                             else
1046                                 $baseurl        .= "?{$name}[]=".$valuevalue;
1047                         }
1048                     } else {
1049                         $value = urlencode($value);
1050                         if(substr_count($baseurl, '?') > 0) {
1051                             $baseurl    .= "&$name=$value";
1052                         } else {
1053                             $baseurl    .= "?$name=$value";
1054                         }
1055                     }
1056                 }
1057             }
1058
1059
1060             if($_SERVER['REQUEST_METHOD'] == 'POST') {
1061                 // at this point it is possible that the above foreach already executed resulting in double ?'s in the url
1062                 if(substr_count($baseurl, '?') == 0) {
1063                     $baseurl .= '?';
1064                 }
1065                 if(isset($_REQUEST['action'])) $baseurl.= '&action='.$_REQUEST['action'];
1066                 if(isset($_REQUEST['record'])) $baseurl .= '&record='.$_REQUEST['record'];
1067                 if(isset($_REQUEST['module'])) $baseurl .= '&module='.$_REQUEST['module'];
1068             }
1069
1070             $baseurl .= "&".ListView::getSessionVariableName($html_varName,"offset")."=";
1071             $cache[$html_varName] = $baseurl;
1072             return $baseurl;
1073     }
1074     /**
1075     * @return void
1076     * @param unknown $data
1077     * @param unknown $xTemplateSection
1078     * @param unknown $html_varName
1079     * @desc INTERNAL FUNCTION process the List Navigation
1080     * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1081     * All Rights Reserved.
1082     * Contributor(s): ______________________________________..
1083     */
1084     function processListNavigation($xtemplateSection, $html_varName, $current_offset, $next_offset, $previous_offset, $row_count, $sugarbean=null, $subpanel_def=null, $col_count = 20) {
1085
1086         global $export_module;
1087         global $sugar_config;
1088         global $current_user;
1089         global $currentModule;
1090         global $app_strings;
1091
1092         $start_record = $current_offset + 1;
1093
1094         if(!is_numeric($col_count))
1095             $col_count = 20;
1096
1097         if($row_count == 0)
1098             $start_record = 0;
1099
1100         $end_record = $start_record + $this->records_per_page;
1101         // back up the the last page.
1102         if($end_record > $row_count+1) {
1103             $end_record = $row_count+1;
1104         }
1105         // Determine the start location of the last page
1106         if($row_count == 0)
1107             $number_pages = 0;
1108         else
1109             $number_pages = floor(($row_count - 1) / $this->records_per_page);
1110
1111         $last_offset = $number_pages * $this->records_per_page;
1112
1113         if(empty($this->query_limit)  || $this->query_limit > $this->records_per_page) {
1114             $this->base_URL = $this->getBaseURL($html_varName);
1115             $dynamic_url = '';
1116
1117             if($this->is_dynamic) {
1118                 $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;
1119             }
1120
1121             $current_URL = $this->base_URL.$current_offset.$dynamic_url;
1122             $start_URL = $this->base_URL."0".$dynamic_url;
1123             $previous_URL  = $this->base_URL.$previous_offset.$dynamic_url;
1124             $next_URL  = $this->base_URL.$next_offset.$dynamic_url;
1125             $end_URL  = $this->base_URL.'end'.$dynamic_url;
1126
1127             if(!empty($this->start_link_wrapper)) {
1128                 $current_URL = $this->start_link_wrapper.$current_URL.$this->end_link_wrapper;
1129                 $start_URL = $this->start_link_wrapper.$start_URL.$this->end_link_wrapper;
1130                 $previous_URL = $this->start_link_wrapper.$previous_URL.$this->end_link_wrapper;
1131                 $next_URL = $this->start_link_wrapper.$next_URL.$this->end_link_wrapper;
1132                 $end_URL = $this->start_link_wrapper.$end_URL.$this->end_link_wrapper;
1133             }
1134
1135             $moduleString = "{$currentModule}_{$html_varName}_offset";
1136             $moduleStringOrder = "{$currentModule}_{$html_varName}_ORDER_BY";
1137             if($this->shouldProcess && !$this->multi_select_popup) {
1138                 // check the checkboxes onload
1139                 echo "<script>YAHOO.util.Event.addListener(window, \"load\", sListView.check_boxes);</script>\n";
1140
1141                 $massUpdateRun = isset($_REQUEST['massupdate']) && $_REQUEST['massupdate'] == 'true';
1142                 $uids = empty($_REQUEST['uid']) || $massUpdateRun ? '' : $_REQUEST['uid'];
1143                 $select_entire_list = isset($_REQUEST['select_entire_list']) && !$massUpdateRun ? $_REQUEST['select_entire_list'] : 0;
1144
1145                 echo "<textarea style='display: none' name='uid'>{$uids}</textarea>\n" .
1146                     "<input type='hidden' name='select_entire_list' value='{$select_entire_list}'>\n".
1147                     "<input type='hidden' name='{$moduleString}' value='0'>\n".
1148                     "<input type='hidden' name='{$moduleStringOrder}' value='0'>\n";
1149
1150             }
1151
1152
1153             $GLOBALS['log']->debug("Offsets: (start, previous, next, last)(0, $previous_offset, $next_offset, $last_offset)");
1154
1155             if(0 == $current_offset) {
1156                 $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>";
1157                 $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>";
1158             } else {
1159                 if($this->multi_select_popup) {// nav links for multiselect popup, submit form to save checks.
1160                     $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>";
1161                     $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>";
1162                 } elseif($this->shouldProcess) {
1163                     $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>";
1164                     $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>";
1165                 } else {
1166                     $onClick = '';
1167                     if(0 != preg_match('/javascript.*/', $start_URL)){
1168                         $onClick = "\"$start_URL;\"";
1169                     }else{
1170                         $onClick ="'location.href=\"$start_URL\";'";
1171                     }
1172                     $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>";
1173
1174                     $onClick = '';
1175                     if(0 != preg_match('/javascript.*/', $previous_URL)){
1176                         $onClick = "\"$previous_URL;\"";
1177                     }else{
1178                         $onClick = "'location.href=\"$previous_URL\";'";
1179                     }
1180                     $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>";
1181                 }
1182             }
1183
1184             if($last_offset <= $current_offset) {
1185                 $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>";
1186                 $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>";
1187             } else {
1188                 if($this->multi_select_popup) { // nav links for multiselect popup, submit form to save checks.
1189                     $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>";
1190                     if(!empty($sugar_config['disable_count_query'])) {
1191                         $end_link = '';
1192                     }
1193                     $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>";
1194                 } elseif($this->shouldProcess) {
1195                     $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>";
1196                     $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>";
1197                 } else {
1198                     $onClick = '';
1199                     if(0 != preg_match('/javascript.*/', $next_URL)){
1200                         $onClick = "\"$next_URL;\"";
1201                     }else{
1202                         $onClick ="'location.href=\"$next_URL\";'";
1203                     }
1204                     $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>";
1205
1206                     $onClick = '';
1207                     if(0 != preg_match('/javascript.*/', $end_URL)){
1208                         $onClick = "\"$end_URL;\"";
1209                     }else{
1210                         $onClick = "'location.href=\"$end_URL\";'";
1211                     }
1212                     $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>";
1213
1214                 }
1215             }
1216
1217             $GLOBALS['log']->info("Offset (next, current, prev)($next_offset, $current_offset, $previous_offset)");
1218             $GLOBALS['log']->info("Start/end records ($start_record, $end_record)");
1219
1220             $end_record = $end_record-1;
1221
1222 $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>"
1223  . "<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>"
1224  . "<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>";
1225
1226 $close_inline_img = SugarThemeRegistry::current()->getImage('close_inline', 'border=0', null, null, ".gif", $app_strings['LBL_CLOSEINLINE']);
1227
1228             echo "<script>
1229                 function select_dialog() {
1230                         var \$dialog = \$('<div></div>')
1231                                         .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>"
1232                 . "<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>"
1233                 . "<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>')
1234                                         .dialog({
1235                                                 autoOpen: false,
1236                                                 width: 150
1237                                         });
1238                                         \$dialog.dialog('open');
1239
1240                 }
1241                 </script>";
1242
1243             if($this->show_select_menu)
1244             {
1245                 $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>";
1246             } else {
1247                 $select_link = "&nbsp;";
1248             }
1249
1250             $export_link = '<input class="button" type="button" value="'.$this->local_app_strings['LBL_EXPORT'].'" ' .
1251                     'onclick="return sListView.send_form(true, \''.$_REQUEST['module'].'\', \'index.php?entryPoint=export\',\''.$this->local_app_strings['LBL_LISTVIEW_NO_SELECTED'].'\')">';
1252
1253             if($this->show_delete_button) {
1254                 $delete_link = '<input class="button" type="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)">';
1255             } else {
1256                 $delete_link = '&nbsp;';
1257             }
1258
1259             $admin = new Administration();
1260             $admin->retrieveSettings('system');
1261
1262             $user_merge = $current_user->getPreference('mailmerge_on');
1263             if($user_merge == 'on' && isset($admin->settings['system_mailmerge_on']) && $admin->settings['system_mailmerge_on']) {
1264                 echo "<script>
1265                 function mailmerge_dialog(el) {
1266                         var \$dialog = \$('<div></div>')
1267                                         .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>"
1268                         . "<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>"
1269                         . "<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>')
1270                                         .dialog({
1271                                                 autoOpen: false,
1272                                                 title: '". $this->local_app_strings['LBL_MAILMERGE']."',
1273                                                 width: 150,
1274                                                 position: {
1275                                                     my: myPos,
1276                                                     at: atPos,
1277                                                     of: \$(el)
1278                                                 }
1279                                         });
1280
1281                 }
1282             </script>";
1283                 $merge_link = "&nbsp;|&nbsp;<a id='mailmerge_link' onclick='return mailmerge_dialog(this)'; href=\"javascript:void(0)\">".$this->local_app_strings['LBL_MAILMERGE']."</a>";
1284             } else {
1285                 $merge_link = "&nbsp;";
1286             }
1287
1288             $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='" . (!empty($select_entire_list) ? $row_count : 0) . "' />";
1289
1290             if($_REQUEST['module'] == 'Home' || $this->local_current_module == 'Import'
1291                 || $this->show_export_button == false
1292                 || (!empty($sugar_config['disable_export']))
1293                 || (!empty($sugar_config['admin_export_only'])
1294                 && !(
1295                         is_admin($current_user)
1296                         || (ACLController::moduleSupportsACL($_REQUEST['module'])
1297                             && ACLAction::getUserAccessLevel($current_user->id,$_REQUEST['module'], 'access') == ACL_ALLOW_ENABLED
1298                             && (ACLAction::getUserAccessLevel($current_user->id, $_REQUEST['module'], 'admin') == ACL_ALLOW_ADMIN ||
1299                                 ACLAction::getUserAccessLevel($current_user->id, $_REQUEST['module'], 'admin') == ACL_ALLOW_ADMIN_DEV)))))
1300             {
1301                 if ($_REQUEST['module'] != 'InboundEmail' && $_REQUEST['module'] != 'EmailMan' && $_REQUEST['module'] != 'iFrames') {
1302                     $selected_objects_span = '';
1303                 }
1304                 $export_link = "&nbsp;";
1305                 $merge_link = "&nbsp;";
1306             } elseif($_REQUEST['module'] != "Accounts" && $_REQUEST['module'] != "Cases" && $_REQUEST['module'] != "Contacts" && $_REQUEST['module'] != "Leads" && $_REQUEST['module'] != "Opportunities") {
1307                 $merge_link = "&nbsp;";
1308             }
1309
1310             if($this->show_paging == true) {
1311                 if(!empty($sugar_config['disable_count_query'])) {
1312                     if($row_count > $end_record) {
1313                         $row_count .= '+';
1314                     }
1315                 }
1316
1317                 $html_text = '';
1318                 $html_text .= "<tr class='pagination' role='presentation'>\n";
1319                 $html_text .= "<td COLSPAN=\"$col_count\" align=\"right\">\n";
1320                 //$html_text .= "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"  >$export_link$merge_link$selected_objects_span</td>\n";
1321                 //$html_text .= "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"  >";
1322                 if ($subpanel_def != null) {
1323                     include_once('include/SubPanel/SubPanelTiles.php');
1324                     $subpanelTiles = new SubPanelTiles($sugarbean);
1325                     $html_text .= "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\"  >";
1326
1327                     //attempt to get the query to recreate this subpanel
1328                     if(!empty($this->response)){
1329                         $response =& $this->response;
1330                     }else{
1331                         $response = SugarBean::get_union_related_list($sugarbean,$this->sortby, $this->sort_order, $this->query_where, $current_offset, -1,-1,$this->query_limit,$subpanel_def);
1332                         $this->response = $response;
1333                     }
1334                     //if query is present, then pass it in as parameter
1335                     if (isset($response['query']) && !empty($response['query'])){
1336                         $html_text .= $subpanelTiles->get_buttons($subpanel_def, $response['query']);
1337                     }else{
1338                         $html_text .= $subpanelTiles->get_buttons($subpanel_def);
1339                     }
1340                 }
1341                 else {
1342                     $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";
1343                 }
1344                 $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";
1345                 $html_text .= "</td>\n";
1346                 $html_text .= "</tr>\n";
1347                 $this->xTemplate->assign("PAGINATION",$html_text);
1348             }
1349
1350             //C.L. - Fix for 23461
1351             if(empty($_REQUEST['action']) || $_REQUEST['action'] != 'Popup') {
1352                 $_SESSION['export_where'] = $this->query_where;
1353             }
1354             $this->xTemplate->parse($xtemplateSection.".list_nav_row");
1355         }
1356     } // end processListNavigation
1357
1358     function processOrderBy($html_varName) {
1359
1360         if(!isset($this->base_URL)) {
1361             $this->base_URL = $_SERVER['PHP_SELF'];
1362
1363             if(isset($_SERVER['QUERY_STRING'])) {
1364                 $this->base_URL = preg_replace("/\&".$this->getSessionVariableName($html_varName,"ORDER_BY")."=[0-9a-zA-Z\_\.]*/","",$this->base_URL .'?'.$_SERVER['QUERY_STRING']);
1365                 $this->base_URL = preg_replace("/\&".$this->getSessionVariableName($html_varName,"offset")."=[0-9]*/","",$this->base_URL);
1366             }
1367             if($_SERVER['REQUEST_METHOD'] == 'POST') {
1368                 $this->base_URL .= '?';
1369                 if(isset($_REQUEST['action'])) $this->base_URL .= '&action='.$_REQUEST['action'];
1370                 if(isset($_REQUEST['record'])) $this->base_URL .= '&record='.$_REQUEST['record'];
1371                 if(isset($_REQUEST['module'])) $this->base_URL .= '&module='.$_REQUEST['module'];
1372             }
1373             $this->base_URL .= "&".$this->getSessionVariableName($html_varName,"offset")."=";
1374         }
1375
1376         if($this->is_dynamic) {
1377             $this->base_URL.='&to_pdf=true&action=SubPanelViewer&subpanel=' . $this->source_module;
1378         }
1379
1380         $sort_URL_base = $this->base_URL. "&".$this->getSessionVariableName($html_varName,"ORDER_BY")."=";
1381
1382         if($sort_URL_base !== "")
1383         {
1384             $this->xTemplate->assign("ORDER_BY", $sort_URL_base);
1385             return $sort_URL_base;
1386         } else {
1387             return '';
1388         }
1389     }
1390
1391
1392     function getAdditionalHeader() {
1393
1394     }
1395
1396
1397     /**
1398     * @return void
1399     * @param unknown $data
1400     * @param unknown $xTemplateSection
1401     * @param unknown $html_varName
1402     * @desc INTERNAL FUNCTION handles the rows
1403     * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1404     * All Rights Reserved.
1405     * Contributor(s): ______________________________________..
1406     */
1407     function processListRows($data, $xtemplateSection, $html_varName)
1408     {
1409         global $odd_bg;
1410         global $even_bg;
1411         global $hilite_bg;
1412         global $app_strings, $sugar_version, $sugar_config;
1413         global $currentModule;
1414
1415
1416
1417         $this->xTemplate->assign('BG_HILITE', $hilite_bg);
1418         $this->xTemplate->assign('CHECKALL', SugarThemeRegistry::current()->getImage('blank', '', 1, 1, ".gif", ''));
1419     //$this->xTemplate->assign("BG_CLICK", $click_bg);
1420         $oddRow = true;
1421         $count = 0;
1422         reset($data);
1423
1424         //GETTING OFFSET
1425         $offset = $this->getOffset($html_varName);
1426         $timeStamp = $this->unique_id();
1427         $_SESSION[$html_varName."_FROM_LIST_VIEW"] = $timeStamp;
1428
1429         $associated_row_data = array();
1430
1431         //mail merge list
1432         $mergeList = array();
1433         $module = '';
1434         //todo what is this?  It is using an array as a boolean
1435         while(list($aVal, $aItem) = each($data))
1436         {
1437             if(isset($this->data_array)) {
1438                 $fields = $this->data_array;
1439             } else {
1440                 $aItem->check_date_relationships_load();
1441                 $fields = $aItem->get_list_view_data();
1442             }
1443
1444             if(is_object($aItem)) { // cn: bug 5349
1445                 //add item id to merge list, if the button is clicked
1446                 $mergeList[] = $aItem->id;
1447                 if(empty($module)) {
1448                     $module = $aItem->module_dir;
1449                 }
1450             }
1451             //ADD OFFSET TO ARRAY
1452
1453                 $fields['OFFSET'] = ($offset + $count + 1);
1454
1455             $fields['STAMP'] = $timeStamp;
1456             if($this->shouldProcess) {
1457
1458             $prerow = '';
1459             if(!isset($this->data_array)) {
1460                 $prerow .= "<input onclick='sListView.check_item(this, document.MassUpdate)' type='checkbox' class='checkbox' name='mass[]' value='". $fields['ID']. "'>";
1461             }
1462             $this->xTemplate->assign('PREROW', $prerow);
1463
1464             $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)'>");
1465             }
1466             if(!isset($this->data_array)) {
1467                 $tag = $aItem->listviewACLHelper();
1468                 $this->xTemplate->assign('TAG',$tag) ;
1469             }
1470
1471             if($oddRow)
1472             {
1473                 $ROW_COLOR = 'oddListRow';
1474                 $BG_COLOR =  $odd_bg;
1475             }
1476             else
1477             {
1478                 $ROW_COLOR = 'evenListRow';
1479                 $BG_COLOR =  $even_bg;
1480             }
1481             $oddRow = !$oddRow;
1482
1483             $this->xTemplate->assign('ROW_COLOR', $ROW_COLOR);
1484             $this->xTemplate->assign('BG_COLOR', $BG_COLOR);
1485
1486             if(isset($this->data_array))
1487             {
1488                 $this->xTemplate->assign('KEY', $aVal);
1489                 $this->xTemplate->assign('VALUE', $aItem);
1490                 $this->xTemplate->assign('INDEX', $count);
1491
1492             }
1493             else
1494             {
1495     //AED -- some modules do not have their additionalDetails.php established. Add a check to ensure require_once does not fail
1496     // Bug #2786
1497                 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'))) {
1498
1499                     $additionalDetailsFile = 'modules/' . $aItem->module_dir . '/metadata/additionalDetails.php';
1500                     if(file_exists('custom/modules/' . $aItem->module_dir . '/metadata/additionalDetails.php')){
1501                         $additionalDetailsFile = 'custom/modules/' . $aItem->module_dir . '/metadata/additionalDetails.php';
1502                     }
1503
1504                     require_once($additionalDetailsFile);
1505                     $ad_function = (empty($this->additionalDetailsFunction) ? 'additionalDetails' : $this->additionalDetailsFunction) . $aItem->object_name;
1506                     $results = $ad_function($fields);
1507                     $results['string'] = str_replace(array("&#039", "'"), '\&#039', $results['string']); // no xss!
1508
1509                     if(trim($results['string']) == '') $results['string'] = $app_strings['LBL_NONE'];
1510                     $fields[$results['fieldToAddTo']] = $fields[$results['fieldToAddTo']].'</a>';
1511                 }
1512                 //fixes bug for IE where empty list view rows causes IE to not display bottom border
1513                 if(isset($fields['DESCRIPTION']) && empty($fields['DESCRIPTION']))
1514                 $fields['DESCRIPTION'] = "&nbsp;";
1515                 if(isset($fields['LIST_ORDER']) && empty($fields['LIST_ORDER']))
1516                 $fields['LIST_ORDER'] = "&nbsp;";
1517
1518                 $this->xTemplate->assign($html_varName, $fields);
1519                 $aItem->setupCustomFields($aItem->module_dir);
1520                 $aItem->custom_fields->populateAllXTPL($this->xTemplate, 'detail', $html_varName, $fields);
1521             }
1522             if(!isset($this->data_array) && $aItem->ACLAccess('DetailView')) {
1523                 $count++;
1524             }
1525             if(isset($this->data_array)) {
1526                 $count++;
1527             }
1528             if(!isset($this->data_array)) {
1529                 $aItem->list_view_parse_additional_sections($this->xTemplate, $xtemplateSection);
1530
1531                 if($this->xTemplate->exists($xtemplateSection.'.row.pro')) {
1532                     $this->xTemplate->parse($xtemplateSection.'.row.pro');
1533                 }
1534             }
1535             $this->xTemplate->parse($xtemplateSection . '.row');
1536
1537             if(isset($fields['ID'])) {
1538                 $associated_row_data[$fields['ID']] = $fields;
1539                 // Bug 38908: cleanup data for JS to avoid having &nbsp; shuffled around
1540                 foreach($fields as $key => $value) {
1541                     if($value == '&nbsp;') {
1542                         $associated_row_data[$fields['ID']][$key] = '';
1543                     }
1544                 }
1545             }
1546         }
1547
1548         $_SESSION['MAILMERGE_RECORDS'] = $mergeList;
1549         $_SESSION['MAILMERGE_MODULE_FROM_LISTVIEW'] = $module;
1550         if(empty($_REQUEST['action']) || $_REQUEST['action'] != 'Popup') {
1551             $_SESSION['MAILMERGE_MODULE'] = $module;
1552         }
1553
1554         if($this->process_for_popups)
1555         {
1556             $json = getJSONobj();
1557             $is_show_fullname = showFullName() ? 1 : 0;
1558             $associated_javascript_data = '<script type="text/javascript">' . "\n"
1559                 //. '<!-- // associated javascript data generated by ListView' . "\n"
1560                 . 'var associated_javascript_data = '
1561                 . $json->encode($associated_row_data) . ";\n"
1562                 //. '-->' . "\n"
1563                 . 'var is_show_fullname = '
1564                 . $is_show_fullname . ";\n"
1565                 . '</script>';
1566             $this->xTemplate->assign('ASSOCIATED_JAVASCRIPT_DATA', $associated_javascript_data);
1567         }
1568
1569         $this->xTemplate->parse($xtemplateSection);
1570     }
1571
1572
1573     function getLayoutManager()
1574     {
1575         require_once('include/generic/LayoutManager.php');
1576         if($this->layout_manager == null)
1577         {
1578             $this->layout_manager = new LayoutManager();
1579         }
1580         return $this->layout_manager;
1581     }
1582
1583
1584     function process_dynamic_listview_header($source_module, $subpanel_def, $html_var = 'CELL')
1585     {
1586
1587
1588         $layout_manager = $this->getLayoutManager();
1589         $layout_manager->setAttribute('order_by_link',$this->processOrderBy($html_var));
1590         $layout_manager->setAttribute('context','HeaderCell');
1591         $layout_manager->setAttribute('image_path',$this->local_image_path);
1592         $layout_manager->setAttribute('html_varName',$html_var);
1593         $layout_manager->setAttribute('module_name', $source_module);
1594         list($orderBy,$desc) = $this->getOrderByInfo($html_var);
1595
1596         if($orderBy == 'amount*1')
1597         {
1598             $orderBy=  'amount';
1599         }
1600                 $buttons = false;
1601         foreach($subpanel_def->get_list_fields() as $column_name=>$widget_args)
1602         {
1603             $usage = empty($widget_args['usage']) ? '' : $widget_args['usage'];
1604             if($usage != 'query_only')
1605             {
1606                 $imgArrow = '';
1607
1608                 if($orderBy == $column_name || (isset($widget_args['sort_by']) && str_replace('.','_',$widget_args['sort_by']) == $orderBy))
1609                 {
1610                     $imgArrow = "_down";
1611                     if($this->sort_order == 'desc') {
1612                         $imgArrow = "_up";
1613                     }
1614                 }
1615
1616                 if (!preg_match("/_button/i", $column_name)) {
1617                         $widget_args['name']=$column_name;
1618                         $widget_args['sort'] = $imgArrow;
1619                         $widget_args['start_link_wrapper'] = $this->start_link_wrapper;
1620                         $widget_args['end_link_wrapper'] = $this->end_link_wrapper;
1621                         $widget_args['subpanel_module'] = $this->subpanel_module;
1622
1623                         $widget_contents = $layout_manager->widgetDisplay($widget_args);
1624                         $cell_width = empty($widget_args['width']) ? '' : $widget_args['width'];
1625                         $this->xTemplate->assign('HEADER_CELL', $widget_contents);
1626                         static $count;
1627                     if(!isset($count))$count = 0; else $count++;
1628                         $this->xTemplate->assign('CELL_COUNT', $count);
1629                         $this->xTemplate->assign('CELL_WIDTH', $cell_width);
1630                         $this->xTemplate->parse('dyn_list_view.header_cell');
1631                 } else {
1632                         $buttons = true;
1633                 }
1634             }
1635         }
1636
1637         if($buttons) {
1638                                 $this->xTemplate->assign('HEADER_CELL', "&nbsp;");
1639                                 $this->xTemplate->assign('CELL_COUNT', $count);
1640                         $this->xTemplate->assign('CELL_WIDTH', $cell_width);
1641                         $this->xTemplate->parse('dyn_list_view.header_cell');
1642         }
1643
1644     }
1645
1646
1647     /**
1648     * @return void
1649     * @param unknown $seed
1650     * @param unknown $xTemplateSection
1651     * @param unknown $html_varName
1652     * @desc PUBLIC FUNCTION Handles List Views using seeds that extend SugarBean
1653         $XTemplateSection is the section in the XTemplate file that should be parsed usually main
1654         $html_VarName is the variable name used in the XTemplateFile e.g. TASK
1655         $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
1656         if no XTemplate is set it will create  a new XTemplate
1657         * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
1658         * All Rights Reserved..
1659         * Contributor(s): ______________________________________..
1660     */
1661
1662     function processListViewTwo($seed, $xTemplateSection, $html_varName) {
1663         global $current_user;
1664         if(!isset($this->xTemplate)) {
1665             $this->createXTemplate();
1666         }
1667
1668         $isSugarBean = is_subclass_of($seed, "SugarBean");
1669         $list = null;
1670
1671         if($isSugarBean) {
1672             $list = $this->processSugarBean($xTemplateSection, $html_varName, $seed);
1673         } else {
1674             $list = $seed;
1675         }
1676
1677         if (is_object($seed) && isset($seed->object_name) && $seed->object_name == 'WorkFlow') {
1678             $tab=array();
1679             $access = get_workflow_admin_modules_for_user($current_user);
1680             for ($i = 0; $i < count($list); $i++) {
1681                 if(!empty($access[$list[$i]->base_module])){
1682                     $tab[]=$list[$i];
1683                 }
1684             }
1685             $list = $tab;
1686         }
1687
1688         if($this->is_dynamic) {
1689             $this->processHeaderDynamic($xTemplateSection,$html_varName);
1690             $this->processListRows($list,$xTemplateSection, $html_varName);
1691         } else {
1692             $this->processSortArrows($html_varName);
1693
1694             if($isSugarBean) {
1695                 $seed->parse_additional_headers($this->xTemplate, $xTemplateSection);
1696             }
1697             $this->xTemplateAssign('CHECKALL', SugarThemeRegistry::current()->getImage('blank', '', 1, 1, ".gif", ''));
1698
1699             // Process the  order by before processing the pro_nav.  The pro_nav requires the order by values to be set
1700             $this->processOrderBy($html_varName);
1701
1702
1703             $this->processListRows($list,$xTemplateSection, $html_varName);
1704         }
1705
1706         if($this->display_header_and_footer) {
1707             $this->getAdditionalHeader();
1708             if(!empty($this->header_title)) {
1709                 echo get_form_header($this->header_title, $this->header_text, false);
1710             }
1711         }
1712
1713         $this->xTemplate->out($xTemplateSection);
1714
1715         if(isset($_SESSION['validation'])) {
1716             print base64_decode('PGEgaHJlZj0naHR0cDovL3d3dy5zdWdhcmNybS5jb20nPlBPV0VSRUQmbmJzcDtCWSZuYnNwO1NVR0FSQ1JNPC9hPg==');
1717         }
1718     }
1719
1720     function getArrowStart() {
1721         $imgFileParts = pathinfo(SugarThemeRegistry::current()->getImageURL("arrow.gif"));
1722
1723         return "&nbsp;<!--not_in_theme!--><img border='0' src='".$imgFileParts['dirname']."/".$imgFileParts['filename']."";
1724     }
1725
1726     function getArrowUpDownStart($upDown) {
1727         $ext = ( SugarThemeRegistry::current()->pngSupport ? "png" : "gif" );
1728
1729         if (!isset($upDown) || empty($upDown)) {
1730             $upDown = "";
1731         }
1732         return "&nbsp;<img border='0' src='".SugarThemeRegistry::current()->getImageURL("arrow{$upDown}.{$ext}")."' ";
1733     }
1734
1735         function getArrowEnd() {
1736                 $imgFileParts = pathinfo(SugarThemeRegistry::current()->getImageURL("arrow.gif"));
1737
1738         list($width,$height) = ListView::getArrowImageSize();
1739
1740                 return '.'.$imgFileParts['extension']."' width='$width' height='$height' align='absmiddle' alt=".translate('LBL_SORT').">";
1741     }
1742
1743     function getArrowUpDownEnd($upDown) {
1744         if (!isset($upDown) || empty($upDown)) {
1745             $upDown = "";
1746         }
1747         $imgFileParts = pathinfo(SugarThemeRegistry::current()->getImageURL("arrow{$upDown}.gif"));
1748
1749         list($width,$height) = ListView::getArrowUpDownImageSize($upDown);
1750
1751         //get the right alt tag for the sort
1752         $sortStr = translate('LBL_ALT_SORT');
1753         if($upDown == '_down'){
1754             $sortStr = translate('LBL_ALT_SORT_DESC');
1755         }elseif($upDown == '_up'){
1756             $sortStr = translate('LBL_ALT_SORT_ASC');
1757         }
1758         return " width='$width' height='$height' align='absmiddle' alt='$sortStr'>";
1759     }
1760
1761         function getArrowImageSize() {
1762             // jbasicChartDashletsExpColust get the non-sort image's size.. the up and down have be the same.
1763                 $image = SugarThemeRegistry::current()->getImageURL("arrow.gif",false);
1764
1765         $cache_key = 'arrow_size.'.$image;
1766
1767         // Check the cache
1768         $result = sugar_cache_retrieve($cache_key);
1769         if(!empty($result))
1770         return $result;
1771
1772         // No cache hit.  Calculate the value and return.
1773         $result = getimagesize($image);
1774         sugar_cache_put($cache_key, $result);
1775         return $result;
1776     }
1777
1778     function getArrowUpDownImageSize($upDown) {
1779         // just get the non-sort image's size.. the up and down have be the same.
1780         $image = SugarThemeRegistry::current()->getImageURL("arrow{$upDown}.gif",false);
1781
1782         $cache_key = 'arrowupdown_size.'.$image;
1783
1784         // Check the cache
1785         $result = sugar_cache_retrieve($cache_key);
1786         if(!empty($result))
1787         return $result;
1788
1789         // No cache hit.  Calculate the value and return.
1790         $result = getimagesize($image);
1791         sugar_cache_put($cache_key, $result);
1792         return $result;
1793     }
1794
1795         function getOrderByInfo($html_varName)
1796         {
1797                 $orderBy = $this->getSessionVariable($html_varName, "OBL");
1798                 $desc = $this->getSessionVariable($html_varName, $orderBy.'S');
1799                 $orderBy = str_replace('.', '_', $orderBy);
1800                 return array($orderBy,$desc);
1801         }
1802
1803     function processSortArrows($html_varName)
1804     {
1805
1806         $this->xTemplateAssign("arrow_start", $this->getArrowStart());
1807
1808         list($orderBy,$desc) = $this->getOrderByInfo($html_varName);
1809
1810                 $imgArrow = "_up";
1811                 if($desc) {
1812                         $imgArrow = "_down";
1813                 }
1814                 /**
1815                  * @deprecated only used by legacy opportunites listview, nothing current. Leaving for BC
1816                  */
1817                 if($orderBy == 'amount*1')
1818                 {
1819                         $this->xTemplateAssign('amount_arrow', $imgArrow);
1820                 }
1821                 else if($orderBy == 'amount_usdollar*1')
1822                 {
1823                         $this->xTemplateAssign('amount_usdollar_arrow', $imgArrow);
1824                 }
1825                 else
1826                 {
1827                         $this->xTemplateAssign($orderBy.'_arrow', $imgArrow);
1828                 }
1829
1830         $this->xTemplateAssign('arrow_end', $this->getArrowEnd());
1831     }
1832
1833     // this is where translation happens for dynamic list views
1834     function loadListFieldDefs(&$subpanel_fields,&$child_focus)
1835     {
1836         $this->list_field_defs = $subpanel_fields;
1837
1838         for($i=0;$i < count($this->list_field_defs);$i++)
1839         {
1840             $list_field = $this->list_field_defs[$i];
1841             $field_def = null;
1842             $key = '';
1843             if(!empty($list_field['vname']))
1844             {
1845                 $key = $list_field['vname'];
1846             } else if(isset($list_field['name']) &&  isset($child_focus->field_defs[$list_field['name']]))
1847             {
1848                     $field_def = $child_focus->field_defs[$list_field['name']];
1849                     $key = $field_def['vname'];
1850             }
1851             if(!empty($key))
1852             {
1853                 $list_field['label'] = translate($key,$child_focus->module_dir);
1854                 $this->list_field_defs[$i]['label'] = preg_replace('/:$/','',$list_field['label']);
1855             }
1856             else
1857             {
1858                 $this->list_field_defs[$i]['label'] ='&nbsp;';
1859             }
1860         }
1861     }
1862
1863     function unique_id() {
1864         return sugar_microtime();
1865     }
1866
1867      /**INTERNAL FUNCTION sets a session variable keeping it local to the listview
1868      not the current_module
1869      * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1870      * All Rights Reserved.
1871      * Contributor(s): ______________________________________.
1872      */
1873      function setLocalSessionVariable($localVarName,$varName, $value) {
1874         $_SESSION[$localVarName."_".$varName] = $value;
1875      }
1876
1877      /**INTERNAL FUNCTION returns a session variable that is local to the listview,
1878      not the current_module
1879      * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1880      * All Rights Reserved.
1881      * Contributor(s): ______________________________________.
1882      */
1883  function getLocalSessionVariable($localVarName,$varName) {
1884     if(isset($_SESSION[$localVarName."_".$varName])) {
1885         return $_SESSION[$localVarName."_".$varName];
1886     }
1887     else{
1888         return "";
1889     }
1890  }
1891
1892  /* Set to true if you want Additional Details to appear in the listview
1893   */
1894  function setAdditionalDetails($value = true, $function = '') {
1895     if(!empty($function)) $this->additionalDetailsFunction = $function;
1896     $this->_additionalDetails = $value;
1897  }
1898
1899 }
1900 ?>