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