]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/MVC/View/SugarView.php
Release 6.1.4
[Github/sugarcrm.git] / include / MVC / View / SugarView.php
1 <?php
2 /*********************************************************************************
3  * SugarCRM is a customer relationship management program developed by
4  * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
5  * 
6  * This program is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU Affero General Public License version 3 as published by the
8  * Free Software Foundation with the addition of the following permission added
9  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
10  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
11  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
12  * 
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
16  * details.
17  * 
18  * You should have received a copy of the GNU Affero General Public License along with
19  * this program; if not, see http://www.gnu.org/licenses or write to the Free
20  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  * 02110-1301 USA.
22  * 
23  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
24  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
25  * 
26  * The interactive user interfaces in modified source and object code versions
27  * of this program must display Appropriate Legal Notices, as required under
28  * Section 5 of the GNU Affero General Public License version 3.
29  * 
30  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
31  * these Appropriate Legal Notices must retain the display of the "Powered by
32  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
33  * technical reasons, the Appropriate Legal Notices must display the words
34  * "Powered by SugarCRM".
35  ********************************************************************************/
36
37 class SugarView
38 {
39     /**
40      * This array is meant to hold an objects/data that we would like to pass between
41      * the controller and the view.  The bean will automatically be set for us, but this
42      * is meant to hold anything else.
43      */
44     var $view_object_map = array();
45     /**
46      * The name of the current module.
47      */
48         var $module = '';
49     /**
50      * The name of the current action.
51      */
52     var $action = '';
53     /**
54      */
55     var $bean = null;
56     /**
57      * Sugar_Smarty. This is useful if you have a view and a subview you can
58      * share the same smarty object.
59      */
60     var $ss = null;
61     /**
62      * Any errors that occured this can either be set by the view or the controller or the model
63      */
64     var $errors = array();
65     /**
66      * Options for what UI elements to hide/show/
67      */
68     var $options = array('show_header' => true, 'show_title' => true, 'show_subpanels' => false, 'show_search' => true, 'show_footer' => true, 'show_javascript' => true, 'view_print' => false,);
69     var $type = null;
70     var $responseTime;
71     var $fileResources;
72     
73     /**
74      * Constructor which will peform the setup.
75      */
76     public function SugarView(
77         $bean = null, 
78         $view_object_map = array()
79         )
80     {
81     }
82
83     public function init(
84         $bean = null, 
85         $view_object_map = array()
86         )
87     {
88         $this->bean = &$bean;
89         $this->view_object_map = $view_object_map;
90         $this->action = $GLOBALS['action'];
91         $this->module = $GLOBALS['module'];
92         $this->_initSmarty();
93     }
94     
95     protected function _initSmarty()
96     {
97         $this->ss = new Sugar_Smarty();
98         $this->ss->assign('MOD', $GLOBALS['mod_strings']);
99         $this->ss->assign('APP', $GLOBALS['app_strings']);
100     }
101
102     /**
103      * This method will be called from the controller and is not meant to be overridden.
104      */
105     public function process()
106     {
107         LogicHook::initialize();
108         $this->_checkModule();     
109         
110         //trackView has to be here in order to track for breadcrumbs
111         $this->_trackView();
112         
113         if ($this->_getOption('show_header')) {
114             $this->displayHeader();
115         } else {
116             $this->renderJavascript();  
117         }
118         
119         $this->_buildModuleList();
120         $this->preDisplay();
121         $this->displayErrors();
122         $this->display();
123         $GLOBALS['logic_hook']->call_custom_logic('', 'after_ui_frame');
124         if ($this->_getOption('show_subpanels')) $this->_displaySubPanels();
125         if ($this->action === 'Login') {
126             //this is needed for a faster loading login page ie won't render unless the tables are closed
127             ob_flush();                                   
128         }
129         if ($this->_getOption('show_footer')) $this->displayFooter();
130         $GLOBALS['logic_hook']->call_custom_logic('', 'after_ui_footer');
131         //Do not track if there is no module or if module is not a String
132         $this->_track();
133     }
134
135     /**
136      * This method will display the errors on the page.
137      */
138     public function displayErrors()
139     {
140         foreach($this->errors as $error) {
141             echo '<span class="error">' . $error . '</span><br>';
142         }
143     }
144
145     /**
146      * [OVERRIDE] - This method is meant to overidden in a subclass. The purpose of this method is
147      * to allow a view to do some preprocessing before the display method is called. This becomes
148      * useful when you have a view defined at the application level and then within a module
149      * have a sub-view that extends from this application level view.  The application level
150      * view can do the setup in preDisplay() that is common to itself and any subviews
151      * and then the subview can just override display(). If it so desires, can also override
152      * preDisplay().
153      */
154     public function preDisplay()
155     {
156     }
157
158     /**
159      * [OVERRIDE] - This method is meant to overidden in a subclass. This method
160      * will handle the actual display logic of the view.
161      */
162     public function display()
163     {
164     }
165
166
167     /**
168      * trackView
169      */
170     protected function _trackView() 
171     {
172         $action = strtolower($this->action);
173         //Skip save, tracked in SugarBean instead
174         if($action == 'save') {
175            return;
176         }
177
178        
179         $trackerManager = TrackerManager::getInstance();
180         $timeStamp = gmdate($GLOBALS['timedate']->get_db_date_time_format());
181         if($monitor = $trackerManager->getMonitor('tracker')){ 
182                 $monitor->setValue('action', $action);
183                 $monitor->setValue('user_id', $GLOBALS['current_user']->id);
184                 $monitor->setValue('module_name', $this->module);
185                 $monitor->setValue('date_modified', $timeStamp);
186                 $monitor->setValue('visible', (($monitor->action == 'detailview') || ($monitor->action == 'editview')
187                                                                                 ) ? 1 : 0);
188         
189                 if (!empty($this->bean->id)) {
190                     $monitor->setValue('item_id', $this->bean->id);
191                     $monitor->setValue('item_summary', $this->bean->get_summary_text());
192                 }
193         
194                 //If visible is true, but there is no bean, do not track (invalid/unauthorized reference)
195                 //Also, do not track save actions where there is no bean id
196                 if($monitor->visible && empty($this->bean->id)) {
197                    $trackerManager->unsetMonitor($monitor);
198                    return;
199                 }
200                 $trackerManager->saveMonitor($monitor, true, true);
201                 }
202     }
203
204
205     /**
206      * Displays the header on section of the page; basically everything before the content
207      */
208     public function displayHeader()
209     {
210         global $theme;
211         global $max_tabs;
212         global $app_strings;
213         global $current_user;
214         global $sugar_config;
215         global $app_list_strings;
216         global $mod_strings;
217         global $current_language;
218         
219         $GLOBALS['app']->headerDisplayed = true;
220         
221         $themeObject = SugarThemeRegistry::current();
222         $theme = $themeObject->__toString();
223         
224         $ss = new Sugar_Smarty();
225         $ss->assign("APP", $app_strings);
226         $ss->assign("THEME", $theme);
227         $ss->assign("THEME_IE6COMPAT", $themeObject->ie6compat ? 'true':'false');
228         $ss->assign("MODULE_NAME", $this->module);
229         
230         // get browser title
231         $ss->assign("SYSTEM_NAME", $this->getBrowserTitle());
232         
233         // get css
234         $css = $themeObject->getCSS();
235         if ($this->_getOption('view_print')) {
236             $css .= '<link rel="stylesheet" type="text/css" href="'.$themeObject->getCSSURL('print.css').'" media="all" />';
237         }
238         $ss->assign("SUGAR_CSS",$css);
239         
240         // get javascript
241         ob_start();
242         $this->renderJavascript();
243
244         $ss->assign("SUGAR_JS",ob_get_contents().$themeObject->getJS());
245         ob_end_clean();
246         
247         // get favicon
248         if(isset($GLOBALS['sugar_config']['default_module_favicon'])) 
249             $module_favicon = $GLOBALS['sugar_config']['default_module_favicon'];
250         else
251             $module_favicon = false;
252         
253         $favicon = '';
254         if ( $module_favicon ) 
255             $favicon = $themeObject->getImageURL($this->module.'.gif',false);
256         if ( !sugar_is_file($favicon) || !$module_favicon )
257             $favicon = $themeObject->getImageURL('sugar_icon.ico',false);
258         $ss->assign('FAVICON_URL',getJSPath($favicon));
259         
260         // build the shortcut menu
261         $shortcut_menu = array();
262         foreach ( $this->getMenu() as $key => $menu_item )
263             $shortcut_menu[$key] = array(
264                 "URL"         => $menu_item[0],
265                 "LABEL"       => $menu_item[1],
266                 "MODULE_NAME" => $menu_item[2],
267                 "IMAGE"       => $themeObject
268                     ->getImage($menu_item[2],"alt='".$menu_item[1]."'  border='0' align='absmiddle'"),
269                 );
270         $ss->assign("SHORTCUT_MENU",$shortcut_menu);
271         
272         // handle rtl text direction
273         if(isset($_REQUEST['RTL']) && $_REQUEST['RTL'] == 'RTL'){
274             $_SESSION['RTL'] = true;
275         }
276         if(isset($_REQUEST['LTR']) && $_REQUEST['LTR'] == 'LTR'){
277             unset($_SESSION['RTL']);
278         }
279         if(isset($_SESSION['RTL']) && $_SESSION['RTL']){
280             $ss->assign("DIR", 'dir="RTL"');
281         }
282         
283         // handle resizing of the company logo correctly on the fly
284         $companyLogoURL = $themeObject->getImageURL('company_logo.png');
285                 $companyLogoURL_arr = explode('?', $companyLogoURL);
286                 $companyLogoURL = $companyLogoURL_arr[0];               
287         
288         $company_logo_attributes = sugar_cache_retrieve('company_logo_attributes');
289         if(!empty($company_logo_attributes)) {
290             $ss->assign("COMPANY_LOGO_MD5", $company_logo_attributes[0]);
291             $ss->assign("COMPANY_LOGO_WIDTH", $company_logo_attributes[1]);
292             $ss->assign("COMPANY_LOGO_HEIGHT", $company_logo_attributes[2]);
293         }
294         else {
295             // Always need to md5 the file
296             $ss->assign("COMPANY_LOGO_MD5", md5_file($companyLogoURL));
297
298             list($width,$height) = getimagesize($companyLogoURL);
299             if ( $width > 212 || $height > 40 ) {
300                 $resizePctWidth  = ($width - 212)/212;
301                 $resizePctHeight = ($height - 40)/40;
302                 if ( $resizePctWidth > $resizePctHeight )
303                     $resizeAmount = $width / 212;
304                 else
305                     $resizeAmount = $height / 40;
306                 $ss->assign("COMPANY_LOGO_WIDTH", round($width * (1/$resizeAmount)));
307                 $ss->assign("COMPANY_LOGO_HEIGHT", round($height * (1/$resizeAmount)));
308             }
309             else {
310                 $ss->assign("COMPANY_LOGO_WIDTH", $width);
311                 $ss->assign("COMPANY_LOGO_HEIGHT", $height);
312             }
313
314             // Let's cache the results
315             sugar_cache_put('company_logo_attributes',
316                             array(
317                                 $ss->get_template_vars("COMPANY_LOGO_MD5"),
318                                 $ss->get_template_vars("COMPANY_LOGO_WIDTH"),
319                                 $ss->get_template_vars("COMPANY_LOGO_HEIGHT")
320                                 )
321             );
322         }
323         $ss->assign("COMPANY_LOGO_URL",getJSPath($companyLogoURL)."&logo_md5=".$ss->get_template_vars("COMPANY_LOGO_MD5"));
324         
325         // get the global links
326         $gcls = array();
327         $global_control_links = array();
328         require("include/globalControlLinks.php");
329         
330         foreach($global_control_links as $key => $value) {
331             if ($key == 'users')  {   //represents logout link.
332                 $ss->assign("LOGOUT_LINK", $value['linkinfo'][key($value['linkinfo'])]);  
333                 $ss->assign("LOGOUT_LABEL", key($value['linkinfo']));//key value for first element.
334                 continue;
335             }
336             
337             foreach ($value as $linkattribute => $attributevalue) {
338                 // get the main link info
339                 if ( $linkattribute == 'linkinfo' ) {
340                     $gcls[$key] = array(
341                         "LABEL" => key($attributevalue),
342                         "URL"   => current($attributevalue),
343                         "SUBMENU" => array(),
344                         );
345                    if(substr($gcls[$key]["URL"], 0, 11) == "javascript:") {
346                        $gcls[$key]["ONCLICK"] = substr($gcls[$key]["URL"],11);
347                        $gcls[$key]["URL"] = "#";
348                    }
349                 }
350                 // and now the sublinks
351                 if ( $linkattribute == 'submenu' && is_array($attributevalue) ) {
352                     foreach ($attributevalue as $submenulinkkey => $submenulinkinfo)
353                         $gcls[$key]['SUBMENU'][$submenulinkkey] = array(
354                             "LABEL" => key($submenulinkinfo),
355                             "URL"   => current($submenulinkinfo),
356                         );
357                        if(substr($gcls[$key]['SUBMENU'][$submenulinkkey]["URL"], 0, 11) == "javascript:") {
358                            $gcls[$key]['SUBMENU'][$submenulinkkey]["ONCLICK"] = substr($gcls[$key]['SUBMENU'][$submenulinkkey]["URL"],11);
359                            $gcls[$key]['SUBMENU'][$submenulinkkey]["URL"] = "#";
360                        }
361                 }
362             }
363         }
364         $ss->assign("GCLS",$gcls);
365         
366         $ss->assign("SEARCH", isset($_REQUEST['query_string']) ? $_REQUEST['query_string'] : '');
367         
368         if ($this->action == "EditView" || $this->action == "Login") 
369             $ss->assign("ONLOAD", 'onload="set_focus()"');
370
371         $ss->assign("AUTHENTICATED",isset($_SESSION["authenticated_user_id"]));
372         
373         // get other things needed for page style popup
374         if (isset($_SESSION["authenticated_user_id"])) {
375             // get the current user name and id
376             $ss->assign("CURRENT_USER", $current_user->full_name == '' || !showFullName()
377                 ? $current_user->user_name : $current_user->full_name );
378             $ss->assign("CURRENT_USER_ID", $current_user->id);
379             
380             // get the last viewed records
381             $tracker = new Tracker();
382             $history = $tracker->get_recently_viewed($current_user->id);
383             foreach ( $history as $key => $row ) {
384                 $history[$key]['item_summary_short'] = getTrackerSubstring($row['item_summary']);
385                 $history[$key]['image'] = SugarThemeRegistry::current()
386                     ->getImage($row['module_name'],'border="0" align="absmiddle" alt="'.$row['item_summary'].'"');
387             }
388             $ss->assign("recentRecords",$history);
389         }
390         
391                 $bakModStrings = $mod_strings;
392         if (isset($_SESSION["authenticated_user_id"]) ) {
393             // get the module list
394             $moduleTopMenu = array();
395             
396             $max_tabs = $current_user->getPreference('max_tabs');
397             // Attempt to correct if max tabs count is waaay too high.
398             if ( !isset($max_tabs) || $max_tabs <= 0 || $max_tabs > 10 ) {
399                 $max_tabs = $GLOBALS['sugar_config']['default_max_tabs'];
400                 $current_user->setPreference('max_tabs', $max_tabs, 0, 'global');
401             }
402             
403             $moduleTab = $this->_getModuleTab();
404             $ss->assign('MODULE_TAB',$moduleTab);
405             
406
407             // See if they are using grouped tabs or not (removed in 6.0, returned in 6.1)
408             $user_navigation_paradigm = $current_user->getPreference('navigation_paradigm');
409             if ( !isset($user_navigation_paradigm) ) {
410                 $user_navigation_paradigm = $GLOBALS['sugar_config']['default_navigation_paradigm'];
411             }
412
413
414             // Get the full module list for later use
415             foreach ( query_module_access_list($current_user) as $module ) {
416                 // Bug 25948 - Check for the module being in the moduleList
417                 if ( isset($app_list_strings['moduleList'][$module]) ) {
418                     $fullModuleList[$module] = $app_list_strings['moduleList'][$module];
419                 }
420             }
421
422
423             if(!should_hide_iframes()) {
424                 $iFrame = new iFrame();
425                 $frames = $iFrame->lookup_frames('tab');
426                 foreach($frames as $key => $values){
427                         $fullModuleList[$key] = $values;                    
428                 }
429             } 
430             elseif (isset($fullModuleList['iFrames'])) {
431                 unset($fullModuleList['iFrames']);
432             }
433
434             if ( $user_navigation_paradigm == 'gm' && isset($themeObject->group_tabs) && $themeObject->group_tabs) {
435                 // We are using grouped tabs
436                 require_once('include/GroupedTabs/GroupedTabStructure.php');
437                 $groupedTabsClass = new GroupedTabStructure();               
438                 $modules = query_module_access_list($current_user);
439                 //handle with submoremodules
440                 $max_tabs = $current_user->getPreference('max_tabs');
441                 // If the max_tabs isn't set incorrectly, set it within the range, to the default max sub tabs size
442                 if ( !isset($max_tabs) || $max_tabs <= 0 || $max_tabs > 10){
443                     // We have a default value. Use it
444                     if(isset($GLOBALS['sugar_config']['default_max_subtabs'])){
445                         // As of 6.1, we shouldn't have a max subtabs higher than 10.
446                         // If it's larger, bring it down to the max and save it in the config override
447                         if($GLOBALS['sugar_config']['default_max_subtabs'] > 10){
448                             require_once('modules/Configurator/Configurator.php');
449                             $configurator = new Configurator();
450                             $configurator->config['default_max_subtabs'] = '10';
451                             $configurator->handleOverride();
452                             $configurator->clearCache();
453                         }
454                         $max_tabs = $GLOBALS['sugar_config']['default_max_subtabs'];
455                     }
456                     else{
457                         $max_tabs = 8;
458                     }
459                 }
460                 
461                                 $subMoreModules = false;
462                                 $groupTabs = $groupedTabsClass->get_tab_structure(get_val_array($modules));
463                 // We need to put this here, so the "All" group is valid for the user's preference.
464                 $groupTabs[$app_strings['LBL_TABGROUP_ALL']]['modules'] = $fullModuleList;
465
466
467                 // Setup the default group tab.
468                 $allGroup = $app_strings['LBL_TABGROUP_ALL'];
469                 $ss->assign('currentGroupTab',$allGroup);
470                 $currentGroupTab = $allGroup;
471                 $usersGroup = $current_user->getPreference('theme_current_group');
472                 // Figure out which tab they currently have selected (stored as a user preference)
473                 if ( !empty($usersGroup) && isset($groupTabs[$usersGroup]) ) {
474                     $currentGroupTab = $usersGroup;
475                 } else {
476                     $current_user->setPreference('theme_current_group',$currentGroupTab);
477                 }
478
479                 $ss->assign('currentGroupTab',$currentGroupTab);
480                 $usingGroupTabs = true;
481                 
482             } else {
483                 // Setup the default group tab.
484                 $ss->assign('currentGroupTab',$app_strings['LBL_TABGROUP_ALL']);
485
486                 $usingGroupTabs = false;
487
488                 $groupTabs[$app_strings['LBL_TABGROUP_ALL']]['modules'] = $fullModuleList;
489
490             }
491             
492
493             $topTabList = array();
494             
495             // Now time to go through each of the tab sets and fix them up.
496             foreach ( $groupTabs as $tabIdx => $tabData ) {
497                 $topTabs = $tabData['modules'];
498                 if ( ! is_array($topTabs) ) {
499                     $topTabs = array();
500                 }
501                 $extraTabs = array();
502                 
503                 // Split it in to the tabs that go across the top, and the ones that are on the extra menu.
504                 if ( count($topTabs) > $max_tabs ) {
505                     $extraTabs = array_splice($topTabs,$max_tabs);
506                 }
507                 // Make sure the current module is accessable through one of the top tabs
508                 if ( !isset($topTabs[$moduleTab]) ) {
509                     // Nope, we need to add it.
510                     // First, take it out of the extra menu, if it's there
511                     if ( isset($extraTabs[$moduleTab]) ) {
512                         unset($extraTabs[$moduleTab]);
513                     }
514                     if ( count($topTabs) >= $max_tabs - 1 ) {
515                         // We already have the maximum number of tabs, so we need to shuffle the last one
516                         // from the top to the first one of the extras
517                         $lastElem = array_splice($topTabs,$max_tabs-1);
518                         $extraTabs = $lastElem + $extraTabs;
519                     }
520                     $topTabs[$moduleTab] = $app_list_strings['moduleList'][$moduleTab];
521                 }
522                 
523                 
524                 /*
525                 // This was removed, but I like the idea, so I left the code in here in case we decide to turn it back on
526                 // If we are using group tabs, add all the "hidden" tabs to the end of the extra menu
527                 if ( $usingGroupTabs ) {
528                     foreach($fullModuleList as $moduleKey => $module ) {
529                         if ( !isset($topTabs[$moduleKey]) && !isset($extraTabs[$moduleKey]) ) {
530                             $extraTabs[$moduleKey] = $module;
531                         }
532                     }
533                 }
534                 */
535
536                 // Get a unique list of the top tabs so we can build the popup menus for them
537                 foreach ( $topTabs as $moduleKey => $module ) {
538                     $topTabList[$moduleKey] = $module;
539                 }
540                 
541                 $groupTabs[$tabIdx]['modules'] = $topTabs;
542                 $groupTabs[$tabIdx]['extra'] = $extraTabs;
543             }
544         }
545
546         if ( isset($topTabList) && is_array($topTabList) ) {
547             // Adding shortcuts array to menu array for displaying shortcuts associated with each module
548             $shortcutTopMenu = array();
549             foreach($topTabList as $module_key => $label) {
550                 global $mod_strings;
551                 $mod_strings = return_module_language($current_language, $module_key);
552                 foreach ( $this->getMenu($module_key) as $key => $menu_item ) {
553                     $shortcutTopMenu[$module_key][$key] = array(
554                         "URL"         => $menu_item[0],
555                         "LABEL"       => $menu_item[1],
556                         "MODULE_NAME" => $menu_item[2],
557                         "IMAGE"       => $themeObject
558                         ->getImage($menu_item[2],"alt='".$menu_item[1]."'  border='0' align='absmiddle'"),
559                         );
560                 }
561             }
562             $ss->assign("groupTabs",$groupTabs);
563             $ss->assign("shortcutTopMenu",$shortcutTopMenu);
564             $ss->assign('USE_GROUP_TABS',$usingGroupTabs);
565
566             // This is here for backwards compatibility, someday, somewhere, it will be able to be removed
567             $ss->assign("moduleTopMenu",$groupTabs[$app_strings['LBL_TABGROUP_ALL']]['modules']);
568             $ss->assign("moduleExtraMenu",$groupTabs[$app_strings['LBL_TABGROUP_ALL']]['extra']);
569
570         }
571
572                 global $mod_strings;
573                 $mod_strings = $bakModStrings;
574         $headerTpl = $themeObject->getTemplate('header.tpl');
575         if ( isset($GLOBALS['sugar_config']['developerMode']) && $GLOBALS['sugar_config']['developerMode'] )
576             $ss->clear_compiled_tpl($headerTpl);
577         $ss->display($headerTpl);
578         
579         $this->includeClassicFile('modules/Administration/DisplayWarnings.php');
580     }
581     /**
582      * If the view is classic then this method will include the file and
583      * setup any global variables.
584      *
585      * @param string $file
586      */
587     public function includeClassicFile(
588         $file
589         )
590     {
591         global $sugar_config, $theme, $current_user, $sugar_version, $sugar_flavor, $mod_strings, $app_strings, $app_list_strings, $action, $timezones;
592         global $gridline, $request_string, $modListHeader, $dashletData, $authController, $locale, $currentModule, $import_bean_map, $image_path, $license;
593         global $user_unique_key, $server_unique_key, $barChartColors, $modules_exempt_from_availability_check, $dictionary, $current_language, $beanList, $beanFiles, $sugar_build, $sugar_codename;
594         global $timedate, $login_error; // cn: bug 13855 - timedate not available to classic views.
595         $currentModule = $this->module;
596         require_once ($file);
597     }
598
599     protected function _displayLoginJS()
600     {
601         global $sugar_config;
602         
603         if(isset($this->bean->module_dir)){
604             echo "<script>var module_sugar_grp1 = '{$this->bean->module_dir}';</script>";
605         }
606         if(isset($_REQUEST['action'])){
607             echo "<script>var action_sugar_grp1 = '{$_REQUEST['action']}';</script>";
608         }
609         echo '<script>jscal_today = ' . (1000*strtotime($GLOBALS['timedate']->handle_offset(gmdate($GLOBALS['timedate']->get_db_date_time_format()), $GLOBALS['timedate']->get_db_date_time_format()))) . '; if(typeof app_strings == "undefined") app_strings = new Array();</script>';
610         if (!is_file("include/javascript/sugar_grp1.js")) {
611                 $_REQUEST['root_directory'] = ".";
612                 require_once("jssource/minify_utils.php");
613                 ConcatenateFiles(".");
614         }
615         echo '<script type="text/javascript" src="' . getJSPath('include/javascript/sugar_grp1_yui.js') . '"></script>';
616         echo '<script type="text/javascript" src="' . getJSPath('include/javascript/sugar_grp1.js') . '"></script>';
617         echo '<script type="text/javascript" src="' . getJSPath('jscalendar/lang/calendar-' . substr($GLOBALS['current_language'], 0, 2) . '.js') . '"></script>';
618         echo <<<EOQ
619                 <script>
620                         if ( typeof(SUGAR) == 'undefined' ) {SUGAR = {}};
621                         if ( typeof(SUGAR.themes) == 'undefined' ) SUGAR.themes = {};
622                 </script>
623 EOQ;
624         if(isset( $sugar_config['disc_client']) && $sugar_config['disc_client'])
625             echo '<script type="text/javascript" src="' . getJSPath('modules/Sync/headersync.js') . '"></script>';
626     }
627
628     /**
629      * Called from process(). This method will display the correct javascript.
630      */
631     protected function _displayJavascript()
632     {
633         global $locale, $sugar_config;
634         
635         
636         if ($this->_getOption('show_javascript')) {
637             if (!$this->_getOption('show_header'))
638                 echo <<<EOHTML
639 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
640 <html>
641 <head>
642 EOHTML;
643             
644             echo "<script>var sugar_cache_dir = '{$GLOBALS['sugar_config']['cache_dir']}';</script>";
645             echo "<script>var sugar_upload_dir = '{$GLOBALS['sugar_config']['upload_dir']}';</script>";
646         
647                 if(isset($this->bean->module_dir)){
648                 echo "<script>var module_sugar_grp1 = '{$this->bean->module_dir}';</script>";
649             }
650             if(isset($_REQUEST['action'])){
651                 echo "<script>var action_sugar_grp1 = '{$_REQUEST['action']}';</script>";
652             }
653             echo '<script>jscal_today = ' . (1000*strtotime($GLOBALS['timedate']->handle_offset(gmdate($GLOBALS['timedate']->get_db_date_time_format()), $GLOBALS['timedate']->get_db_date_time_format()))) . '; if(typeof app_strings == "undefined") app_strings = new Array();</script>';
654                 if (!is_file("include/javascript/sugar_grp1.js") || !is_file("include/javascript/sugar_grp1_yui.js")) {
655                         $_REQUEST['root_directory'] = ".";
656                         require_once("jssource/minify_utils.php");
657                         ConcatenateFiles(".");
658                 }
659             echo '<script type="text/javascript" src="' . getJSPath('include/javascript/sugar_grp1_yui.js') . '"></script>';
660             echo '<script type="text/javascript" src="' . getJSPath('include/javascript/sugar_grp1.js') . '"></script>';
661             echo '<script type="text/javascript" src="' . getJSPath('jscalendar/lang/calendar-' . substr($GLOBALS['current_language'], 0, 2) . '.js') . '"></script>';
662
663             if ( isset($sugar_config['quicksearch_querydelay']) ) {
664                 echo "<script>SUGAR.config.quicksearch_querydelay = {$GLOBALS['sugar_config']['quicksearch_querydelay']};</script>";
665             }
666             // cn: bug 12274 - prepare secret guid for asynchronous calls
667             if (!isset($_SESSION['asynchronous_key']) || empty($_SESSION['asynchronous_key'])) {
668                 $_SESSION['asynchronous_key'] = create_guid();
669             }
670             $image_server = (defined('TEMPLATE_URL'))?TEMPLATE_URL . '/':'';
671             echo '<script type="text/javascript">var asynchronous_key = "' . $_SESSION['asynchronous_key'] . '";SUGAR.themes.image_server="' . $image_server . '";</script>'; // cn: bug 12274 - create session-stored key to defend against CSRF
672             echo '<script type="text/javascript"> var name_format = "' . $locale->getLocaleFormatMacro() . '";</script>';
673             echo $GLOBALS['timedate']->get_javascript_validation();
674             if (!is_file($GLOBALS['sugar_config']['cache_dir'] . 'jsLanguage/' . $GLOBALS['current_language'] . '.js')) {
675                 require_once ('include/language/jsLanguage.php');
676                 jsLanguage::createAppStringsCache($GLOBALS['current_language']);
677             }
678             echo '<script type="text/javascript" src="' . $GLOBALS['sugar_config']['cache_dir'] . 'jsLanguage/' . $GLOBALS['current_language'] . '.js?s=' . $GLOBALS['js_version_key'] . '&c=' . $GLOBALS['sugar_config']['js_custom_version'] . '&j=' . $GLOBALS['sugar_config']['js_lang_version'] . '"></script>';
679             if (!is_file($GLOBALS['sugar_config']['cache_dir'] . 'jsLanguage/' . $this->module . '/' . $GLOBALS['current_language'] . '.js')) {
680                 require_once ('include/language/jsLanguage.php');
681                 jsLanguage::createModuleStringsCache($this->module, $GLOBALS['current_language']);
682             }
683             echo '<script type="text/javascript" src="' . $GLOBALS['sugar_config']['cache_dir'] . 'jsLanguage/' . $this->module . '/' . $GLOBALS['current_language'] . '.js?s=' . $GLOBALS['js_version_key'] . '&c=' . $GLOBALS['sugar_config']['js_custom_version'] . '&j=' . $GLOBALS['sugar_config']['js_lang_version'] . '"></script>';
684             if(isset( $sugar_config['disc_client']) && $sugar_config['disc_client'])
685                 echo '<script type="text/javascript" src="' . getJSPath('modules/Sync/headersync.js') . '"></script>';
686             echo '<script src="' . getJSPath('include/javascript/yui3/build/yui/yui-min.js') . '" type="text/javascript"></script>';
687         }
688         
689         if (isset($_REQUEST['popup']) && !empty($_REQUEST['popup'])) {
690             // cn: bug 12274 - add security metadata envelope for async calls in popups
691             echo '<script type="text/javascript">var asynchronous_key = "' . $_SESSION['asynchronous_key'] . '";</script>'; // cn: bug 12274 - create session-stored key to defend against CSRF
692         }
693     }
694
695     /**
696      * Called from process(). This method will display the footer on the page.
697      */
698     public function displayFooter()
699     {
700         if (empty($this->responseTime)) {
701             $this->_calculateFooterMetrics();
702         }
703         global $sugar_config;
704         global $app_strings;
705         
706         //decide whether or not to show themepicker, default is to show
707         $showThemePicker = true;
708         if (isset($sugar_config['showThemePicker'])) {
709             $showThemePicker = $sugar_config['showThemePicker'];
710         }
711         
712         echo "<!-- crmprint -->";
713         $jsalerts = new jsAlerts();
714         if ( !isset($_SESSION['isMobile']) )
715             echo $jsalerts->getScript();
716         
717         $ss = new Sugar_Smarty();
718         $ss->assign("AUTHENTICATED",isset($_SESSION["authenticated_user_id"]));
719         $ss->assign('MOD',return_module_language($GLOBALS['current_language'], 'Users'));
720         
721         if (SugarConfig::getInstance()->get('calculate_response_time', false))
722             $ss->assign('STATISTICS',$this->_getStatistics());
723         
724         // Under the License referenced above, you are required to leave in all copyright statements in both
725         // the code and end-user application.
726     
727
728         $copyright = '&copy; 2004-2011 SugarCRM Inc. The Program is provided AS IS, without warranty.  Licensed under <a href="LICENSE.txt" target="_blank" class="copyRightLink">AGPLv3</a>.<br>This program is free software; you can redistribute it and/or modify it under the terms of the <br><a href="LICENSE.txt" target="_blank" class="copyRightLink"> GNU Affero General Public License version 3</a> as published by the Free Software Foundation, including the additional permission set forth in the source code header.<br>';
729
730
731                 
732
733
734
735                 
736
737
738
739                 
740         // The interactive user interfaces in modified source and object code
741         // versions of this program must display Appropriate Legal Notices, as
742         // required under Section 5 of the GNU General Public License version
743         // 3. In accordance with Section 7(b) of the GNU General Public License
744         // version 3, these Appropriate Legal Notices must retain the display
745         // of the "Powered by SugarCRM" logo. If the display of the logo is
746         // not reasonably feasible for technical reasons, the Appropriate
747         // Legal Notices must display the words "Powered by SugarCRM".
748         $attribLinkImg = "<img style='margin-top: 2px' border='0' width='106' height='23' src='include/images/poweredby_sugarcrm.png' alt='Powered By SugarCRM'>\n";
749
750
751         
752         // Bug 38594 - Add in Trademark wording
753         $copyright .= 'SugarCRM is a trademark of SugarCRM, Inc. All other company and product names may be trademarks of the respective companies with which they are associated.<br />';
754
755         //rrs bug: 20923 - if this image does not exist as per the license, then the proper image will be displaye regardless, so no need
756                 //to display an empty image here.
757                 if(file_exists('include/images/poweredby_sugarcrm.png')){
758                         $copyright .= $attribLinkImg;
759                 }
760         // End Required Image
761         $ss->assign('COPYRIGHT',$copyright);
762         $ss->display(SugarThemeRegistry::current()->getTemplate('footer.tpl'));
763     }
764
765     /**
766      * Called from process(). This method will display subpanels.
767      */
768     protected function _displaySubPanels()
769     {
770         if (isset($this->bean) && !empty($this->bean->id) && (file_exists('modules/' . $this->module . '/metadata/subpaneldefs.php') || file_exists('custom/modules/' . $this->module . '/metadata/subpaneldefs.php') || file_exists('custom/modules/' . $this->module . '/Ext/Layoutdefs/layoutdefs.ext.php'))) {
771             $GLOBALS['focus'] = $this->bean;
772             require_once ('include/SubPanel/SubPanelTiles.php');
773             $subpanel = new SubPanelTiles($this->bean, $this->module);
774             echo $subpanel->display();
775         }
776     }
777     
778     protected function _buildModuleList()
779     {
780         if (!empty($GLOBALS['current_user']) && empty($GLOBALS['modListHeader'])) 
781             $GLOBALS['modListHeader'] = query_module_access_list($GLOBALS['current_user']);
782     }
783
784     /**
785      * private method used in process() to determine the value of a passed in option
786      *
787      * @param string option - the option that we want to know the valye of
788      * @param bool default - what the default value should be if we do not find the option
789      *
790      * @return bool - the value of the option
791      */
792     protected function _getOption(
793         $option, 
794         $default = false
795         )
796     {
797         if (!empty($this->options) && isset($this->options['show_all'])) {
798             return $this->options['show_all'];
799         } elseif (!empty($this->options) && isset($this->options[$option])) {
800             return $this->options[$option];
801         } else return $default;
802     }
803     
804     /**
805      * track
806      * Private function to track information about the view request
807      */
808     private function _track()
809     {
810         if (empty($this->responseTime)) {
811             $this->_calculateFooterMetrics();
812         }
813         if (empty($GLOBALS['current_user']->id)) {
814             return;
815         }
816
817         
818         $trackerManager = TrackerManager::getInstance();
819             $trackerManager->save();
820                 
821     }
822
823     /**
824      * Checks to see if the module name passed is valid; dies if it is not
825      */
826     protected function _checkModule()
827     {
828         if(!empty($this->module) && !file_exists('modules/'.$this->module)){
829                 $error = str_replace("[module]", "$this->module", $GLOBALS['app_strings']['ERR_CANNOT_FIND_MODULE']);
830                 $GLOBALS['log']->fatal($error);
831                 echo $error;
832                 die();
833         }
834     }
835
836     public function renderJavascript() 
837     {
838         if ($this->action !== 'Login')
839             $this->_displayJavascript();
840         else
841             $this->_displayLoginJS();   
842     }    
843     
844     private function _calculateFooterMetrics()
845     {
846         $endTime = microtime(true);
847         $deltaTime = $endTime - $GLOBALS['startTime'];
848         $this->responseTime = number_format(round($deltaTime, 2), 2);
849         // Print out the resources used in constructing the page.
850         $included_files = get_included_files();
851         // take all of the included files and make a list that does not allow for duplicates based on case
852         // I believe the full get_include_files result set appears to have one entry for each file in real
853         // case, and one entry in all lower case.
854         $list_of_files_case_insensitive = array();
855         foreach($included_files as $key => $name) {
856             // preserve the first capitalization encountered.
857             $list_of_files_case_insensitive[mb_strtolower($name) ] = $name;
858         }
859         $this->fileResources = sizeof($list_of_files_case_insensitive);
860     }
861     
862     private function _getStatistics()
863     {
864         $endTime = microtime(true);
865         $deltaTime = $endTime - $GLOBALS['startTime'];
866         $response_time_string = $GLOBALS['app_strings']['LBL_SERVER_RESPONSE_TIME'] . " " . number_format(round($deltaTime, 2), 2) . " " . $GLOBALS['app_strings']['LBL_SERVER_RESPONSE_TIME_SECONDS'];
867         $return = $response_time_string;
868         $return .= '<br />';
869         if (!empty($GLOBALS['sugar_config']['show_page_resources'])) {
870             // Print out the resources used in constructing the page.
871             $included_files = get_included_files();
872
873             // take all of the included files and make a list that does not allow for duplicates based on case
874             // I believe the full get_include_files result set appears to have one entry for each file in real
875             // case, and one entry in all lower case.
876             $list_of_files_case_insensitive = array();
877             foreach($included_files as $key => $name) {
878                 // preserve the first capitalization encountered.
879                 $list_of_files_case_insensitive[mb_strtolower($name) ] = $name;
880             }
881             $return .= $GLOBALS['app_strings']['LBL_SERVER_RESPONSE_RESOURCES'] . '(' . DBManager::getQueryCount() . ',' . sizeof($list_of_files_case_insensitive) . ')<br>';
882             // Display performance of the internal and external caches....
883             $return .= "External cache (hits/total=ratio) local ({$GLOBALS['external_cache_request_local_hits']}/{$GLOBALS['external_cache_request_local_total']}=" . round($GLOBALS['external_cache_request_local_hits']*100/$GLOBALS['external_cache_request_local_total'], 0) . "%)";
884             if ($GLOBALS['external_cache_request_external_total']) {
885                 // Only display out of process cache results if there was at least one attempt to retrieve from the out of process cache (this signifies that it was enabled).
886                 $return .= " external ({$GLOBALS['external_cache_request_external_hits']}/{$GLOBALS['external_cache_request_external_total']}=" . round($GLOBALS['external_cache_request_external_hits']*100/$GLOBALS['external_cache_request_external_total'], 0) . "%)<br />";
887             }
888         }
889         
890         return $return;
891     }
892     
893     /**
894      * Loads the module shortcuts menu
895      *
896      * @param  $module string optional, can specify module to retrieve menu for if not the current one
897      * @return array module menu
898      */
899     public function getMenu(
900         $module = null
901         )
902     {
903         global $current_language, $current_user, $mod_strings, $app_strings;
904         
905         if ( empty($module) )
906             $module = $this->module;
907         
908         $module_menu = sugar_cache_retrieve("{$current_user->id}_{$module}_module_menu_{$current_language}");
909         if ( !is_array($module_menu) ) {
910             $final_module_menu = array();
911             
912             if (file_exists('modules/' . $module . '/Menu.php')) {
913                 $GLOBALS['module_menu'] = $module_menu = array();
914                 require('modules/' . $module . '/Menu.php');
915                 $final_module_menu = array_merge($final_module_menu,$GLOBALS['module_menu'],$module_menu);
916             }
917             if (file_exists('custom/modules/' . $module . '/Ext/Menus/menu.ext.php')) {
918                 $GLOBALS['module_menu'] = $module_menu = array();
919                 require('custom/modules/' . $module . '/Ext/Menus/menu.ext.php');
920                 $final_module_menu = array_merge($final_module_menu,$GLOBALS['module_menu'],$module_menu);
921             }
922             if (!file_exists('modules/' . $module . '/Menu.php') 
923                     && !file_exists('custom/modules/' . $module . '/Ext/Menus/menu.ext.php') 
924                     && !empty($GLOBALS['mod_strings']['LNK_NEW_RECORD'])) {
925                 $final_module_menu[] = array("index.php?module=$module&action=EditView&return_module=$module&return_action=DetailView",
926                     $GLOBALS['mod_strings']['LNK_NEW_RECORD'],"{$GLOBALS['app_strings']['LBL_CREATE_BUTTON_LABEL']}$module" ,$module );
927                 $final_module_menu[] = array("index.php?module=$module&action=index", $GLOBALS['mod_strings']['LNK_LIST'], 
928                     $module, $module);
929                 if ( ($this->bean instanceOf SugarBean) && !empty($this->bean->importable) )
930                     if ( !empty($mod_strings['LNK_IMPORT_'.strtoupper($module)]) )
931                         $final_module_menu[] = array("index.php?module=Import&action=Step1&import_module=$module&return_module=$module&return_action=index", 
932                             $mod_strings['LNK_IMPORT_'.strtoupper($module)], "Import", $module);
933                     else
934                         $final_module_menu[] = array("index.php?module=Import&action=Step1&import_module=$module&return_module=$module&return_action=index", 
935                             $app_strings['LBL_IMPORT'], "Import", $module);
936             }
937             if (file_exists('custom/application/Ext/Menus/menu.ext.php')) {
938                 $GLOBALS['module_menu'] = $module_menu = array();
939                 require('custom/application/Ext/Menus/menu.ext.php');
940                 $final_module_menu = array_merge($final_module_menu,$GLOBALS['module_menu'],$module_menu);
941             }
942             $module_menu = $final_module_menu;
943             sugar_cache_put("{$current_user->id}_{$module}_module_menu_{$current_language}",$module_menu);
944         }
945         
946         return $module_menu;
947         }
948     
949         /**
950          * Returns the module name which should be highlighted in the module menu
951      */
952     protected function _getModuleTab()
953     {
954         global $app_list_strings, $moduleTabMap;
955         
956         // Need to figure out what tab this module belongs to, most modules have their own tabs, but there are exceptions.
957         if ( !empty($_REQUEST['module_tab']) )
958             return $_REQUEST['module_tab'];
959         elseif ( isset($moduleTabMap[$this->module]) )
960             return $moduleTabMap[$this->module];
961         // Special cases
962         elseif ( $this->module == 'MergeRecords' )
963             return $_REQUEST['return_module'];
964         elseif ( $this->module == 'Users' && $this->action == 'SetTimezone' )
965             return 'Home';
966         // Default anonymous pages to be under Home
967         elseif ( !isset($app_list_strings['moduleList'][$this->module]) )
968             return 'Home';
969         else
970             return $this->module;
971     }
972     
973    /**
974     * Return the "breadcrumbs" to display at the top of the page
975     *
976     * @param  bool $show_help optional, true if we show the help links
977     * @return HTML string containing breadcrumb title
978     */
979     public function getModuleTitle(
980         $show_help = true
981         )
982     {
983         global $sugar_version, $sugar_flavor, $server_unique_key, $current_language, $action;
984         
985         $theTitle = "<div class='moduleTitle'>\n<h2>";
986         
987         $module = preg_replace("/ /","",$this->module);
988         
989         $params = $this->_getModuleTitleParams();
990         $count = count($params);
991         $index = 0;
992        
993         foreach($params as $parm){
994             $index++;
995             $theTitle .= $parm;
996             if($index < $count){
997                 $theTitle .= "<span class='pointer'>&raquo;</span>";
998             }
999         }
1000         $theTitle .= "</h2>\n";
1001         
1002         if ($show_help) {
1003             $theTitle .= "<span class='utils'>";
1004             if (isset($this->action) && $this->action != "EditView") {
1005                 $printImageURL = SugarThemeRegistry::current()->getImageURL('print.gif');
1006                 $theTitle .= <<<EOHTML
1007 <a href="javascript:void window.open('index.php?{$GLOBALS['request_string']}','printwin','menubar=1,status=0,resizable=1,scrollbars=1,toolbar=0,location=1')" class='utilsLink'>
1008 <img src="{$printImageURL}" alt="{$GLOBALS['app_strings']['LNK_PRINT']}"></a>
1009 <a href="javascript:void window.open('index.php?{$GLOBALS['request_string']}','printwin','menubar=1,status=0,resizable=1,scrollbars=1,toolbar=0,location=1')" class='utilsLink'>
1010 {$GLOBALS['app_strings']['LNK_PRINT']}
1011 </a>
1012 EOHTML;
1013             }
1014             $helpImageURL = SugarThemeRegistry::current()->getImageURL('help.gif');
1015             $theTitle .= <<<EOHTML
1016 &nbsp;
1017 <a href="index.php?module=Administration&action=SupportPortal&view=documentation&version={$sugar_version}&edition={$sugar_flavor}&lang={$current_language}&help_module={$module}&help_action={$this->action}&key={$server_unique_key}" class="utilsLink" target="_blank">
1018 <img src='{$helpImageURL}' alt='{$GLOBALS['app_strings']['LNK_HELP']}'></a>
1019 <a href="index.php?module=Administration&action=SupportPortal&view=documentation&version={$sugar_version}&edition={$sugar_flavor}&lang={$current_language}&help_module={$module}&help_action={$this->action}&key={$server_unique_key}" class="utilsLink" target="_blank">
1020 {$GLOBALS['app_strings']['LNK_HELP']}
1021 </a>
1022 EOHTML;
1023         }
1024         
1025         $theTitle .= "</span></div>\n";
1026         return $theTitle;
1027     }
1028
1029     /**
1030      * Return the metadata file that will be used by this view.
1031      *
1032      * @return string File location of the metadata file.
1033      */
1034     public function getMetaDataFile(){
1035         
1036         $metadataFile = null;
1037                 $foundViewDefs = false;
1038                 $viewDef = strtolower($this->type) . 'viewdefs';
1039                 $coreMetaPath = 'modules/'.$this->module.'/metadata/' . $viewDef . '.php';
1040                 if(file_exists('custom/' .$coreMetaPath )){
1041                         $metadataFile = 'custom/' . $coreMetaPath;
1042                         $foundViewDefs = true;
1043                 }else{
1044                         if(file_exists('custom/modules/'.$this->module.'/metadata/metafiles.php')){
1045                                 require_once('custom/modules/'.$this->module.'/metadata/metafiles.php');
1046                                 if(!empty($metafiles[$this->module][$viewDef])){
1047                                         $metadataFile = $metafiles[$this->module][$viewDef];
1048                                         $foundViewDefs = true;
1049                                 }
1050                         }elseif(file_exists('modules/'.$this->module.'/metadata/metafiles.php')){
1051                                 require_once('modules/'.$this->module.'/metadata/metafiles.php');
1052                                 if(!empty($metafiles[$this->module][$viewDef])){
1053                                         $metadataFile = $metafiles[$this->module][$viewDef];
1054                                         $foundViewDefs = true;
1055                                 }
1056                         }
1057                 }
1058                 
1059                 if(!$foundViewDefs && file_exists($coreMetaPath)){
1060                                 $metadataFile = $coreMetaPath;
1061                 }
1062                 $GLOBALS['log']->debug("metadatafile=". $metadataFile);
1063                 
1064                 return $metadataFile;
1065     }
1066
1067     
1068     /**
1069      * Returns an array composing of the breadcrumbs to use for the module title
1070      *
1071      * @return array
1072      */
1073     protected function _getModuleTitleParams($bTitle=false)
1074     {
1075         $params = array($this->_getModuleTitleListParam($bTitle));
1076         
1077         if (isset($this->action)){
1078             switch ($this->action) {
1079             case 'EditView':
1080                 if(!empty($this->bean->id)) {
1081                     $params[] = "<a href='index.php?module={$this->module}&action=DetailView&record={$this->bean->id}'>".$this->bean->get_summary_text()."</a>";
1082                     $params[] = $GLOBALS['app_strings']['LBL_EDIT_BUTTON_LABEL'];
1083                 }
1084                 else
1085                     $params[] = $GLOBALS['app_strings']['LBL_CREATE_BUTTON_LABEL'];
1086                 break;
1087             case 'DetailView':
1088                 $beanName = $this->bean->get_summary_text();
1089                 $params[] = $beanName;
1090                 break;
1091                 }
1092         }
1093                 
1094         return $params;
1095     }
1096     
1097     /**
1098      * Returns the portion of the array that will represent the listview in the breadcrumb
1099      *
1100      * @return string
1101      */
1102     protected function _getModuleTitleListParam($bTitle=false)
1103     {
1104         global $current_user;
1105         global $app_strings;
1106         
1107         if(!empty($GLOBALS['app_list_strings']['moduleList'][$this->module]))
1108                 $firstParam = $GLOBALS['app_list_strings']['moduleList'][$this->module];
1109         else
1110                 $firstParam = $this->module;
1111         
1112         $iconPath = $this->getModuleTitleIconPath($this->module);
1113         if($this->action == "ListView" || $this->action == "index") 
1114         {
1115             if (!empty($iconPath) && !$bTitle) {
1116                                 return "<a href='index.php?module={$this->module}&action=index'>" 
1117                                      . "<img src='{$iconPath}' alt='".$this->module."' title='".$this->module."' align='absmiddle'></a>" 
1118                                      . "<span class='pointer'>&raquo;</span>".$app_strings['LBL_SEARCH'];
1119                         } else {
1120                                 return $firstParam;
1121                         }
1122         } else 
1123         {
1124                     if (!empty($iconPath) && !$bTitle) {
1125                                 return "<a href='index.php?module={$this->module}&action=index'>" 
1126                                      . "<img src='{$iconPath}' alt='".$this->module."' title='".$this->module."' align='absmiddle'></a>";
1127                         } else {
1128                                 return "<a href='index.php?module={$this->module}&action=index'>{$firstParam}</a>";
1129                         }
1130         }
1131     }
1132     
1133     protected function getModuleTitleIconPath($module) {
1134         $iconPath = "";
1135         if(is_file(SugarThemeRegistry::current()->getImageURL('icon_'.$module.'_32.png',false)))
1136         {
1137                 $iconPath = SugarThemeRegistry::current()->getImageURL('icon_'.$module.'_32.png');
1138         } else if (is_file(SugarThemeRegistry::current()->getImageURL('icon_'.ucfirst($module).'_32.png',false)))
1139         {
1140                 $iconPath = SugarThemeRegistry::current()->getImageURL('icon_'.ucfirst($module).'_32.png');
1141         }
1142         return $iconPath;
1143     }
1144     
1145     /**
1146      * Returns the string which will be shown in the browser's title; defaults to using the same breadcrumb
1147      * as in the module title
1148      *
1149      * @return string
1150      */
1151     public function getBrowserTitle()
1152     {
1153         global $app_strings;
1154         
1155         $browserTitle = $app_strings['LBL_BROWSER_TITLE'];
1156         if ( $this->module == 'Users' && ($this->action == 'SetTimezone' || $this->action == 'Login') )
1157             return $browserTitle;
1158         $params = $this->_getModuleTitleParams(true);
1159         foreach ($params  as $value )
1160             $browserTitle = strip_tags($value) . ' &raquo; ' . $browserTitle;
1161         
1162         return $browserTitle;
1163     }
1164 }