Completed
Push — console-installer ( e2b50d...6ce748 )
by Adam
22:30
created

SugarView   D

Complexity

Total Complexity 286

Size/Duplication

Total Lines 1654
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
dl 0
loc 1654
rs 4.4102
c 0
b 0
f 0
wmc 286
lcom 1
cbo 7

43 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A SugarView() 0 12 2
A init() 0 11 1
A _initSmarty() 0 6 1
F process() 0 85 21
A displayErrors() 0 15 3
A preDisplay() 0 3 1
A display() 0 3 1
C _trackView() 0 33 8
F displayHeader() 0 413 73
A getModuleMenuHTML() 0 4 1
A includeClassicFile() 0 12 2
B _displayLoginJS() 0 29 6
B getJavascriptValidation() 0 32 3
F _displayJavascript() 0 72 15
A _getModLanguageJS() 0 7 2
F displayFooter() 0 140 17
B _displaySubPanels() 0 9 6
A _buildModuleList() 0 5 3
B _getOption() 0 11 5
A _track() 0 14 3
A _checkModule() 0 9 3
A renderJavascript() 0 7 2
A _calculateFooterMetrics() 0 8 1
B _getStatistics() 0 31 3
C logMemoryStatistics() 0 40 7
C getMenu() 0 46 11
C _getModuleTab() 0 26 11
C getModuleTitle() 0 59 11
C getMetaDataFile() 0 32 8
C _getModuleTitleParams() 0 23 7
D _getModuleTitleListParam() 0 33 9
A getModuleTitleIconPath() 0 11 3
B getBrowserTitle() 0 13 5
A getBreadCrumbSymbol() 0 9 2
D getSugarConfigJS() 0 39 10
A prepareConfigVarForJs() 0 5 1
A getHelpText() 0 13 1
C getFavicon() 0 34 7
A getCustomFilePathIfExists() 0 4 1
A fetchTemplate() 0 4 1
A processRecentRecords() 0 8 2
B checkPostMaxSizeError() 0 9 5

How to fix   Complexity   

Complex Class

Complex classes like SugarView often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SugarView, and based on these observations, apply Extract Interface, too.

1
<?php
2
/*********************************************************************************
3
 * SugarCRM Community Edition is a customer relationship management program developed by
4
 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
5
6
 * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd.
7
 * Copyright (C) 2011 - 2014 Salesagility Ltd.
8
 *
9
 * This program is free software; you can redistribute it and/or modify it under
10
 * the terms of the GNU Affero General Public License version 3 as published by the
11
 * Free Software Foundation with the addition of the following permission added
12
 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
13
 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
14
 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
15
 *
16
 * This program is distributed in the hope that it will be useful, but WITHOUT
17
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
 * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
19
 * details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License along with
22
 * this program; if not, see http://www.gnu.org/licenses or write to the Free
23
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24
 * 02110-1301 USA.
25
 *
26
 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
27
 * SW2-130, Cupertino, CA 95014, USA. or at email address [email protected].
28
 *
29
 * The interactive user interfaces in modified source and object code versions
30
 * of this program must display Appropriate Legal Notices, as required under
31
 * Section 5 of the GNU Affero General Public License version 3.
32
 *
33
 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
34
 * these Appropriate Legal Notices must retain the display of the "Powered by
35
 * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not
36
 * reasonably feasible for  technical reasons, the Appropriate Legal Notices must
37
 * display the words  "Powered by SugarCRM" and "Supercharged by SuiteCRM".
38
 ********************************************************************************/
39
40
/**
41
 * Base Sugar view
42
 * @api
43
 */
