1<?php
2/**
3 * DokuWiki Plugin styling (Admin Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Andreas Gohr <andi@splitbrain.org>
7 */
8class admin_plugin_styling extends DokuWiki_Admin_Plugin
9{
10
11    public $ispopup = false;
12
13    /**
14     * @return int sort number in admin menu
15     */
16    public function getMenuSort()
17    {
18        return 1000;
19    }
20
21    /**
22     * @return bool true if only access for superuser, false is for superusers and moderators
23     */
24    public function forAdminOnly()
25    {
26        return true;
27    }
28
29    /**
30     * handle the different actions (also called from ajax)
31     */
32    public function handle()
33    {
34        global $INPUT;
35        $run = $INPUT->extract('run')->str('run');
36        if (!$run) return;
37        if(!checkSecurityToken()) return;
38        $run = 'run'.ucfirst($run);
39        $this->$run();
40    }
41
42    /**
43     * Render HTML output, e.g. helpful text and a form
44     */
45    public function html()
46    {
47        $class = 'nopopup';
48        if ($this->ispopup) $class = 'ispopup page';
49
50        echo '<div id="plugin__styling" class="'.$class.'">';
51        ptln('<h1>'.$this->getLang('menu').'</h1>');
52        $this->form();
53        echo '</div>';
54    }
55
56    /**
57     * Create the actual editing form
58     */
59    public function form()
60    {
61        global $conf;
62        global $ID;
63
64        $styleUtil = new \dokuwiki\StyleUtils($conf['template'], true, true);
65        $styleini     = $styleUtil->cssStyleini();
66        $replacements = $styleini['replacements'];
67
68        if ($this->ispopup) {
69            $target = DOKU_BASE.'lib/plugins/styling/popup.php';
70        } else {
71            $target = wl($ID, array('do' => 'admin', 'page' => 'styling'));
72        }
73
74        if (empty($replacements)) {
75            echo '<p class="error">'.$this->getLang('error').'</p>';
76        } else {
77            echo $this->locale_xhtml('intro');
78
79            echo '<form class="styling" method="post" action="'.$target.'">';
80            formSecurityToken();
81
82            echo '<table><tbody>';
83            foreach ($replacements as $key => $value) {
84                $name = tpl_getLang($key);
85                if (empty($name)) $name = $this->getLang($key);
86                if (empty($name)) $name = $key;
87
88                echo '<tr>';
89                echo '<td><label for="tpl__'.hsc($key).'">'.$name.'</label></td>';
90                echo '<td><input type="'.$this->colorType($value).'" name="tpl['.hsc($key).']" id="tpl__'.hsc($key).'"
91                    value="'.hsc($this->colorValue($value)).'" dir="ltr" required="required"/></td>';
92                echo '</tr>';
93            }
94            echo '</tbody></table>';
95
96            echo '<p>';
97            echo '<button type="submit" name="run[preview]" class="btn_preview primary">'.
98                $this->getLang('btn_preview').'</button> ';
99            #FIXME only if preview.ini exists:
100            echo '<button type="submit" name="run[reset]">'.$this->getLang('btn_reset').'</button>';
101            echo '</p>';
102
103            echo '<p>';
104            echo '<button type="submit" name="run[save]" class="primary">'.$this->getLang('btn_save').'</button>';
105            echo '</p>';
106
107            echo '<p>';
108            #FIXME only if local.ini exists:
109            echo '<button type="submit" name="run[revert]">'.$this->getLang('btn_revert').'</button>';
110            echo '</p>';
111
112            echo '</form>';
113
114            echo tpl_locale_xhtml('style');
115        }
116    }
117
118    /**
119     * Adjust three char color codes to the 6 char one supported by browser's color input
120     *
121     * @param string $value
122     * @return string
123     */
124    protected function colorValue($value)
125    {
126        if (preg_match('/^#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])$/', $value, $match)) {
127            return '#' . $match[1] . $match[1] . $match[2] . $match[2] . $match[3] . $match[3];
128        }
129        return $value;
130    }
131
132    /**
133     * Decide the input type based on the value
134     *
135     * @param string $value
136     * @return string color|text
137     */
138    protected function colorType($value)
139    {
140        if (preg_match('/^#([0-9a-fA-F]{3}){1,2}$/', $value)) {
141            return 'color';
142        } else {
143            return 'text';
144        }
145    }
146
147    /**
148     * saves the preview.ini (alos called from ajax directly)
149     */
150    public function runPreview()
151    {
152        global $conf;
153        $ini = $conf['cachedir'].'/preview.ini';
154        io_saveFile($ini, $this->makeini());
155    }
156
157    /**
158     * deletes the preview.ini
159     */
160    protected function runReset()
161    {
162        global $conf;
163        $ini = $conf['cachedir'].'/preview.ini';
164        io_saveFile($ini, '');
165    }
166
167    /**
168     * deletes the local style.ini replacements
169     */
170    protected function runRevert()
171    {
172        $this->replaceIni('');
173        $this->runReset();
174    }
175
176    /**
177     * save the local style.ini replacements
178     */
179    protected function runSave()
180    {
181        $this->replaceIni($this->makeini());
182        $this->runReset();
183    }
184
185    /**
186     * create the replacement part of a style.ini from submitted data
187     *
188     * @return string
189     */
190    protected function makeini()
191    {
192        global $INPUT;
193
194        $ini = "[replacements]\n";
195        $ini .= ";These overwrites have been generated from the Template styling Admin interface\n";
196        $ini .= ";Any values in this section will be overwritten by that tool again\n";
197        foreach ($INPUT->arr('tpl') as $key => $val) {
198            $ini .= $key.' = "'.addslashes($val).'"'."\n";
199        }
200
201        return $ini;
202    }
203
204    /**
205     * replaces the replacement parts in the local ini
206     *
207     * @param string $new the new ini contents
208     */
209    protected function replaceIni($new)
210    {
211        global $conf;
212        $ini = DOKU_CONF."tpl/".$conf['template']."/style.ini";
213        if (file_exists($ini)) {
214            $old = io_readFile($ini);
215            $old = preg_replace('/\[replacements\]\n.*?(\n\[.*]|$)/s', '\\1', $old);
216            $old = trim($old);
217        } else {
218            $old = '';
219        }
220
221        io_makeFileDir($ini);
222        io_saveFile($ini, "$old\n\n$new");
223    }
224}
225
226// vim:ts=4:sw=4:et:
227