PageRenderTime 507ms CodeModel.GetById 100ms app.highlight 190ms RepoModel.GetById 132ms app.codeStats 1ms

/include/MVC/View/SugarView.php

https://github.com/mikmagic/sugarcrm_dev
PHP | 1243 lines | 833 code | 163 blank | 247 comment | 191 complexity | 3ba5c97ad3a5c2173544fdfede2a672e MD5 | raw file

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file