Issues (4069)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

include/MVC/View/SugarView.php (9 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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 70
    public function __construct(
90
        $bean = null,
91
        $view_object_map = array()
92
        )
93
    {
94 70
    }
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 6
    public function init(
114
        $bean = null,
115
        $view_object_map = array()
116
        )
117
    {
118 6
        $this->bean = $bean;
119 6
        $this->view_object_map = $view_object_map;
120 6
        $this->action = $GLOBALS['action'];
121 6
        $this->module = $GLOBALS['module'];
122 6
        $this->_initSmarty();
123 5
    }
124
125 6
    protected function _initSmarty()
126
    {
127 6
        $this->ss = new Sugar_Smarty();
128 6
        $this->ss->assign('MOD', $GLOBALS['mod_strings']);
129 5
        $this->ss->assign('APP', $GLOBALS['app_strings']);
130 5
    }
131
132
    /**
133
     * This method will be called from the controller and is not meant to be overridden.
134
     */
135 1
    public function process()
136
    {
137 1
        LogicHook::initialize();
138 1
        $this->_checkModule();
139
140
        //trackView has to be here in order to track for breadcrumbs
141 1
        $this->_trackView();
142
143
        //For the ajaxUI, we need to use output buffering to return the page in an ajax friendly format
144 1
        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 1
        if ($this->_getOption('show_header')) {
152 1
            $this->displayHeader();
153
        } else {
154
            $this->renderJavascript();
155
        }
156
157 1
        $this->_buildModuleList();
158 1
        $this->preDisplay();
159 1
        $this->displayErrors();
160 1
        $this->display();
161 1
        if ( !empty($this->module) ) {
162 1
            $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 1
            !isset($_SESSION['isMobile'])
170
            &&
171
            (
172
                $this instanceof ViewList
173 1
                || $this instanceof ViewDetail
174 1
                || $this instanceof ViewEdit
175
            )
176
        ) {
177
            $jsAlerts = new jsAlerts();
178
            echo $jsAlerts->getScript();
179
        }
180
181 1
        if ($this->_getOption('show_subpanels') && !empty($_REQUEST['record'])) $this->_displaySubPanels();
182
183 1
        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 1
        if ($this->_getOption('show_footer')) $this->displayFooter();
188 1
        $GLOBALS['logic_hook']->call_custom_logic('', 'after_ui_footer');
189 1
        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
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 1
        $this->_track();
219 1
    }
220
221
    /**
222
     * This method will display the errors on the page.
223
     */
224 2
    public function displayErrors()
225
    {
226 2
        $errors = '';
227
228 2
        foreach($this->errors as $error) {
229
            $errors .= '<span class="error">' . $error . '</span><br>';
230
        }
231
232 2
        if ( !$this->suppressDisplayErrors ) {
233 2
            echo $errors;
234
        }
235
        else {
236
            return $errors;
237
        }
238 2
    }
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 2
    public function preDisplay()
250
    {
251 2
    }
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 2
    public function display()
258
    {
259 2
    }
260
261
262
    /**
263
     * trackView
264
     */
265 1
    protected function _trackView()
266
    {
267 1
        $action = strtolower($this->action);
268
        //Skip save, tracked in SugarBean instead
269 1
        if($action == 'save') {
270
        return;
271
        }
272
273
274 1
        $trackerManager = TrackerManager::getInstance();
275 1
        $timeStamp = TimeDate::getInstance()->nowDb();
276 1
        if($monitor = $trackerManager->getMonitor('tracker')){
277 1
            $monitor->setValue('action', $action);
278 1
            $monitor->setValue('user_id', $GLOBALS['current_user']->id);
279 1
            $monitor->setValue('module_name', $this->module);
280 1
            $monitor->setValue('date_modified', $timeStamp);
281 1
            $monitor->setValue('visible', (($monitor->action == 'detailview') || ($monitor->action == 'editview')
282 1
                                            ) ? 1 : 0);
283
284 1
            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 1
            if($monitor->visible && empty($this->bean->id)) {
292
            $trackerManager->unsetMonitor($monitor);
293
            return;
294
            }
295 1
            $trackerManager->saveMonitor($monitor, true, true);
296
        }
297 1
    }
298
299
300
    /**
301
     * Displays the header on section of the page; basically everything before the content
302
     */
303 2
    public function displayHeader($retModTabs=false)
304
    {
305 2
        global $theme;
306 2
        global $max_tabs;
307 2
        global $app_strings;
308 2
        global $current_user;
309 2
        global $sugar_config;
310 2
        global $app_list_strings;
311 2
        global $mod_strings;
312 2
        global $current_language;
313
314 2
        $GLOBALS['app']->headerDisplayed = true;
315
316 2
        $themeObject = SugarThemeRegistry::current();
317 2
        $theme = $themeObject->__toString();
318
319 2
        $ss = new Sugar_Smarty();
320 2
        $ss->assign("APP", $app_strings);
321 2
        $ss->assign("THEME", $theme);
322 2
        $ss->assign("THEME_CONFIG", $themeObject->getConfig());
323 2
        $ss->assign("THEME_IE6COMPAT", $themeObject->ie6compat ? 'true':'false');
0 ignored issues
show
The property ie6compat does not exist on object<SugarTheme>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read 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.");
        }
    }

}

