PageRenderTime 50ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/SugarCRM/include/MVC/View/SugarView.php

https://github.com/guolong/ggxw
PHP | 1655 lines | 1101 code | 215 blank | 339 comment | 238 complexity | 71c751182e3989af51828092fe4bc45f MD5 | raw file
Possible License(s): AGPL-3.0, LGPL-2.1, MPL-2.0-no-copyleft-exception

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

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