1fb1f9089SMichael Große<?php 2fb1f9089SMichael Große 3fb1f9089SMichael Großenamespace dokuwiki; 4fb1f9089SMichael Große 5e9f4a0f6SAndreas Gohr/** 6e9f4a0f6SAndreas Gohr * Class StyleUtils 7e9f4a0f6SAndreas Gohr * 8e9f4a0f6SAndreas Gohr * Reads and applies the template's style.ini settings 9e9f4a0f6SAndreas Gohr */ 10fb1f9089SMichael Großeclass StyleUtils 11fb1f9089SMichael Große{ 124593dbd2SAnna Dabrowska /** @var string current template */ 134593dbd2SAnna Dabrowska protected $tpl; 144593dbd2SAnna Dabrowska /** @var bool reinitialize styles config */ 154593dbd2SAnna Dabrowska protected $reinit; 164593dbd2SAnna Dabrowska /** @var bool $preview preview mode */ 174593dbd2SAnna Dabrowska protected $preview; 184593dbd2SAnna Dabrowska /** @var array default replacements to be merged with custom style configs */ 19*24870174SAndreas Gohr protected $defaultReplacements = [ 20fb1f9089SMichael Große '__text__' => "#000", 21fb1f9089SMichael Große '__background__' => "#fff", 22fb1f9089SMichael Große '__text_alt__' => "#999", 23fb1f9089SMichael Große '__background_alt__' => "#eee", 24fb1f9089SMichael Große '__text_neu__' => "#666", 25fb1f9089SMichael Große '__background_neu__' => "#ddd", 26fb1f9089SMichael Große '__border__' => "#ccc", 27fb1f9089SMichael Große '__highlight__' => "#ff9", 28*24870174SAndreas Gohr '__link__' => "#00f" 29*24870174SAndreas Gohr ]; 30fb1f9089SMichael Große 314593dbd2SAnna Dabrowska /** 324593dbd2SAnna Dabrowska * StyleUtils constructor. 334593dbd2SAnna Dabrowska * @param string $tpl template name: if not passed as argument, the default value from $conf will be used 344593dbd2SAnna Dabrowska * @param bool $preview 354593dbd2SAnna Dabrowska * @param bool $reinit whether static style conf should be reinitialized 364593dbd2SAnna Dabrowska */ 374593dbd2SAnna Dabrowska public function __construct($tpl = '', $preview = false, $reinit = false) 384593dbd2SAnna Dabrowska { 394593dbd2SAnna Dabrowska if (!$tpl) { 404593dbd2SAnna Dabrowska global $conf; 412e6e11adSAndreas Gohr $tpl = $conf['template']; 424593dbd2SAnna Dabrowska } 434593dbd2SAnna Dabrowska $this->tpl = $tpl; 444593dbd2SAnna Dabrowska $this->reinit = $reinit; 454593dbd2SAnna Dabrowska $this->preview = $preview; 464593dbd2SAnna Dabrowska } 47fb1f9089SMichael Große 484593dbd2SAnna Dabrowska /** 494593dbd2SAnna Dabrowska * Load style ini contents 504593dbd2SAnna Dabrowska * 514593dbd2SAnna Dabrowska * Loads and merges style.ini files from template and config and prepares 524593dbd2SAnna Dabrowska * the stylesheet modes 534593dbd2SAnna Dabrowska * 544593dbd2SAnna Dabrowska * @author Andreas Gohr <andi@splitbrain.org> 554593dbd2SAnna Dabrowska * @author Anna Dabrowska <info@cosmocode.de> 564593dbd2SAnna Dabrowska * 574593dbd2SAnna Dabrowska * @return array with keys 'stylesheets' and 'replacements' 584593dbd2SAnna Dabrowska */ 594593dbd2SAnna Dabrowska public function cssStyleini() 604593dbd2SAnna Dabrowska { 614593dbd2SAnna Dabrowska static $combined = []; 624593dbd2SAnna Dabrowska if (!empty($combined) && !$this->reinit) { 634593dbd2SAnna Dabrowska return $combined; 644593dbd2SAnna Dabrowska } 654593dbd2SAnna Dabrowska 664593dbd2SAnna Dabrowska global $conf; 674593dbd2SAnna Dabrowska global $config_cascade; 68*24870174SAndreas Gohr $stylesheets = []; // mode, file => base 694593dbd2SAnna Dabrowska 704593dbd2SAnna Dabrowska // guaranteed placeholder => value 714593dbd2SAnna Dabrowska $replacements = $this->defaultReplacements; 724593dbd2SAnna Dabrowska 734593dbd2SAnna Dabrowska // merge all styles from config cascade 744593dbd2SAnna Dabrowska if (!is_array($config_cascade['styleini'])) { 754593dbd2SAnna Dabrowska trigger_error('Missing config cascade for styleini', E_USER_WARNING); 764593dbd2SAnna Dabrowska } 774593dbd2SAnna Dabrowska 784593dbd2SAnna Dabrowska // allow replacement overwrites in preview mode 794593dbd2SAnna Dabrowska if ($this->preview) { 804593dbd2SAnna Dabrowska $config_cascade['styleini']['local'][] = $conf['cachedir'] . '/preview.ini'; 814593dbd2SAnna Dabrowska } 824593dbd2SAnna Dabrowska 834593dbd2SAnna Dabrowska $combined['stylesheets'] = []; 844593dbd2SAnna Dabrowska $combined['replacements'] = []; 854593dbd2SAnna Dabrowska 86*24870174SAndreas Gohr foreach (['default', 'local', 'protected'] as $config_group) { 874593dbd2SAnna Dabrowska if (empty($config_cascade['styleini'][$config_group])) continue; 884593dbd2SAnna Dabrowska 894593dbd2SAnna Dabrowska // set proper server dirs 904593dbd2SAnna Dabrowska $webbase = $this->getWebbase($config_group); 914593dbd2SAnna Dabrowska 924593dbd2SAnna Dabrowska foreach ($config_cascade['styleini'][$config_group] as $inifile) { 934593dbd2SAnna Dabrowska // replace the placeholder with the name of the current template 944593dbd2SAnna Dabrowska $inifile = str_replace('%TEMPLATE%', $this->tpl, $inifile); 954593dbd2SAnna Dabrowska 964593dbd2SAnna Dabrowska $incbase = dirname($inifile) . '/'; 974593dbd2SAnna Dabrowska 984593dbd2SAnna Dabrowska if (file_exists($inifile)) { 994593dbd2SAnna Dabrowska $config = parse_ini_file($inifile, true); 1004593dbd2SAnna Dabrowska 1014daaaa1aSAndreas Gohr if (isset($config['stylesheets']) && is_array($config['stylesheets'])) { 1024593dbd2SAnna Dabrowska foreach ($config['stylesheets'] as $inifile => $mode) { 1034593dbd2SAnna Dabrowska // validate and include style files 104e9f4a0f6SAndreas Gohr $stylesheets = array_merge( 105e9f4a0f6SAndreas Gohr $stylesheets, 106e9f4a0f6SAndreas Gohr $this->getValidatedStyles($stylesheets, $inifile, $mode, $incbase, $webbase) 107e9f4a0f6SAndreas Gohr ); 1084593dbd2SAnna Dabrowska $combined['stylesheets'] = array_merge($combined['stylesheets'], $stylesheets); 1094593dbd2SAnna Dabrowska } 1104593dbd2SAnna Dabrowska } 1114593dbd2SAnna Dabrowska 1124daaaa1aSAndreas Gohr if (isset($config['replacements']) && is_array($config['replacements'])) { 113e9f4a0f6SAndreas Gohr $replacements = array_replace( 114e9f4a0f6SAndreas Gohr $replacements, 115e9f4a0f6SAndreas Gohr $this->cssFixreplacementurls($config['replacements'], $webbase) 116e9f4a0f6SAndreas Gohr ); 1174593dbd2SAnna Dabrowska $combined['replacements'] = array_merge($combined['replacements'], $replacements); 1184593dbd2SAnna Dabrowska } 1194593dbd2SAnna Dabrowska } 1204593dbd2SAnna Dabrowska } 1214593dbd2SAnna Dabrowska } 1224593dbd2SAnna Dabrowska 1234593dbd2SAnna Dabrowska return $combined; 1244593dbd2SAnna Dabrowska } 1254593dbd2SAnna Dabrowska 1264593dbd2SAnna Dabrowska /** 1274593dbd2SAnna Dabrowska * Checks if configured style files exist and, if necessary, adjusts file extensions in config 1284593dbd2SAnna Dabrowska * 1294593dbd2SAnna Dabrowska * @param array $stylesheets 1304593dbd2SAnna Dabrowska * @param string $file 1314593dbd2SAnna Dabrowska * @param string $mode 1324593dbd2SAnna Dabrowska * @param string $incbase 1334593dbd2SAnna Dabrowska * @param string $webbase 1344593dbd2SAnna Dabrowska * @return mixed 1354593dbd2SAnna Dabrowska */ 1364593dbd2SAnna Dabrowska protected function getValidatedStyles($stylesheets, $file, $mode, $incbase, $webbase) 1374593dbd2SAnna Dabrowska { 1384593dbd2SAnna Dabrowska global $conf; 139432cf0d1SMichael Große if (!file_exists($incbase . $file)) { 140*24870174SAndreas Gohr [$extension, $basename] = array_map('strrev', sexplode('.', strrev($file), 2, '')); 141432cf0d1SMichael Große $newExtension = $extension === 'css' ? 'less' : 'css'; 142432cf0d1SMichael Große if (file_exists($incbase . $basename . '.' . $newExtension)) { 143432cf0d1SMichael Große $stylesheets[$mode][$incbase . $basename . '.' . $newExtension] = $webbase; 144432cf0d1SMichael Große if ($conf['allowdebug']) { 145e9f4a0f6SAndreas Gohr msg("Stylesheet $file not found, using $basename.$newExtension instead. " . 146e9f4a0f6SAndreas Gohr "Please contact developer of \"$this->tpl\" template.", 2); 147432cf0d1SMichael Große } 1484593dbd2SAnna Dabrowska } elseif ($conf['allowdebug']) { 1494593dbd2SAnna Dabrowska msg("Stylesheet $file not found, please contact the developer of \"$this->tpl\" template.", 2); 150432cf0d1SMichael Große } 151432cf0d1SMichael Große } 1524593dbd2SAnna Dabrowska $stylesheets[$mode][fullpath($incbase . $file)] = $webbase; 1534593dbd2SAnna Dabrowska return $stylesheets; 154fb1f9089SMichael Große } 155fb1f9089SMichael Große 1564593dbd2SAnna Dabrowska /** 1574593dbd2SAnna Dabrowska * Returns the web base path for the given level/group in config cascade. 1584593dbd2SAnna Dabrowska * Style resources are relative to the template directory for the main (default) styles 1594593dbd2SAnna Dabrowska * but relative to DOKU_BASE for everything else" 1604593dbd2SAnna Dabrowska * 1614593dbd2SAnna Dabrowska * @param string $config_group 1624593dbd2SAnna Dabrowska * @return string 1634593dbd2SAnna Dabrowska */ 1644593dbd2SAnna Dabrowska protected function getWebbase($config_group) 1654593dbd2SAnna Dabrowska { 1664593dbd2SAnna Dabrowska if ($config_group === 'default') { 1674593dbd2SAnna Dabrowska return tpl_basedir($this->tpl); 1684593dbd2SAnna Dabrowska } else { 1694593dbd2SAnna Dabrowska return DOKU_BASE; 170fb1f9089SMichael Große } 171fb1f9089SMichael Große } 172fb1f9089SMichael Große 173fb1f9089SMichael Große /** 174fb1f9089SMichael Große * Amend paths used in replacement relative urls, refer FS#2879 175fb1f9089SMichael Große * 176fb1f9089SMichael Große * @author Chris Smith <chris@jalakai.co.uk> 177fb1f9089SMichael Große * 178fb1f9089SMichael Große * @param array $replacements with key-value pairs 179fb1f9089SMichael Große * @param string $location 180fb1f9089SMichael Große * @return array 181fb1f9089SMichael Große */ 1824593dbd2SAnna Dabrowska protected function cssFixreplacementurls($replacements, $location) 1834593dbd2SAnna Dabrowska { 184fb1f9089SMichael Große foreach ($replacements as $key => $value) { 18564159a61SAndreas Gohr $replacements[$key] = preg_replace( 18664159a61SAndreas Gohr '#(url\([ \'"]*)(?!/|data:|http://|https://| |\'|")#', 18764159a61SAndreas Gohr '\\1' . $location, 18864159a61SAndreas Gohr $value 18964159a61SAndreas Gohr ); 190fb1f9089SMichael Große } 191fb1f9089SMichael Große return $replacements; 192fb1f9089SMichael Große } 193fb1f9089SMichael Große} 194