Completed
Push — master ( 0cefed...4593db )
by Andreas
04:16
created

StyleUtils::getWebbase()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

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