If the property has read access only, you can use the @property-read 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...
324 2
        $ss->assign("MODULE_NAME", $this->module);
325 2
        $ss->assign("langHeader", get_language_header());
326
327
        // set ab testing if exists
328 2
        $testing = (isset($_REQUEST["testing"]) ? $_REQUEST['testing'] : "a");
329 2
        $ss->assign("ABTESTING", $testing);
330
331
        // get browser title
332 2
        $ss->assign("SYSTEM_NAME", $this->getBrowserTitle());
333
334
        // get css
335 2
        $css = $themeObject->getCSS();
336 2
        if ($this->_getOption('view_print')) {
337
            $css .= '<link rel="stylesheet" type="text/css" href="'.$themeObject->getCSSURL('print.css').'" media="all" />';
338
        }
339 2
        $ss->assign("SUGAR_CSS",$css);
340
341
        // get javascript
342 2
        ob_start();
343 2
        $this->renderJavascript();
344
345 2
        $ss->assign("SUGAR_JS",ob_get_contents().$themeObject->getJS());
346 2
        ob_end_clean();
347
348
        // get favicon
349 2
        if(isset($GLOBALS['sugar_config']['default_module_favicon']))
350
            $module_favicon = $GLOBALS['sugar_config']['default_module_favicon'];
351
        else
352 2
            $module_favicon = false;
353
354 2
        $favicon = $this->getFavicon();
355 2
        $ss->assign('FAVICON_URL', $favicon['url']);
356
357
        // build the shortcut menu
358 2
        $shortcut_menu = array();
359 2
        foreach ( $this->getMenu() as $key => $menu_item )
360 2
            $shortcut_menu[$key] = array(
361 2
                "URL"         => $menu_item[0],
362 2
                "LABEL"       => $menu_item[1],
363 2
                "MODULE_NAME" => $menu_item[2],
364
                "IMAGE"       => $themeObject
365 2
                    ->getImage($menu_item[2],"border='0' align='absmiddle'",null,null,'.gif',$menu_item[1]),
366
                );
367 2
        $ss->assign("SHORTCUT_MENU",$shortcut_menu);
368
369
        // handle rtl text direction
370 2
        if(isset($_REQUEST['RTL']) && $_REQUEST['RTL'] == 'RTL'){
371
            $_SESSION['RTL'] = true;
372
        }
373 2
        if(isset($_REQUEST['LTR']) && $_REQUEST['LTR'] == 'LTR'){
374
            unset($_SESSION['RTL']);
375
        }
376 2
        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 2
        $companyLogoURL = $themeObject->getImageURL('company_logo.png');
382 2
        $companyLogoURL_arr = explode('?', $companyLogoURL);
383 2
        $companyLogoURL = $companyLogoURL_arr[0];
384
385 2
        $company_logo_attributes = sugar_cache_retrieve('company_logo_attributes');
386 2
        if(!empty($company_logo_attributes)) {
387 1
            $ss->assign("COMPANY_LOGO_MD5", $company_logo_attributes[0]);
388 1
            $ss->assign("COMPANY_LOGO_WIDTH", $company_logo_attributes[1]);
389 1
            $ss->assign("COMPANY_LOGO_HEIGHT", $company_logo_attributes[2]);
390
        }
