1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
|
<?php
namespace dokuwiki;
/**
* Class StyleUtils
*
* Reads and applies the template's style.ini settings
*/
class StyleUtils
{
/** @var string current template */
protected $tpl;
/** @var bool reinitialize styles config */
protected $reinit;
/** @var bool $preview preview mode */
protected $preview;
/** @var array default replacements to be merged with custom style configs */
protected $defaultReplacements = array(
'__text__' => "#000",
'__background__' => "#fff",
'__text_alt__' => "#999",
'__background_alt__' => "#eee",
'__text_neu__' => "#666",
'__background_neu__' => "#ddd",
'__border__' => "#ccc",
'__highlight__' => "#ff9",
'__link__' => "#00f",
);
/**
* StyleUtils constructor.
* @param string $tpl template name: if not passed as argument, the default value from $conf will be used
* @param bool $preview
* @param bool $reinit whether static style conf should be reinitialized
*/
public function __construct($tpl = '', $preview = false, $reinit = false)
{
if (!$tpl) {
global $conf;
$tpl = $conf['template'];
}
$this->tpl = $tpl;
$this->reinit = $reinit;
$this->preview = $preview;
}
/**
* Load style ini contents
*
* Loads and merges style.ini files from template and config and prepares
* the stylesheet modes
*
* @author Andreas Gohr <andi@splitbrain.org>
* @author Anna Dabrowska <info@cosmocode.de>
*
* @return array with keys 'stylesheets' and 'replacements'
*/
public function cssStyleini()
{
static $combined = [];
if (!empty($combined) && !$this->reinit) {
return $combined;
}
global $conf;
global $config_cascade;
$stylesheets = array(); // mode, file => base
// guaranteed placeholder => value
$replacements = $this->defaultReplacements;
// merge all styles from config cascade
if (!is_array($config_cascade['styleini'])) {
trigger_error('Missing config cascade for styleini', E_USER_WARNING);
}
// allow replacement overwrites in preview mode
if ($this->preview) {
$config_cascade['styleini']['local'][] = $conf['cachedir'] . '/preview.ini';
}
$combined['stylesheets'] = [];
$combined['replacements'] = [];
foreach (array('default', 'local', 'protected') as $config_group) {
if (empty($config_cascade['styleini'][$config_group])) continue;
// set proper server dirs
$webbase = $this->getWebbase($config_group);
foreach ($config_cascade['styleini'][$config_group] as $inifile) {
// replace the placeholder with the name of the current template
$inifile = str_replace('%TEMPLATE%', $this->tpl, $inifile);
$incbase = dirname($inifile) . '/';
if (file_exists($inifile)) {
$config = parse_ini_file($inifile, true);
if (isset($config['stylesheets']) && is_array($config['stylesheets'])) {
foreach ($config['stylesheets'] as $inifile => $mode) {
// validate and include style files
$stylesheets = array_merge(
$stylesheets,
$this->getValidatedStyles($stylesheets, $inifile, $mode, $incbase, $webbase)
);
$combined['stylesheets'] = array_merge($combined['stylesheets'], $stylesheets);
}
}
if (isset($config['replacements']) && is_array($config['replacements'])) {
$replacements = array_replace(
$replacements,
$this->cssFixreplacementurls($config['replacements'], $webbase)
);
$combined['replacements'] = array_merge($combined['replacements'], $replacements);
}
}
}
}
return $combined;
}
/**
* Checks if configured style files exist and, if necessary, adjusts file extensions in config
*
* @param array $stylesheets
* @param string $file
* @param string $mode
* @param string $incbase
* @param string $webbase
* @return mixed
*/
protected function getValidatedStyles($stylesheets, $file, $mode, $incbase, $webbase)
{
global $conf;
if (!file_exists($incbase . $file)) {
list($extension, $basename) = array_map('strrev', explode('.', strrev($file), 2));
$newExtension = $extension === 'css' ? 'less' : 'css';
if (file_exists($incbase . $basename . '.' . $newExtension)) {
$stylesheets[$mode][$incbase . $basename . '.' . $newExtension] = $webbase;
if ($conf['allowdebug']) {
msg("Stylesheet $file not found, using $basename.$newExtension instead. " .
"Please contact developer of \"$this->tpl\" template.", 2);
}
} elseif ($conf['allowdebug']) {
msg("Stylesheet $file not found, please contact the developer of \"$this->tpl\" template.", 2);
}
}
$stylesheets[$mode][fullpath($incbase . $file)] = $webbase;
return $stylesheets;
}
/**
* Returns the web base path for the given level/group in config cascade.
* Style resources are relative to the template directory for the main (default) styles
* but relative to DOKU_BASE for everything else"
*
* @param string $config_group
* @return string
*/
protected function getWebbase($config_group)
{
if ($config_group === 'default') {
return tpl_basedir($this->tpl);
} else {
return DOKU_BASE;
}
}
/**
* Amend paths used in replacement relative urls, refer FS#2879
*
* @author Chris Smith <chris@jalakai.co.uk>
*
* @param array $replacements with key-value pairs
* @param string $location
* @return array
*/
protected function cssFixreplacementurls($replacements, $location)
{
foreach ($replacements as $key => $value) {
$replacements[$key] = preg_replace(
'#(url\([ \'"]*)(?!/|data:|http://|https://| |\'|")#',
'\\1' . $location,
$value
);
}
return $replacements;
}
}
|