Theme.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * hold Theme class
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. namespace PhpMyAdmin;
  9. use PhpMyAdmin\Template;
  10. use PhpMyAdmin\ThemeManager;
  11. use PhpMyAdmin\Url;
  12. /**
  13. * handles theme
  14. *
  15. * @todo add the possibility to make a theme depend on another theme
  16. * and by default on original
  17. * @todo make all components optional - get missing components from 'parent' theme
  18. *
  19. * @package PhpMyAdmin
  20. */
  21. class Theme
  22. {
  23. /**
  24. * @var string theme version
  25. * @access protected
  26. */
  27. var $version = '0.0.0.0';
  28. /**
  29. * @var string theme name
  30. * @access protected
  31. */
  32. var $name = '';
  33. /**
  34. * @var string theme id
  35. * @access protected
  36. */
  37. var $id = '';
  38. /**
  39. * @var string theme path
  40. * @access protected
  41. */
  42. var $path = '';
  43. /**
  44. * @var string image path
  45. * @access protected
  46. */
  47. var $img_path = '';
  48. /**
  49. * @var integer last modification time for info file
  50. * @access protected
  51. */
  52. var $mtime_info = 0;
  53. /**
  54. * needed because sometimes, the mtime for different themes
  55. * is identical
  56. * @var integer filesize for info file
  57. * @access protected
  58. */
  59. var $filesize_info = 0;
  60. /**
  61. * @var array List of css files to load
  62. * @access private
  63. */
  64. private $_cssFiles = array(
  65. 'common',
  66. 'enum_editor',
  67. 'gis',
  68. 'navigation',
  69. 'designer',
  70. 'rte',
  71. 'codemirror',
  72. 'jqplot',
  73. 'resizable-menu',
  74. 'icons',
  75. );
  76. /**
  77. * Loads theme information
  78. *
  79. * @return boolean whether loading them info was successful or not
  80. * @access public
  81. */
  82. function loadInfo()
  83. {
  84. $infofile = $this->getPath() . '/theme.json';
  85. if (! @file_exists($infofile)) {
  86. return false;
  87. }
  88. if ($this->mtime_info === filemtime($infofile)) {
  89. return true;
  90. }
  91. $content = @file_get_contents($infofile);
  92. if ($content === false) {
  93. return false;
  94. }
  95. $data = json_decode($content, true);
  96. // Did we get expected data?
  97. if (! is_array($data)) {
  98. return false;
  99. }
  100. // Check that all required data are there
  101. $members = array('name', 'version', 'supports');
  102. foreach ($members as $member) {
  103. if (! isset($data[$member])) {
  104. return false;
  105. }
  106. }
  107. // Version check
  108. if (! is_array($data['supports'])) {
  109. return false;
  110. }
  111. if (! in_array(PMA_MAJOR_VERSION, $data['supports'])) {
  112. return false;
  113. }
  114. $this->mtime_info = filemtime($infofile);
  115. $this->filesize_info = filesize($infofile);
  116. $this->setVersion($data['version']);
  117. $this->setName($data['name']);
  118. return true;
  119. }
  120. /**
  121. * returns theme object loaded from given folder
  122. * or false if theme is invalid
  123. *
  124. * @param string $folder path to theme
  125. *
  126. * @return Theme|false
  127. * @static
  128. * @access public
  129. */
  130. static public function load($folder)
  131. {
  132. $theme = new Theme();
  133. $theme->setPath($folder);
  134. if (! $theme->loadInfo()) {
  135. return false;
  136. }
  137. $theme->checkImgPath();
  138. return $theme;
  139. }
  140. /**
  141. * checks image path for existence - if not found use img from fallback theme
  142. *
  143. * @access public
  144. * @return bool
  145. */
  146. public function checkImgPath()
  147. {
  148. // try current theme first
  149. if (is_dir($this->getPath() . '/img/')) {
  150. $this->setImgPath($this->getPath() . '/img/');
  151. return true;
  152. }
  153. // try fallback theme
  154. $fallback = './themes/' . ThemeManager::FALLBACK_THEME . '/img/';
  155. if (is_dir($fallback)) {
  156. $this->setImgPath($fallback);
  157. return true;
  158. }
  159. // we failed
  160. trigger_error(
  161. sprintf(
  162. __('No valid image path for theme %s found!'),
  163. $this->getName()
  164. ),
  165. E_USER_ERROR
  166. );
  167. return false;
  168. }
  169. /**
  170. * returns path to theme
  171. *
  172. * @access public
  173. * @return string path to theme
  174. */
  175. public function getPath()
  176. {
  177. return $this->path;
  178. }
  179. /**
  180. * returns layout file
  181. *
  182. * @access public
  183. * @return string layout file
  184. */
  185. public function getLayoutFile()
  186. {
  187. return $this->getPath() . '/layout.inc.php';
  188. }
  189. /**
  190. * set path to theme
  191. *
  192. * @param string $path path to theme
  193. *
  194. * @return void
  195. * @access public
  196. */
  197. public function setPath($path)
  198. {
  199. $this->path = trim($path);
  200. }
  201. /**
  202. * sets version
  203. *
  204. * @param string $version version to set
  205. *
  206. * @return void
  207. * @access public
  208. */
  209. public function setVersion($version)
  210. {
  211. $this->version = trim($version);
  212. }
  213. /**
  214. * returns version
  215. *
  216. * @return string version
  217. * @access public
  218. */
  219. public function getVersion()
  220. {
  221. return $this->version;
  222. }
  223. /**
  224. * checks theme version against $version
  225. * returns true if theme version is equal or higher to $version
  226. *
  227. * @param string $version version to compare to
  228. *
  229. * @return boolean true if theme version is equal or higher to $version
  230. * @access public
  231. */
  232. public function checkVersion($version)
  233. {
  234. return version_compare($this->getVersion(), $version, 'lt');
  235. }
  236. /**
  237. * sets name
  238. *
  239. * @param string $name name to set
  240. *
  241. * @return void
  242. * @access public
  243. */
  244. public function setName($name)
  245. {
  246. $this->name = trim($name);
  247. }
  248. /**
  249. * returns name
  250. *
  251. * @access public
  252. * @return string name
  253. */
  254. public function getName()
  255. {
  256. return $this->name;
  257. }
  258. /**
  259. * sets id
  260. *
  261. * @param string $id new id
  262. *
  263. * @return void
  264. * @access public
  265. */
  266. public function setId($id)
  267. {
  268. $this->id = trim($id);
  269. }
  270. /**
  271. * returns id
  272. *
  273. * @return string id
  274. * @access public
  275. */
  276. public function getId()
  277. {
  278. return $this->id;
  279. }
  280. /**
  281. * Sets path to images for the theme
  282. *
  283. * @param string $path path to images for this theme
  284. *
  285. * @return void
  286. * @access public
  287. */
  288. public function setImgPath($path)
  289. {
  290. $this->img_path = $path;
  291. }
  292. /**
  293. * Returns the path to image for the theme.
  294. * If filename is given, it possibly fallbacks to fallback
  295. * theme for it if image does not exist.
  296. *
  297. * @param string $file file name for image
  298. * @param string $fallback fallback image
  299. *
  300. * @access public
  301. * @return string image path for this theme
  302. */
  303. public function getImgPath($file = null, $fallback = null)
  304. {
  305. if (is_null($file)) {
  306. return $this->img_path;
  307. }
  308. if (is_readable($this->img_path . $file)) {
  309. return $this->img_path . $file;
  310. }
  311. if (! is_null($fallback)) {
  312. return $this->getImgPath($fallback);
  313. }
  314. return './themes/' . ThemeManager::FALLBACK_THEME . '/img/' . $file;
  315. }
  316. /**
  317. * load css (send to stdout, normally the browser)
  318. *
  319. * @return bool
  320. * @access public
  321. */
  322. public function loadCss()
  323. {
  324. $success = true;
  325. /* Variables to be used by the themes: */
  326. $theme = $this;
  327. if ($GLOBALS['text_dir'] === 'ltr') {
  328. $right = 'right';
  329. $left = 'left';
  330. } else {
  331. $right = 'left';
  332. $left = 'right';
  333. }
  334. foreach ($this->_cssFiles as $file) {
  335. $path = $this->getPath() . "/css/$file.css.php";
  336. $fallback = "./themes/"
  337. . ThemeManager::FALLBACK_THEME . "/css/$file.css.php";
  338. if (is_readable($path)) {
  339. echo "\n/* FILE: " , $file , ".css.php */\n";
  340. include $path;
  341. } elseif (is_readable($fallback)) {
  342. echo "\n/* FILE: " , $file , ".css.php */\n";
  343. include $fallback;
  344. } else {
  345. $success = false;
  346. }
  347. }
  348. return $success;
  349. }
  350. /**
  351. * Renders the preview for this theme
  352. *
  353. * @return string
  354. * @access public
  355. */
  356. public function getPrintPreview()
  357. {
  358. $url_params = ['set_theme' => $this->getId()];
  359. $screen = null;
  360. $path = $this->getPath() . '/screen.png';
  361. if (@file_exists($path)) {
  362. $screen = $path;
  363. }
  364. return Template::get('theme_preview')->render([
  365. 'url_params' => $url_params,
  366. 'name' => $this->getName(),
  367. 'version' => $this->getVersion(),
  368. 'id' => $this->getId(),
  369. 'screen' => $screen,
  370. ]);
  371. }
  372. /**
  373. * Gets currently configured font size.
  374. *
  375. * @return String with font size.
  376. */
  377. function getFontSize()
  378. {
  379. $fs = $GLOBALS['PMA_Config']->get('FontSize');
  380. if (!is_null($fs)) {
  381. return $fs;
  382. }
  383. return '82%';
  384. }
  385. /**
  386. * Generates code for CSS gradient using various browser extensions.
  387. *
  388. * @param string $start_color Color of gradient start, hex value without #
  389. * @param string $end_color Color of gradient end, hex value without #
  390. *
  391. * @return string CSS code.
  392. */
  393. function getCssGradient($start_color, $end_color)
  394. {
  395. $result = array();
  396. // Opera 9.5+, IE 9
  397. $result[] = 'background-image: url(./themes/svg_gradient.php?from='
  398. . $start_color . '&to=' . $end_color . ');';
  399. $result[] = 'background-size: 100% 100%;';
  400. // Safari 4-5, Chrome 1-9
  401. $result[] = 'background: '
  402. . '-webkit-gradient(linear, left top, left bottom, from(#'
  403. . $start_color . '), to(#' . $end_color . '));';
  404. // Safari 5.1, Chrome 10+
  405. $result[] = 'background: -webkit-linear-gradient(top, #'
  406. . $start_color . ', #' . $end_color . ');';
  407. // Firefox 3.6+
  408. $result[] = 'background: -moz-linear-gradient(top, #'
  409. . $start_color . ', #' . $end_color . ');';
  410. // IE 10
  411. $result[] = 'background: -ms-linear-gradient(top, #'
  412. . $start_color . ', #' . $end_color . ');';
  413. // Opera 11.10
  414. $result[] = 'background: -o-linear-gradient(top, #'
  415. . $start_color . ', #' . $end_color . ');';
  416. return implode("\n", $result);
  417. }
  418. }