391
        else {
392
            // Always need to md5 the file
393 1
            $ss->assign("COMPANY_LOGO_MD5", md5_file($companyLogoURL));
394
395 1
            list($width,$height) = getimagesize($companyLogoURL);
396 1
            if ( $width > 212 || $height > 40 ) {
397 1
                $resizePctWidth  = ($width - 212)/212;
398 1
                $resizePctHeight = ($height - 40)/40;
399 1
                if ( $resizePctWidth > $resizePctHeight )
400
                    $resizeAmount = $width / 212;
401
                else
402 1
                    $resizeAmount = $height / 40;
403 1
                $ss->assign("COMPANY_LOGO_WIDTH", round($width * (1/$resizeAmount)));
404 1
                $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 1
            sugar_cache_put('company_logo_attributes',
413
                            array(
414 1
                                $ss->get_template_vars("COMPANY_LOGO_MD5"),
415 1
                                $ss->get_template_vars("COMPANY_LOGO_WIDTH"),
416 1
                                $ss->get_template_vars("COMPANY_LOGO_HEIGHT")
417
                                )
418
            );
419
        }
420 2
        $ss->assign("COMPANY_LOGO_URL",getJSPath($companyLogoURL)."&logo_md5=".$ss->get_template_vars("COMPANY_LOGO_MD5"));
421
422
        // get the global links
423 2
        $gcls = array();
424 2
        $global_control_links = array();
425 2
        require("include/globalControlLinks.php");
426
427 2
        foreach($global_control_links as $key => $value) {
428 2
            if ($key == 'users')  {   //represents logout link.
429 2
                $ss->assign("LOGOUT_LINK", $value['linkinfo'][key($value['linkinfo'])]);
430 2
                $ss->assign("LOGOUT_LABEL", key($value['linkinfo']));//key value for first element.
431 2
                continue;
432
            }
433
434 2
            foreach ($value as $linkattribute => $attributevalue) {
435
                // get the main link info
436 2
                if ( $linkattribute == 'linkinfo' ) {
437 2
                    $gcls[$key] = array(
438 2
                        "LABEL" => key($attributevalue),
439 2
                        "URL"   => current($attributevalue),
440
                        "SUBMENU" => array(),
441
                        );
442 2
                   if(substr($gcls[$key]["URL"], 0, 11) == "javascript:") {
443 2
                       $gcls[$key]["ONCLICK"] = substr($gcls[$key]["URL"],11);
444 2
                       $gcls[$key]["URL"] = "javascript:void(0)";
445
                   }
446
                }
447
                // and now the sublinks
448 2
                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
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 2
                           $gcls[$key]['SUBMENU'][$submenulinkkey]["URL"] = "javascript:void(0)";
457
                       }
458
                }
459
            }
460
        }
461 2
        $ss->assign("GCLS",$gcls);
462
463 2
        $ss->assign("SEARCH", isset($_REQUEST['query_string']) ? $_REQUEST['query_string'] : '');
464
465 2
        if ($this->action == "EditView" || $this->action == "Login")
466
            $ss->assign("ONLOAD", 'onload="set_focus()"');
467
468 2
        $ss->assign("AUTHENTICATED",isset($_SESSION["authenticated_user_id"]));
469
470
        // get other things needed for page style popup
471 2
        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 2
        $bakModStrings = $mod_strings;
489 2
        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 2
        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 2
        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 2
       if(!empty($current_user)){
686 2
       	$ss->assign("max_tabs", $current_user->getPreference("max_tabs"));
687
       }
688
689
690 2
        $imageURL = SugarThemeRegistry::current()->getImageURL("dashboard.png");
691 2
        $homeImage = "<img src='$imageURL'>";
692 2
		$ss->assign("homeImage",$homeImage);
693 2
        global $mod_strings;
694 2
        $mod_strings = $bakModStrings;
695 2
        $headerTpl = $themeObject->getTemplate('header.tpl');
696 2
        if (inDeveloperMode() )
697
            $ss->clear_compiled_tpl($headerTpl);
698
699 2
        if ($retModTabs)
700
        {
701
            return $ss->fetch($themeObject->getTemplate('_headerModuleList.tpl'));
702
        } else {
703 2
            $ss->display($headerTpl);
704
705 2
            $this->includeClassicFile('modules/Administration/DisplayWarnings.php');
706
707 2
            $errorMessages = SugarApplication::getErrorMessages();
708 2
            if ( !empty($errorMessages)) {
709
                foreach ( $errorMessages as $error_message ) {
710
                    echo('<p class="error">' . $error_message.'</p>');
711
                }
712
            }
713
        }
714
715 2
    }
716
717 1
    function getModuleMenuHTML()
