PageRenderTime 59ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/include/MVC/View/SugarView.php

https://github.com/vincentamari/SuperSweetAdmin
PHP | 1248 lines | 838 code | 161 blank | 249 comment | 192 complexity | 6f087797e1a4bc67abb8c17fcae9aac1 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, AGPL-3.0, LGPL-2.1

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

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

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