44
class SugarView
45
{
46
    /**
47
     * This array is meant to hold an objects/data that we would like to pass between
48
     * the controller and the view.  The bean will automatically be set for us, but this
49
     * is meant to hold anything else.
50
     */
51
    var $view_object_map = array();
52
    /**
53
     * The name of the current module.
54
     */
55
    var $module = '';
56
    /**
57
     * The name of the current action.
58
     */
59
    var $action = '';
60
    /**
61
     */
62
    var $bean = null;
63
    /**
64
     * @var Sugar_Smarty
65
     * Sugar_Smarty. This is useful if you have a view and a subview you can
66
     * share the same smarty object.
67
     */
68
    var $ss = null;
69
    /**
70
     * Any errors that occured this can either be set by the view or the controller or the model
71
     */
72
    var $errors = array();
73
    /**
74
     * Set to true if you do not want to display errors from SugarView::displayErrors(); instead they will be returned
75
     */
76
    var $suppressDisplayErrors = false;
77
78
    /**
79
     * Options for what UI elements to hide/show/
80
     */
81
    var $options = array('show_header' => true, 'show_title' => true, 'show_subpanels' => false, 'show_search' => true, 'show_footer' => true, 'show_javascript' => true, 'view_print' => false,);
82
    var $type = null;
83
    var $responseTime;
84
    var $fileResources;
85
86
    /**
87
     * Constructor which will peform the setup.
88
     */
89
    public function __construct(
90
        $bean = null,
91
        $view_object_map = array()
92
        )
93
    {
94
    }
95
96
    /**
97
     * @deprecated deprecated since version 7.6, PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code, use __construct instead
98
     */
99
    public function SugarView($bean = null,
100
        $view_object_map = array()
101
        ){
102
        $deprecatedMessage = 'PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code';
103
        if(isset($GLOBALS['log'])) {
104
            $GLOBALS['log']->deprecated($deprecatedMessage);
105
        }
106
        else {
107
            trigger_error($deprecatedMessage, E_USER_DEPRECATED);
108
        }
109
        self::__construct($bean, $view_object_map);
110
    }
111
112
113
    public function init(
114
        $bean = null,
115
        $view_object_map = array()
116
        )
117
    {
118
        $this->bean = $bean;
119
        $this->view_object_map = $view_object_map;
120
        $this->action = $GLOBALS['action'];
121
        $this->module = $GLOBALS['module'];
122
        $this->_initSmarty();
123
    }
124
125
    protected function _initSmarty()
126
    {
127
        $this->ss = new Sugar_Smarty();
128
        $this->ss->assign('MOD', $GLOBALS['mod_strings']);
129
        $this->ss->assign('APP', $GLOBALS['app_strings']);
130
    }
131
132
    /**
133
     * This method will be called from the controller and is not meant to be overridden.
134
     */
135
    public function process()
136
    {
137
        LogicHook::initialize();
138
        $this->_checkModule();
139
140
        //trackView has to be here in order to track for breadcrumbs
141
        $this->_trackView();
142
143
        //For the ajaxUI, we need to use output buffering to return the page in an ajax friendly format
144
        if ($this->_getOption('json_output')){
145
			ob_start();
146
			if(!empty($_REQUEST['ajax_load']) && !empty($_REQUEST['loadLanguageJS'])) {
147
				echo $this->_getModLanguageJS();
148
			}
149
		}
150
151
        if ($this->_getOption('show_header')) {
152
            $this->displayHeader();
153
        } else {
154
            $this->renderJavascript();
155
        }
156
157
        $this->_buildModuleList();
158
        $this->preDisplay();
159
        $this->displayErrors();
160
        $this->display();
161
        if ( !empty($this->module) ) {
162
            $GLOBALS['logic_hook']->call_custom_logic($this->module, 'after_ui_frame');
163
        } else {
164
            $GLOBALS['logic_hook']->call_custom_logic('', 'after_ui_frame');
165
        }
166
167
        // We have to update jsAlerts as soon as possible
168
        if (
169
            !isset($_SESSION['isMobile'])
170
            &&
171
            (
172
                $this instanceof ViewList
173
                || $this instanceof ViewDetail
174
                || $this instanceof ViewEdit
175
            )
176
        ) {
177
            $jsAlerts = new jsAlerts();
178
            echo $jsAlerts->getScript();
179
        }
180
181
        if ($this->_getOption('show_subpanels') && !empty($_REQUEST['record'])) $this->_displaySubPanels();
182
183
        if ($this->action === 'Login') {
184
            //this is needed for a faster loading login page ie won't render unless the tables are closed
185
            ob_flush();
186
        }
187
        if ($this->_getOption('show_footer')) $this->displayFooter();
188
        $GLOBALS['logic_hook']->call_custom_logic('', 'after_ui_footer');
189
        if ($this->_getOption('json_output'))
190
        {
191
            $content = ob_get_clean();
192
            $module = $this->module;
193
            $ajax_ret = array(
194
                'content' => mb_detect_encoding($content) == "UTF-8" ? $content : utf8_encode($content),
195
                 'menu' => array(
196
                     'module' => $module,
197
                     'label' => translate($module),
198
                     $this->getMenu($module),
199
                 ),
200
                'title' => $this->getBrowserTitle(),
201
                'action' => isset($_REQUEST['action']) ? $_REQUEST['action'] : "",
202
                'record' => isset($_REQUEST['record']) ? $_REQUEST['record'] : "",
203
                'favicon' => $this->getFavicon(),
204
            );
205
206
            if(SugarThemeRegistry::current()->name == 'Classic' || SugarThemeRegistry::current()->classic)
0 ignored issues
show
Documentation introduced by
The property $name is declared protected in SugarTheme. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
207
                $ajax_ret['moduleList'] = $this->displayHeader(true);
208
209
            if(empty($this->responseTime))
210
                $this->_calculateFooterMetrics();
211
            $ajax_ret['responseTime'] = $this->responseTime;
212
            $json = getJSONobj();
213
            echo $json->encode($ajax_ret);
214
            $GLOBALS['app']->headerDisplayed = false;
215
            ob_flush();
216
        }
217
        //Do not track if there is no module or if module is not a String
218
        $this->_track();
219
    }
220
221
    /**
222
     * This method will display the errors on the page.
223
     */
224
    public function displayErrors()
225
    {
226
        $errors = '';
227
228
        foreach($this->errors as $error) {
229
            $errors .= '<span class="error">' . $error . '</span><br>';
230
        }
231
232
        if ( !$this->suppressDisplayErrors ) {
233
            echo $errors;
234
        }
235
        else {
236
            return $errors;
237
        }
238
    }
239
240
    /**
241
     * [OVERRIDE] - This method is meant to overidden in a subclass. The purpose of this method is
242
     * to allow a view to do some preprocessing before the display method is called. This becomes
243
     * useful when you have a view defined at the application level and then within a module
244
     * have a sub-view that extends from this application level view.  The application level
245
     * view can do the setup in preDisplay() that is common to itself and any subviews
246
     * and then the subview can just override display(). If it so desires, can also override
247
     * preDisplay().
248
     */
249
    public function preDisplay()
250
    {
251
    }
252
253
    /**
254
     * [OVERRIDE] - This method is meant to overidden in a subclass. This method
255
     * will handle the actual display logic of the view.
256
     */
257
    public function display()
258
    {
259
    }
260
261
262
    /**
263
     * trackView
264
     */
265
    protected function _trackView()
266
    {
267
        $action = strtolower($this->action);
268
        //Skip save, tracked in SugarBean instead
269
        if($action == 'save') {
270
        return;
271
        }
272
273
274
        $trackerManager = TrackerManager::getInstance();
275
        $timeStamp = TimeDate::getInstance()->nowDb();
276
        if($monitor = $trackerManager->getMonitor('tracker')){
277
            $monitor->setValue('action', $action);
278
            $monitor->setValue('user_id', $GLOBALS['current_user']->id);
279
            $monitor->setValue('module_name', $this->module);
280
            $monitor->setValue('date_modified', $timeStamp);
281
            $monitor->setValue('visible', (($monitor->action == 'detailview') || ($monitor->action == 'editview')
282
                                            ) ? 1 : 0);
283
284
            if (!empty($this->bean->id)) {
285
                $monitor->setValue('item_id', $this->bean->id);
286
                $monitor->setValue('item_summary', $this->bean->get_summary_text());
287
            }
288
289
            //If visible is true, but there is no bean, do not track (invalid/unauthorized reference)
290
            //Also, do not track save actions where there is no bean id
291
            if($monitor->visible && empty($this->bean->id)) {
292
            $trackerManager->unsetMonitor($monitor);
293
            return;
294
            }
295
            $trackerManager->saveMonitor($monitor, true, true);
296
        }
297
    }
298
299
300
    /**
301
     * Displays the header on section of the page; basically everything before the content
302
     */
303
    public function displayHeader($retModTabs=false)
304
    {
305
        global $theme;
306
        global $max_tabs;
307
        global $app_strings;
308
        global $current_user;
309
        global $sugar_config;
310
        global $app_list_strings;
311
        global $mod_strings;
312
        global $current_language;
313
314
        $GLOBALS['app']->headerDisplayed = true;
315
316
        $themeObject = SugarThemeRegistry::current();
317
        $theme = $themeObject->__toString();
318
319
        $ss = new Sugar_Smarty();
320
        $ss->assign("APP", $app_strings);
321
        $ss->assign("THEME", $theme);
322
        $ss->assign("THEME_CONFIG", $themeObject->getConfig());
323
        $ss->assign("THEME_IE6COMPAT", $themeObject->ie6compat ? 'true':'false');
324
        $ss->assign("MODULE_NAME", $this->module);
325
        $ss->assign("langHeader", get_language_header());
326
327
        // set ab testing if exists
328
        $testing = (isset($_REQUEST["testing"]) ? $_REQUEST['testing'] : "a");
329
        $ss->assign("ABTESTING", $testing);
330
331
        // get browser title
332
        $ss->assign("SYSTEM_NAME", $this->getBrowserTitle());
333
334
        // get css
335
        $css = $themeObject->getCSS();
336
        if ($this->_getOption('view_print')) {
337
            $css .= '<link rel="stylesheet" type="text/css" href="'.$themeObject->getCSSURL('print.css').'" media="all" />';
338
        }
339
        $ss->assign("SUGAR_CSS",$css);
340
341
        // get javascript
342
        ob_start();
343
        $this->renderJavascript();
344
345
        $ss->assign("SUGAR_JS",ob_get_contents().$themeObject->getJS());
346
        ob_end_clean();
347
348
        // get favicon
349
        if(isset($GLOBALS['sugar_config']['default_module_favicon']))
350
            $module_favicon = $GLOBALS['sugar_config']['default_module_favicon'];
351
        else
352
            $module_favicon = false;
353
354
        $favicon = $this->getFavicon();
355
        $ss->assign('FAVICON_URL', $favicon['url']);
356
357
        // build the shortcut menu
358
        $shortcut_menu = array();
359
        foreach ( $this->getMenu() as $key => $menu_item )
360
            $shortcut_menu[$key] = array(
361
                "URL"         => $menu_item[0],
362
                "LABEL"       => $menu_item[1],
363
                "MODULE_NAME" => $menu_item[2],
364
                "IMAGE"       => $themeObject
365
                    ->getImage($menu_item[2],"border='0' align='absmiddle'",null,null,'.gif',$menu_item[1]),
366
                );
367
        $ss->assign("SHORTCUT_MENU",$shortcut_menu);
368
369
        // handle rtl text direction
370
        if(isset($_REQUEST['RTL']) && $_REQUEST['RTL'] == 'RTL'){
371
            $_SESSION['RTL'] = true;
372
        }
373
        if(isset($_REQUEST['LTR']) && $_REQUEST['LTR'] == 'LTR'){
374
            unset($_SESSION['RTL']);
375
        }
376
        if(isset($_SESSION['RTL']) && $_SESSION['RTL']){
377
            $ss->assign("DIR", 'dir="RTL"');
378
        }
379
380
        // handle resizing of the company logo correctly on the fly
381
        $companyLogoURL = $themeObject->getImageURL('company_logo.png');
382
        $companyLogoURL_arr = explode('?', $companyLogoURL);
383
        $companyLogoURL = $companyLogoURL_arr[0];
384
385
        $company_logo_attributes = sugar_cache_retrieve('company_logo_attributes');
386
        if(!empty($company_logo_attributes)) {
387
            $ss->assign("COMPANY_LOGO_MD5", $company_logo_attributes[0]);
388
            $ss->assign("COMPANY_LOGO_WIDTH", $company_logo_attributes[1]);
389
            $ss->assign("COMPANY_LOGO_HEIGHT", $company_logo_attributes[2]);
390
        }
391
        else {
392
            // Always need to md5 the file
393
            $ss->assign("COMPANY_LOGO_MD5", md5_file($companyLogoURL));
394
395
            list($width,$height) = getimagesize($companyLogoURL);
396
            if ( $width > 212 || $height > 40 ) {
397
                $resizePctWidth  = ($width - 212)/212;
398
                $resizePctHeight = ($height - 40)/40;
399
                if ( $resizePctWidth > $resizePctHeight )
400
                    $resizeAmount = $width / 212;
401
                else
402
                    $resizeAmount = $height / 40;
403
                $ss->assign("COMPANY_LOGO_WIDTH", round($width * (1/$resizeAmount)));
404
                $ss->assign("COMPANY_LOGO_HEIGHT", round($height * (1/$resizeAmount)));
405
            }
406
            else {
407
                $ss->assign("COMPANY_LOGO_WIDTH", $width);
408
                $ss->assign("COMPANY_LOGO_HEIGHT", $height);
409
            }
410
411
            // Let's cache the results
412
            sugar_cache_put('company_logo_attributes',
413
                            array(
414
                                $ss->get_template_vars("COMPANY_LOGO_MD5"),
415
                                $ss->get_template_vars("COMPANY_LOGO_WIDTH"),
416
                                $ss->get_template_vars("COMPANY_LOGO_HEIGHT")
417
                                )
418
            );
419
        }
420
        $ss->assign("COMPANY_LOGO_URL",getJSPath($companyLogoURL)."&logo_md5=".$ss->get_template_vars("COMPANY_LOGO_MD5"));
421
422
        // get the global links
423
        $gcls = array();
424
        $global_control_links = array();
425
        require("include/globalControlLinks.php");
426
427
        foreach($global_control_links as $key => $value) {
428
            if ($key == 'users')  {   //represents logout link.
429
                $ss->assign("LOGOUT_LINK", $value['linkinfo'][key($value['linkinfo'])]);
430
                $ss->assign("LOGOUT_LABEL", key($value['linkinfo']));//key value for first element.
431
                continue;
432
            }
433
434
            foreach ($value as $linkattribute => $attributevalue) {
435
                // get the main link info
436
                if ( $linkattribute == 'linkinfo' ) {
437
                    $gcls[$key] = array(
438
                        "LABEL" => key($attributevalue),
439
                        "URL"   => current($attributevalue),
440
                        "SUBMENU" => array(),
441
                        );
442
                   if(substr($gcls[$key]["URL"], 0, 11) == "javascript:") {
443
                       $gcls[$key]["ONCLICK"] = substr($gcls[$key]["URL"],11);
444
                       $gcls[$key]["URL"] = "javascript:void(0)";
445
                   }
446
                }
447
                // and now the sublinks
448
                if ( $linkattribute == 'submenu' && is_array($attributevalue) ) {
449
                    foreach ($attributevalue as $submenulinkkey => $submenulinkinfo)
450
                        $gcls[$key]['SUBMENU'][$submenulinkkey] = array(
451
                            "LABEL" => key($submenulinkinfo),
452
                            "URL"   => current($submenulinkinfo),
453
                        );
454
                       if(substr($gcls[$key]['SUBMENU'][$submenulinkkey]["URL"], 0, 11) == "javascript:") {
455
                           $gcls[$key]['SUBMENU'][$submenulinkkey]["ONCLICK"] = substr($gcls[$key]['SUBMENU'][$submenulinkkey]["URL"],11);
0 ignored issues
show
Bug introduced by
The variable $submenulinkkey seems to be defined by a foreach iteration on line 449. Are you sure the iterator is never empty, otherwise this variable is not defined?

It seems like you are relying on a variable being defined by an iteration:

foreach ($a as $b) {
}

// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.


// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}

// $b is now guaranteed to be defined here.
Loading history...
456
                           $gcls[$key]['SUBMENU'][$submenulinkkey]["URL"] = "javascript:void(0)";
457
                       }
458
                }
459
            }
460
        }
461
        $ss->assign("GCLS",$gcls);
462
463
        $ss->assign("SEARCH", isset($_REQUEST['query_string']) ? $_REQUEST['query_string'] : '');
464
465
        if ($this->action == "EditView" || $this->action == "Login")
466
            $ss->assign("ONLOAD", 'onload="set_focus()"');
467
468
        $ss->assign("AUTHENTICATED",isset($_SESSION["authenticated_user_id"]));
469
470
        // get other things needed for page style popup
471
        if (isset($_SESSION["authenticated_user_id"])) {
472
            // get the current user name and id
473
            $ss->assign("CURRENT_USER", $current_user->full_name == '' || !showFullName()
474
                ? $current_user->user_name : $current_user->full_name );
475
            $ss->assign("CURRENT_USER_ID", $current_user->id);
476
477
            // get the last viewed records
478
            require_once("modules/Favorites/Favorites.php");
479
            $favorites = new Favorites();
480
            $favorite_records = $favorites->getCurrentUserSidebarFavorites();
481
            $ss->assign("favoriteRecords",$favorite_records);
482
483
            $tracker = new Tracker();
484
            $history = $tracker->get_recently_viewed($current_user->id);
485
            $ss->assign("recentRecords",$this->processRecentRecords($history));
486
        }
487
488
        $bakModStrings = $mod_strings;
489
        if (isset($_SESSION["authenticated_user_id"]) ) {
490
            // get the module list
491
            $moduleTopMenu = array();
492
493
            $max_tabs = $current_user->getPreference('max_tabs');
494
            // Attempt to correct if max tabs count is extremely high.
495
            if ( !isset($max_tabs) || $max_tabs <= 0 || $max_tabs > 10 ) {
496
                $max_tabs = $GLOBALS['sugar_config']['default_max_tabs'];
497
                $current_user->setPreference('max_tabs', $max_tabs, 0, 'global');
498
            }
499
500
            $moduleTab = $this->_getModuleTab();
501
            $ss->assign('MODULE_TAB',$moduleTab);
502
503
504
            // See if they are using grouped tabs or not (removed in 6.0, returned in 6.1)
505
            $user_navigation_paradigm = $current_user->getPreference('navigation_paradigm');
506
            if ( !isset($user_navigation_paradigm) ) {
507
                $user_navigation_paradigm = $GLOBALS['sugar_config']['default_navigation_paradigm'];
508
            }
509
510
511
            // Get the full module list for later use
512
            foreach ( query_module_access_list($current_user) as $module ) {
513
                // Bug 25948 - Check for the module being in the moduleList
514
                if ( isset($app_list_strings['moduleList'][$module]) ) {
515
                    $fullModuleList[$module] = $app_list_strings['moduleList'][$module];
516
                }
517
            }
518
519
520
            if(!should_hide_iframes()) {
521
                $iFrame = new iFrame();
522
                $frames = $iFrame->lookup_frames('tab');
523
                foreach($frames as $key => $values){
524
                        $fullModuleList[$key] = $values;
525
                }
526
            }
527
            elseif (isset($fullModuleList['iFrames'])) {
528
                unset($fullModuleList['iFrames']);
529
            }
530
531
            if ( $user_navigation_paradigm == 'gm' && isset($themeObject->group_tabs) && $themeObject->group_tabs) {
532
                // We are using grouped tabs
533
                require_once('include/GroupedTabs/GroupedTabStructure.php');
534
                $groupedTabsClass = new GroupedTabStructure();
535
                $modules = query_module_access_list($current_user);
536
                //handle with submoremodules
537
                $max_tabs = $current_user->getPreference('max_tabs');
538
                // If the max_tabs isn't set incorrectly, set it within the range, to the default max sub tabs size
539
                if ( !isset($max_tabs) || $max_tabs <= 0 || $max_tabs > 10){
540
                    // We have a default value. Use it
541
                    if(isset($GLOBALS['sugar_config']['default_max_tabs'])){
542
                        $max_tabs = $GLOBALS['sugar_config']['default_max_tabs'];
543
                    }
544
                    else{
545
                        $max_tabs = 8;
546
                    }
547
                }
548
549
                $subMoreModules = false;
550
                $groupTabs = $groupedTabsClass->get_tab_structure(get_val_array($modules));
551
                // We need to put this here, so the "All" group is valid for the user's preference.
552
                $groupTabs[$app_strings['LBL_TABGROUP_ALL']]['modules'] = $fullModuleList;
553
554
555
                // Setup the default group tab.
556
                $allGroup = $app_strings['LBL_TABGROUP_ALL'];
557
                $ss->assign('currentGroupTab',$allGroup);
558
                $currentGroupTab = $allGroup;
559
                $usersGroup = $current_user->getPreference('theme_current_group');
560
                // Figure out which tab they currently have selected (stored as a user preference)
561
                if ( !empty($usersGroup) && isset($groupTabs[$usersGroup]) ) {
562
                    $currentGroupTab = $usersGroup;
563
                } else {
564
                    $current_user->setPreference('theme_current_group',$currentGroupTab);
565
                }
566
567
                $ss->assign('currentGroupTab',$currentGroupTab);
568
                $usingGroupTabs = true;
569
570
            } else {
571
                // Setup the default group tab.
572
                $ss->assign('currentGroupTab',$app_strings['LBL_TABGROUP_ALL']);
573
574
                $usingGroupTabs = false;
575
576
                $groupTabs[$app_strings['LBL_TABGROUP_ALL']]['modules'] = $fullModuleList;
577
578
            }
579
580
581
            $topTabList = array();
582
583
            // Now time to go through each of the tab sets and fix them up.
584
            foreach ( $groupTabs as $tabIdx => $tabData ) {
585
                $topTabs = $tabData['modules'];
586
                if ( ! is_array($topTabs) ) {
587
                    $topTabs = array();
588
                }
589
                $extraTabs = array();
590
591
                // Split it in to the tabs that go across the top, and the ones that are on the extra menu.
592
                if ( count($topTabs) > $max_tabs ) {
593
                    $extraTabs = array_splice($topTabs,$max_tabs);
594
                }
595
                // Make sure the current module is accessable through one of the top tabs
596
                if ( !isset($topTabs[$moduleTab]) ) {
597
                    // Nope, we need to add it.
598
                    // First, take it out of the extra menu, if it's there
599
                    if ( isset($extraTabs[$moduleTab]) ) {
600
                        unset($extraTabs[$moduleTab]);
601
                    }
602
                    if ( count($topTabs) >= $max_tabs - 1 ) {
603
                        // We already have the maximum number of tabs, so we need to shuffle the last one
604
                        // from the top to the first one of the extras
605
                        $lastElem = array_splice($topTabs,$max_tabs-1);
606
                        $extraTabs = $lastElem + $extraTabs;
607
                    }
608
                    if ( !empty($moduleTab) ) {
609
                        $topTabs[$moduleTab] = $app_list_strings['moduleList'][$moduleTab];
610
                    }
611
                }
612
613
614
                /*
615
                // This was removed, but I like the idea, so I left the code in here in case we decide to turn it back on
616
                // If we are using group tabs, add all the "hidden" tabs to the end of the extra menu
617
                if ( $usingGroupTabs ) {
618
                    foreach($fullModuleList as $moduleKey => $module ) {
619
                        if ( !isset($topTabs[$moduleKey]) && !isset($extraTabs[$moduleKey]) ) {
620
                            $extraTabs[$moduleKey] = $module;
621
                        }
622
                    }
623
                }
624
                */
625
626
                // Get a unique list of the top tabs so we can build the popup menus for them
627
                foreach ( $topTabs as $moduleKey => $module ) {
628
                    $topTabList[$moduleKey] = $module;
629
                }
630
631
                $groupTabs[$tabIdx]['modules'] = $topTabs;
632
                $groupTabs[$tabIdx]['extra'] = $extraTabs;
633
            }
634
        }
635
636
        if ( isset($topTabList) && is_array($topTabList) ) {
637
            // Adding shortcuts array to menu array for displaying shortcuts associated with each module
638
            $shortcutTopMenu = array();
639
            foreach($topTabList as $module_key => $label) {
640
                global $mod_strings;
641
                $mod_strings = return_module_language($current_language, $module_key);
642
                foreach ( $this->getMenu($module_key) as $key => $menu_item ) {
643
                    $shortcutTopMenu[$module_key][$key] = array(
644
                        "URL"         => $menu_item[0],
645
                        "LABEL"       => $menu_item[1],
646
                        "MODULE_NAME" => $menu_item[2],
647
                        "IMAGE"       => $themeObject
648
                        ->getImage($menu_item[2],"border='0' align='absmiddle'",null,null,'.gif',$menu_item[1]),
649
                        "ID"          => $menu_item[2]."_link",
650
                        );
651
                }
652
            }
653
            if(!empty($sugar_config['lock_homepage']) && $sugar_config['lock_homepage'] == true) $ss->assign('lock_homepage', true);
654
            $ss->assign("groupTabs",$groupTabs);
655
            $ss->assign("shortcutTopMenu",$shortcutTopMenu);
656
            $ss->assign('USE_GROUP_TABS',$usingGroupTabs);
657
658
            // This is here for backwards compatibility, someday, somewhere, it will be able to be removed
659
            $ss->assign("moduleTopMenu",$groupTabs[$app_strings['LBL_TABGROUP_ALL']]['modules']);
660
            $ss->assign("moduleExtraMenu",$groupTabs[$app_strings['LBL_TABGROUP_ALL']]['extra']);
661
662
663
        }
664
665
        if ( isset($extraTabs) && is_array($extraTabs) ) {
666
            // Adding shortcuts array to extra menu array for displaying shortcuts associated with each module
667
            $shortcutExtraMenu = array();
668
            foreach($extraTabs as $module_key => $label) {
669
                global $mod_strings;
670
                $mod_strings = return_module_language($current_language, $module_key);
671
                foreach ( $this->getMenu($module_key) as $key => $menu_item ) {
672
                    $shortcutExtraMenu[$module_key][$key] = array(
673
                        "URL"         => $menu_item[0],
674
                        "LABEL"       => $menu_item[1],
675
                        "MODULE_NAME" => $menu_item[2],
676
                        "IMAGE"       => $themeObject
677
                        ->getImage($menu_item[2],"border='0' align='absmiddle'",null,null,'.gif',$menu_item[1]),
678
                        "ID"          => $menu_item[2]."_link",
679
                        );
680
                }
681
            }
682
            $ss->assign("shortcutExtraMenu",$shortcutExtraMenu);
683
        }
684
685
       if(!empty($current_user)){
686
       	$ss->assign("max_tabs", $current_user->getPreference("max_tabs"));
687
       }
688
689
690
        $imageURL = SugarThemeRegistry::current()->getImageURL("dashboard.png");
691
        $homeImage = "<img src='$imageURL'>";
692
		$ss->assign("homeImage",$homeImage);
693
        global $mod_strings;
694
        $mod_strings = $bakModStrings;
695
        $headerTpl = $themeObject->getTemplate('header.tpl');
696
        if (inDeveloperMode() )
697
            $ss->clear_compiled_tpl($headerTpl);
698
699
        if ($retModTabs)
700
        {
701
            return $ss->fetch($themeObject->getTemplate('_headerModuleList.tpl'));
702
        } else {
703
            $ss->display($headerTpl);
704
705
            $this->includeClassicFile('modules/Administration/DisplayWarnings.php');
706
707
            $errorMessages = SugarApplication::getErrorMessages();
708
            if ( !empty($errorMessages)) {
709
                foreach ( $errorMessages as $error_message ) {
710
                    echo('<p class="error">' . $error_message.'</p>');
711
                }
712
            }
713
        }
714
715
    }
716
717
    function getModuleMenuHTML()
718
    {
719
720
    }
721
722
    /**
723
     * If the view is classic then this method will include the file and
724
     * setup any global variables.
725
     *
726
     * @param string $file
727
     */
728
    public function includeClassicFile(
729
        $file
730
        )
731
    {
732
        global $sugar_config, $theme, $current_user, $sugar_version, $sugar_flavor, $mod_strings, $app_strings, $app_list_strings, $action;
733
        global $gridline, $request_string, $modListHeader, $dashletData, $authController, $locale, $currentModule, $import_bean_map, $image_path, $license;
734
        global $user_unique_key, $server_unique_key, $barChartColors, $modules_exempt_from_availability_check, $dictionary, $current_language, $beanList, $beanFiles, $sugar_build, $sugar_codename;
735
        global $timedate, $login_error; // cn: bug 13855 - timedate not available to classic views.
736
        if (!empty($this->module))
737
            $currentModule = $this->module;
738
        require_once ($file);
739
    }
740
741
    protected function _displayLoginJS()
742
    {
743
        global $sugar_config, $timedate;
744
745
        if(isset($this->bean->module_dir)){
746
            echo "<script>var module_sugar_grp1 = '{$this->bean->module_dir}';</script>";
747
        }
748
        if(isset($_REQUEST['action'])){
749
            echo "<script>var action_sugar_grp1 = '{$_REQUEST['action']}';</script>";
750
        }
751
        echo '<script>jscal_today = 1000*' . $timedate->asUserTs($timedate->getNow()) . '; if(typeof app_strings == "undefined") app_strings = new Array();</script>';
752
        if (!is_file(sugar_cached("include/javascript/sugar_grp1.js"))) {
753
            $_REQUEST['root_directory'] = ".";
754
            require_once("jssource/minify_utils.php");
755
            ConcatenateFiles(".");
756
        }
757
        echo getVersionedScript('cache/include/javascript/sugar_grp1_jquery.js');
758
        echo getVersionedScript('cache/include/javascript/sugar_grp1_yui.js');
759
        echo getVersionedScript('cache/include/javascript/sugar_grp1.js');
760
        echo getVersionedScript('include/javascript/calendar.js');
761
        echo <<<EOQ
762
        <script>
763
            if ( typeof(SUGAR) == 'undefined' ) {SUGAR = {}};
764
            if ( typeof(SUGAR.themes) == 'undefined' ) SUGAR.themes = {};
765
        </script>
766
EOQ;
767
        if(isset( $sugar_config['disc_client']) && $sugar_config['disc_client'])
768
            echo getVersionedScript('modules/Sync/headersync.js');
769
    }
770
771
    /**
772
     * Get JS validation code for views
773
     */
774
    public static function getJavascriptValidation()
775
    {
776
        global $timedate;
777
        $cal_date_format = $timedate->get_cal_date_format();
778
        $timereg = $timedate->get_regular_expression($timedate->get_time_format());
779
        $datereg = $timedate->get_regular_expression($timedate->get_date_format());
780
        $date_pos = '';
781
        foreach ($datereg['positions'] as $type => $pos) {
782
            if (empty($date_pos)) {
783
                $date_pos .= "'$type': $pos";
784
            } else {
785
                $date_pos .= ",'$type': $pos";
786
            }
787
        }
788
789
        $time_separator = $timedate->timeSeparator();
790
        $hour_offset = $timedate->getUserUTCOffset() * 60;
791
792
        // Add in the number formatting styles here as well, we have been handling this with individual modules.
793
        require_once ('modules/Currencies/Currency.php');
794
        list ($num_grp_sep, $dec_sep) = get_number_seperators();
795
796
        $the_script = "<script type=\"text/javascript\">\n" . "\tvar time_reg_format = '" .
797
             $timereg['format'] . "';\n" . "\tvar date_reg_format = '" .
798
             $datereg['format'] . "';\n" . "\tvar date_reg_positions = { $date_pos };\n" .
799
             "\tvar time_separator = '$time_separator';\n" .
800
             "\tvar cal_date_format = '$cal_date_format';\n" .
801
             "\tvar time_offset = $hour_offset;\n" . "\tvar num_grp_sep = '$num_grp_sep';\n" .
802
             "\tvar dec_sep = '$dec_sep';\n" . "</script>";
803
804
        return $the_script;
805
    }
806
807
    /**
808
     * Called from process(). This method will display the correct javascript.
809
     */
810
    protected function _displayJavascript()
811
    {
812
        global $locale, $sugar_config, $timedate;
813
814
815
        if ($this->_getOption('show_javascript')) {
816
            if (!$this->_getOption('show_header')) {
817
                $langHeader = get_language_header();
818
819
                echo <<<EOHTML
820
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
821
<html {$langHeader}>
822
<head>
823
EOHTML;
824
            }
825
826
            $js_vars = array(
827
                "sugar_cache_dir" => "cache/",
828
                );
829
830
            if(isset($this->bean->module_dir)){
831
                $js_vars['module_sugar_grp1'] = $this->bean->module_dir;
832
            }
833
            if(isset($_REQUEST['action'])){
834
                $js_vars['action_sugar_grp1'] = $_REQUEST['action'];
835
            }
836
            echo '<script>jscal_today = 1000*' . $timedate->asUserTs($timedate->getNow()) . '; if(typeof app_strings == "undefined") app_strings = new Array();</script>';
837
            if (!is_file(sugar_cached("include/javascript/sugar_grp1.js")) || !is_file(sugar_cached("include/javascript/sugar_grp1_yui.js")) || !is_file(sugar_cached("include/javascript/sugar_grp1_jquery.js"))) {
838
                $_REQUEST['root_directory'] = ".";
839
                require_once("jssource/minify_utils.php");
840
                ConcatenateFiles(".");
841
            }
842
            echo getVersionedScript('cache/include/javascript/sugar_grp1_jquery.js');
843
            echo getVersionedScript('cache/include/javascript/sugar_grp1_yui.js');
844
            echo getVersionedScript('cache/include/javascript/sugar_grp1.js');
845
            echo getVersionedScript('include/javascript/calendar.js');
846
847
            // output necessary config js in the top of the page
848
            $config_js = $this->getSugarConfigJS();
849
            if(!empty($config_js)){
850
                echo "<script>\n".implode("\n", $config_js)."</script>\n";
851
            }
852
853
            if ( isset($sugar_config['email_sugarclient_listviewmaxselect']) ) {
854
                echo "<script>SUGAR.config.email_sugarclient_listviewmaxselect = {$GLOBALS['sugar_config']['email_sugarclient_listviewmaxselect']};</script>";
855
            }
856
857
            $image_server = (defined('TEMPLATE_URL'))?TEMPLATE_URL . '/':'';
858
            echo '<script type="text/javascript">SUGAR.themes.image_server="' . $image_server . '";</script>'; // cn: bug 12274 - create session-stored key to defend against CSRF
859
            echo '<script type="text/javascript">var name_format = "' . $locale->getLocaleFormatMacro() . '";</script>';
860
            echo self::getJavascriptValidation();
861
            if (!is_file(sugar_cached('jsLanguage/') . $GLOBALS['current_language'] . '.js')) {
862
                require_once ('include/language/jsLanguage.php');
863
                jsLanguage::createAppStringsCache($GLOBALS['current_language']);
864
            }
865
            echo getVersionedScript('cache/jsLanguage/'. $GLOBALS['current_language'] . '.js', $GLOBALS['sugar_config']['js_lang_version']);
866
867
			echo $this->_getModLanguageJS();
868
869
            if(isset( $sugar_config['disc_client']) && $sugar_config['disc_client'])
870
                echo getVersionedScript('modules/Sync/headersync.js');
871
872
873
            //echo out the $js_vars variables as javascript variables
874
            echo "<script type='text/javascript'>\n";
875
            foreach($js_vars as $var=>$value)
876
            {
877
                echo "var {$var} = '{$value}';\n";
878
            }
879
            echo "</script>\n";
880
        }
881
    }
882
883
	protected function _getModLanguageJS(){
884
		if (!is_file(sugar_cached('jsLanguage/') . $this->module . '/' . $GLOBALS['current_language'] . '.js')) {
885
			require_once ('include/language/jsLanguage.php');
886
			jsLanguage::createModuleStringsCache($this->module, $GLOBALS['current_language']);
887
		}
888
		return getVersionedScript("cache/jsLanguage/{$this->module}/". $GLOBALS['current_language'] . '.js', $GLOBALS['sugar_config']['js_lang_version']);
889
	}
890
891
    /**
892
     * Called from process(). This method will display the footer on the page.
893
     */
894
    public function displayFooter()
895
    {
896
        if (empty($this->responseTime)) {
897
            $this->_calculateFooterMetrics();
898
        }
899
        global $sugar_config;
900
        global $app_strings;
901
        global $mod_strings;
902
		$themeObject = SugarThemeRegistry::current();
903
        //decide whether or not to show themepicker, default is to show
904
        $showThemePicker = true;
905
        if (isset($sugar_config['showThemePicker'])) {
906
            $showThemePicker = $sugar_config['showThemePicker'];
907
        }
908
909
        $ss = new Sugar_Smarty();
910
        $ss->assign("AUTHENTICATED",isset($_SESSION["authenticated_user_id"]));
911
        $ss->assign('MOD',return_module_language($GLOBALS['current_language'], 'Users'));
912
913
		$bottomLinkList = array();
914
		 if (isset($this->action) && $this->action != "EditView") {
915
			 $bottomLinkList['print'] = array($app_strings['LNK_PRINT'] => getPrintLink());
916
		}
917
		$bottomLinkList['backtotop'] = array($app_strings['LNK_BACKTOTOP'] => 'javascript:SUGAR.util.top();');
918
919
		$bottomLinksStr = "";
920
		foreach($bottomLinkList as $key => $value) {
921
			foreach($value as $text => $link) {
922
				   $href = $link;
923
				   if(substr($link, 0, 11) == "javascript:") {
924
                       $onclick = " onclick=\"".substr($link,11)."\"";
925
                       $href = "javascript:void(0)";
926
                   } else {
927
                   		$onclick = "";
928
                   	}
929
                $imageURL = SugarThemeRegistry::current()->getImageURL($key.'.gif');
930
				$bottomLinksStr .= "<a href=\"{$href}\"";
931
				$bottomLinksStr .= (isset($onclick)) ? $onclick : "";
932
				$bottomLinksStr .= "><img src='{$imageURL}' alt=''>"; //keeping alt blank on purpose for 508 (text will be read instead)
933
				$bottomLinksStr .= " ".$text."</a>";
934
			}
935
		}
936
		$ss->assign("BOTTOMLINKS",$bottomLinksStr);
937
        if (SugarConfig::getInstance()->get('calculate_response_time', false))
938
            $ss->assign('STATISTICS',$this->_getStatistics());
939
940
        // Under the License referenced above, you are required to leave in all copyright statements in both
941
        // the code and end-user application.
942
943
944
        $copyright = '&copy; 2004-2013 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>';
945
946
947
948
949
950
951
952
953
954
955
        // The interactive user interfaces in modified source and object code
956
        // versions of this program must display Appropriate Legal Notices, as
957
        // required under Section 5 of the GNU General Public License version
958
        // 3. In accordance with Section 7(b) of the GNU General Public License
959
        // version 3, these Appropriate Legal Notices must retain the display
960
        // of the "Powered by SugarCRM" logo. If the display of the logo is
961
        // not reasonably feasible for technical reasons, the Appropriate
962
        // Legal Notices must display the words "Powered by SugarCRM".
963
        $attribLinkImg = "<img style='margin-top: 2px' border='0' width='120' height='34' src='include/images/poweredby_sugarcrm_65.png' alt='Powered By SugarCRM'>\n";
964
965
966
		// handle resizing of the company logo correctly on the fly
967
        $companyLogoURL = $themeObject->getImageURL('company_logo.png');
968
        $companyLogoURL_arr = explode('?', $companyLogoURL);
969
        $companyLogoURL = $companyLogoURL_arr[0];
970
971
        $company_logo_attributes = sugar_cache_retrieve('company_logo_attributes');
972
        if(!empty($company_logo_attributes)) {
973
            $ss->assign("COMPANY_LOGO_MD5", $company_logo_attributes[0]);
974
            $ss->assign("COMPANY_LOGO_WIDTH", $company_logo_attributes[1]);
975
            $ss->assign("COMPANY_LOGO_HEIGHT", $company_logo_attributes[2]);
976
        }
977
        else {
978
            // Always need to md5 the file
979
            $ss->assign("COMPANY_LOGO_MD5", md5_file($companyLogoURL));
980
981
            list($width,$height) = getimagesize($companyLogoURL);
982
            if ( $width > 212 || $height > 40 ) {
983
                $resizePctWidth  = ($width - 212)/212;
984
                $resizePctHeight = ($height - 40)/40;
985
                if ( $resizePctWidth > $resizePctHeight )
986
                    $resizeAmount = $width / 212;
987
                else
988
                    $resizeAmount = $height / 40;
989
                $ss->assign("COMPANY_LOGO_WIDTH", round($width * (1/$resizeAmount)));
990
                $ss->assign("COMPANY_LOGO_HEIGHT", round($height * (1/$resizeAmount)));
991
            }
992
            else {
993
                $ss->assign("COMPANY_LOGO_WIDTH", $width);
994
                $ss->assign("COMPANY_LOGO_HEIGHT", $height);
995
            }
996
997
            // Let's cache the results
998
            sugar_cache_put('company_logo_attributes',
999
                            array(
1000
                                $ss->get_template_vars("COMPANY_LOGO_MD5"),
1001
                                $ss->get_template_vars("COMPANY_LOGO_WIDTH"),
1002
                                $ss->get_template_vars("COMPANY_LOGO_HEIGHT")
1003
                                )
1004
            );
1005
        }
1006
        $ss->assign("COMPANY_LOGO_URL",getJSPath($companyLogoURL)."&logo_md5=".$ss->get_template_vars("COMPANY_LOGO_MD5"));
1007
1008
        // Bug 38594 - Add in Trademark wording
1009
        $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 />';
1010
1011
        //rrs bug: 20923 - if this image does not exist as per the license, then the proper image will be displayed regardless, so no need
1012
        //to display an empty image here.
1013
        if(file_exists('include/images/poweredby_sugarcrm_65.png')){
1014
            $copyright .= $attribLinkImg;
1015
        }
1016
        // End Required Image
1017
        $ss->assign('COPYRIGHT',$copyright);
1018
1019
        // here we allocate the help link data
1020
        $help_actions_blacklist = array('Login'); // we don't want to show a context help link here
1021
        if (!in_array($this->action,$help_actions_blacklist)) {
1022
            $url = 'javascript:void(window.open(\'index.php?module=Administration&action=SupportPortal&view=documentation&version='.$GLOBALS['sugar_version'].'&edition='.$GLOBALS['sugar_flavor'].'&lang='.$GLOBALS['current_language'].
1023
                        '&help_module='.$this->module.'&help_action='.$this->action.'&key='.$GLOBALS['server_unique_key'].'\'))';
1024
            $label = (isset($GLOBALS['app_list_strings']['moduleList'][$this->module]) ?
1025
                        $GLOBALS['app_list_strings']['moduleList'][$this->module] : $this->module). ' '.$app_strings['LNK_HELP'];
1026
            $ss->assign('HELP_LINK',SugarThemeRegistry::current()->getLink($url, $label, "id='help_link_two'",
1027
                'help-dashlet.png', 'class="icon"',null,null,'','left'));
1028
        }
1029
        // end
1030
1031
1032
        $ss->display(SugarThemeRegistry::current()->getTemplate('footer.tpl'));
1033
    }
1034
1035
    /**
1036
     * Called from process(). This method will display subpanels.
1037
     */
1038
    protected function _displaySubPanels()
1039
    {
1040
        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'))) {
1041
            $GLOBALS['focus'] = $this->bean;
1042
            require_once ('include/SubPanel/SubPanelTiles.php');
1043
            $subpanel = new SubPanelTiles($this->bean, $this->module);
1044
            echo $subpanel->display();
1045
        }
1046
    }