718
    {
719
720 1
    }
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 4
    public function includeClassicFile(
729
        $file
730
        )
731
    {
732 4
        global $sugar_config, $theme, $current_user, $sugar_version, $sugar_flavor, $mod_strings, $app_strings, $app_list_strings, $action;
733 4
        global $gridline, $request_string, $modListHeader, $dashletData, $authController, $locale, $currentModule, $import_bean_map, $image_path, $license;
734 4
        global $user_unique_key, $server_unique_key, $barChartColors, $modules_exempt_from_availability_check, $dictionary, $current_language, $beanList, $beanFiles, $sugar_build, $sugar_codename;
735 4
        global $timedate, $login_error; // cn: bug 13855 - timedate not available to classic views.
736 4
        if (!empty($this->module))
737 3
            $currentModule = $this->module;
738 4
        require_once ($file);
739 4
    }
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 4
    public static function getJavascriptValidation()
775
    {
776 4
        global $timedate;
777 4
        $cal_date_format = $timedate->get_cal_date_format();
778 4
        $timereg = $timedate->get_regular_expression($timedate->get_time_format());
779 4
        $datereg = $timedate->get_regular_expression($timedate->get_date_format());
780 4
        $date_pos = '';
781 4
        foreach ($datereg['positions'] as $type => $pos) {
782 4
            if (empty($date_pos)) {
783 4
                $date_pos .= "'$type': $pos";
784
            } else {
785 4
                $date_pos .= ",'$type': $pos";
786
            }
787
        }
788
789 4
        $time_separator = $timedate->timeSeparator();
790 4
        $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 4
        require_once ('modules/Currencies/Currency.php');
794 4
        list ($num_grp_sep, $dec_sep) = get_number_seperators();
795
796
        $the_script = "<script type=\"text/javascript\">\n" . "\tvar time_reg_format = '" .
797 4
             $timereg['format'] . "';\n" . "\tvar date_reg_format = '" .
798 4
             $datereg['format'] . "';\n" . "\tvar date_reg_positions = { $date_pos };\n" .
799 4
             "\tvar time_separator = '$time_separator';\n" .
800 4
             "\tvar cal_date_format = '$cal_date_format';\n" .
801 4
             "\tvar time_offset = $hour_offset;\n" . "\tvar num_grp_sep = '$num_grp_sep';\n" .
802 4
             "\tvar dec_sep = '$dec_sep';\n" . "</script>";
803
804 4
        return $the_script;
805
    }
806
807
    /**
808
     * Called from process(). This method will display the correct javascript.
809
     */
810 3
    protected function _displayJavascript()
811
    {
812 3
        global $locale, $sugar_config, $timedate;
813
814
815 3
        if ($this->_getOption('show_javascript')) {
816 3
            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 3
                "sugar_cache_dir" => "cache/",
828
                );
829
830 3
            if(isset($this->bean->module_dir)){
831
                $js_vars['module_sugar_grp1'] = $this->bean->module_dir;
832
            }
833 3
            if(isset($_REQUEST['action'])){
834
                $js_vars['action_sugar_grp1'] = $_REQUEST['action'];
835
            }
836 3
            echo '<script>jscal_today = 1000*' . $timedate->asUserTs($timedate->getNow()) . '; if(typeof app_strings == "undefined") app_strings = new Array();</script>';
837 3
            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 3
            echo getVersionedScript('cache/include/javascript/sugar_grp1_jquery.js');
843 3
            echo getVersionedScript('cache/include/javascript/sugar_grp1_yui.js');
844 3
            echo getVersionedScript('cache/include/javascript/sugar_grp1.js');
845 3
            echo getVersionedScript('include/javascript/calendar.js');
846
847
            // output necessary config js in the top of the page
848 3
            $config_js = $this->getSugarConfigJS();
849 3
            if(!empty($config_js)){
850 3
                echo "<script>\n".implode("\n", $config_js)."</script>\n";
851
            }
852
853 3
            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 3
            $image_server = (defined('TEMPLATE_URL'))?TEMPLATE_URL . '/':'';
858 3
            echo '<script type="text/javascript">SUGAR.themes.image_server="' . $image_server . '";</script>'; // cn: bug 12274 - create session-stored key to defend against CSRF
859 3
            echo '<script type="text/javascript">var name_format = "' . $locale->getLocaleFormatMacro() . '";</script>';
860 3
            echo self::getJavascriptValidation();
861 3
            if (!is_file(sugar_cached('jsLanguage/') . $GLOBALS['current_language'] . '.js')) {
862 1
                require_once ('include/language/jsLanguage.php');
863 1
                jsLanguage::createAppStringsCache($GLOBALS['current_language']);
864
            }
865 3
            echo getVersionedScript('cache/jsLanguage/'. $GLOBALS['current_language'] . '.js', $GLOBALS['sugar_config']['js_lang_version']);
866
867 3
			echo $this->_getModLanguageJS();
868
869 3
            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 3
            echo "<script type='text/javascript'>\n";
875 3
            foreach($js_vars as $var=>$value)
876
            {
877 3
                echo "var {$var} = '{$value}';\n";
878
            }
879 3
            echo "</script>\n";
880
        }
