[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/inc/ -> StyleUtils.php (source)

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