1047
1048
    protected function _buildModuleList()
1049
    {
1050
        if (!empty($GLOBALS['current_user']) && empty($GLOBALS['modListHeader']))
1051
            $GLOBALS['modListHeader'] = query_module_access_list($GLOBALS['current_user']);
1052
    }
1053
1054
    /**
1055
     * private method used in process() to determine the value of a passed in option
1056
     *
1057
     * @param string option - the option that we want to know the valye of
1058
     * @param bool default - what the default value should be if we do not find the option
1059
     *
1060
     * @return bool - the value of the option
1061
     */
1062
    protected function _getOption(
1063
        $option,
1064
        $default = false
1065
        )
1066
    {
1067
        if (!empty($this->options) && isset($this->options['show_all'])) {
1068
            return $this->options['show_all'];
1069
        } elseif (!empty($this->options) && isset($this->options[$option])) {
1070
            return $this->options[$option];
1071
        } else return $default;
1072
    }
1073
1074
    /**
1075
     * track
1076
     * Private function to track information about the view request
1077
     */
1078
    private function _track()
1079
    {
1080
        if (empty($this->responseTime)) {
1081
            $this->_calculateFooterMetrics();
1082
        }
1083
        if (empty($GLOBALS['current_user']->id)) {
1084
            return;
1085
        }
1086
1087
1088
        $trackerManager = TrackerManager::getInstance();
1089
	    $trackerManager->save();
1090
1091
    }
