2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4 * SugarCRM Community Edition is a customer relationship management program developed by
5 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
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.
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
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
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.
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.
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 ********************************************************************************/
38 require_once('include/EditView/SugarVCR.php');
40 * ListView - list of many objects
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;
69 var $is_dynamic = false;
71 var $start_link_wrapper = '';
72 var $end_link_wrapper = '';
73 var $list_field_defs = array();
75 var $shouldProcess = false;
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;
85 var $force_mass_update=false;
86 var $keep_mass_update_form_open=false;
87 var $ignorePopulateOnly = false;
89 function setDataArray($value) {
90 $this->data_array = $value;
93 function processListViewMulti($seed, $xTemplateSection, $html_varName) {
95 $this->shouldProcess = true;
97 echo "<form name='MassUpdate' method='post' action='index.php'>";
98 $this->processListViewTwo($seed, $xTemplateSection, $html_varName);
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>";
105 function processListView($seed, $xTemplateSection, $html_varName)
107 global $sugar_config;
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'] ;
116 if(strcmp(strtolower($_REQUEST['action']), 'popup') != 0){
117 $_SESSION['last_search_mod'] = $_REQUEST['module'] ;
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);
123 require_once('include/MassUpdate.php');
124 $mass = new MassUpdate();
125 $add_acl_javascript = false;
126 if(!isset($_REQUEST['action'])) {
127 $this->shouldProcess=false;
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);
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();
146 if(!ACLController::checkAccess($seed->module_dir,'export',true)) {
147 $sugar_config['disable_export']= true;
153 //force mass update form if requested.
154 if($this->force_mass_update) {
155 $this->shouldProcess = true;
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);
163 //C.L. Fix for 10048, do not process handleMassUpdate for multi select popups
164 if(!$this->multi_select_popup) {
165 $mass->handleMassUpdate();
169 $this->processListViewTwo($seed,$xTemplateSection, $html_varName);
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();
177 if(!$this->keep_mass_update_form_open) {
178 echo $mass->endMassUpdateForm();
184 function process_dynamic_listview($source_module, $sugarbean,$subpanel_def)
186 $this->source_module = $source_module;
187 $this->subpanel_module = $subpanel_def->name;
188 if(!isset($this->xTemplate))
189 $this->createXTemplate();
191 $html_var = $this->subpanel_module . "_CELL";
193 $list_data = $this->processUnionBeans($sugarbean,$subpanel_def, $html_var);
195 $list = $list_data['list'];
196 $parent_data = $list_data['parent_data'];
198 if($subpanel_def->isCollection()) {
199 $thepanel=$subpanel_def->get_header_panel_def();
201 $thepanel=$subpanel_def;
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);
209 if($this->display_header_and_footer)
211 $this->getAdditionalHeader();
212 if(!empty($this->header_title))
214 echo get_form_header($this->header_title, $this->header_text, false);
218 $this->xTemplate->out('dyn_list_view');
220 if(isset($_SESSION['validation']))
222 print base64_decode('PGEgaHJlZj0naHR0cDovL3d3dy5zdWdhcmNybS5jb20nPlBPV0VSRUQmbmJzcDtCWSZuYnNwO1NVR0FSQ1JNPC9hPg==');
224 if(isset($list_data['query'])) {
225 return ($list_data['query']);
231 * @param unknown $data
232 * @param unknown $xTemplateSection
233 * @param unknown $html_varName
234 * @desc INTERNAL FUNCTION handles the rows
236 function process_dynamic_listview_rows($data,$parent_data, $xtemplateSection, $html_varName, $subpanel_def)
238 global $subpanel_item_count;
244 $this->xTemplate->assign("BG_HILITE", $hilite_bg);
245 $this->xTemplate->assign('CHECKALL', SugarThemeRegistry::current()->getImage('blank', '', 1, 1, ".gif", ''));
246 //$this->xTemplate->assign("BG_CLICK", $click_bg);
247 $subpanel_item_count = 0;
253 $offset = $this->getOffset($html_varName);
255 $processed_ids = array();
257 $fill_additional_fields = array();
258 //Either retrieve the is_fill_in_additional_fields property from the lone
259 //subpanel or visit each subpanel's subpanels to retrieve the is_fill_in_addition_fields
261 $subpanel_list=array();
262 if($subpanel_def->isCollection()) {
263 $subpanel_list=$subpanel_def->sub_subpanels;
265 $subpanel_list[]= $subpanel_def;
268 foreach($subpanel_list as $this_subpanel)
270 if($this_subpanel->is_fill_in_additional_fields())
272 $fill_additional_fields[] = $this_subpanel->bean_name;
273 $fill_additional_fields[$this_subpanel->bean_name] = true;
277 if ( empty($data) ) {
278 $this->xTemplate->assign("ROW_COLOR", 'oddListRow');
279 $thepanel=$subpanel_def;
280 if($subpanel_def->isCollection())
281 $thepanel=$subpanel_def->get_header_panel_def();
282 $this->xTemplate->assign("COL_COUNT", count($thepanel->get_list_fields()));
283 $this->xTemplate->parse($xtemplateSection.".nodata");
285 while(list($aVal, $aItem) = each($data))
287 $subpanel_item_count++;
288 $aItem->check_date_relationships_load();
289 // TODO: expensive and needs to be removed and done better elsewhere
291 if(!empty($fill_additional_fields[$aItem->object_name])
292 || ($aItem->object_name == 'Case' && !empty($fill_additional_fields['aCase']))
295 $aItem->fill_in_additional_list_fields();
296 //$aItem->fill_in_additional_detail_fields();
299 $aItem->call_custom_logic("process_record");
301 if(isset($parent_data[$aItem->id])) {
303 $aItem->parent_name = $parent_data[$aItem->id]['parent_name'];
304 if(!empty($parent_data[$aItem->id]['parent_name_owner'])) {
305 $aItem->parent_name_owner = $parent_data[$aItem->id]['parent_name_owner'];
306 $aItem->parent_name_mod = $parent_data[$aItem->id]['parent_name_mod'];
308 $fields = $aItem->get_list_view_data();
309 if(isset($processed_ids[$aItem->id])) {
313 $processed_ids[$aItem->id] = 1;
317 //ADD OFFSET TO ARRAY
318 $fields['OFFSET'] = ($offset + $count + 1);
320 if($this->shouldProcess) {
321 if($aItem->ACLAccess('EditView')) {
322 $this->xTemplate->assign('PREROW', "<input type='checkbox' class='checkbox' name='mass[]' value='". $fields['ID']. "' />");
324 $this->xTemplate->assign('PREROW', '');
327 if($aItem->ACLAccess('DetailView')) {
328 $this->xTemplate->assign('TAG_NAME','a');
330 $this->xTemplate->assign('TAG_NAME','span');
332 $this->xTemplate->assign('CHECKALL', "<input type='checkbox' title='".$GLOBALS['app_strings']['LBL_SELECT_ALL_TITLE']."' class='checkbox' name='massall' id='massall' value='' onclick='sListView.check_all(document.MassUpdate, \"mass[]\", this.checked);' />");
337 $ROW_COLOR = 'oddListRow';
342 $ROW_COLOR = 'evenListRow';
343 $BG_COLOR = $even_bg;
346 $button_contents = array();
347 $this->xTemplate->assign("ROW_COLOR", $ROW_COLOR);
348 $this->xTemplate->assign("BG_COLOR", $BG_COLOR);
349 $layout_manager = $this->getLayoutManager();
350 $layout_manager->setAttribute('context','List');
351 $layout_manager->setAttribute('image_path',$this->local_image_path);
352 $layout_manager->setAttribute('module_name', $subpanel_def->_instance_properties['module']);
353 if(!empty($this->child_focus))
354 $layout_manager->setAttribute('related_module_name',$this->child_focus->module_dir);
356 //AG$subpanel_data = $this->list_field_defs;
357 //$bla = array_pop($subpanel_data);
358 //select which sub-panel to display here, the decision will be made based on the type of
359 //the sub-panel and panel in the bean being processed.
360 if($subpanel_def->isCollection()) {
361 $thepanel=$subpanel_def->sub_subpanels[$aItem->panel_name];
363 $thepanel=$subpanel_def;
365 //get data source name
366 $linked_field=$thepanel->get_data_source_name();
367 $linked_field_set=$thepanel->get_data_source_name(true);
369 if(!isset($count))$count = 0;
371 $field_acl['DetailView'] = $aItem->ACLAccess('DetailView');
372 $field_acl['ListView'] = $aItem->ACLAccess('ListView');
373 $field_acl['EditView'] = $aItem->ACLAccess('EditView');
374 $field_acl['Delete'] = $aItem->ACLAccess('Delete');
375 foreach($thepanel->get_list_fields() as $field_name=>$list_field)
377 //add linked field attribute to the array.
378 $list_field['linked_field']=$linked_field;
379 $list_field['linked_field_set']=$linked_field_set;
381 $usage = empty($list_field['usage']) ? '' : $list_field['usage'];
382 if($usage == 'query_only' && !empty($list_field['force_query_only_display'])){
383 //if you are here you have column that is query only but needs to be displayed as blank. This is helpful
384 //for collections such as Activities where you have a field in only one object and wish to show it in the subpanel list
386 $widget_contents = ' ';
387 $this->xTemplate->assign('CLASS', "");
388 $this->xTemplate->assign('CELL_COUNT', $count);
389 $this->xTemplate->assign('CELL', $widget_contents);
390 $this->xTemplate->parse($xtemplateSection.".row.cell");
392 }else if($usage != 'query_only')
394 $list_field['name']=$field_name;
396 $module_field = $field_name.'_mod';
397 $owner_field = $field_name.'_owner';
398 if(!empty($aItem->$module_field)) {
400 $list_field['owner_id'] = $aItem->$owner_field;
401 $list_field['owner_module'] = $aItem->$module_field;
404 $list_field['owner_id'] = false;
405 $list_field['owner_module'] = false;
407 if(isset($list_field['alias'])) $list_field['name'] = $list_field['alias'];
408 else $list_field['name']=$field_name;
409 $list_field['fields'] = $fields;
410 $list_field['module'] = $aItem->module_dir;
411 $list_field['start_link_wrapper'] = $this->start_link_wrapper;
412 $list_field['end_link_wrapper'] = $this->end_link_wrapper;
413 $list_field['subpanel_id'] = $this->subpanel_id;
414 $list_field += $field_acl;
415 if ( isset($aItem->field_defs[strtolower($list_field['name'])])) {
416 require_once('include/SugarFields/SugarFieldHandler.php');
417 // We need to see if a sugar field exists for this field type first,
418 // if it doesn't, toss it at the old sugarWidgets. This is for
419 // backwards compatibility and will be removed in a future release
420 $vardef = $aItem->field_defs[strtolower($list_field['name'])];
421 if ( isset($vardef['type']) ) {
422 $fieldType = isset($vardef['custom_type'])?$vardef['custom_type']:$vardef['type'];
423 $tmpField = SugarFieldHandler::getSugarField($fieldType,true);
428 if ( $tmpField != NULL ) {
429 $widget_contents = SugarFieldHandler::displaySmarty($list_field['fields'],$vardef,'ListView',$list_field);
431 // No SugarField for this particular type
432 // Use the old, icky, SugarWidget for now
433 $widget_contents = $layout_manager->widgetDisplay($list_field);
436 if ( isset($list_field['widget_class']) && $list_field['widget_class'] == 'SubPanelDetailViewLink' ) {
437 // We need to call into the old SugarWidgets for the time being, so it can generate a proper link with all the various corner-cases handled
438 // So we'll populate the field data with the pre-rendered display for the field
439 $list_field['fields'][$field_name] = $widget_contents;
440 if('full_name' == $field_name){//bug #32465
441 $list_field['fields'][strtoupper($field_name)] = $widget_contents;
444 //vardef source is non db, assign the field name to varname for processing of column.
445 if(!empty($vardef['source']) && $vardef['source']=='non-db'){
446 $list_field['varname'] = $field_name;
449 $widget_contents = $layout_manager->widgetDisplay($list_field);
450 } else if(isset($list_field['widget_class']) && $list_field['widget_class'] == 'SubPanelEmailLink' ) {
451 $widget_contents = $layout_manager->widgetDisplay($list_field);
455 $this->xTemplate->assign('CELL_COUNT', $count);
456 $this->xTemplate->assign('CLASS', "");
457 if ( empty($widget_contents) ) $widget_contents = ' ';
458 $this->xTemplate->assign('CELL', $widget_contents);
459 $this->xTemplate->parse($xtemplateSection.".row.cell");
461 // This handles the edit and remove buttons and icon widget
462 if( isset($list_field['widget_class']) && $list_field['widget_class'] == "SubPanelIcon") {
464 $widget_contents = $layout_manager->widgetDisplay($list_field);
465 $this->xTemplate->assign('CELL_COUNT', $count);
466 $this->xTemplate->assign('CLASS', "");
467 if ( empty($widget_contents) ) $widget_contents = ' ';
468 $this->xTemplate->assign('CELL', $widget_contents);
469 $this->xTemplate->parse($xtemplateSection.".row.cell");
470 } elseif (preg_match("/button/i", $list_field['name'])) {
471 if ((($list_field['name'] === 'edit_button' && $field_acl['EditView']) || ($list_field['name'] === 'close_button' && $field_acl['EditView']) || ($list_field['name'] === 'remove_button' && $field_acl['Delete'])) && '' != ($_content = $layout_manager->widgetDisplay($list_field)) )
473 $button_contents[] = $_content;
478 $button_contents[] = '';
482 $this->xTemplate->assign('CLASS', "");
483 $widget_contents = $layout_manager->widgetDisplay($list_field);
484 $this->xTemplate->assign('CELL_COUNT', $count);
485 if ( empty($widget_contents) ) $widget_contents = ' ';
486 $this->xTemplate->assign('CELL', $widget_contents);
487 $this->xTemplate->parse($xtemplateSection.".row.cell");
495 // Make sure we have at least one button before rendering a column for
496 // the action buttons in a list view. Relevant bugs: #51647 and #51640.
497 if(!empty($button_contents))
499 $button_contents = array_filter($button_contents);
500 if (!empty($button_contents))
502 // this is for inline buttons on listviews
503 // bug#51275: smarty widget to help provide the action menu functionality as it is currently sprinkled throughout the app with html
504 require_once('include/Smarty/plugins/function.sugar_action_menu.php');
505 $tempid = create_guid();
506 array_unshift($button_contents, "<div style='display: inline' id='$tempid'>" . array_shift($button_contents) . "</div>");
507 $action_button = smarty_function_sugar_action_menu(array(
509 'buttons' => $button_contents,
510 'class' => 'clickMenu subpanel records fancymenu button',
511 'flat' => false //assign flat value as false to display dropdown menu at any other preferences.
512 ), $this->xTemplate);
518 $this->xTemplate->assign('CLASS', "inlineButtons");
519 $this->xTemplate->assign('CELL_COUNT', ++$count);
520 //Bug#51275 for beta3 pre_script is not required any more
521 $this->xTemplate->assign('CELL', $action_button);
522 $this->xTemplate->parse($xtemplateSection . ".row.cell");
526 $aItem->setupCustomFields($aItem->module_dir);
527 $aItem->custom_fields->populateAllXTPL($this->xTemplate, 'detail', $html_varName, $fields);
531 $this->xTemplate->parse($xtemplateSection.".row");
534 $this->xTemplate->parse($xtemplateSection);
537 /**sets whether or not to display the xtemplate header and footer
538 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
539 * All Rights Reserved.
540 * Contributor(s): ______________________________________.
542 function setDisplayHeaderAndFooter($bool) {
543 $this->display_header_and_footer = $bool;
546 /**initializes ListView
547 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
548 * All Rights Reserved.
549 * Contributor(s): ______________________________________.
551 function ListView() {
554 if(!$this->initialized) {
555 global $sugar_config;
556 $this->records_per_page = $sugar_config['list_max_entries_per_page'] + 0;
557 $this->initialized = true;
558 global $app_strings, $currentModule;
559 $this->local_theme = SugarThemeRegistry::current()->__toString();
560 $this->local_app_strings =$app_strings;
561 $this->local_image_path = SugarThemeRegistry::current()->getImagePath();
562 $this->local_current_module = $currentModule;
565 /**sets how many records should be displayed per page in the list view
566 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
567 * All Rights Reserved.
568 * Contributor(s): ______________________________________.
570 function setRecordsPerPage($count) {
571 $this->records_per_page = $count;
573 /**sets the header title */
574 function setHeaderTitle($value) {
575 $this->header_title = $value;
577 /**sets the header text this is text that's appended to the header table and is usually used for the creation of buttons
578 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
579 * All Rights Reserved.
580 * Contributor(s): ______________________________________.
582 function setHeaderText($value) {
583 $this->header_text = $value;
585 /**sets the path for the XTemplate HTML file to be used this is only needed to be set if you are allowing ListView to create the XTemplate
586 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
587 * All Rights Reserved.
588 * Contributor(s): ______________________________________.
590 function setXTemplatePath($value) {
591 $this->xTemplatePath= $value;
594 /**this is a helper function for allowing ListView to create a new XTemplate it groups parameters that should be set into a single function
595 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
596 * All Rights Reserved.
597 * Contributor(s): ______________________________________.
599 function initNewXTemplate($XTemplatePath, $modString, $imagePath = null) {
600 $this->setXTemplatePath($XTemplatePath);
601 if(isset($modString))
602 $this->setModStrings($modString);
603 if(isset($imagePath))
604 $this->setImagePath($imagePath);
608 function getOrderBy($varName, $defaultOrderBy='', $force_sortorder='') {
609 $sortBy = $this->getSessionVariable($varName, "ORDER_BY") ;
611 $orderByDirection = $this->getSessionVariableName($varName, "order_by_direction");
612 $orderByColumn = $this->getSessionVariableName($varName, "ORDER_BY");
613 $lastEqualsSortBy = false;
614 $defaultOrder = false; //ascending
617 $this->setUserVariable($varName, "ORDER_BY", $defaultOrderBy);
618 $sortBy = $defaultOrderBy;
620 $this->setUserVariable($varName, "ORDER_BY", $sortBy);
623 $desc = $this->getSessionVariable($varName, $sortBy."S");
627 $desc = $defaultOrder;
629 $defaultOrder = $desc ? 'desc' : 'asc';
630 $orderByValue = $defaultOrder;
631 if (isset($_REQUEST[$orderByDirection]))
633 $possibleRequestOrderBy = $_REQUEST[$orderByDirection];
634 if ($possibleRequestOrderBy == 'asc' || $possibleRequestOrderBy == 'desc')
636 $orderByValue = $possibleRequestOrderBy;
640 if (isset($_REQUEST[$orderByColumn]))
642 $last = $this->getSessionVariable($varName, "OBL");
644 if (!empty($last) && $last == $sortBy)
646 $lastEqualsSortBy = true;
649 $orderByValue = $defaultOrder;
650 $this->setSessionVariable($varName, "OBL", $sortBy);
652 $desc = $orderByValue == 'desc';
653 $orderByDirectionValue = false;
654 $this->setSessionVariable($varName, $sortBy . "S", $desc);
657 if (empty($force_sortorder))
659 if (substr_count(strtolower($sortBy), ' desc') == 0 && substr_count(strtolower($sortBy), ' asc') == 0)
663 $orderByDirectionValue = $desc ? 'asc' : 'desc';
665 $this->query_orderby = $sortBy . ' ' . $orderByValue;
669 $this->query_orderby = $sortBy . ' ' . $force_sortorder;
671 if (!isset($this->appendToBaseUrl))
673 $this->appendToBaseUrl = array();
675 if ($orderByDirectionValue)
677 $this->appendToBaseUrl[$orderByDirection] = $orderByDirectionValue;
679 $offsetVar = $this->getSessionVariableName($varName, "offset");
680 if (isset($_REQUEST[$offsetVar]))
682 $this->appendToBaseUrl[$offsetVar] = $_REQUEST[$offsetVar];
684 //Just clear from url...
685 $this->appendToBaseUrl[$orderByColumn] = false;
687 $this->query_orderby = "";
689 $this->sortby = $sortBy;
690 return $this->query_orderby;
695 /**sets the parameters dealing with the db
696 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
697 * All Rights Reserved.
698 * Contributor(s): ______________________________________.
700 function setQuery($where, $limit, $orderBy, $varName, $allowOrderByOveride=true) {
701 $this->query_where = $where;
702 if($this->getSessionVariable("query", "where") != $where) {
703 $this->query_where_has_changed = true;
704 $this->setSessionVariable("query", "where", $where);
707 $this->query_limit = $limit;
708 if(!$allowOrderByOveride) {
709 $this->query_orderby = $orderBy;
712 $this->getOrderBy($varName, $orderBy);
714 $this->setLocalSessionVariable($varName, "QUERY_WHERE", $where);
716 //SETTING ORDER_BY FOR USE IN DETAILVIEW
717 $this->setLocalSessionVariable($varName, "ORDER_BY_DETAIL", $this->query_orderby);
720 function displayArrow() {
724 /**sets the theme used only use if it is different from the global
725 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
726 * All Rights Reserved.
727 * Contributor(s): ______________________________________.
729 function setTheme($theme) {
730 $this->local_theme = $theme;
731 if(isset($this->xTemplate))$this->xTemplate->assign("THEME", $this->local_theme);
734 /**sets the AppStrings used only use if it is different from the global
735 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
736 * All Rights Reserved.
737 * Contributor(s): ______________________________________.
739 function setAppStrings($app_strings) {
740 unset($this->local_app_strings);
741 $this->local_app_strings = $app_strings;
742 if(isset($this->xTemplate))$this->xTemplate->assign("APP", $this->local_app_strings);
745 /**sets the ModStrings used
746 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
747 * All Rights Reserved.
748 * Contributor(s): ______________________________________.
750 function setModStrings($mod_strings) {
751 unset($this->local_module_strings);
752 $this->local_mod_strings = $mod_strings;
753 if(isset($this->xTemplate))$this->xTemplate->assign("MOD", $this->local_mod_strings);
756 /**sets the ImagePath used
757 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
758 * All Rights Reserved.
759 * Contributor(s): ______________________________________.
761 function setImagePath($image_path) {
762 $this->local_image_path = $image_path;
763 if(empty($this->local_image_path)) {
764 $this->local_image_path = SugarThemeRegistry::get($this->local_theme)->getImagePath();
766 if(isset($this->xTemplate))$this->xTemplate->assign("IMAGE_PATH", $this->local_image_path);
769 /**sets the currentModule only use if this is different from the global
770 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
771 * All Rights Reserved.
772 * Contributor(s): ______________________________________.
774 function setCurrentModule($currentModule) {
775 unset($this->local_current_module);
776 $this->local_current_module = $currentModule;
777 if(isset($this->xTemplate))$this->xTemplate->assign("MODULE_NAME", $this->local_current_module);
780 /**INTERNAL FUNCTION creates an XTemplate DO NOT CALL THIS THIS IS AN INTERNAL FUNCTION
781 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
782 * All Rights Reserved.
783 * Contributor(s): ______________________________________.
785 function createXTemplate() {
786 if(!isset($this->xTemplate)) {
787 if(isset($this->xTemplatePath)) {
789 $this->xTemplate = new XTemplate($this->xTemplatePath);
790 $this->xTemplate->assign("APP", $this->local_app_strings);
791 if(isset($this->local_mod_strings))$this->xTemplate->assign("MOD", $this->local_mod_strings);
792 $this->xTemplate->assign("THEME", $this->local_theme);
793 $this->xTemplate->assign("IMAGE_PATH", $this->local_image_path);
794 $this->xTemplate->assign("MODULE_NAME", $this->local_current_module);
796 $GLOBALS['log']->error("NO XTEMPLATEPATH DEFINED CANNOT CREATE XTEMPLATE");
801 /**sets the XTemplate telling ListView to use newXTemplate as its current XTemplate
802 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
803 * All Rights Reserved.
804 * Contributor(s): ______________________________________.
806 function setXTemplate($newXTemplate) {
807 $this->xTemplate = $newXTemplate;
810 /**returns the XTemplate
811 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
812 * All Rights Reserved.
813 * Contributor(s): ______________________________________.
815 function getXTemplate() {
816 return $this->xTemplate;
819 /**assigns a name value pair to the XTemplate
820 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
821 * All Rights Reserved.
822 * Contributor(s): ______________________________________.
824 function xTemplateAssign($name, $value) {
826 if(!isset($this->xTemplate)) {
827 $this->createXTemplate();
829 $this->xTemplate->assign($name, $value);
833 /**INTERNAL FUNCTION returns the offset first checking the query then checking the session if the where clause has changed from the last time it returns 0
834 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
835 * All Rights Reserved.
836 * Contributor(s): ______________________________________.
838 function getOffset($localVarName) {
839 if($this->query_where_has_changed || isset($GLOBALS['record_has_changed'])) {
840 $this->setSessionVariable($localVarName,"offset", 0);
842 $offset = $this->getSessionVariable($localVarName,"offset");
849 /**INTERNAL FUNCTION sets the offset in the session
850 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
851 * All Rights Reserved.
852 * Contributor(s): ______________________________________.
854 function setOffset($localVarName, $value) {
855 $this->setSessionVariable($localVarName, "offset", $value);
858 /**INTERNAL FUNCTION sets a session variable
859 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
860 * All Rights Reserved.
861 * Contributor(s): ______________________________________.
863 function setSessionVariable($localVarName,$varName, $value) {
864 $_SESSION[$this->local_current_module."_".$localVarName."_".$varName] = $value;
867 function setUserVariable($localVarName,$varName, $value) {
868 if($this->is_dynamic || $localVarName == 'CELL')return;
869 global $current_user;
870 $current_user->setPreference($this->local_current_module."_".$localVarName."_".$varName, $value);
873 /**INTERNAL FUNCTION returns a session variable first checking the query for it then checking the session
874 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
875 * All Rights Reserved.
876 * Contributor(s): ______________________________________.
878 function getSessionVariable($localVarName,$varName) {
879 //Set any variables pass in through request first
880 if(isset($_REQUEST[$this->getSessionVariableName($localVarName, $varName)])) {
881 $this->setSessionVariable($localVarName,$varName,$_REQUEST[$this->getSessionVariableName($localVarName, $varName)]);
884 if(isset($_SESSION[$this->getSessionVariableName($localVarName, $varName)])) {
885 return $_SESSION[$this->getSessionVariableName($localVarName, $varName)];
890 function getUserVariable($localVarName, $varName) {
891 global $current_user;
892 if($this->is_dynamic || $localVarName == 'CELL')return;
893 if(isset($_REQUEST[$this->getSessionVariableName($localVarName, $varName)])) {
895 $this->setUserVariable($localVarName,$varName,$_REQUEST[$this->getSessionVariableName($localVarName, $varName)]);
897 return $current_user->getPreference($this->getSessionVariableName($localVarName, $varName));
902 * helper method to determine sort order by priority of source
903 * 1. explicit in request object
904 * 2. in session variable
905 * 3. subpaneldefs metadata
907 * @param array $sortOrderList - contains options
908 * @return string 'asc' | 'desc'
910 function calculateSortOrder($sortOrderList)
912 $priority_map = array(
919 foreach($priority_map as $p) {
920 if (key_exists($p, $sortOrderList)) {
921 $order = strtolower($sortOrderList[$p]);
922 if (in_array($order, array('asc', 'desc'))) {
934 * @param unknown $localVarName
935 * @param unknown $varName
936 * @desc INTERNAL FUNCTION returns the session/query variable name
937 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
938 * All Rights Reserved.
939 * Contributor(s): ______________________________________..
941 function getSessionVariableName($localVarName,$varName) {
942 return $this->local_current_module."_".$localVarName."_".$varName;
948 * @param unknown $seed
949 * @param unknown $xTemplateSection
950 * @param unknown $html_varName
951 * @desc INTERNAL FUNCTION Handles List Views using seeds that extend SugarBean
952 $XTemplateSection is the section in the XTemplate file that should be parsed usually main
953 $html_VarName is the variable name used in the XTemplateFile e.g. TASK
954 $seed is a seed that extends SugarBean
955 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
956 * All Rights Reserved..
957 * Contributor(s): ______________________________________..
959 function processSugarBean($xtemplateSection, $html_varName, $seed) {
960 global $list_view_row_count;
962 $current_offset = $this->getOffset($html_varName);
966 SugarVCR::erase($seed->module_dir);
968 //$filter = array('id', 'full_name');
970 $ret_array = $seed->create_new_list_query($this->query_orderby, $this->query_where, $filter, $params, 0, '', true, $seed, true);
971 if(!is_array($params)) $params = array();
972 if(!isset($params['custom_select'])) $params['custom_select'] = '';
973 if(!isset($params['custom_from'])) $params['custom_from'] = '';
974 if(!isset($params['custom_where'])) $params['custom_where'] = '';
975 if(!isset($params['custom_order_by'])) $params['custom_order_by'] = '';
976 $main_query = $ret_array['select'] . $params['custom_select'] . $ret_array['from'] . $params['custom_from'] . $ret_array['where'] . $params['custom_where'] . $ret_array['order_by'] . $params['custom_order_by'];
977 SugarVCR::store($seed->module_dir, $main_query);
980 if(empty($this->related_field_name)) {
981 $response = $seed->get_list($this->query_orderby, $this->query_where, $current_offset, $this->query_limit);
983 $related_field_name = $this->related_field_name;
984 $response = $seed->get_related_list($this->child_focus,$related_field_name, $this->query_orderby,
985 $this->query_where, $current_offset, $this->query_limit);
988 $list = $response['list'];
989 $row_count = $response['row_count'];
990 $next_offset = $response['next_offset'];
991 $previous_offset = $response['previous_offset'];
993 if(!empty($response['current_offset'])) {
994 $current_offset = $response['current_offset'];
997 $list_view_row_count = $row_count;
998 $this->processListNavigation($xtemplateSection,$html_varName, $current_offset, $next_offset, $previous_offset, $row_count, null, null, empty($seed->column_fields) ? null : count($seed->column_fields));
1005 function processUnionBeans($sugarbean, $subpanel_def, $html_var = 'CELL') {
1007 $last_detailview_record = $this->getSessionVariable("detailview", "record");
1008 if(!empty($last_detailview_record) && $last_detailview_record != $sugarbean->id){
1009 $GLOBALS['record_has_changed'] = true;
1011 $this->setSessionVariable("detailview", "record", $sugarbean->id);
1013 $current_offset = $this->getOffset($html_var);
1014 $module = isset($_REQUEST['module']) ? $_REQUEST['module'] : '';
1015 $response = array();
1017 // choose sort order
1018 $sort_order = array();
1019 $sort_order['default'] = 'asc';
1021 // explicit request parameter gets priority over all
1022 $sort_order['request'] = isset($_REQUEST['sort_order']) ? $_REQUEST['sort_order'] : null;
1024 // see if the session data has a sort order
1025 if (isset($_SESSION['last_sub' . $this->subpanel_module . '_order']))
1027 $sort_order['session'] = $_SESSION['last_sub' . $this->subpanel_module . '_order'];
1029 // We swap the order when the request contains an offset (indicating a column sort issued);
1030 // otherwise we do not sort. If we don't make this check, then the subpanel listview will
1031 // swap ordering each time a new record is entered via quick create forms
1032 if (isset($_REQUEST[$module . '_' . $html_var . '_offset']))
1034 $sort_order['session'] = $sort_order['session'] == 'asc' ? 'desc' : 'asc';
1039 $sort_order['session'] = null;
1042 // does the metadata have a default sort order?
1043 $sort_order['subpaneldefs'] = isset($subpanel_def->_instance_properties['sort_order']) ?
1044 $subpanel_def->_instance_properties['sort_order'] : null;
1046 $this->sort_order = $this->calculateSortOrder($sort_order);
1049 if (isset($subpanel_def->_instance_properties['sort_by'])) {
1050 $this->query_orderby = $subpanel_def->_instance_properties['sort_by'];
1052 $this->query_orderby = 'id';
1055 $this->getOrderBy($html_var,$this->query_orderby, $this->sort_order);
1057 $_SESSION['last_sub' .$this->subpanel_module. '_order'] = $this->sort_order;
1058 $_SESSION['last_sub' .$this->subpanel_module. '_url'] = $this->getBaseURL($html_var);
1060 // Bug 8139 - Correct Subpanel sorting on 'name', when subpanel sorting default is 'last_name, first_name'
1061 if (($this->sortby == 'name' || $this->sortby == 'last_name') &&
1062 str_replace(' ', '', trim($subpanel_def->_instance_properties['sort_by'])) == 'last_name,first_name') {
1063 $this->sortby = 'last_name '.$this->sort_order.', first_name ';
1066 if(!empty($this->response)){
1067 $response =& $this->response;
1070 $response = SugarBean::get_union_related_list($sugarbean,$this->sortby, $this->sort_order, $this->query_where, $current_offset, -1, $this->records_per_page,$this->query_limit,$subpanel_def);
1071 $this->response =& $response;
1073 $list = $response['list'];
1074 $row_count = $response['row_count'];
1075 $next_offset = $response['next_offset'];
1076 $previous_offset = $response['previous_offset'];
1077 if(!empty($response['current_offset']))$current_offset = $response['current_offset'];
1078 global $list_view_row_count;
1079 $list_view_row_count = $row_count;
1080 $this->processListNavigation('dyn_list_view', $html_var, $current_offset, $next_offset, $previous_offset, $row_count, $sugarbean,$subpanel_def);
1082 return array('list'=>$list, 'parent_data'=>$response['parent_data'], 'query'=>$response['query']);
1085 function getBaseURL($html_varName) {
1086 static $cache = array();
1088 if(!empty($cache[$html_varName]))return $cache[$html_varName];
1089 $blockVariables = array('mass', 'uid', 'massupdate', 'delete', 'merge', 'selectCount','current_query_by_page');
1090 if(!empty($this->base_URL)) {
1091 return $this->base_URL;
1094 $baseurl = $_SERVER['PHP_SELF'];
1095 if(empty($baseurl)) {
1096 $baseurl = 'index.php';
1099 /*fixes an issue with deletes when doing a search*/
1100 foreach(array_merge($_GET, $_POST) as $name=>$value) {
1101 //echo ("$name = $value <br/>");
1102 if(!empty($value) && $name != 'sort_order' //&& $name != ListView::getSessionVariableName($html_varName,"ORDER_BY")
1103 && $name != ListView::getSessionVariableName($html_varName,"offset")
1104 /*&& substr_count($name, "ORDER_BY")==0*/ && !in_array($name, $blockVariables))
1106 if(is_array($value)) {
1107 foreach($value as $valuename=>$valuevalue) {
1108 if(substr_count($baseurl, '?') > 0)
1109 $baseurl .= "&{$name}[]=".$valuevalue;
1111 $baseurl .= "?{$name}[]=".$valuevalue;
1114 $value = urlencode($value);
1115 if(substr_count($baseurl, '?') > 0) {
1116 $baseurl .= "&$name=$value";
1118 $baseurl .= "?$name=$value";
1125 if($_SERVER['REQUEST_METHOD'] == 'POST') {
1126 // at this point it is possible that the above foreach already executed resulting in double ?'s in the url
1127 if(substr_count($baseurl, '?') == 0) {
1130 if(isset($_REQUEST['action'])) $baseurl.= '&action='.$_REQUEST['action'];
1131 if(isset($_REQUEST['record'])) $baseurl .= '&record='.$_REQUEST['record'];
1132 if(isset($_REQUEST['module'])) $baseurl .= '&module='.$_REQUEST['module'];
1135 $baseurl .= "&".ListView::getSessionVariableName($html_varName,"offset")."=";
1136 $cache[$html_varName] = $baseurl;
1141 * @param unknown $data
1142 * @param unknown $xTemplateSection
1143 * @param unknown $html_varName
1144 * @desc INTERNAL FUNCTION process the List Navigation
1145 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1146 * All Rights Reserved.
1147 * Contributor(s): ______________________________________..
1149 function processListNavigation($xtemplateSection, $html_varName, $current_offset, $next_offset, $previous_offset, $row_count, $sugarbean=null, $subpanel_def=null, $col_count = 20) {
1151 global $export_module;
1152 global $sugar_config;
1153 global $current_user;
1154 global $currentModule;
1155 global $app_strings;
1157 $start_record = $current_offset + 1;
1159 if(!is_numeric($col_count))
1165 $end_record = $start_record + $this->records_per_page;
1166 // back up the the last page.
1167 if($end_record > $row_count+1) {
1168 $end_record = $row_count+1;
1170 // Determine the start location of the last page
1174 $number_pages = floor(($row_count - 1) / $this->records_per_page);
1176 $last_offset = $number_pages * $this->records_per_page;
1178 if(empty($this->query_limit) || $this->query_limit > $this->records_per_page) {
1179 $this->base_URL = $this->getBaseURL($html_varName);
1182 if($this->is_dynamic) {
1183 $dynamic_url .='&'. $this->getSessionVariableName($html_varName,'ORDER_BY') . '='. $this->getSessionVariable($html_varName,'ORDER_BY').'&sort_order='.$this->sort_order.'&to_pdf=true&action=SubPanelViewer&subpanel=' . $this->subpanel_module;
1186 $current_URL = htmlentities($this->base_URL.$current_offset.$dynamic_url);
1187 $start_URL = htmlentities($this->base_URL."0".$dynamic_url);
1188 $previous_URL = htmlentities($this->base_URL.$previous_offset.$dynamic_url);
1189 $next_URL = htmlentities($this->base_URL.$next_offset.$dynamic_url);
1190 $end_URL = htmlentities($this->base_URL.'end'.$dynamic_url);
1192 if(!empty($this->start_link_wrapper)) {
1193 $current_URL = $this->start_link_wrapper.$current_URL.$this->end_link_wrapper;
1194 $start_URL = $this->start_link_wrapper.$start_URL.$this->end_link_wrapper;
1195 $previous_URL = $this->start_link_wrapper.$previous_URL.$this->end_link_wrapper;
1196 $next_URL = $this->start_link_wrapper.$next_URL.$this->end_link_wrapper;
1197 $end_URL = $this->start_link_wrapper.$end_URL.$this->end_link_wrapper;
1200 $moduleString = "{$currentModule}_{$html_varName}_offset";
1201 $moduleStringOrder = "{$currentModule}_{$html_varName}_ORDER_BY";
1202 if($this->shouldProcess && !$this->multi_select_popup) {
1203 // check the checkboxes onload
1204 echo "<script>YAHOO.util.Event.addListener(window, \"load\", sListView.check_boxes);</script>\n";
1206 $massUpdateRun = isset($_REQUEST['massupdate']) && $_REQUEST['massupdate'] == 'true';
1207 $uids = empty($_REQUEST['uid']) || $massUpdateRun ? '' : $_REQUEST['uid'];
1208 $select_entire_list = ($massUpdateRun) ? 0 : (isset($_POST['select_entire_list']) ? $_POST['select_entire_list'] : (isset($_REQUEST['select_entire_list']) ? $_REQUEST['select_entire_list'] : 0));
1210 echo "<textarea style='display: none' name='uid'>{$uids}</textarea>\n" .
1211 "<input type='hidden' name='select_entire_list' value='{$select_entire_list}'>\n".
1212 "<input type='hidden' name='{$moduleString}' value='0'>\n".
1213 "<input type='hidden' name='{$moduleStringOrder}' value='0'>\n";
1218 $GLOBALS['log']->debug("Offsets: (start, previous, next, last)(0, $previous_offset, $next_offset, $last_offset)");
1220 if(0 == $current_offset) {
1221 $start_link = "<button type='button' name='listViewStartButton' title='{$this->local_app_strings['LNK_LIST_START']}' class='button' disabled>".SugarThemeRegistry::current()->getImage("start_off","aborder='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_START'])."</button>";
1222 $previous_link = "<button type='button' name='listViewPrevButton' title='{$this->local_app_strings['LNK_LIST_PREVIOUS']}' class='button' disabled>".SugarThemeRegistry::current()->getImage("previous_off","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_PREVIOUS'])."</button>";
1224 if($this->multi_select_popup) {// nav links for multiselect popup, submit form to save checks.
1225 $start_link = "<button type='button' class='button' name='listViewStartButton' title='{$this->local_app_strings['LNK_LIST_START']}' onClick='javascript:save_checks(0, \"{$moduleString}\");'>".SugarThemeRegistry::current()->getImage("start","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_START'])."</button>";
1226 $previous_link = "<button type='button' class='button' name='listViewPrevButton' title='{$this->local_app_strings['LNK_LIST_PREVIOUS']}' onClick='javascript:save_checks($previous_offset, \"{$moduleString}\");'>".SugarThemeRegistry::current()->getImage("previous","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_PREVIOUS'])."</button>";
1227 } elseif($this->shouldProcess) {
1228 $start_link = "<button type='button' class='button' name='listViewStartButton' title='{$this->local_app_strings['LNK_LIST_START']}' onClick='location.href=\"$start_URL\"; sListView.save_checks(0, \"{$moduleString}\");'>".SugarThemeRegistry::current()->getImage("start","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_START'])."</button>";
1229 $previous_link = "<button type='button' class='button' name='listViewPrevButton' title='{$this->local_app_strings['LNK_LIST_PREVIOUS']}' onClick='location.href=\"$previous_URL\"; sListView.save_checks($previous_offset, \"{$moduleString}\");'>".SugarThemeRegistry::current()->getImage("previous","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_PREVIOUS'])."</button>";
1232 if(0 != preg_match('/javascript.*/', $start_URL)){
1233 $onClick = "\"$start_URL;\"";
1235 $onClick ="'location.href=\"$start_URL\";'";
1237 $start_link = "<button type='button' class='button' name='listViewStartButton' title='{$this->local_app_strings['LNK_LIST_START']}' onClick=".$onClick.">".SugarThemeRegistry::current()->getImage("start","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_START'])."</button>";
1240 if(0 != preg_match('/javascript.*/', $previous_URL)){
1241 $onClick = "\"$previous_URL;\"";
1243 $onClick = "'location.href=\"$previous_URL\";'";
1245 $previous_link = "<button type='button' class='button' name='listViewPrevButton' title='{$this->local_app_strings['LNK_LIST_PREVIOUS']}' onClick=".$onClick.">".SugarThemeRegistry::current()->getImage("previous","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_PREVIOUS'])."</button>";
1249 if($last_offset <= $current_offset) {
1250 $end_link = "<button type='button' name='listViewEndButton' title='{$this->local_app_strings['LNK_LIST_END']}' class='button' disabled>".SugarThemeRegistry::current()->getImage("end_off","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_END'])."</button>";
1251 $next_link = "<button type='button' name='listViewNextButton' title='{$this->local_app_strings['LNK_LIST_NEXT']}' class='button' disabled>".SugarThemeRegistry::current()->getImage("next_off","aborder='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_NEXT'])."</button>";
1253 if($this->multi_select_popup) { // nav links for multiselect popup, submit form to save checks.
1254 $end_link = "<button type='button' name='listViewEndButton' class='button' title='{$this->local_app_strings['LNK_LIST_END']}' onClick='javascript:save_checks($last_offset, \"{$moduleString}\");'>".SugarThemeRegistry::current()->getImage("end","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_END'])."</button>";
1255 if(!empty($sugar_config['disable_count_query'])) {
1258 $next_link = "<button type='button' name='listViewNextButton' title='{$this->local_app_strings['LNK_LIST_NEXT']}' class='button' onClick='javascript:save_checks($next_offset, \"{$moduleString}\");'>".SugarThemeRegistry::current()->getImage("next","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_NEXT'])."</button>";
1259 } elseif($this->shouldProcess) {
1260 $end_link = "<button type='button' name='listViewEndButton' class='button' title='{$this->local_app_strings['LNK_LIST_END']}' onClick='location.href=\"$end_URL\"; sListView.save_checks(\"end\", \"{$moduleString}\");'>".SugarThemeRegistry::current()->getImage("end","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_END'])."</button>";
1261 $next_link = "<button type='button' name='listViewNextButton' class='button' title='{$this->local_app_strings['LNK_LIST_NEXT']}' onClick='location.href=\"$next_URL\"; sListView.save_checks($next_offset, \"{$moduleString}\");'>".SugarThemeRegistry::current()->getImage("next","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_NEXT'])."</button>";
1264 if(0 != preg_match('/javascript.*/', $next_URL)){
1265 $onClick = "\"$next_URL;\"";
1267 $onClick ="'location.href=\"$next_URL\";'";
1269 $next_link = "<button type='button' name='listViewNextButton' class='button' title='{$this->local_app_strings['LNK_LIST_NEXT']}' onClick=".$onClick.">".SugarThemeRegistry::current()->getImage("next","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_NEXT'])."</button>";
1272 if(0 != preg_match('/javascript.*/', $end_URL)){
1273 $onClick = "\"$end_URL;\"";
1275 $onClick = "'location.href=\"$end_URL\";'";
1277 $end_link = "<button type='button' name='listViewEndButton' class='button' title='{$this->local_app_strings['LNK_LIST_END']}' onClick=".$onClick.">".SugarThemeRegistry::current()->getImage("end","border='0' align='absmiddle'",null,null,'.gif',$this->local_app_strings['LNK_LIST_END'])."</button>";
1282 $GLOBALS['log']->info("Offset (next, current, prev)($next_offset, $current_offset, $previous_offset)");
1283 $GLOBALS['log']->info("Start/end records ($start_record, $end_record)");
1285 $end_record = $end_record-1;
1287 $script_href = "<a style=\'width: 150px\' name=\"thispage\" class=\'menuItem\' onmouseover=\'hiliteItem(this,\"yes\");\' onmouseout=\'unhiliteItem(this);\' onclick=\'if (document.MassUpdate.select_entire_list.value==1){document.MassUpdate.select_entire_list.value=0;sListView.check_all(document.MassUpdate, \"mass[]\", true, $this->records_per_page)}else {sListView.check_all(document.MassUpdate, \"mass[]\", true)};\' href=\'#\'>{$this->local_app_strings['LBL_LISTVIEW_OPTION_CURRENT']} ({$this->records_per_page})‎</a>"
1288 . "<a style=\'width: 150px\' name=\"selectall\" class=\'menuItem\' onmouseover=\'hiliteItem(this,\"yes\");\' onmouseout=\'unhiliteItem(this);\' onclick=\'sListView.check_entire_list(document.MassUpdate, \"mass[]\",true,{$row_count});\' href=\'#\'>{$this->local_app_strings['LBL_LISTVIEW_OPTION_ENTIRE']} ({$row_count})‎</a>"
1289 . "<a style=\'width: 150px\' name=\"deselect\" class=\'menuItem\' onmouseover=\'hiliteItem(this,\"yes\");\' onmouseout=\'unhiliteItem(this);\' onclick=\'sListView.clear_all(document.MassUpdate, \"mass[]\", false);\' href=\'#\'>{$this->local_app_strings['LBL_LISTVIEW_NONE']}</a>";
1291 $close_inline_img = SugarThemeRegistry::current()->getImage('close_inline', 'border=0', null, null, ".gif", $app_strings['LBL_CLOSEINLINE']);
1294 function select_dialog() {
1295 var \$dialog = \$('<div></div>')
1296 .html('<a style=\'width: 150px\' name=\"thispage\" class=\'menuItem\' onmouseover=\'hiliteItem(this,\"yes\");\' onmouseout=\'unhiliteItem(this);\' onclick=\'if (document.MassUpdate.select_entire_list.value==1){document.MassUpdate.select_entire_list.value=0;sListView.check_all(document.MassUpdate, \"mass[]\", true, $this->records_per_page)}else {sListView.check_all(document.MassUpdate, \"mass[]\", true)};\' href=\'javascript:void(0)\'>{$this->local_app_strings['LBL_LISTVIEW_OPTION_CURRENT']} ({$this->records_per_page})‎</a>"
1297 . "<a style=\'width: 150px\' name=\"selectall\" class=\'menuItem\' onmouseover=\'hiliteItem(this,\"yes\");\' onmouseout=\'unhiliteItem(this);\' onclick=\'sListView.check_entire_list(document.MassUpdate, \"mass[]\",true,{$row_count});\' href=\'javascript:void(0)\'>{$this->local_app_strings['LBL_LISTVIEW_OPTION_ENTIRE']} ({$row_count})‎</a>"
1298 . "<a style=\'width: 150px\' name=\"deselect\" class=\'menuItem\' onmouseover=\'hiliteItem(this,\"yes\");\' onmouseout=\'unhiliteItem(this);\' onclick=\'sListView.clear_all(document.MassUpdate, \"mass[]\", false);\' href=\'javascript:void(0)\'>{$this->local_app_strings['LBL_LISTVIEW_NONE']}</a>')
1303 \$dialog.dialog('open');
1308 if($this->show_select_menu)
1311 $total = $row_count;
1312 $pageTotal = ($row_count > 0) ? $end_record - $start_record + 1 : 0;
1313 if (!empty($GLOBALS['sugar_config']['disable_count_query']) && $GLOBALS['sugar_config']['disable_count_query'] === true && $total > $pageTotal) {
1314 $this->show_plus = true;
1315 $total = $pageTotal;
1316 $total_label = $total.'+';
1318 $this->show_plus = false;
1319 $total_label = $total;
1321 echo "<input type='hidden' name='show_plus' value='{$this->show_plus}'>\n";
1323 //Bug#52931: Replace with actionMenu
1324 //$select_link = "<a id='select_link' onclick='return select_dialog();' href=\"javascript:void(0)\">".$this->local_app_strings['LBL_LINK_SELECT']." ".SugarThemeRegistry::current()->getImage('MoreDetail', 'border=0', 11, 7, '.png', $app_strings['LBL_MOREDETAIL'])."</a>";
1326 "<input title=\"".$app_strings['LBL_SELECT_ALL_TITLE']."\" type='checkbox' class='checkbox massall' name='massall' id='massall' value='' onclick='sListView.check_all(document.MassUpdate, \"mass[]\", this.checked);' /><a href='javascript: void(0);'></a>",
1327 "<a name='thispage' id='button_select_this_page' class='menuItem' onmouseover='hiliteItem(this,\"yes\");' onmouseout='unhiliteItem(this);' onclick='if (document.MassUpdate.select_entire_list.value==1){document.MassUpdate.select_entire_list.value=0;sListView.check_all(document.MassUpdate, \"mass[]\", true, $pageTotal)}else {sListView.check_all(document.MassUpdate, \"mass[]\", true)};' href='#'>{$app_strings['LBL_LISTVIEW_OPTION_CURRENT']} ({$pageTotal})‎</a>",
1328 "<a name='selectall' id='button_select_all' class='menuItem' onmouseover='hiliteItem(this,\"yes\");' onmouseout='unhiliteItem(this);' onclick='sListView.check_entire_list(document.MassUpdate, \"mass[]\",true,{$total});' href='#'>{$app_strings['LBL_LISTVIEW_OPTION_ENTIRE']} ({$total_label})‎</a>",
1329 "<a name='deselect' id='button_deselect' class='menuItem' onmouseover='hiliteItem(this,\"yes\");' onmouseout='unhiliteItem(this);' onclick='sListView.clear_all(document.MassUpdate, \"mass[]\", false);' href='#'>{$app_strings['LBL_LISTVIEW_NONE']}</a>",
1331 require_once('include/Smarty/plugins/function.sugar_action_menu.php');
1332 $select_link = smarty_function_sugar_action_menu(array(
1333 'class' => 'clickMenu selectmenu',
1334 'id' => 'selectLink',
1335 'buttons' => $menuItems,
1337 ),$this->xTemplate);
1340 $select_link = " ";
1343 $export_link = '<input class="button" type="button" value="'.$this->local_app_strings['LBL_EXPORT'].'" ' .
1344 'onclick="return sListView.send_form(true, \''.$_REQUEST['module'].'\', \'index.php?entryPoint=export\',\''.$this->local_app_strings['LBL_LISTVIEW_NO_SELECTED'].'\')">';
1346 if($this->show_delete_button) {
1347 $delete_link = '<input class="button" type="button" id="delete_button" name="Delete" value="'.$this->local_app_strings['LBL_DELETE_BUTTON_LABEL'].'" onclick="return sListView.send_mass_update(\'selected\',\''.$this->local_app_strings['LBL_LISTVIEW_NO_SELECTED'].'\', 1)">';
1349 $delete_link = ' ';
1352 $admin = new Administration();
1353 $admin->retrieveSettings('system');
1355 $user_merge = $current_user->getPreference('mailmerge_on');
1356 if($user_merge == 'on' && isset($admin->settings['system_mailmerge_on']) && $admin->settings['system_mailmerge_on']) {
1358 function mailmerge_dialog(el) {
1359 var \$dialog = \$('<div></div>')
1360 .html('<a style=\'width: 150px\' class=\'menuItem\' onmouseover=\'hiliteItem(this,\"yes\");\' onmouseout=\'unhiliteItem(this);\' onclick=\'return sListView.send_form(true, \"MailMerge\", \"index.php\", \"{$this->local_app_strings['LBL_LISTVIEW_NO_SELECTED']}\")\' href=\'javascript:void(0)\'>{$this->local_app_strings['LBL_LISTVIEW_OPTION_SELECTED']}</a>"
1361 . "<a style=\'width: 150px\' class=\'menuItem\' onmouseover=\'hiliteItem(this,\"yes\");\' onmouseout=\'unhiliteItem(this);\' href=\'index.php?action=index&module=MailMerge\'>{$this->local_app_strings['LBL_LISTVIEW_OPTION_CURRENT']}</a>"
1362 . "<a style=\'width: 150px\' class=\'menuItem\' onmouseover=\'hiliteItem(this,\"yes\");\' onmouseout=\'unhiliteItem(this);\' href=\'index.php?action=index&module=MailMerge&entire=true\'>{$this->local_app_strings['LBL_LISTVIEW_OPTION_ENTIRE']}</a>')
1365 title: '". $this->local_app_strings['LBL_MAILMERGE']."',
1376 $merge_link = " | <a id='mailmerge_link' onclick='return mailmerge_dialog(this)'; href=\"javascript:void(0)\">".$this->local_app_strings['LBL_MAILMERGE']."</a>";
1378 $merge_link = " ";
1381 $selected_objects_span = " | {$this->local_app_strings['LBL_LISTVIEW_SELECTED_OBJECTS']}<input style='border: 0px; background: transparent; font-size: inherit; color: inherit' type='text' readonly name='selectCount[]' value='" . ((isset($_POST['mass'])) ? count($_POST['mass']): 0) . "' />";
1383 if($_REQUEST['module'] == 'Home' || $this->local_current_module == 'Import'
1384 || $this->show_export_button == false
1385 || (!empty($sugar_config['disable_export']))
1386 || (!empty($sugar_config['admin_export_only'])
1388 is_admin($current_user)
1389 || (ACLController::moduleSupportsACL($_REQUEST['module'])
1390 && ACLAction::getUserAccessLevel($current_user->id,$_REQUEST['module'], 'access') == ACL_ALLOW_ENABLED
1391 && (ACLAction::getUserAccessLevel($current_user->id, $_REQUEST['module'], 'admin') == ACL_ALLOW_ADMIN ||
1392 ACLAction::getUserAccessLevel($current_user->id, $_REQUEST['module'], 'admin') == ACL_ALLOW_ADMIN_DEV)))))
1394 if ($_REQUEST['module'] != 'InboundEmail' && $_REQUEST['module'] != 'EmailMan' && $_REQUEST['module'] != 'iFrames') {
1395 $selected_objects_span = '';
1397 $export_link = " ";
1398 $merge_link = " ";
1399 } elseif($_REQUEST['module'] != "Accounts" && $_REQUEST['module'] != "Cases" && $_REQUEST['module'] != "Contacts" && $_REQUEST['module'] != "Leads" && $_REQUEST['module'] != "Opportunities") {
1400 $merge_link = " ";
1403 if($this->show_paging == true) {
1404 if(!empty($sugar_config['disable_count_query'])) {
1405 if($row_count > $end_record) {
1411 $html_text .= "<tr class='pagination' role='presentation'>\n";
1412 $html_text .= "<td COLSPAN=\"$col_count\" align=\"right\">\n";
1413 //$html_text .= "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\" >$export_link$merge_link$selected_objects_span</td>\n";
1414 //$html_text .= "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\" >";
1415 if ($subpanel_def != null) {
1416 include_once('include/SubPanel/SubPanelTiles.php');
1417 $subpanelTiles = new SubPanelTiles($sugarbean);
1418 $html_text .= "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\" >";
1420 //attempt to get the query to recreate this subpanel
1421 if(!empty($this->response)){
1422 $response =& $this->response;
1424 $response = SugarBean::get_union_related_list($sugarbean,$this->sortby, $this->sort_order, $this->query_where, $current_offset, -1, $this->records_per_page,$this->query_limit,$subpanel_def);
1425 $this->response = $response;
1427 //if query is present, then pass it in as parameter
1428 if (isset($response['query']) && !empty($response['query'])){
1429 $html_text .= $subpanelTiles->get_buttons($subpanel_def, $response['query']);
1431 $html_text .= $subpanelTiles->get_buttons($subpanel_def);
1435 $html_text .= "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"100%\"><tr><td align=\"left\" nowrap>$select_link $export_link $delete_link $selected_objects_span";
1437 $html_text .= "</td>\n<td nowrap align=\"right\">".$start_link." ".$previous_link." <span class='pageNumbers'>(".$start_record." - ".$end_record." ".$this->local_app_strings['LBL_LIST_OF']." ".$row_count.")</span> ".$next_link." ".$end_link."</td></tr></table>\n";
1438 $html_text .= "</td>\n";
1439 $html_text .= "</tr>\n";
1440 $this->xTemplate->assign("PAGINATION",$html_text);
1443 //C.L. - Fix for 23461
1444 if(empty($_REQUEST['action']) || $_REQUEST['action'] != 'Popup') {
1445 $_SESSION['export_where'] = $this->query_where;
1447 $this->xTemplate->parse($xtemplateSection.".list_nav_row");
1449 } // end processListNavigation
1451 function processOrderBy($html_varName) {
1453 if(!isset($this->base_URL)) {
1454 $this->base_URL = $_SERVER['PHP_SELF'];
1456 if(isset($_SERVER['QUERY_STRING'])) {
1457 $this->base_URL = preg_replace("/\&".$this->getSessionVariableName($html_varName,"ORDER_BY")."=[0-9a-zA-Z\_\.]*/","",$this->base_URL .'?'.$_SERVER['QUERY_STRING']);
1458 $this->base_URL = preg_replace("/\&".$this->getSessionVariableName($html_varName,"offset")."=[0-9]*/","",$this->base_URL);
1460 if($_SERVER['REQUEST_METHOD'] == 'POST') {
1461 $this->base_URL .= '?';
1462 if(isset($_REQUEST['action'])) $this->base_URL .= '&action='.$_REQUEST['action'];
1463 if(isset($_REQUEST['record'])) $this->base_URL .= '&record='.$_REQUEST['record'];
1464 if(isset($_REQUEST['module'])) $this->base_URL .= '&module='.$_REQUEST['module'];
1466 $this->base_URL .= "&".$this->getSessionVariableName($html_varName,"offset")."=";
1469 if($this->is_dynamic) {
1470 $this->base_URL.='&to_pdf=true&action=SubPanelViewer&subpanel=' . $this->source_module;
1474 if (isset($this->appendToBaseUrl) && is_array($this->appendToBaseUrl))
1476 foreach ($this->appendToBaseUrl as $key => $value)
1478 $fullRequestString = $key . '=' . $value;
1480 if ($this->base_URL == "/index.php")
1482 $this->base_URL .= "?";
1485 if ($fullRequestString == substr($this->baseURL, '-' . strlen($fullRequestString)))
1487 $this->base_URL = preg_replace("/&" . $key . "\=.*/", "", $this->base_URL);
1490 $this->base_URL = preg_replace("/&" . $key . "\=.*?&/", "&", $this->base_URL);
1492 $this->base_URL .= "&";
1496 $this->base_URL .= "{$key}={$value}";
1502 $sort_URL_base = $this->base_URL. "&".$this->getSessionVariableName($html_varName,"ORDER_BY")."=";
1504 if($sort_URL_base !== "")
1506 $this->xTemplate->assign("ORDER_BY", $sort_URL_base);
1507 return $sort_URL_base;
1514 function getAdditionalHeader() {
1521 * @param unknown $data
1522 * @param unknown $xTemplateSection
1523 * @param unknown $html_varName
1524 * @desc INTERNAL FUNCTION handles the rows
1525 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1526 * All Rights Reserved.
1527 * Contributor(s): ______________________________________..
1529 function processListRows($data, $xtemplateSection, $html_varName)
1534 global $app_strings, $sugar_version, $sugar_config;
1535 global $currentModule;
1537 $this->xTemplate->assign('BG_HILITE', $hilite_bg);
1538 $this->xTemplate->assign('CHECKALL', SugarThemeRegistry::current()->getImage('blank', '', 1, 1, ".gif", ''));
1539 //$this->xTemplate->assign("BG_CLICK", $click_bg);
1545 $offset = $this->getOffset($html_varName);
1546 $timeStamp = $this->unique_id();
1547 $_SESSION[$html_varName."_FROM_LIST_VIEW"] = $timeStamp;
1549 $associated_row_data = array();
1552 $mergeList = array();
1554 //todo what is this? It is using an array as a boolean
1555 while(list($aVal, $aItem) = each($data))
1557 if(isset($this->data_array)) {
1558 $fields = $this->data_array;
1560 $aItem->check_date_relationships_load();
1561 $fields = $aItem->get_list_view_data();
1564 if(is_object($aItem)) { // cn: bug 5349
1565 //add item id to merge list, if the button is clicked
1566 $mergeList[] = $aItem->id;
1567 if(empty($module)) {
1568 $module = $aItem->module_dir;
1571 //ADD OFFSET TO ARRAY
1573 $fields['OFFSET'] = ($offset + $count + 1);
1575 $fields['STAMP'] = $timeStamp;
1576 if($this->shouldProcess) {
1579 if(!isset($this->data_array)) {
1580 $prerow .= "<input onclick='sListView.check_item(this, document.MassUpdate)' type='checkbox' class='checkbox' name='mass[]' value='". $fields['ID']. "'>";
1582 $this->xTemplate->assign('PREROW', $prerow);
1584 $this->xTemplate->assign('CHECKALL', "<input type='checkbox' class='checkbox' title='".$GLOBALS['app_strings']['LBL_SELECT_ALL_TITLE']."' name='massall' id='massall' value='' onclick='sListView.check_all(document.MassUpdate, \"mass[]\", this.checked)'>");
1586 if(!isset($this->data_array)) {
1587 $tag = $aItem->listviewACLHelper();
1588 $this->xTemplate->assign('TAG',$tag) ;
1593 $ROW_COLOR = 'oddListRow';
1594 $BG_COLOR = $odd_bg;
1598 $ROW_COLOR = 'evenListRow';
1599 $BG_COLOR = $even_bg;
1603 $this->xTemplate->assign('ROW_COLOR', $ROW_COLOR);
1604 $this->xTemplate->assign('BG_COLOR', $BG_COLOR);
1606 if(isset($this->data_array))
1608 $this->xTemplate->assign('KEY', $aVal);
1609 $this->xTemplate->assign('VALUE', $aItem);
1610 $this->xTemplate->assign('INDEX', $count);
1615 //AED -- some modules do not have their additionalDetails.php established. Add a check to ensure require_once does not fail
1617 if($this->_additionalDetails && $aItem->ACLAccess('DetailView') && (file_exists('modules/' . $aItem->module_dir . '/metadata/additionalDetails.php') || file_exists('custom/modules/' . $aItem->module_dir . '/metadata/additionalDetails.php'))) {
1619 $additionalDetailsFile = 'modules/' . $aItem->module_dir . '/metadata/additionalDetails.php';
1620 if(file_exists('custom/modules/' . $aItem->module_dir . '/metadata/additionalDetails.php')){
1621 $additionalDetailsFile = 'custom/modules/' . $aItem->module_dir . '/metadata/additionalDetails.php';
1624 require_once($additionalDetailsFile);
1625 $ad_function = (empty($this->additionalDetailsFunction) ? 'additionalDetails' : $this->additionalDetailsFunction) . $aItem->object_name;
1626 $results = $ad_function($fields);
1627 $results['string'] = str_replace(array("'", "'"), '\'', $results['string']); // no xss!
1629 if(trim($results['string']) == '') $results['string'] = $app_strings['LBL_NONE'];
1630 $fields[$results['fieldToAddTo']] = $fields[$results['fieldToAddTo']].'</a>';
1633 if($aItem->ACLAccess('Delete')) {
1634 $delete = '<a class="listViewTdToolsS1" onclick="return confirm(\''.$this->local_app_strings['NTC_DELETE_CONFIRMATION'].'\')" href="'.'index.php?action=Delete&module='.$aItem->module_dir.'&record='.$fields['ID'].'&return_module='.$aItem->module_dir.'&return_action=index&return_id=">'.$this->local_app_strings['LBL_DELETE_INLINE'].'</a>';
1635 require_once('include/Smarty/plugins/function.sugar_action_menu.php');
1636 $fields['DELETE_BUTTON'] = smarty_function_sugar_action_menu(array(
1637 'id' => $aItem->module_dir.'_'.$fields['ID'].'_create_button',
1638 'buttons' => array($delete),
1643 $this->xTemplate->assign($html_varName, $fields);
1644 $aItem->setupCustomFields($aItem->module_dir);
1645 $aItem->custom_fields->populateAllXTPL($this->xTemplate, 'detail', $html_varName, $fields);
1647 if(!isset($this->data_array) && $aItem->ACLAccess('DetailView')) {
1650 if(isset($this->data_array)) {
1653 if(!isset($this->data_array)) {
1654 $aItem->list_view_parse_additional_sections($this->xTemplate, $xtemplateSection);
1656 if($this->xTemplate->exists($xtemplateSection.'.row.pro')) {
1657 $this->xTemplate->parse($xtemplateSection.'.row.pro');
1660 $this->xTemplate->parse($xtemplateSection . '.row');
1662 if(isset($fields['ID'])) {
1663 $associated_row_data[$fields['ID']] = $fields;
1664 // Bug 38908: cleanup data for JS to avoid having shuffled around
1665 foreach($fields as $key => $value) {
1666 if($value == ' ') {
1667 $associated_row_data[$fields['ID']][$key] = '';
1673 $_SESSION['MAILMERGE_RECORDS'] = $mergeList;
1674 $_SESSION['MAILMERGE_MODULE_FROM_LISTVIEW'] = $module;
1675 if(empty($_REQUEST['action']) || $_REQUEST['action'] != 'Popup') {
1676 $_SESSION['MAILMERGE_MODULE'] = $module;
1679 if($this->process_for_popups)
1681 $json = getJSONobj();
1682 $is_show_fullname = showFullName() ? 1 : 0;
1683 $associated_javascript_data = '<script type="text/javascript">' . "\n"
1684 //. '<!-- // associated javascript data generated by ListView' . "\n"
1685 . 'var associated_javascript_data = '
1686 . $json->encode($associated_row_data) . ";\n"
1688 . 'var is_show_fullname = '
1689 . $is_show_fullname . ";\n"
1691 $this->xTemplate->assign('ASSOCIATED_JAVASCRIPT_DATA', $associated_javascript_data);
1694 $this->xTemplate->parse($xtemplateSection);
1698 function getLayoutManager()
1700 require_once('include/generic/LayoutManager.php');
1701 if($this->layout_manager == null)
1703 $this->layout_manager = new LayoutManager();
1705 return $this->layout_manager;
1709 function process_dynamic_listview_header($source_module, $subpanel_def, $html_var = 'CELL')
1713 $layout_manager = $this->getLayoutManager();
1714 $layout_manager->setAttribute('order_by_link',$this->processOrderBy($html_var));
1715 $layout_manager->setAttribute('context','HeaderCell');
1716 $layout_manager->setAttribute('image_path',$this->local_image_path);
1717 $layout_manager->setAttribute('html_varName',$html_var);
1718 $layout_manager->setAttribute('module_name', $source_module);
1719 list($orderBy,$desc) = $this->getOrderByInfo($html_var);
1721 if($orderBy == 'amount*1')
1726 foreach($subpanel_def->get_list_fields() as $column_name=>$widget_args)
1728 $usage = empty($widget_args['usage']) ? '' : $widget_args['usage'];
1729 if($usage != 'query_only' || !empty($widget_args['force_query_only_display']))
1733 if($orderBy == $column_name || (isset($widget_args['sort_by']) && str_replace('.','_',$widget_args['sort_by']) == $orderBy))
1735 $imgArrow = "_down";
1736 if($this->sort_order == 'asc') {
1741 if (!preg_match("/_button/i", $column_name)) {
1742 $widget_args['name']=$column_name;
1743 $widget_args['sort'] = $imgArrow;
1744 $widget_args['start_link_wrapper'] = $this->start_link_wrapper;
1745 $widget_args['end_link_wrapper'] = $this->end_link_wrapper;
1746 $widget_args['subpanel_module'] = $this->subpanel_module;
1748 $widget_contents = $layout_manager->widgetDisplay($widget_args);
1749 $cell_width = empty($widget_args['width']) ? '' : $widget_args['width'];
1750 $this->xTemplate->assign('HEADER_CELL', $widget_contents);
1752 if(!isset($count))$count = 0; else $count++;
1753 $this->xTemplate->assign('CELL_COUNT', $count);
1754 $this->xTemplate->assign('CELL_WIDTH', $cell_width);
1755 $this->xTemplate->parse('dyn_list_view.header_cell');
1763 $this->xTemplate->assign('HEADER_CELL', " ");
1764 $this->xTemplate->assign('CELL_COUNT', $count);
1765 $this->xTemplate->assign('CELL_WIDTH', $cell_width);
1766 $this->xTemplate->parse('dyn_list_view.header_cell');
1774 * @param unknown $seed
1775 * @param unknown $xTemplateSection
1776 * @param unknown $html_varName
1777 * @desc PUBLIC FUNCTION Handles List Views using seeds that extend SugarBean
1778 $XTemplateSection is the section in the XTemplate file that should be parsed usually main
1779 $html_VarName is the variable name used in the XTemplateFile e.g. TASK
1780 $seed is a seed there are two types of seeds one is a subclass of SugarBean, the other is a list usually created from a sugar bean using get_list
1781 if no XTemplate is set it will create a new XTemplate
1782 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc..
1783 * All Rights Reserved..
1784 * Contributor(s): ______________________________________..
1787 function processListViewTwo($seed, $xTemplateSection, $html_varName) {
1788 global $current_user;
1789 if(!isset($this->xTemplate)) {
1790 $this->createXTemplate();
1793 $isSugarBean = is_subclass_of($seed, "SugarBean");
1797 $list = $this->processSugarBean($xTemplateSection, $html_varName, $seed);
1802 if (is_object($seed) && isset($seed->object_name) && $seed->object_name == 'WorkFlow') {
1804 $access = get_workflow_admin_modules_for_user($current_user);
1805 for ($i = 0; $i < count($list); $i++) {
1806 if(!empty($access[$list[$i]->base_module])){
1813 if($this->is_dynamic) {
1814 $this->processHeaderDynamic($xTemplateSection,$html_varName);
1815 $this->processListRows($list,$xTemplateSection, $html_varName);
1817 $this->processSortArrows($html_varName);
1820 $seed->parse_additional_headers($this->xTemplate, $xTemplateSection);
1822 $this->xTemplateAssign('CHECKALL', SugarThemeRegistry::current()->getImage('blank', '', 1, 1, ".gif", ''));
1824 // Process the order by before processing the pro_nav. The pro_nav requires the order by values to be set
1825 $this->processOrderBy($html_varName);
1828 $this->processListRows($list,$xTemplateSection, $html_varName);
1831 if($this->display_header_and_footer) {
1832 $this->getAdditionalHeader();
1833 if(!empty($this->header_title)) {
1834 echo get_form_header($this->header_title, $this->header_text, false);
1838 $this->xTemplate->out($xTemplateSection);
1840 if(isset($_SESSION['validation'])) {
1841 print base64_decode('PGEgaHJlZj0naHR0cDovL3d3dy5zdWdhcmNybS5jb20nPlBPV0VSRUQmbmJzcDtCWSZuYnNwO1NVR0FSQ1JNPC9hPg==');
1845 function getArrowStart() {
1846 $imgFileParts = pathinfo(SugarThemeRegistry::current()->getImageURL("arrow.gif"));
1848 return " <!--not_in_theme!--><img border='0' src='".$imgFileParts['dirname']."/".$imgFileParts['filename']."";
1851 function getArrowUpDownStart($upDown) {
1852 $ext = ( SugarThemeRegistry::current()->pngSupport ? "png" : "gif" );
1854 if (!isset($upDown) || empty($upDown)) {
1857 return " <img border='0' src='".SugarThemeRegistry::current()->getImageURL("arrow{$upDown}.{$ext}")."' ";
1860 function getArrowEnd() {
1861 $imgFileParts = pathinfo(SugarThemeRegistry::current()->getImageURL("arrow.gif"));
1863 list($width,$height) = ListView::getArrowImageSize();
1865 return '.'.$imgFileParts['extension']."' width='$width' height='$height' align='absmiddle' alt=".translate('LBL_SORT').">";
1868 function getArrowUpDownEnd($upDown) {
1869 if (!isset($upDown) || empty($upDown)) {
1872 $imgFileParts = pathinfo(SugarThemeRegistry::current()->getImageURL("arrow{$upDown}.gif"));
1874 list($width,$height) = ListView::getArrowUpDownImageSize($upDown);
1876 //get the right alt tag for the sort
1877 $sortStr = translate('LBL_ALT_SORT');
1878 if($upDown == '_down'){
1879 $sortStr = translate('LBL_ALT_SORT_DESC');
1880 }elseif($upDown == '_up'){
1881 $sortStr = translate('LBL_ALT_SORT_ASC');
1883 return " width='$width' height='$height' align='absmiddle' alt='$sortStr'>";
1886 function getArrowImageSize() {
1887 // jbasicChartDashletsExpColust get the non-sort image's size.. the up and down have be the same.
1888 $image = SugarThemeRegistry::current()->getImageURL("arrow.gif",false);
1890 $cache_key = 'arrow_size.'.$image;
1893 $result = sugar_cache_retrieve($cache_key);
1897 // No cache hit. Calculate the value and return.
1898 $result = getimagesize($image);
1899 sugar_cache_put($cache_key, $result);
1903 function getArrowUpDownImageSize($upDown) {
1904 // just get the non-sort image's size.. the up and down have be the same.
1905 $image = SugarThemeRegistry::current()->getImageURL("arrow{$upDown}.gif",false);
1907 $cache_key = 'arrowupdown_size.'.$image;
1910 $result = sugar_cache_retrieve($cache_key);
1914 // No cache hit. Calculate the value and return.
1915 $result = getimagesize($image);
1916 sugar_cache_put($cache_key, $result);
1920 function getOrderByInfo($html_varName)
1922 $orderBy = $this->getSessionVariable($html_varName, "OBL");
1923 $desc = $this->getSessionVariable($html_varName, $orderBy.'S');
1924 $orderBy = str_replace('.', '_', $orderBy);
1925 return array($orderBy,$desc);
1928 function processSortArrows($html_varName)
1931 $this->xTemplateAssign("arrow_start", $this->getArrowStart());
1933 list($orderBy,$desc) = $this->getOrderByInfo($html_varName);
1937 $imgArrow = "_down";
1940 * @deprecated only used by legacy opportunites listview, nothing current. Leaving for BC
1942 if($orderBy == 'amount')
1944 $this->xTemplateAssign('amount_arrow', $imgArrow);
1946 else if($orderBy == 'amount_usdollar')
1948 $this->xTemplateAssign('amount_usdollar_arrow', $imgArrow);
1952 $this->xTemplateAssign($orderBy.'_arrow', $imgArrow);
1955 $this->xTemplateAssign('arrow_end', $this->getArrowEnd());
1958 // this is where translation happens for dynamic list views
1959 function loadListFieldDefs(&$subpanel_fields,&$child_focus)
1961 $this->list_field_defs = $subpanel_fields;
1963 for($i=0;$i < count($this->list_field_defs);$i++)
1965 $list_field = $this->list_field_defs[$i];
1968 if(!empty($list_field['vname']))
1970 $key = $list_field['vname'];
1971 } else if(isset($list_field['name']) && isset($child_focus->field_defs[$list_field['name']]))
1973 $field_def = $child_focus->field_defs[$list_field['name']];
1974 $key = $field_def['vname'];
1978 $list_field['label'] = translate($key,$child_focus->module_dir);
1979 $this->list_field_defs[$i]['label'] = preg_replace('/:$/','',$list_field['label']);
1983 $this->list_field_defs[$i]['label'] =' ';
1988 function unique_id() {
1989 return sugar_microtime();
1992 /**INTERNAL FUNCTION sets a session variable keeping it local to the listview
1993 not the current_module
1994 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
1995 * All Rights Reserved.
1996 * Contributor(s): ______________________________________.
1998 function setLocalSessionVariable($localVarName,$varName, $value) {
1999 $_SESSION[$localVarName."_".$varName] = $value;
2002 /**INTERNAL FUNCTION returns a session variable that is local to the listview,
2003 not the current_module
2004 * Portions created by SugarCRM are Copyright (C) SugarCRM, Inc.
2005 * All Rights Reserved.
2006 * Contributor(s): ______________________________________.
2008 function getLocalSessionVariable($localVarName,$varName) {
2009 if(isset($_SESSION[$localVarName."_".$varName])) {
2010 return $_SESSION[$localVarName."_".$varName];
2017 /* Set to true if you want Additional Details to appear in the listview
2019 function setAdditionalDetails($value = true, $function = '') {
2020 if(!empty($function)) $this->additionalDetailsFunction = $function;
2021 $this->_additionalDetails = $value;