PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/libraries/ThemeManager.php

https://gitlab.com/trungthao379/phpmyadmin
PHP | 528 lines | 259 code | 59 blank | 210 comment | 40 complexity | fa4669f7821be95e328121a854de9557 MD5 | raw file
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * phpMyAdmin theme manager
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. namespace PMA\libraries;
  9. use PMA\libraries\URL;
  10. /**
  11. * phpMyAdmin theme manager
  12. *
  13. * @package PhpMyAdmin
  14. */
  15. class ThemeManager
  16. {
  17. /**
  18. * ThemeManager instance
  19. *
  20. * @access private
  21. * @static
  22. * @var ThemeManager
  23. */
  24. private static $_instance;
  25. /**
  26. * @var string path to theme folder
  27. * @access protected
  28. */
  29. private $_themes_path = './themes/';
  30. /**
  31. * @var array available themes
  32. */
  33. var $themes = array();
  34. /**
  35. * @var string cookie name
  36. */
  37. var $cookie_name = 'pma_theme';
  38. /**
  39. * @var boolean
  40. */
  41. var $per_server = false;
  42. /**
  43. * @var string name of active theme
  44. */
  45. var $active_theme = '';
  46. /**
  47. * @var Theme Theme active theme
  48. */
  49. var $theme = null;
  50. /**
  51. * @var string
  52. */
  53. var $theme_default;
  54. /**
  55. * @const string The name of the fallback theme
  56. */
  57. const FALLBACK_THEME = 'pmahomme';
  58. /**
  59. * Constructor for Theme Manager class
  60. *
  61. * @access public
  62. */
  63. public function __construct()
  64. {
  65. $this->init();
  66. }
  67. /**
  68. * Returns the singleton Response object
  69. *
  70. * @return Response object
  71. */
  72. public static function getInstance()
  73. {
  74. if (empty(self::$_instance)) {
  75. self::$_instance = new ThemeManager();
  76. }
  77. return self::$_instance;
  78. }
  79. /**
  80. * sets path to folder containing the themes
  81. *
  82. * @param string $path path to themes folder
  83. *
  84. * @access public
  85. * @return boolean success
  86. */
  87. public function setThemesPath($path)
  88. {
  89. if (! $this->_checkThemeFolder($path)) {
  90. return false;
  91. }
  92. $this->_themes_path = trim($path);
  93. return true;
  94. }
  95. /**
  96. * sets if there are different themes per server
  97. *
  98. * @param boolean $per_server Whether to enable per server flag
  99. *
  100. * @access public
  101. * @return void
  102. */
  103. public function setThemePerServer($per_server)
  104. {
  105. $this->per_server = (bool) $per_server;
  106. }
  107. /**
  108. * Initialise the class
  109. *
  110. * @access public
  111. * @return void
  112. */
  113. public function init()
  114. {
  115. $this->themes = array();
  116. $this->theme_default = self::FALLBACK_THEME;
  117. $this->active_theme = '';
  118. if (! $this->setThemesPath('./themes/')) {
  119. return;
  120. }
  121. $this->setThemePerServer($GLOBALS['cfg']['ThemePerServer']);
  122. $this->loadThemes();
  123. $this->theme = new Theme;
  124. if (! $this->checkTheme($GLOBALS['cfg']['ThemeDefault'])) {
  125. trigger_error(
  126. sprintf(
  127. __('Default theme %s not found!'),
  128. htmlspecialchars($GLOBALS['cfg']['ThemeDefault'])
  129. ),
  130. E_USER_ERROR
  131. );
  132. $GLOBALS['cfg']['ThemeDefault'] = false;
  133. }
  134. $this->theme_default = $GLOBALS['cfg']['ThemeDefault'];
  135. // check if user have a theme cookie
  136. if (! $this->getThemeCookie()
  137. || ! $this->setActiveTheme($this->getThemeCookie())
  138. ) {
  139. if ($GLOBALS['cfg']['ThemeDefault']) {
  140. // otherwise use default theme
  141. $this->setActiveTheme($this->theme_default);
  142. } else {
  143. // or fallback theme
  144. $this->setActiveTheme(self::FALLBACK_THEME);
  145. }
  146. }
  147. }
  148. /**
  149. * Checks configuration
  150. *
  151. * @access public
  152. * @return void
  153. */
  154. public function checkConfig()
  155. {
  156. if ($this->theme_default != $GLOBALS['cfg']['ThemeDefault']
  157. ) {
  158. $this->init();
  159. } else {
  160. // at least the theme path needs to be checked every time for new
  161. // themes, as there is no other way at the moment to keep track of
  162. // new or removed themes
  163. $this->loadThemes();
  164. }
  165. }
  166. /**
  167. * Sets active theme
  168. *
  169. * @param string $theme theme name
  170. *
  171. * @access public
  172. * @return bool true on success
  173. */
  174. public function setActiveTheme($theme = null)
  175. {
  176. if (! $this->checkTheme($theme)) {
  177. trigger_error(
  178. sprintf(
  179. __('Theme %s not found!'),
  180. htmlspecialchars($theme)
  181. ),
  182. E_USER_ERROR
  183. );
  184. return false;
  185. }
  186. $this->active_theme = $theme;
  187. $this->theme = $this->themes[$theme];
  188. // need to set later
  189. //$this->setThemeCookie();
  190. return true;
  191. }
  192. /**
  193. * Returns name for storing theme
  194. *
  195. * @return string cookie name
  196. * @access public
  197. */
  198. public function getThemeCookieName()
  199. {
  200. // Allow different theme per server
  201. if (isset($GLOBALS['server']) && $this->per_server) {
  202. return $this->cookie_name . '-' . $GLOBALS['server'];
  203. } else {
  204. return $this->cookie_name;
  205. }
  206. }
  207. /**
  208. * returns name of theme stored in the cookie
  209. *
  210. * @return string theme name from cookie
  211. * @access public
  212. */
  213. public function getThemeCookie()
  214. {
  215. if (isset($_COOKIE[$this->getThemeCookieName()])) {
  216. return $_COOKIE[$this->getThemeCookieName()];
  217. }
  218. return false;
  219. }
  220. /**
  221. * save theme in cookie
  222. *
  223. * @return bool true
  224. * @access public
  225. */
  226. public function setThemeCookie()
  227. {
  228. $GLOBALS['PMA_Config']->setCookie(
  229. $this->getThemeCookieName(),
  230. $this->theme->id,
  231. $this->theme_default
  232. );
  233. // force a change of a dummy session variable to avoid problems
  234. // with the caching of phpmyadmin.css.php
  235. $GLOBALS['PMA_Config']->set('theme-update', $this->theme->id);
  236. return true;
  237. }
  238. /**
  239. * Checks whether folder is valid for storing themes
  240. *
  241. * @param string $folder Folder name to test
  242. *
  243. * @return boolean
  244. * @access private
  245. */
  246. private function _checkThemeFolder($folder)
  247. {
  248. if (! is_dir($folder)) {
  249. trigger_error(
  250. sprintf(
  251. __('Theme path not found for theme %s!'),
  252. htmlspecialchars($folder)
  253. ),
  254. E_USER_ERROR
  255. );
  256. return false;
  257. }
  258. return true;
  259. }
  260. /**
  261. * read all themes
  262. *
  263. * @return bool true
  264. * @access public
  265. */
  266. public function loadThemes()
  267. {
  268. $this->themes = array();
  269. if (false === ($handleThemes = opendir($this->_themes_path))) {
  270. trigger_error(
  271. 'phpMyAdmin-ERROR: cannot open themes folder: '
  272. . $this->_themes_path,
  273. E_USER_WARNING
  274. );
  275. return false;
  276. }
  277. // check for themes directory
  278. while (false !== ($PMA_Theme = readdir($handleThemes))) {
  279. // Skip non dirs, . and ..
  280. if ($PMA_Theme == '.'
  281. || $PMA_Theme == '..'
  282. || ! is_dir($this->_themes_path . $PMA_Theme)
  283. ) {
  284. continue;
  285. }
  286. if (array_key_exists($PMA_Theme, $this->themes)) {
  287. continue;
  288. }
  289. $new_theme = Theme::load(
  290. $this->_themes_path . $PMA_Theme
  291. );
  292. if ($new_theme) {
  293. $new_theme->setId($PMA_Theme);
  294. $this->themes[$PMA_Theme] = $new_theme;
  295. }
  296. } // end get themes
  297. closedir($handleThemes);
  298. ksort($this->themes);
  299. return true;
  300. }
  301. /**
  302. * checks if given theme name is a known theme
  303. *
  304. * @param string $theme name fo theme to check for
  305. *
  306. * @return bool
  307. * @access public
  308. */
  309. public function checkTheme($theme)
  310. {
  311. if (! array_key_exists($theme, $this->themes)) {
  312. return false;
  313. }
  314. return true;
  315. }
  316. /**
  317. * returns HTML selectbox, with or without form enclosed
  318. *
  319. * @param boolean $form whether enclosed by from tags or not
  320. *
  321. * @return string
  322. * @access public
  323. */
  324. public function getHtmlSelectBox($form = true)
  325. {
  326. $select_box = '';
  327. if ($form) {
  328. $select_box .= '<form name="setTheme" method="get"';
  329. $select_box .= ' action="index.php" class="disableAjax">';
  330. $select_box .= URL::getHiddenInputs();
  331. }
  332. $theme_preview_path= './themes.php';
  333. $theme_preview_href = '<a href="'
  334. . $theme_preview_path . '" target="themes" class="themeselect">';
  335. $select_box .= $theme_preview_href . __('Theme:') . '</a>' . "\n";
  336. $select_box .= '<select name="set_theme" lang="en" dir="ltr"'
  337. . ' class="autosubmit">';
  338. foreach ($this->themes as $each_theme_id => $each_theme) {
  339. $select_box .= '<option value="' . $each_theme_id . '"';
  340. if ($this->active_theme === $each_theme_id) {
  341. $select_box .= ' selected="selected"';
  342. }
  343. $select_box .= '>' . htmlspecialchars($each_theme->getName())
  344. . '</option>';
  345. }
  346. $select_box .= '</select>';
  347. if ($form) {
  348. $select_box .= '</form>';
  349. }
  350. return $select_box;
  351. }
  352. /**
  353. * enables backward compatibility
  354. *
  355. * @return void
  356. * @access public
  357. */
  358. public function makeBc()
  359. {
  360. $GLOBALS['theme'] = $this->theme->getId();
  361. $GLOBALS['pmaThemePath'] = $this->theme->getPath();
  362. $GLOBALS['pmaThemeImage'] = $this->theme->getImgPath();
  363. /**
  364. * load layout file if exists
  365. */
  366. if (file_exists($this->theme->getLayoutFile())) {
  367. include $this->theme->getLayoutFile();
  368. }
  369. }
  370. /**
  371. * Renders the previews for all themes
  372. *
  373. * @return string
  374. * @access public
  375. */
  376. public function getPrintPreviews()
  377. {
  378. $retval = '';
  379. foreach ($this->themes as $each_theme) {
  380. $retval .= $each_theme->getPrintPreview();
  381. } // end 'open themes'
  382. return $retval;
  383. }
  384. /**
  385. * returns Theme object for fall back theme
  386. *
  387. * @return Theme fall back theme
  388. * @access public
  389. */
  390. public function getFallBackTheme()
  391. {
  392. if (isset($this->themes[self::FALLBACK_THEME])) {
  393. return $this->themes[self::FALLBACK_THEME];
  394. }
  395. return false;
  396. }
  397. /**
  398. * prints css data
  399. *
  400. * @return bool
  401. * @access public
  402. */
  403. public function printCss()
  404. {
  405. if ($this->theme->loadCss()) {
  406. return true;
  407. }
  408. // if loading css for this theme failed, try default theme css
  409. $fallback_theme = $this->getFallBackTheme();
  410. if ($fallback_theme && $fallback_theme->loadCss()) {
  411. return true;
  412. }
  413. return false;
  414. }
  415. /**
  416. * Theme initialization
  417. *
  418. * @return void
  419. * @access public
  420. */
  421. public static function initializeTheme()
  422. {
  423. $tmanager = self::getInstance();
  424. // for the theme per server feature
  425. if (isset($_REQUEST['server']) && ! isset($_REQUEST['set_theme'])) {
  426. $GLOBALS['server'] = $_REQUEST['server'];
  427. $tmp = $tmanager->getThemeCookie();
  428. if (empty($tmp)) {
  429. $tmp = $tmanager->theme_default;
  430. }
  431. $tmanager->setActiveTheme($tmp);
  432. }
  433. /**
  434. * @todo move into ThemeManager::__wakeup()
  435. */
  436. if (isset($_REQUEST['set_theme'])) {
  437. // if user selected a theme
  438. $tmanager->setActiveTheme($_REQUEST['set_theme']);
  439. }
  440. /**
  441. * the theme object
  442. *
  443. * @global Theme $_SESSION['PMA_Theme']
  444. */
  445. $_SESSION['PMA_Theme'] = $tmanager->theme;
  446. // BC
  447. /**
  448. * the active theme
  449. * @global string $GLOBALS['theme']
  450. */
  451. $GLOBALS['theme'] = $_SESSION['PMA_Theme']->getName();
  452. /**
  453. * the theme path
  454. * @global string $GLOBALS['pmaThemePath']
  455. */
  456. $GLOBALS['pmaThemePath'] = $_SESSION['PMA_Theme']->getPath();
  457. /**
  458. * the theme image path
  459. * @global string $GLOBALS['pmaThemeImage']
  460. */
  461. $GLOBALS['pmaThemeImage'] = $_SESSION['PMA_Theme']->getImgPath();
  462. /**
  463. * load layout file if exists
  464. */
  465. if (@file_exists($_SESSION['PMA_Theme']->getLayoutFile())) {
  466. include $_SESSION['PMA_Theme']->getLayoutFile();
  467. }
  468. }
  469. }