1092
1093
    /**
1094
     * Checks to see if the module name passed is valid; dies if it is not
1095
     */
1096
    protected function _checkModule()
1097
    {
1098
        if(!empty($this->module) && !file_exists('modules/'.$this->module)){
1099
            $error = str_replace("[module]", "$this->module", $GLOBALS['app_strings']['ERR_CANNOT_FIND_MODULE']);
1100
            $GLOBALS['log']->fatal($error);
1101
            echo $error;
1102
            die();
1103
        }
1104
    }
1105
1106
    public function renderJavascript()
1107
    {
1108
        if ($this->action !== 'Login')
1109
            $this->_displayJavascript();
1110
        else
1111
            $this->_displayLoginJS();
1112
    }
1113
1114
    private function _calculateFooterMetrics()
1115
    {
1116
        $endTime = microtime(true);
1117
        $deltaTime = $endTime - $GLOBALS['startTime'];
1118
        $this->responseTime = number_format(round($deltaTime, 2), 2);
1119
        // Print out the resources used in constructing the page.
1120
        $this->fileResources = count(get_included_files());
1121
    }
1122
1123
    private function _getStatistics()
1124
    {
1125
        $endTime = microtime(true);
1126
        $deltaTime = $endTime - $GLOBALS['startTime'];
1127
        $response_time_string = $GLOBALS['app_strings']['LBL_SERVER_RESPONSE_TIME'] . ' ' . number_format(round($deltaTime, 2), 2) . ' ' . $GLOBALS['app_strings']['LBL_SERVER_RESPONSE_TIME_SECONDS'];
1128
        $return = $response_time_string;
1129
       // $return .= '<br />';
1130
        if (!empty($GLOBALS['sugar_config']['show_page_resources'])) {
1131
            // Print out the resources used in constructing the page.
1132
            $included_files = get_included_files();
1133
1134
            // take all of the included files and make a list that does not allow for duplicates based on case
1135
            // I believe the full get_include_files result set appears to have one entry for each file in real
1136
            // case, and one entry in all lower case.
1137
            $list_of_files_case_insensitive = array();
1138
            foreach($included_files as $key => $name) {
1139
                // preserve the first capitalization encountered.
1140
                $list_of_files_case_insensitive[mb_strtolower($name) ] = $name;
1141
            }
1142
            $return .= $GLOBALS['app_strings']['LBL_SERVER_RESPONSE_RESOURCES'] . '(' . DBManager::getQueryCount() . ',' . sizeof($list_of_files_case_insensitive) . ')<br>';
1143
            // Display performance of the internal and external caches....
1144
            $cacheStats = SugarCache::instance()->getCacheStats();
1145
            $return .= "External cache (hits/total=ratio) local ({$cacheStats['localHits']}/{$cacheStats['requests']}=" . round($cacheStats['localHits']*100/$cacheStats['requests'], 0) . "%)";
1146
            $return .= " external ({$cacheStats['externalHits']}/{$cacheStats['requests']}=" . round($cacheStats['externalHits']*100/$cacheStats['requests'], 0) . "%)<br />";
1147
            $return .= " misses ({$cacheStats['misses']}/{$cacheStats['requests']}=" . round($cacheStats['misses']*100/$cacheStats['requests'], 0) . "%)<br />";
1148
        }
1149
1150
        $return .= $this->logMemoryStatistics();
1151
1152
        return $return;
1153
    }
