1fb1f9089SMichael Große<?php 2fb1f9089SMichael Große 3fb1f9089SMichael Großenamespace dokuwiki; 4fb1f9089SMichael Große 5fb1f9089SMichael Großeclass StyleUtils 6fb1f9089SMichael Große{ 7fb1f9089SMichael Große 84593dbd2SAnna Dabrowska /** @var string current template */ 94593dbd2SAnna Dabrowska protected $tpl; 104593dbd2SAnna Dabrowska /** @var bool reinitialize styles config */ 114593dbd2SAnna Dabrowska protected $reinit; 124593dbd2SAnna Dabrowska /** @var bool $preview preview mode */ 134593dbd2SAnna Dabrowska protected $preview; 144593dbd2SAnna Dabrowska /** @var array default replacements to be merged with custom style configs */ 154593dbd2SAnna Dabrowska protected $defaultReplacements = array( 16fb1f9089SMichael Große '__text__' => "#000", 17fb1f9089SMichael Große '__background__' => "#fff", 18fb1f9089SMichael Große '__text_alt__' => "#999", 19fb1f9089SMichael Große '__background_alt__' => "#eee", 20fb1f9089SMichael Große '__text_neu__' => "#666", 21fb1f9089SMichael Große '__background_neu__' => "#ddd", 22fb1f9089SMichael Große '__border__' => "#ccc", 23fb1f9089SMichael Große '__highlight__' => "#ff9", 24fb1f9089SMichael Große '__link__' => "#00f", 25fb1f9089SMichael Große ); 26fb1f9089SMichael Große 274593dbd2SAnna Dabrowska /** 284593dbd2SAnna Dabrowska * StyleUtils constructor. 294593dbd2SAnna Dabrowska * @param string $tpl template name: if not passed as argument, the default value from $conf will be used 304593dbd2SAnna Dabrowska * @param bool $preview 314593dbd2SAnna Dabrowska * @param bool $reinit whether static style conf should be reinitialized 324593dbd2SAnna Dabrowska */ 334593dbd2SAnna Dabrowska public function __construct($tpl = '', $preview = false, $reinit = false) 344593dbd2SAnna Dabrowska { 354593dbd2SAnna Dabrowska if (!$tpl) { 364593dbd2SAnna Dabrowska global $conf; 37*2e6e11adSAndreas Gohr $tpl = $conf['template']; 384593dbd2SAnna Dabrowska } 394593dbd2SAnna Dabrowska $this->tpl = $tpl; 404593dbd2SAnna Dabrowska $this->reinit = $reinit; 414593dbd2SAnna Dabrowska $this->preview = $preview; 424593dbd2SAnna Dabrowska } 43fb1f9089SMichael Große 444593dbd2SAnna Dabrowska /** 454593dbd2SAnna Dabrowska * Load style ini contents 464593dbd2SAnna Dabrowska * 474593dbd2SAnna Dabrowska * Loads and merges style.ini files from template and config and prepares 484593dbd2SAnna Dabrowska * the stylesheet modes 494593dbd2SAnna Dabrowska * 504593dbd2SAnna Dabrowska * @author Andreas Gohr <andi@splitbrain.org> 514593dbd2SAnna Dabrowska * @author Anna Dabrowska <info@cosmocode.de> 524593dbd2SAnna Dabrowska * 534593dbd2SAnna Dabrowska * @return array with keys 'stylesheets' and 'replacements' 544593dbd2SAnna Dabrowska */ 554593dbd2SAnna Dabrowska public function cssStyleini() 564593dbd2SAnna Dabrowska { 574593dbd2SAnna Dabrowska static $combined = []; 584593dbd2SAnna Dabrowska if (!empty($combined) && !$this->reinit) { 594593dbd2SAnna Dabrowska return $combined; 604593dbd2SAnna Dabrowska } 614593dbd2SAnna Dabrowska 624593dbd2SAnna Dabrowska global $conf; 634593dbd2SAnna Dabrowska global $config_cascade; 644593dbd2SAnna Dabrowska $stylesheets = array(); // mode, file => base 654593dbd2SAnna Dabrowska 664593dbd2SAnna Dabrowska // guaranteed placeholder => value 674593dbd2SAnna Dabrowska $replacements = $this->defaultReplacements; 684593dbd2SAnna Dabrowska 694593dbd2SAnna Dabrowska // merge all styles from config cascade 704593dbd2SAnna Dabrowska if (!is_array($config_cascade['styleini'])) { 714593dbd2SAnna Dabrowska trigger_error('Missing config cascade for styleini', E_USER_WARNING); 724593dbd2SAnna Dabrowska } 734593dbd2SAnna Dabrowska 744593dbd2SAnna Dabrowska // allow replacement overwrites in preview mode 754593dbd2SAnna Dabrowska if ($this->preview) { 764593dbd2SAnna Dabrowska $config_cascade['styleini']['local'][] = $conf['cachedir'] . '/preview.ini'; 774593dbd2SAnna Dabrowska } 784593dbd2SAnna Dabrowska 794593dbd2SAnna Dabrowska $combined['stylesheets'] = []; 804593dbd2SAnna Dabrowska $combined['replacements'] = []; 814593dbd2SAnna Dabrowska 824593dbd2SAnna Dabrowska foreach (array('default', 'local', 'protected') as $config_group) { 834593dbd2SAnna Dabrowska if (empty($config_cascade['styleini'][$config_group])) continue; 844593dbd2SAnna Dabrowska 854593dbd2SAnna Dabrowska // set proper server dirs 864593dbd2SAnna Dabrowska $webbase = $this->getWebbase($config_group); 874593dbd2SAnna Dabrowska 884593dbd2SAnna Dabrowska foreach ($config_cascade['styleini'][$config_group] as $inifile) { 894593dbd2SAnna Dabrowska // replace the placeholder with the name of the current template 904593dbd2SAnna Dabrowska $inifile = str_replace('%TEMPLATE%', $this->tpl, $inifile); 914593dbd2SAnna Dabrowska 924593dbd2SAnna Dabrowska $incbase = dirname($inifile) . '/'; 934593dbd2SAnna Dabrowska 944593dbd2SAnna Dabrowska if (file_exists($inifile)) { 954593dbd2SAnna Dabrowska $config = parse_ini_file($inifile, true); 964593dbd2SAnna Dabrowska 974593dbd2SAnna Dabrowska if (is_array($config['stylesheets'])) { 984593dbd2SAnna Dabrowska 994593dbd2SAnna Dabrowska foreach ($config['stylesheets'] as $inifile => $mode) { 1004593dbd2SAnna Dabrowska // validate and include style files 1014593dbd2SAnna Dabrowska $stylesheets = array_merge($stylesheets, $this->getValidatedStyles($stylesheets, $inifile, $mode, $incbase, $webbase)); 1024593dbd2SAnna Dabrowska $combined['stylesheets'] = array_merge($combined['stylesheets'], $stylesheets); 1034593dbd2SAnna Dabrowska } 1044593dbd2SAnna Dabrowska } 1054593dbd2SAnna Dabrowska 1064593dbd2SAnna Dabrowska if (is_array($config['replacements'])) { 1074593dbd2SAnna Dabrowska $replacements = array_replace($replacements, $this->cssFixreplacementurls($config['replacements'], $webbase)); 1084593dbd2SAnna Dabrowska $combined['replacements'] = array_merge($combined['replacements'], $replacements); 1094593dbd2SAnna Dabrowska } 1104593dbd2SAnna Dabrowska } 1114593dbd2SAnna Dabrowska } 1124593dbd2SAnna Dabrowska } 1134593dbd2SAnna Dabrowska 1144593dbd2SAnna Dabrowska 1154593dbd2SAnna Dabrowska return $combined; 1164593dbd2SAnna Dabrowska } 1174593dbd2SAnna Dabrowska 1184593dbd2SAnna Dabrowska /** 1194593dbd2SAnna Dabrowska * Checks if configured style files exist and, if necessary, adjusts file extensions in config 1204593dbd2SAnna Dabrowska * 1214593dbd2SAnna Dabrowska * @param array $stylesheets 1224593dbd2SAnna Dabrowska * @param string $file 1234593dbd2SAnna Dabrowska * @param string $mode 1244593dbd2SAnna Dabrowska * @param string $incbase 1254593dbd2SAnna Dabrowska * @param string $webbase 1264593dbd2SAnna Dabrowska * @return mixed 1274593dbd2SAnna Dabrowska */ 1284593dbd2SAnna Dabrowska protected function getValidatedStyles($stylesheets, $file, $mode, $incbase, $webbase) 1294593dbd2SAnna Dabrowska { 1304593dbd2SAnna Dabrowska global $conf; 131432cf0d1SMichael Große if (!file_exists($incbase . $file)) { 132432cf0d1SMichael Große list($extension, $basename) = array_map('strrev', explode('.', strrev($file), 2)); 133432cf0d1SMichael Große $newExtension = $extension === 'css' ? 'less' : 'css'; 134432cf0d1SMichael Große if (file_exists($incbase . $basename . '.' . $newExtension)) { 135432cf0d1SMichael Große $stylesheets[$mode][$incbase . $basename . '.' . $newExtension] = $webbase; 136432cf0d1SMichael Große if ($conf['allowdebug']) { 1374593dbd2SAnna Dabrowska msg("Stylesheet $file not found, using $basename.$newExtension instead. Please contact developer of \"$this->tpl\" template.", 2); 138432cf0d1SMichael Große } 1394593dbd2SAnna Dabrowska } elseif ($conf['allowdebug']) { 1404593dbd2SAnna Dabrowska msg("Stylesheet $file not found, please contact the developer of \"$this->tpl\" template.", 2); 141432cf0d1SMichael Große } 142432cf0d1SMichael Große } 1434593dbd2SAnna Dabrowska $stylesheets[$mode][fullpath($incbase . $file)] = $webbase; 1444593dbd2SAnna Dabrowska return $stylesheets; 145fb1f9089SMichael Große } 146fb1f9089SMichael Große 1474593dbd2SAnna Dabrowska /** 1484593dbd2SAnna Dabrowska * Returns the web base path for the given level/group in config cascade. 1494593dbd2SAnna Dabrowska * Style resources are relative to the template directory for the main (default) styles 1504593dbd2SAnna Dabrowska * but relative to DOKU_BASE for everything else" 1514593dbd2SAnna Dabrowska * 1524593dbd2SAnna Dabrowska * @param string $config_group 1534593dbd2SAnna Dabrowska * @return string 1544593dbd2SAnna Dabrowska */ 1554593dbd2SAnna Dabrowska protected function getWebbase($config_group) 1564593dbd2SAnna Dabrowska { 1574593dbd2SAnna Dabrowska if ($config_group === 'default') { 1584593dbd2SAnna Dabrowska return tpl_basedir($this->tpl); 1594593dbd2SAnna Dabrowska } else { 1604593dbd2SAnna Dabrowska return DOKU_BASE; 161fb1f9089SMichael Große } 162fb1f9089SMichael Große } 163fb1f9089SMichael Große 164fb1f9089SMichael Große /** 165fb1f9089SMichael Große * Amend paths used in replacement relative urls, refer FS#2879 166fb1f9089SMichael Große * 167fb1f9089SMichael Große * @author Chris Smith <chris@jalakai.co.uk> 168fb1f9089SMichael Große * 169fb1f9089SMichael Große * @param array $replacements with key-value pairs 170fb1f9089SMichael Große * @param string $location 171fb1f9089SMichael Große * @return array 172fb1f9089SMichael Große */ 1734593dbd2SAnna Dabrowska protected function cssFixreplacementurls($replacements, $location) 1744593dbd2SAnna Dabrowska { 175fb1f9089SMichael Große foreach ($replacements as $key => $value) { 176fb1f9089SMichael Große $replacements[$key] = preg_replace('#(url\([ \'"]*)(?!/|data:|http://|https://| |\'|")#', '\\1' . $location, $value); 177fb1f9089SMichael Große } 178fb1f9089SMichael Große return $replacements; 179fb1f9089SMichael Große } 180fb1f9089SMichael Große} 181