SproutCMS

This is the code documentation for the SproutCMS project

source of /sprout/Helpers/Skin.php

  1. <?php
  2. /*
  3.  * Copyright (C) 2017 Karmabunny Pty Ltd.
  4.  *
  5.  * This file is a part of SproutCMS.
  6.  *
  7.  * SproutCMS is free software: you can redistribute it and/or modify it under the terms
  8.  * of the GNU General Public License as published by the Free Software Foundation, either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * For more information, visit <http://getsproutcms.com>.
  12.  */
  13.  
  14. namespace Sprout\Helpers;
  15.  
  16. use Exception;
  17. use Kohana;
  18. use Sprout\Exceptions\FileMissingException;
  19.  
  20. /**
  21. * Skin stuff - autoversioning mainly.
  22. **/
  23. class Skin
  24. {
  25.  
  26. /**
  27.   * ECHOs a <link> tag and a <script> tag which point to common.css and common.js respectively.
  28.   **/
  29. public static function common()
  30. {
  31. echo '<link href="ROOT/media/css/common.css" rel="stylesheet">', PHP_EOL;
  32. echo '<script type="text/javascript" src="ROOT/media/js/common.js"></script>', PHP_EOL;
  33. }
  34.  
  35.  
  36. /**
  37.   * ECHOs one or more <link> tags for the module css
  38.   * Uses either modules.css in the the skin css directory or the module.css in the modules media directories
  39.   **/
  40. public static function modules()
  41. {
  42. if (file_exists(DOCROOT . 'skin/' . SubsiteSelector::$subsite_code . '/css/modules.css')) {
  43. $ts = @filemtime(DOCROOT . 'skin/' . SubsiteSelector::$subsite_code . '/css/modules.css');
  44. if (! $ts) $ts = time();
  45. echo '<link href="ROOT/skin/', SubsiteSelector::$subsite_code, '/css/modules.css" rel="stylesheet">', PHP_EOL;
  46.  
  47. } else {
  48. $ts = time();
  49. foreach (Register::getModuleDirs() as $module_path) {
  50. if (file_exists($module_path . '/media/css/modules.css')) {
  51. $mod = basename($module_path);
  52. echo '<link href="ROOT/media-' . $ts . '/' . $mod . '/css/modules.css" rel="stylesheet">', PHP_EOL;
  53. }
  54. }
  55. }
  56. }
  57.  
  58.  
  59. /**
  60.   * Return the URL for a CSS file in the skin for the current subsite.
  61.   * The URL will have an embedded timestamp.
  62.   *
  63.   * Usage example:
  64.   * <link href="<?php echo Skin::cssUrl('layout'); ?>" rel="stylesheet">
  65.   *
  66.   * @return string URL for the specified css file
  67.   **/
  68. public static function cssUrl($file)
  69. {
  70. $ts = @filemtime(DOCROOT . 'skin/' . SubsiteSelector::$subsite_code . '/css/' . $file . '.css');
  71. if (! $ts) $ts = time();
  72.  
  73. return 'ROOT/skin-' . $ts . '/' . SubsiteSelector::$subsite_code . '/css/' . $file . '.css';
  74. }
  75.  
  76.  
  77. /**
  78.   * ECHOs one or more <link> tags referring to specified CSS files.
  79.   * Uses variable arguments, one per css file.
  80.   * The URLs will contain embedded timestamps, making them auto-versioned
  81.   *
  82.   * Usage example:
  83.   * <?php Skin::css('reset', 'layout', 'content'); ?>
  84.   *
  85.   * Optionally provide an array to specify attributes, like so:
  86.   * <?php Skin::css('site', 'home', ['crossorigin' => 'anonymous', 'media' => 'print']); ?>
  87.   * Will return:
  88.   * <link href="skin-ts/skin/css/site.css" rel='stylesheet' media='print'>
  89.   * <link href="skin-ts/skin/css/home.css" rel='stylesheet' media='print'>
  90.   *
  91.   * There isn't a guarantee that multiple tags will be ECHOed, but the order will always remain as specified.
  92.   * If you need more control use the helper `css_url` and echo the tags yourself.
  93.   **/
  94. public static function css()
  95. {
  96. $attributes = ['rel' => 'stylesheet'];
  97. $args = [];
  98. $ts = 0;
  99.  
  100. // Collect attributes or args.
  101. // Also calculate the oldest timestamp.
  102. foreach (func_get_args() as $arg) {
  103. if (is_array($arg)) {
  104. $attributes += $arg;
  105. }
  106. else {
  107. $args[] = $arg;
  108. $ts = max($ts, @filemtime(DOCROOT . 'skin/' . SubsiteSelector::$subsite_code . '/css/' . $arg . '.css'));
  109. }
  110. }
  111. if (! $ts) $ts = time();
  112.  
  113. // Build the attributes.
  114. $attr = '';
  115. foreach ($attributes as $key => $value) {
  116. $attr .= ' ' . $key . '="' . Enc::html($value) . '"';
  117. }
  118.  
  119. foreach ($args as $arg) {
  120. echo '<link href="ROOT/skin-' . $ts . '/' . SubsiteSelector::$subsite_code . '/css/' . $arg . '.css"' . $attr . '>' . PHP_EOL;
  121. }
  122. }
  123.  
  124.  
  125. /**
  126.   * Return the URL for a JS file in the skin for the current subsite.
  127.   * The URL will have an embedded timestamp.
  128.   *
  129.   * Usage example:
  130.   * <script src="<?php echo Skin::cssUrl('site'); ?>"></script>
  131.   *
  132.   * @return string URL for the specified js file
  133.   **/
  134. public static function jsUrl($file)
  135. {
  136. $ts = @filemtime(DOCROOT . 'skin/' . SubsiteSelector::$subsite_code . '/js/' . $file . '.js');
  137. if (! $ts) $ts = time();
  138.  
  139. return 'ROOT/skin-' . $ts . '/' . SubsiteSelector::$subsite_code . '/js/' . $file . '.js';
  140. }
  141.  
  142.  
  143. /**
  144.   * ECHOs one or more <script> tags referring to specified JS files.
  145.   * Uses variable arguments, one per css file.
  146.   * The URLs will contain embedded timestamps, making them auto-versioned
  147.   *
  148.   * Usage example:
  149.   * <?php Skin::js('site', 'home'); ?>
  150.   *
  151.   * Optionally provide an array to specify attributes, like so:
  152.   * <?php Skin::js('site', 'home', ['crossorigin' => 'anonymous', 'defer' => '']); ?>
  153.   * Will return:
  154.   * <script src="skin-ts/skin/js/site.js" crossorigin="anonymous" defer=""></script>
  155.   * <script src="skin-ts/skin/js/home.js" crossorigin="anonymous" defer=""></script>
  156.   *
  157.   * There isn't a guarantee that multiple tags will be ECHOed, but the order will always remain as specified.
  158.   * If you need more control use the helper `js_url` and echo the tags yourself.
  159.   **/
  160. public static function js()
  161. {
  162. $attributes = [];
  163. $args = [];
  164. $ts = 0;
  165.  
  166. // Collect attributes or args.
  167. // Also calculate the oldest timestamp.
  168. foreach (func_get_args() as $arg) {
  169. if (is_array($arg)) {
  170. $attributes += $arg;
  171. }
  172. else {
  173. $args[] = $arg;
  174. $ts = max($ts, @filemtime(DOCROOT . 'skin/' . SubsiteSelector::$subsite_code . '/js/' . $arg . '.js'));
  175. }
  176. }
  177. if (! $ts) $ts = time();
  178.  
  179. // Build the attributes.
  180. $attr = '';
  181. foreach ($attributes as $key => $value) {
  182. $attr .= ' ' . $key . '="' . Enc::html($value) . '"';
  183. }
  184.  
  185. foreach ($args as $arg) {
  186. echo '<script src="ROOT/skin-' . $ts . '/' . SubsiteSelector::$subsite_code . '/js/' . $arg . '.js"' . $attr . '></script>' . PHP_EOL;
  187. }
  188. }
  189.  
  190.  
  191. /**
  192.   * Find a template within the current skin.
  193.   *
  194.   * @param mixed $name
  195.   * @param mixed $extension
  196.   * @return string
  197.   */
  198. public static function findTemplate($name, $extension)
  199. {
  200. if (preg_match('/^skin\/(.+)$/', $name, $matches)) {
  201. $name = 'skin/' . SubsiteSelector::$subsite_code . '/' . $matches[1];
  202.  
  203. $unavail = Kohana::config('sprout.unavailable');
  204. if (!empty($_GET['_unavailable'])) {
  205. $_GET['_unavailable'] = preg_replace('/[^_a-z]/', '', $_GET['_unavailable']);
  206. $unavail = $_GET['_unavailable'];
  207. }
  208.  
  209. if ($unavail and !AdminAuth::isLoggedIn()) {
  210. SubsiteSelector::$subsite_code = 'unavailable';
  211. $name = 'skin/unavailable/' . $unavail;
  212. }
  213.  
  214. } else {
  215. $matches = [];
  216. if (!preg_match('!^(sprout/|modules/[^/]+/)(.+)$!', $name, $matches)) {
  217. throw new Exception('View files must begin with skin/, sprout/, or modules/*/');
  218. }
  219. $base = $matches[1];
  220. $file = $matches[2];
  221. if (substr($file, 0, 6) != 'views/') {
  222. $file = 'views/' . $file;
  223. }
  224. $name = $base . $file;
  225. }
  226.  
  227. $name .= $extension;
  228.  
  229. if (!file_exists(DOCROOT . $name)) {
  230. throw new FileMissingException("View file missing: {$name}");
  231. }
  232.  
  233. return $name;
  234. }
  235. }
  236.  
  237.