1154
1155
    /**
1156
     * logMemoryStatistics
1157
     *
1158
     * This function returns a string message containing the memory statistics as well as writes to the memory_usage.log
1159
     * file the memory statistics for the SugarView invocation.
1160
     *
1161
     * @param $newline String of newline character to use (defaults to </ br>)
1162
     * @return $message String formatted message about memory statistics
0 ignored issues
show
Documentation introduced by
The doc-type $message could not be parsed: Unknown type name "$message" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1163
     */
1164
    protected function logMemoryStatistics($newline='<br>')
1165
    {
1166
        $log_message = '';
1167
1168
        if(!empty($GLOBALS['sugar_config']['log_memory_usage']))
1169
        {
1170
            if(function_exists('memory_get_usage'))
1171
            {
1172
                $memory_usage = memory_get_usage();
1173
                $bytes = $GLOBALS['app_strings']['LBL_SERVER_MEMORY_BYTES'];
1174
                $data = array($memory_usage, $bytes);
1175
                $log_message = string_format($GLOBALS['app_strings']['LBL_SERVER_MEMORY_USAGE'], $data) . $newline;
1176
            }
1177
1178
            if(function_exists('memory_get_peak_usage'))
1179
            {
1180
                $memory_peak_usage = memory_get_peak_usage();
1181
                $bytes = $GLOBALS['app_strings']['LBL_SERVER_MEMORY_BYTES'];
1182
                $data = array($memory_peak_usage, $bytes);
1183
                $log_message .= string_format($GLOBALS['app_strings']['LBL_SERVER_PEAK_MEMORY_USAGE'], $data) . $newline;
1184
            }
1185
1186
            if(!empty($log_message))
1187
            {
1188
                $data = array
1189
                (
1190
                   !empty($this->module) ? $this->module : $GLOBALS['app_strings']['LBL_LINK_NONE'],
1191
                   !empty($this->action) ? $this->action : $GLOBALS['app_strings']['LBL_LINK_NONE'],
1192
                );
1193
1194
                $output = string_format($GLOBALS['app_strings']['LBL_SERVER_MEMORY_LOG_MESSAGE'], $data) . $newline;
1195
                $output .= $log_message;
1196
                $fp = fopen("memory_usage.log", "ab");
1197
                fwrite($fp, $output);
1198
                fclose($fp);
1199
            }
1200
        }
1201
1202
        return $log_message;
1203
    }
