Theme_Manager.class.php 11 KB

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