881 3
    }
882
883 3
	protected function _getModLanguageJS(){
884 3
		if (!is_file(sugar_cached('jsLanguage/') . $this->module . '/' . $GLOBALS['current_language'] . '.js')) {
885 1
			require_once ('include/language/jsLanguage.php');
886 1
			jsLanguage::createModuleStringsCache($this->module, $GLOBALS['current_language']);
887
		}
888 3
		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 2
    public function displayFooter()
895
    {
896 2
        if (empty($this->responseTime)) {
897 2
            $this->_calculateFooterMetrics();
898
        }
899 2
        global $sugar_config;
900 2
        global $app_strings;
901 2
        global $mod_strings;
902 2
		$themeObject = SugarThemeRegistry::current();
903
        //decide whether or not to show themepicker, default is to show
904 2
        $showThemePicker = true;
905 2
        if (isset($sugar_config['showThemePicker'])) {
906 2
            $showThemePicker = $sugar_config['showThemePicker'];
907
        }
908
909 2
        $ss = new Sugar_Smarty();
910 2
        $ss->assign("AUTHENTICATED",isset($_SESSION["authenticated_user_id"]));
911 2
        $ss->assign('MOD',return_module_language($GLOBALS['current_language'], 'Users'));
912
913 2
		$bottomLinkList = array();
914 2
		 if (isset($this->action) && $this->action != "EditView") {
915 2
			 $bottomLinkList['print'] = array($app_strings['LNK_PRINT'] => getPrintLink());
916
		}
917 2
		$bottomLinkList['backtotop'] = array($app_strings['LNK_BACKTOTOP'] => 'javascript:SUGAR.util.top();');
918
919 2
		$bottomLinksStr = "";
920 2
		foreach($bottomLinkList as $key => $value) {
921 2
			foreach($value as $text => $link) {
922 2
				   $href = $link;
923 2
				   if(substr($link, 0, 11) == "javascript:") {
924 2
                       $onclick = " onclick=\"".substr($link,11)."\"";
925 2
                       $href = "javascript:void(0)";
926
                   } else {
927
                   		$onclick = "";
928
                   	}
929 2
                $imageURL = SugarThemeRegistry::current()->getImageURL($key.'.gif');
930 2
				$bottomLinksStr .= "<a href=\"{$href}\"";
931 2
				$bottomLinksStr .= (isset($onclick)) ? $onclick : "";
932 2
				$bottomLinksStr .= "><img src='{$imageURL}' alt=''>"; //keeping alt blank on purpose for 508 (text will be read instead)
933 2
				$bottomLinksStr .= " ".$text."</a>";
934
			}
935
		}
936 2
		$ss->assign("BOTTOMLINKS",$bottomLinksStr);
937 2
        if (SugarConfig::getInstance()->get('calculate_response_time', false))
938 2
            $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 2
        $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 2
        $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 2
        $companyLogoURL = $themeObject->getImageURL('company_logo.png');
968 2
        $companyLogoURL_arr = explode('?', $companyLogoURL);
969 2
        $companyLogoURL = $companyLogoURL_arr[0];
970
971 2
        $company_logo_attributes = sugar_cache_retrieve('company_logo_attributes');
972 2
        if(!empty($company_logo_attributes)) {
973 2
            $ss->assign("COMPANY_LOGO_MD5", $company_logo_attributes[0]);
974 2
            $ss->assign("COMPANY_LOGO_WIDTH", $company_logo_attributes[1]);
975 2
            $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 2
        $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 2
        $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 2
        if(file_exists('include/images/poweredby_sugarcrm_65.png')){
1014 2
            $copyright .= $attribLinkImg;
1015
        }
1016
        // End Required Image
1017 2
        $ss->assign('COPYRIGHT',$copyright);
1018
1019
        // here we allocate the help link data
1020 2
        $help_actions_blacklist = array('Login'); // we don't want to show a context help link here
1021 2
        if (!in_array($this->action,$help_actions_blacklist)) {
1022 2
            $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 2
                        '&help_module='.$this->module.'&help_action='.$this->action.'&key='.$GLOBALS['server_unique_key'].'\'))';
1024 2
            $label = (isset($GLOBALS['app_list_strings']['moduleList'][$this->module]) ?
1025 2
                        $GLOBALS['app_list_strings']['moduleList'][$this->module] : $this->module). ' '.$app_strings['LNK_HELP'];
1026 2
            $ss->assign('HELP_LINK',SugarThemeRegistry::current()->getLink($url, $label, "id='help_link_two'",
1027 2
                'help-dashlet.png', 'class="icon"',null,null,'','left'));
1028
        }
1029
        // end
1030
1031
1032 2
        $ss->display(SugarThemeRegistry::current()->getTemplate('footer.tpl'));
1033 2
    }
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 1
    protected function _buildModuleList()
1049
    {
1050 1
        if (!empty($GLOBALS['current_user']) && empty($GLOBALS['modListHeader']))
1051 1
            $GLOBALS['modListHeader'] = query_module_access_list($GLOBALS['current_user']);
1052 1
    }
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 3
    protected function _getOption(
1063
        $option,
1064
        $default = false
1065
        )
1066
    {
1067 3
        if (!empty($this->options) && isset($this->options['show_all'])) {
1068
            return $this->options['show_all'];
1069 3
        } elseif (!empty($this->options) && isset($this->options[$option])) {
1070 3
            return $this->options[$option];
1071 1
        } else return $default;
1072
    }
1073
1074
    /**
1075
     * track
1076
     * Private function to track information about the view request
1077
     */
1078 1
    private function _track()
1079
    {
1080 1
        if (empty($this->responseTime)) {
1081
            $this->_calculateFooterMetrics();
1082
        }
1083 1
        if (empty($GLOBALS['current_user']->id)) {
1084 1
            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 1
    protected function _checkModule()
1097
    {
1098 1
        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 1
    }
1105
1106 3
    public function renderJavascript()
1107
    {
1108 3
        if ($this->action !== 'Login')
1109 3
            $this->_displayJavascript();
1110
        else
1111
            $this->_displayLoginJS();
1112 3
    }
1113
1114 2
    private function _calculateFooterMetrics()
1115
    {
1116 2
        $endTime = microtime(true);
1117 2
        $deltaTime = $endTime - $GLOBALS['startTime'];
1118 2
        $this->responseTime = number_format(round($deltaTime, 2), 2);
1119
        // Print out the resources used in constructing the page.
1120 2
        $this->fileResources = count(get_included_files());
1121 2
    }
1122
1123 2
    private function _getStatistics()
1124
    {
1125 2
        $endTime = microtime(true);
1126 2
        $deltaTime = $endTime - $GLOBALS['startTime'];
1127 2
        $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 2
        $return = $response_time_string;
1129
       // $return .= '<br />';
1130 2
        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 2
        $return .= $this->logMemoryStatistics();
1151
1152 2
        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
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 2
    protected function logMemoryStatistics($newline='<br>')
1165
    {
1166 2
        $log_message = '';
1167
1168 2
        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 2
        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 3
    public function getMenu(
1213
        $module = null
1214
        )
1215
    {
1216 3
        global $current_language, $current_user, $mod_strings, $app_strings, $module_menu;
1217
1218 3
        if ( empty($module) )
1219 2
            $module = $this->module;
1220
1221
        //Need to make sure the mod_strings match the requested module or Menus may fail
1222 3
        $curr_mod_strings = $mod_strings;
1223 3
        $mod_strings = return_module_language ( $current_language, $module ) ;
1224
1225 3
        $module_menu = array();
1226
1227 3
        if (file_exists('modules/' . $module . '/Menu.php')) {
1228 3
            require('modules/' . $module . '/Menu.php');
1229
        }
1230 3
        if (file_exists('custom/modules/' . $module . '/Ext/Menus/menu.ext.php')) {
1231
            require('custom/modules/' . $module . '/Ext/Menus/menu.ext.php');
1232
        }
1233 3
        if (!file_exists('modules/' . $module . '/Menu.php')
1234 3
                && !file_exists('custom/modules/' . $module . '/Ext/Menus/menu.ext.php')
1235 3
                && !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 3
        if (file_exists('custom/application/Ext/Menus/menu.ext.php')) {
1249
            require('custom/application/Ext/Menus/menu.ext.php');
1250
        }
1251
1252 3
        $mod_strings = $curr_mod_strings;
1253 3
        $builtModuleMenu = $module_menu;
1254 3
        unset($module_menu);
1255
1256 3
        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 5
    public function getModuleTitle(
1296
        $show_help = true
1297
        )
1298
    {
1299 5
        global $sugar_version, $sugar_flavor, $server_unique_key, $current_language, $action;
1300
1301 5
        $theTitle = "<div class='moduleTitle'>\n";
1302
1303 5
        $module = preg_replace("/ /","",$this->module);
1304
1305 5
        $params = $this->_getModuleTitleParams();
1306 5
        $index = 0;
1307
1308 5
		if(SugarThemeRegistry::current()->directionality == "rtl") {
1309
			$params = array_reverse($params);
1310
		}
1311 5
		if(count($params) > 1) {
1312
			array_shift($params);
1313
		}
1314 5
		$count = count($params);
1315 5
        $paramString = '';
1316 5
        foreach($params as $parm){
1317 5
            $index++;
1318 5
            $paramString .= $parm;
1319 5
            if($index < $count){
1320 5
                $paramString .= $this->getBreadCrumbSymbol();
1321
            }
1322
        }
1323
1324 5
        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 5
        if($show_help || $this->type == 'list') {
1335 5
            $theTitle .= "<span class='utils'>";
1336 5
            $createImageURL = SugarThemeRegistry::current()->getImageURL('create-record.gif');
1337 5
            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 5
            if($show_help) {
1339
                $theTitle .= <<<EOHTML
1340
&nbsp;
1341 5
<a id="create_image" href="{$url}" class="utilsLink">
1342 5
<img src='{$createImageURL}' alt='{$GLOBALS['app_strings']['LNK_CREATE']}'></a>
1343 5
<a id="create_link" href="{$url}" class="utilsLink">
1344 5
{$GLOBALS['app_strings']['LNK_CREATE']}
1345 5
</a>
1346
EOHTML;
1347
            }
1348 5
            $theTitle .= "</span>";
1349
        }
1350
1351 5
        $theTitle .= "<div class='clear'></div></div>\n";
1352 5
        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 7
    public function getMetaDataFile()
1361
    {
1362 7
        $metadataFile = null;
1363 7
        $foundViewDefs = false;
1364 7
        $viewDef = strtolower($this->type) . 'viewdefs';
1365 7
        $coreMetaPath = 'modules/'.$this->module.'/metadata/' . $viewDef . '.php';
1366 7
        if(file_exists('custom/' .$coreMetaPath )){
1367
            $metadataFile = 'custom/' . $coreMetaPath;
1368
            $foundViewDefs = true;
1369
        }else{
1370 7
            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
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 7
            }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 7
        if(!$foundViewDefs && file_exists($coreMetaPath)){
1386 7
                $metadataFile = $coreMetaPath;
1387
        }
1388 7
        $GLOBALS['log']->debug("metadatafile=". $metadataFile);
1389
1390 7
        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 8
    protected function _getModuleTitleParams($browserTitle = false)
1402
    {
1403 8
        $params = array($this->_getModuleTitleListParam($browserTitle));
1404
		//$params = array();
1405 8
        if (isset($this->action)){
1406 8
            switch ($this->action) {
1407 8
            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 8
            case 'DetailView':
1416
                $beanName = $this->bean->get_summary_text();
1417
                $params[] = $beanName;
1418
                break;
1419
            }
1420
        }
1421
1422 8
        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 8
    protected function _getModuleTitleListParam( $browserTitle = false )
1433
    {
1434 8
    	global $current_user;
1435 8
    	global $app_strings;
1436
1437 8
    	if(!empty($GLOBALS['app_list_strings']['moduleList'][$this->module]))
1438 3
    		$firstParam = $GLOBALS['app_list_strings']['moduleList'][$this->module];
1439
    	else
1440 6
    		$firstParam = $this->module;
1441
1442 8
    	$iconPath = $this->getModuleTitleIconPath($this->module);
1443 8
    	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 8
		    if (!empty($iconPath) && !$browserTitle) {
0 ignored issues
show
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 8
				return $firstParam;
1462
			}
1463
    	}
1464 1
    }
1465
1466 8
    protected function getModuleTitleIconPath($module)
1467
    {
1468 8
    	$iconPath = "";
1469 8
    	if(is_file(SugarThemeRegistry::current()->getImageURL('icon_'.$module.'_32.png',false))) {
1470 3
    		$iconPath = SugarThemeRegistry::current()->getImageURL('icon_'.$module.'_32.png');
1471
    	}
1472 6
    	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 8
    	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 3
    public function getBrowserTitle()
1485
    {
1486 3
        global $app_strings;
1487
1488 3
        $browserTitle = $app_strings['LBL_BROWSER_TITLE'];
1489 3
        if ( $this->module == 'Users' && ($this->action == 'SetTimezone' || $this->action == 'Login') )
1490
            return $browserTitle;
1491 3
        $params = $this->_getModuleTitleParams(true);
1492 3
        foreach ($params as $value )
1493 3
            $browserTitle = strip_tags($value) . ' &raquo; ' . $browserTitle;
1494
1495 3
        return $browserTitle;
1496
    }
1497
1498
    /**
1499
     * Returns the correct breadcrumb symbol according to theme's directionality setting
1500
     *
1501
     * @return string
1502
     */
1503 2
    public function getBreadCrumbSymbol()
1504
    {
1505 2
    	if(SugarThemeRegistry::current()->directionality == "ltr") {
1506 2
        	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 3
    protected function getSugarConfigJS(){
1519 3
        global $sugar_config;
1520
1521
        // Set all the config parameters in the JS config as necessary
1522 3
        $config_js = array();
1523
        // AjaxUI stock banned modules
1524 3
        $config_js[] = "SUGAR.config.stockAjaxBannedModules = ".json_encode(ajaxBannedModules()).";";
1525 3
        if ( isset($sugar_config['quicksearch_querydelay']) ) {
1526
            $config_js[] = $this->prepareConfigVarForJs('quicksearch_querydelay', $sugar_config['quicksearch_querydelay']);
1527
        }
1528 3
        if ( empty($sugar_config['disableAjaxUI']) ) {
1529 3
            $config_js[] = "SUGAR.config.disableAjaxUI = false;";
1530
        }
1531
        else{
1532
            $config_js[] = "SUGAR.config.disableAjaxUI = true;";
1533
        }
1534 3
        if ( !empty($sugar_config['addAjaxBannedModules']) ){
1535 3
            $config_js[] = $this->prepareConfigVarForJs('addAjaxBannedModules', $sugar_config['addAjaxBannedModules']);
1536
        }
1537 3
        if ( !empty($sugar_config['overrideAjaxBannedModules']) ){
1538
            $config_js[] = $this->prepareConfigVarForJs('overrideAjaxBannedModules', $sugar_config['overrideAjaxBannedModules']);
1539
        }
1540 3
        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 3
        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 3
    protected function prepareConfigVarForJs($key, $value)
1566
    {
1567 3
        $value = json_encode($value);
1568 3
        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
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 2
    protected function getFavicon()
1599
    {
1600
        // get favicon
1601 2
        if(isset($GLOBALS['sugar_config']['default_module_favicon']))
1602
            $module_favicon = $GLOBALS['sugar_config']['default_module_favicon'];
1603
        else
1604 2
            $module_favicon = false;
1605
1606 2
        $themeObject = SugarThemeRegistry::current();
1607
1608 2
        $favicon = '';
1609 2
        if ( $module_favicon )
1610
            $favicon = $themeObject->getImageURL($this->module.'.gif',false);
1611 2
        if ( !sugar_is_file($favicon) || !$module_favicon )
1612 2
            $favicon = $themeObject->getImageURL('sugar_icon.ico',false);
1613
1614 2
        $extension = pathinfo($favicon, PATHINFO_EXTENSION);
1615
        switch ($extension)
1616
        {
1617 2
            case 'png':
1618
                $type = 'image/png';
1619
                break;
1620 2
            case 'ico':
1621
                // fall through
1622
            default:
1623 2
                $type = 'image/x-icon';
1624 2
                break;
1625
        }
1626
1627
        return array(
1628 2
            'url'  => getJSPath($favicon),
1629 2
            '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
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 2
    protected function getCustomFilePathIfExists($file)
1643
    {
1644 2
        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
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 1
    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 1
         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 1
        return false;
1694
    }
1695
1696
1697
}
1698