1204
1205
1206
    /**
1207
     * Loads the module shortcuts menu
1208
     *
1209
     * @param  $module string optional, can specify module to retrieve menu for if not the current one
1210
     * @return array module menu
1211
     */
1212
    public function getMenu(
1213
        $module = null
1214
        )
1215
    {
1216
        global $current_language, $current_user, $mod_strings, $app_strings, $module_menu;
1217
1218
        if ( empty($module) )
1219
            $module = $this->module;
1220
1221
        //Need to make sure the mod_strings match the requested module or Menus may fail
1222
        $curr_mod_strings = $mod_strings;
1223
        $mod_strings = return_module_language ( $current_language, $module ) ;
1224
1225
        $module_menu = array();
1226
1227
        if (file_exists('modules/' . $module . '/Menu.php')) {
1228
            require('modules/' . $module . '/Menu.php');
1229
        }
1230
        if (file_exists('custom/modules/' . $module . '/Ext/Menus/menu.ext.php')) {
1231
            require('custom/modules/' . $module . '/Ext/Menus/menu.ext.php');
1232
        }
1233
        if (!file_exists('modules/' . $module . '/Menu.php')
1234
                && !file_exists('custom/modules/' . $module . '/Ext/Menus/menu.ext.php')
1235
                && !empty($GLOBALS['mod_strings']['LNK_NEW_RECORD'])) {
1236
            $module_menu[] = array("index.php?module=$module&action=EditView&return_module=$module&return_action=DetailView",
1237
                $GLOBALS['mod_strings']['LNK_NEW_RECORD'],"{$GLOBALS['app_strings']['LBL_CREATE_BUTTON_LABEL']}$module" ,$module );
1238
            $module_menu[] = array("index.php?module=$module&action=index", $GLOBALS['mod_strings']['LNK_LIST'],
1239
                $module, $module);
1240
            if ( ($this->bean instanceOf SugarBean) && !empty($this->bean->importable) )
1241
                if ( !empty($mod_strings['LNK_IMPORT_'.strtoupper($module)]) )
1242
                    $module_menu[] = array("index.php?module=Import&action=Step1&import_module=$module&return_module=$module&return_action=index",
1243
                        $mod_strings['LNK_IMPORT_'.strtoupper($module)], "Import", $module);
1244
                else
1245
                    $module_menu[] = array("index.php?module=Import&action=Step1&import_module=$module&return_module=$module&return_action=index",
1246
                        $app_strings['LBL_IMPORT'], "Import", $module);
1247
        }
1248
        if (file_exists('custom/application/Ext/Menus/menu.ext.php')) {
1249
            require('custom/application/Ext/Menus/menu.ext.php');
1250
        }
1251
1252
        $mod_strings = $curr_mod_strings;
1253
        $builtModuleMenu = $module_menu;
1254
        unset($module_menu);
1255
1256
        return $builtModuleMenu;
1257
    }
1258
1259
    /**
1260
    * Returns the module name which should be highlighted in the module menu
1261
     */
