1<?php
2/**
3 * Helper class to load standrad DokuWiki CSS files.
4 * Adopted code from dw2pdf plugin by Andreas Gohr <andi@splitbrain.org>.
5 *
6 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
7 * @author     LarsDW223
8 */
9
10// must be run within Dokuwiki
11if (!defined('DOKU_INC')) die();
12
13
14/**
15 * Class helper_plugin_odt_dwcssloader
16 *
17 * @package helper\dwcssloader
18 */
19class helper_plugin_odt_dwcssloader extends DokuWiki_Plugin {
20    /** var string Usually empty, can be used for debugging */
21    public $trace_dump = NULL;
22
23    /**
24     * Return list of implemented methods.
25     *
26     * @return array
27     */
28    function getMethods() {
29        $result = array();
30        $result[] = array(
31                'name'   => 'load',
32                'desc'   => 'Loads standard DokuWiki, plugin specific and format specific CSS files and templates. Includes handling of replacements and less parsing.',
33                'params' => array('$plugin_name' => 'string',
34                                  '$format' => 'string',
35                                  '$template' => 'string'),
36                'return' => array('All CSS styles' => 'string'),
37                );
38        return $result;
39    }
40
41    /**
42     * Load all the style sheets and apply the needed replacements
43     * @param $plugin_name
44     * @param $format
45     * @param $template
46     * @return string
47     */
48    public function load($plugin_name, $format, $template) {
49        $mediatypes = array('screen', 'all', 'print');
50
51        //reusue the CSS dispatcher functions without triggering the main function
52        define('SIMPLE_TEST', 1);
53        require_once(DOKU_INC . 'lib/exe/css.php');
54
55        // Always only use small letters in format
56        $format = strtolower ($format);
57
58        // load style.ini
59        if (function_exists('css_styleini')) {
60            // compatiblity layer for pre-Greebo releases of DokuWiki
61            $styleini = css_styleini($template);
62        } else {
63            // Greebo functionality
64            $styleUtils = new \dokuwiki\StyleUtils();
65            $styleini = $styleUtils->cssStyleini($template);
66        }
67
68        $template_files = array();
69        foreach($mediatypes as $mediatype) {
70            $template_files[$mediatype] = array();
71
72            // load template styles
73            if (isset($styleini['stylesheets'][$mediatype])) {
74                $template_files[$mediatype] = array_merge($template_files[$mediatype], $styleini['stylesheets'][$mediatype]);
75            }
76        }
77
78        // prepare CSS files
79        $files = array_merge(
80            array(
81                DOKU_INC . 'lib/styles/screen.css'
82                    => DOKU_BASE . 'lib/styles/',
83                DOKU_INC . 'lib/styles/print.css'
84                    => DOKU_BASE . 'lib/styles/',
85            ),
86            css_pluginstyles('all'),
87            $this->css_pluginFormatStyles($format),
88            array(
89                DOKU_PLUGIN . $plugin_name.'/conf/style.css'
90                    => DOKU_BASE . 'lib/plugins/'.$plugin_name.'/conf/',
91                DOKU_PLUGIN . $plugin_name.'/tpl/' . $template . '/style.css'
92                    => DOKU_BASE . 'lib/plugins/'.$plugin_name.'/tpl/' . $template . '/',
93                DOKU_PLUGIN . $plugin_name.'/conf/style.local.css'
94                    => DOKU_BASE . 'lib/plugins/'.$plugin_name.'/conf/',
95            )
96        );
97        $css = '';
98        $css .= $this->get_css_for_filetypes();
99
100        // build the stylesheet
101        foreach($files as $file => $location) {
102            $display = str_replace(fullpath(DOKU_INC), '', fullpath($file));
103            $css_content = "\n/* XXXXXXXXX $display XXXXXXXXX */\n";
104            $css_content = css_loadfile($file, $location);
105            if (strpos ($file, 'screen.css') !== false ||
106                strpos ($file, 'screen.less') !== false) {
107                $css .= "\n@media screen {\n" . $css_content . "\n}\n";
108            } else if (strpos ($file, 'style.css') !== false ||
109                       strpos ($file, 'style.less') !== false) {
110                $css .= "\n@media screen {\n" . $css_content . "\n}\n";
111            } else if (strpos ($file, $format.'.css') !== false ||
112                       strpos ($file, $format.'.less') !== false) {
113                $css .= "\n@media print {\n" . $css_content . "\n}\n";
114            } else if (strpos ($file, 'print.css') !== false ||
115                       strpos ($file, 'print.less') !== false) {
116                $css .= "\n@media print {\n" . $css_content . "\n}\n";
117            } else {
118                $css .= $css_content;
119            }
120        }
121
122        foreach ($mediatypes as $mediatype) {
123            // load files
124            $css_content = '';
125            foreach($template_files[$mediatype] as $file => $location){
126                $display = str_replace(fullpath(DOKU_INC), '', fullpath($file));
127                $css_content .= "\n/* XXXXXXXXX $display XXXXXXXXX */\n";
128                $css_content .= css_loadfile($file, $location);
129            }
130            switch ($mediatype) {
131                case 'screen':
132                    $css .= NL.'@media screen { /* START screen styles */'.NL.$css_content.NL.'} /* /@media END screen styles */'.NL;
133                    break;
134                case 'print':
135                    $css .= NL.'@media print { /* START print styles */'.NL.$css_content.NL.'} /* /@media END print styles */'.NL;
136                    break;
137                case 'all':
138                case 'feed':
139                default:
140                    $css .= NL.'/* START rest styles */ '.NL.$css_content.NL.'/* END rest styles */'.NL;
141                    break;
142            }
143        }
144
145        if(function_exists('css_parseless')) {
146            // apply pattern replacements
147            $css = css_applystyle($css, $styleini['replacements']);
148
149            // parse less
150            $css = css_parseless($css);
151        } else {
152            // @deprecated 2013-12-19: fix backward compatibility
153            $css = css_applystyle($css, DOKU_INC . 'lib/tpl/' . $template . '/');
154        }
155
156        return $css;
157    }
158
159    /**
160     * Returns a list of possible Plugin Styles for format $format
161     *
162     * Checks for a $format.'.css', falls back to print.css
163     *
164     * @author Andreas Gohr <andi@splitbrain.org>
165     *
166     * @param string $format
167     * @return array
168     */
169    protected function css_pluginFormatStyles($format) {
170        $list = array();
171        $plugins = plugin_list();
172
173        foreach($plugins as $p) {
174            // Always load normal/screen CSS code
175            // That way plugins can choose with the media selector which CSS code they like to use
176            $list[DOKU_PLUGIN . $p ."/screen.css"] = DOKU_INC . "lib/plugins/". $p ."/";
177            $list[DOKU_PLUGIN . $p ."/screen.less"] = DOKU_INC . "lib/plugins/". $p ."/";
178            $list[DOKU_PLUGIN . $p ."/style.css"] = DOKU_INC . "lib/plugins/". $p ."/";
179            $list[DOKU_PLUGIN . $p ."/style.less"] = DOKU_INC . "lib/plugins/". $p ."/";
180
181            // Do $format.css (e.g. odt.css) or print.css exists?
182            $format_css = file_exists(DOKU_PLUGIN . $p ."/". $format .".css");
183            $format_less = file_exists(DOKU_PLUGIN . $p ."/". $format .".less");
184            $print_css = file_exists(DOKU_PLUGIN . $p ."/print.css");
185            $print_less = file_exists(DOKU_PLUGIN . $p ."/print.less");
186            if($format_css || $format_less) {
187                $list[DOKU_PLUGIN . $p ."/". $format .".css"] = DOKU_INC . "lib/plugins/". $p ."/";
188                $list[DOKU_PLUGIN . $p ."/". $format .".less"] = DOKU_INC . "lib/plugins/". $p ."/";
189            } else if ($print_css || $print_less) {
190                $list[DOKU_PLUGIN . $p ."/print.css"] = DOKU_INC . "lib/plugins/". $p ."/";
191                $list[DOKU_PLUGIN . $p ."/print.less"] = DOKU_INC . "lib/plugins/". $p ."/";
192            }
193        }
194        return $list;
195    }
196
197    /**
198     * Returns classes for file download links
199     * (Adjusted from lib/exe/css.php: function css_filetypes())
200     *
201     * @author Andreas Gohr <andi@splitbrain.org>
202     */
203    protected function get_css_for_filetypes() {
204        $css = '';
205
206        // default style
207        $css .= '.mediafile {';
208        $css .= ' background: transparent url('.DOKU_BASE.'lib/images/fileicons/file.png) 0px 1px no-repeat;';
209        $css .= ' padding-left: 18px;';
210        $css .= ' padding-bottom: 1px;';
211        $css .= '}';
212
213        // additional styles when icon available
214        // scan directory for all icons
215        $exts = array();
216        if($dh = opendir(DOKU_INC.'lib/images/fileicons')){
217            while(false !== ($file = readdir($dh))){
218                if(preg_match('/([_\-a-z0-9]+(?:\.[_\-a-z0-9]+)*?)\.(png|gif)/i',$file,$match)){
219                    $ext = strtolower($match[1]);
220                    $type = '.'.strtolower($match[2]);
221                    if($ext!='file' && (!isset($exts[$ext]) || $type=='.png')){
222                        $exts[$ext] = $type;
223                    }
224                }
225            }
226            closedir($dh);
227        }
228        foreach($exts as $ext=>$type){
229            $class = preg_replace('/[^_\-a-z0-9]+/','_',$ext);
230            $css .= ".mf_$class {";
231            $css .= '  background-image: url('.DOKU_BASE.'lib/images/fileicons/'.$ext.$type.')';
232            $css .= '}';
233        }
234
235        return $css;
236    }
237}
238