1262
    protected function _getModuleTab()
1263
    {
1264
        global $app_list_strings, $moduleTabMap, $current_user;
1265
1266
		$userTabs = query_module_access_list($current_user);
1267
		//If the home tab is in the user array use it as the default tab, otherwise use the first element in the tab array
1268
		$defaultTab = (in_array("Home",$userTabs)) ? "Home" : key($userTabs);
1269
1270
        // Need to figure out what tab this module belongs to, most modules have their own tabs, but there are exceptions.
1271
        if ( !empty($_REQUEST['module_tab']) )
1272
            return $_REQUEST['module_tab'];
1273
        elseif ( isset($moduleTabMap[$this->module]) )
1274
            return $moduleTabMap[$this->module];
1275
        // Special cases
1276
        elseif ( $this->module == 'MergeRecords' )
1277
            return !empty($_REQUEST['merge_module']) ? $_REQUEST['merge_module'] : $_REQUEST['return_module'];
1278
        elseif ( $this->module == 'Users' && $this->action == 'SetTimezone' )
1279
            return $defaultTab;
1280
        // Default anonymous pages to be under Home
1281
        elseif ( !isset($app_list_strings['moduleList'][$this->module]) )
1282
            return $defaultTab;
1283
        elseif ( isset($_REQUEST['action']) && $_REQUEST['action'] == "ajaxui" )
1284
        	return $defaultTab;
1285
        else
1286
            return $this->module;
1287
    }
1288
1289
   /**
1290
    * Return the "breadcrumbs" to display at the top of the page
1291
    *
1292
    * @param  bool $show_help optional, true if we show the help links
1293
    * @return HTML string containing breadcrumb title
1294
    */
1295
    public function getModuleTitle(
1296
        $show_help = true
1297
        )
1298
    {
1299
        global $sugar_version, $sugar_flavor, $server_unique_key, $current_language, $action;
1300
1301
        $theTitle = "<div class='moduleTitle'>\n";
1302
1303
        $module = preg_replace("/ /","",$this->module);
1304
1305
        $params = $this->_getModuleTitleParams();
1306
        $index = 0;
1307
1308
		if(SugarThemeRegistry::current()->directionality == "rtl") {
1309
			$params = array_reverse($params);
1310
		}
1311
		if(count($params) > 1) {
1312
			array_shift($params);
1313
		}
1314
		$count = count($params);
1315
        $paramString = '';
1316
        foreach($params as $parm){
1317
            $index++;
1318
            $paramString .= $parm;
1319
            if($index < $count){
1320
                $paramString .= $this->getBreadCrumbSymbol();
1321
            }
1322
        }
1323
1324
        if(!empty($paramString)){
1325
               $theTitle .= "<h2> $paramString </h2>";
1326
1327
            if($this->type == "detail"){
1328
                $theTitle .= "<div class='favorite' record_id='" . $this->bean->id . "' module='" . $this->bean->module_dir . "'><div class='favorite_icon_outline'>" . SugarThemeRegistry::current()->getImage('favorite-star-outline','title="' . translate('LBL_DASHLET_EDIT', 'Home') . '" border="0"  align="absmiddle"', null,null,'.gif',translate('LBL_DASHLET_EDIT', 'Home')) . "</div>
1329
                                                    <div class='favorite_icon_fill'>" . SugarThemeRegistry::current()->getImage('favorite-star','title="' . translate('LBL_DASHLET_EDIT', 'Home') . '" border="0"  align="absmiddle"', null,null,'.gif',translate('LBL_DASHLET_EDIT', 'Home')) . "</div></div>";
1330
            }
1331
           }
1332
1333
        // bug 56131 - restore conditional so that link doesn't appear where it shouldn't
1334
        if($show_help || $this->type == 'list') {
1335
            $theTitle .= "<span class='utils'>";
1336
            $createImageURL = SugarThemeRegistry::current()->getImageURL('create-record.gif');
1337
            if($this->type == 'list') $theTitle .= '<a href="#" class="btn btn-success showsearch"><span class=" glyphicon glyphicon-search" aria-hidden="true"></span></a>';$url = ajaxLink("index.php?module=$module&action=EditView&return_module=$module&return_action=DetailView");
1338
            if($show_help) {
1339
                $theTitle .= <<<EOHTML
1340
&nbsp;
1341
<a id="create_image" href="{$url}" class="utilsLink">
1342
<img src='{$createImageURL}' alt='{$GLOBALS['app_strings']['LNK_CREATE']}'></a>
1343
<a id="create_link" href="{$url}" class="utilsLink">
1344
{$GLOBALS['app_strings']['LNK_CREATE']}
1345
</a>
1346
EOHTML;
1347
            }
1348
            $theTitle .= "</span>";
1349
        }
1350
1351
        $theTitle .= "<div class='clear'></div></div>\n";
1352
        return $theTitle;
1353
    }
1354
1355
    /**
1356
     * Return the metadata file that will be used by this view.
1357
     *
1358
     * @return string File location of the metadata file.
1359
     */
1360
    public function getMetaDataFile()
1361
    {
1362
        $metadataFile = null;
1363
        $foundViewDefs = false;
1364
        $viewDef = strtolower($this->type) . 'viewdefs';
1365
        $coreMetaPath = 'modules/'.$this->module.'/metadata/' . $viewDef . '.php';
1366
        if(file_exists('custom/' .$coreMetaPath )){
1367
            $metadataFile = 'custom/' . $coreMetaPath;
1368
            $foundViewDefs = true;
1369
        }else{
1370
            if(file_exists('custom/modules/'.$this->module.'/metadata/metafiles.php')){
1371
                require_once('custom/modules/'.$this->module.'/metadata/metafiles.php');
1372
                if(!empty($metafiles[$this->module][$viewDef])){
0 ignored issues
show
Bug introduced by
The variable $metafiles seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
1373
                    $metadataFile = $metafiles[$this->module][$viewDef];
1374
                    $foundViewDefs = true;
1375
                }
1376
            }elseif(file_exists('modules/'.$this->module.'/metadata/metafiles.php')){
1377
                require_once('modules/'.$this->module.'/metadata/metafiles.php');
1378
                if(!empty($metafiles[$this->module][$viewDef])){
1379
                    $metadataFile = $metafiles[$this->module][$viewDef];
1380
                    $foundViewDefs = true;
1381
                }
1382
            }
1383
        }
1384
1385
        if(!$foundViewDefs && file_exists($coreMetaPath)){
1386
                $metadataFile = $coreMetaPath;
1387
        }
1388
        $GLOBALS['log']->debug("metadatafile=". $metadataFile);
1389
1390
        return $metadataFile;
1391
    }
1392
1393
1394
    /**
1395
     * Returns an array composing of the breadcrumbs to use for the module title
1396
     *
1397
     * @param bool $browserTitle true if the returned string is being used for the browser title, meaning
1398
     *                           there should be no HTML in the string
1399
     * @return array
1400
     */
1401
    protected function _getModuleTitleParams($browserTitle = false)
1402
    {
1403
        $params = array($this->_getModuleTitleListParam($browserTitle));
1404
		//$params = array();
1405
        if (isset($this->action)){
1406
            switch ($this->action) {
1407
            case 'EditView':
1408
                if(!empty($this->bean->id) && (empty($_REQUEST['isDuplicate']) || $_REQUEST['isDuplicate'] === 'false')) {
1409
                    $params[] = "<a href='index.php?module={$this->module}&action=DetailView&record={$this->bean->id}'>".$this->bean->get_summary_text()."</a>";
1410
                    $params[] = $GLOBALS['app_strings']['LBL_EDIT_BUTTON_LABEL'];
1411
                }
1412
                else
1413
                    $params[] = $GLOBALS['app_strings']['LBL_CREATE_BUTTON_LABEL'];
1414
                break;
1415
            case 'DetailView':
1416
                $beanName = $this->bean->get_summary_text();
1417
                $params[] = $beanName;
1418
                break;
1419
            }
1420
        }
1421
1422
        return $params;
1423
    }
1424
1425
    /**
1426
     * Returns the portion of the array that will represent the listview in the breadcrumb
1427
     *
1428
     * @param bool $browserTitle true if the returned string is being used for the browser title, meaning
1429
     *                           there should be no HTML in the string
1430
     * @return string
1431
     */
1432
    protected function _getModuleTitleListParam( $browserTitle = false )
1433
    {
1434
    	global $current_user;
1435
    	global $app_strings;
1436
1437
    	if(!empty($GLOBALS['app_list_strings']['moduleList'][$this->module]))
1438
    		$firstParam = $GLOBALS['app_list_strings']['moduleList'][$this->module];
1439
    	else
1440
    		$firstParam = $this->module;
1441
1442
    	$iconPath = $this->getModuleTitleIconPath($this->module);
1443
    	if($this->action == "ListView" || $this->action == "index") {
1444
    	    if (!empty($iconPath) && !$browserTitle) {
1445
    	    	if (SugarThemeRegistry::current()->directionality == "ltr") {
1446
    	    		return $app_strings['LBL_SEARCH']."&nbsp;"
1447
    	    			 . "$firstParam";
1448
1449
    	    	} else {
1450
					return "$firstParam"
1451
					     . "&nbsp;".$app_strings['LBL_SEARCH'];
1452
    	    	}
1453
			} else {
1454
				return $firstParam;
1455
			}
1456
    	}
1457
    	else {
1458
		    if (!empty($iconPath) && !$browserTitle) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
1459
				//return "<a href='index.php?module={$this->module}&action=index'>$this->module</a>";
1460
			} else {
1461
				return $firstParam;
1462
			}
1463
    	}
1464
    }
1465
1466
    protected function getModuleTitleIconPath($module)
1467
    {
1468
    	$iconPath = "";
1469
    	if(is_file(SugarThemeRegistry::current()->getImageURL('icon_'.$module.'_32.png',false))) {
1470
    		$iconPath = SugarThemeRegistry::current()->getImageURL('icon_'.$module.'_32.png');
1471
    	}
1472
    	else if (is_file(SugarThemeRegistry::current()->getImageURL('icon_'.ucfirst($module).'_32.png',false))) {
1473
    		$iconPath = SugarThemeRegistry::current()->getImageURL('icon_'.ucfirst($module).'_32.png');
1474
    	}
1475
    	return $iconPath;
1476
    }
1477
1478
    /**
1479
     * Returns the string which will be shown in the browser's title; defaults to using the same breadcrumb
1480
     * as in the module title
1481
     *
1482
     * @return string
1483
     */
1484
    public function getBrowserTitle()
1485
    {
1486
        global $app_strings;
1487
1488
        $browserTitle = $app_strings['LBL_BROWSER_TITLE'];
1489
        if ( $this->module == 'Users' && ($this->action == 'SetTimezone' || $this->action == 'Login') )
1490
            return $browserTitle;
1491
        $params = $this->_getModuleTitleParams(true);
1492
        foreach ($params as $value )
1493
            $browserTitle = strip_tags($value) . ' &raquo; ' . $browserTitle;
1494
1495
        return $browserTitle;
1496
    }
1497
1498
    /**
1499
     * Returns the correct breadcrumb symbol according to theme's directionality setting
1500
     *
1501
     * @return string
1502
     */
1503
    public function getBreadCrumbSymbol()
1504
    {
1505
    	if(SugarThemeRegistry::current()->directionality == "ltr") {
1506
        	return "<span class='pointer'>&raquo;</span>";
1507
        }
1508
        else {
1509
        	return "<span class='pointer'>&laquo;</span>";
1510
        }
1511
    }
1512
1513
    /**
1514
     * Fetch config values to be put into an array for JavaScript
1515
     *
1516
     * @return array
1517
     */
1518
    protected function getSugarConfigJS(){
1519
        global $sugar_config;
1520
1521
        // Set all the config parameters in the JS config as necessary
1522
        $config_js = array();
1523
        // AjaxUI stock banned modules
1524
        $config_js[] = "SUGAR.config.stockAjaxBannedModules = ".json_encode(ajaxBannedModules()).";";
1525
        if ( isset($sugar_config['quicksearch_querydelay']) ) {
1526
            $config_js[] = $this->prepareConfigVarForJs('quicksearch_querydelay', $sugar_config['quicksearch_querydelay']);
1527
        }
1528
        if ( empty($sugar_config['disableAjaxUI']) ) {
1529
            $config_js[] = "SUGAR.config.disableAjaxUI = false;";
1530
        }
1531
        else{
1532
            $config_js[] = "SUGAR.config.disableAjaxUI = true;";
1533
        }
1534
        if ( !empty($sugar_config['addAjaxBannedModules']) ){
1535
            $config_js[] = $this->prepareConfigVarForJs('addAjaxBannedModules', $sugar_config['addAjaxBannedModules']);
1536
        }
1537
        if ( !empty($sugar_config['overrideAjaxBannedModules']) ){
1538
            $config_js[] = $this->prepareConfigVarForJs('overrideAjaxBannedModules', $sugar_config['overrideAjaxBannedModules']);
1539
        }
1540
        if (!empty($sugar_config['js_available']) && is_array ($sugar_config['js_available']))
1541
        {
1542
            foreach ($sugar_config['js_available'] as $configKey)
1543
            {
1544
                if (isset($sugar_config[$configKey]))
1545
                {
1546
                    $jsVariableStatement = $this->prepareConfigVarForJs($configKey, $sugar_config[$configKey]);
1547
                    if (!array_search($jsVariableStatement, $config_js))
1548
                    {
1549
                        $config_js[] = $jsVariableStatement;
1550
                    }
1551
                }
1552
            }
1553
        }
1554
1555
        return $config_js;
1556
    }
1557
1558
    /**
1559
     * Utility method to convert sugar_config values into a JS acceptable format.
1560
     *
1561
     * @param string $key       Config Variable Name
1562
     * @param string $value     Config Variable Value
1563
     * @return string
1564
     */
1565
    protected function prepareConfigVarForJs($key, $value)
1566
    {
1567
        $value = json_encode($value);
1568
        return "SUGAR.config.{$key} = {$value};";
1569
    }
1570
1571
    /**
1572
     * getHelpText
1573
     *
1574
     * This is a protected function that returns the help text portion.  It is called from getModuleTitle.
1575
     *
1576
     * @param $module String the formatted module name
1577
     * @return $theTitle String the HTML for the help text
0 ignored issues
show
Documentation introduced by
The doc-type $theTitle could not be parsed: Unknown type name "$theTitle" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1578
     */
1579
    protected function getHelpText($module)
1580
    {
1581
        $createImageURL = SugarThemeRegistry::current()->getImageURL('create-record.gif');
1582
        $url = ajaxLink("index.php?module=$module&action=EditView&return_module=$module&return_action=DetailView");
1583
        $theTitle = <<<EOHTML
1584
&nbsp;
1585
<img src='{$createImageURL}' alt='{$GLOBALS['app_strings']['LNK_CREATE']}'>
1586
<a href="{$url}" class="utilsLink">
1587
{$GLOBALS['app_strings']['LNK_CREATE']}
1588
</a>
1589
EOHTML;
1590
        return $theTitle;
1591
    }
1592
1593
    /**
1594
     * Retrieves favicon corresponding to currently requested module
1595
     *
1596
     * @return array
1597
     */
1598
    protected function getFavicon()
1599
    {
1600
        // get favicon
1601
        if(isset($GLOBALS['sugar_config']['default_module_favicon']))
1602
            $module_favicon = $GLOBALS['sugar_config']['default_module_favicon'];
1603
        else
1604
            $module_favicon = false;
1605
1606
        $themeObject = SugarThemeRegistry::current();
1607
1608
        $favicon = '';
1609
        if ( $module_favicon )
1610
            $favicon = $themeObject->getImageURL($this->module.'.gif',false);
1611
        if ( !sugar_is_file($favicon) || !$module_favicon )
1612
            $favicon = $themeObject->getImageURL('sugar_icon.ico',false);
1613
1614
        $extension = pathinfo($favicon, PATHINFO_EXTENSION);
1615
        switch ($extension)
1616
        {
1617
            case 'png':
1618
                $type = 'image/png';
1619
                break;
1620
            case 'ico':
1621
                // fall through
1622
            default:
1623
                $type = 'image/x-icon';
1624
                break;
1625
        }
1626
1627
        return array(
1628
            'url'  => getJSPath($favicon),
1629
            'type' => $type,
1630
        );
1631
    }
1632
1633
1634
    /**
1635
     * getCustomFilePathIfExists
1636
     *
1637
     * This function wraps a call to get_custom_file_if_exists from include/utils.php
1638
     *
1639
     * @param $file String of filename to check
1640
     * @return $file String of filename including custom directory if found
0 ignored issues
show
Documentation introduced by
The doc-type $file could not be parsed: Unknown type name "$file" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1641
     */
1642
    protected function getCustomFilePathIfExists($file)
1643
    {
1644
        return get_custom_file_if_exists($file);
1645
    }
1646
1647
1648
    /**
1649
     * fetchTemplate
1650
     *
1651
     * This function wraps the call to the fetch function of the Smarty variable for the view
1652
     *
1653
     * @param $file String path of the file to fetch
1654
     * @return $content String content from resulting Smarty fetch operation on template
0 ignored issues
show
Documentation introduced by
The doc-type $content could not be parsed: Unknown type name "$content" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1655
     */
1656
    protected function fetchTemplate($file)
1657
    {
1658
        return $this->ss->fetch($file);
1659
    }
1660
1661
    /**
1662
     * handles the tracker output, and adds a link and a shortened name.
1663
     * given html safe input, it will preserve html safety
1664
     *
1665
     * @param array $history - returned from the tracker
1666
     * @return array augmented history with image link and shortened name
1667
     */
1668
    protected function processRecentRecords($history) {
1669
        foreach ( $history as $key => $row ) {
1670
            $history[$key]['item_summary_short'] = to_html(getTrackerSubstring($row['item_summary'])); //bug 56373 - need to re-HTML-encode
1671
            $history[$key]['image'] = SugarThemeRegistry::current()
1672
                ->getImage($row['module_name'],'border="0" align="absmiddle"',null,null,'.gif',$row['item_summary']);
1673
        }
1674
        return $history;
1675
    }
1676
1677
    /**
1678
	 * Determines whether the state of the post global array indicates there was an error uploading a
1679
     * file that exceeds the post_max_size setting.  Such an error can be detected if:
1680
     *  1. The Server['REQUEST_METHOD'] will still point to POST
1681
     *  2. POST and FILES global arrays will be returned empty despite the request method
1682
     * This also results in a redirect to the home page (due to lack of module and action in POST)
1683
     *
1684
	 * @return boolean indicating true or false
1685
	 */
1686
    public function checkPostMaxSizeError(){
1687
         //if the referrer is post, and the post array is empty, then an error has occurred, most likely
1688
         //while uploading a file that exceeds the post_max_size.
1689
         if(empty($_FILES) && empty($_POST) && isset($_SERVER['REQUEST_METHOD']) && strtolower($_SERVER['REQUEST_METHOD']) == 'post'){
1690
             $GLOBALS['log']->fatal($GLOBALS['app_strings']['UPLOAD_ERROR_HOME_TEXT']);
1691
             return true;
1692
        }
1693
        return false;
1694
    }
1695
1696
1697
}
1698