1<?php
2/**
3 * DokuWiki Action Plugin LoadSkin
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     Michael Klier <chi@chimeric.de>
7 * @author     Anika Henke <anika@selfthinker.org>
8 */
9// must be run within Dokuwiki
10if(!defined('DOKU_INC')) die();
11
12if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC.'lib/plugins/');
13if(!defined('DOKU_LF')) define('DOKU_LF', "\n");
14
15require_once(DOKU_PLUGIN.'action.php');
16
17/**
18 * All DokuWiki plugins to interfere with the event system
19 * need to inherit from this class
20 */
21class action_plugin_loadskin extends DokuWiki_Action_Plugin {
22
23    // register hook
24    public function register(Doku_Event_Handler $controller) {
25        $controller->register_hook('DOKUWIKI_STARTED', 'BEFORE', $this, '_handleConf');
26        $controller->register_hook('MEDIAMANAGER_STARTED', 'BEFORE', $this, '_handleConf');
27        $controller->register_hook('DETAIL_STARTED', 'BEFORE', $this, '_handleConf');
28        $controller->register_hook('TPL_CONTENT_DISPLAY', 'BEFORE', $this, '_handleContent', array());
29        // only needed for not yet up-to-date templates:
30        $controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, '_defineConstants');
31        $controller->register_hook('MEDIAMANAGER_STARTED', 'AFTER', $this, '_defineConstants');
32        $controller->register_hook('DETAIL_STARTED', 'AFTER', $this, '_defineConstants');
33    }
34
35    /**
36     * Define DOKU_TPL and DOKU_TPLINC after $conf['template'] has been overwritten
37     *  (this still needs the original constant definition in init.php to be removed)
38     * @deprecated DOKU_TPL and DOKU_TPLINC are deprecated since Adora Belle
39     *
40     * @author Anika Henke <anika@selfthinker.org>
41     */
42    public function _defineConstants(Doku_Event $event, $param) {
43        global $conf;
44
45        // define Template baseURL
46        if(!defined('DOKU_TPL'))
47            define('DOKU_TPL', DOKU_BASE.'lib/tpl/'.$conf['template'].'/');
48
49        // define real Template directory
50        if(!defined('DOKU_TPLINC'))
51            define('DOKU_TPLINC', DOKU_INC.'lib/tpl/'.$conf['template'].'/');
52    }
53
54    /**
55     * Overwrites the $conf['template'] setting
56     *
57     * @author Michael Klier <chi@chimeric.de>
58     * @author Anika Henke <anika@selfthinker.org>
59     */
60    public function _handleConf(Doku_Event $event, $param) {
61        global $conf;
62        global $ACT;
63
64        // store original template in helper attribute
65        $helper = $this->loadHelper('loadskin', true);
66        $helper->origTpl = $conf['template'];
67
68        // set template
69        $tpl = $this->_getTpl();
70        $inAdmin = $ACT == 'admin';
71        $allowInAdmin = $this->getConf('allowInAdmin');
72        if($tpl && (!$inAdmin || ($inAdmin && $allowInAdmin))) {
73            $conf['template'] = $tpl;
74        }
75    }
76
77    /**
78     * Output the template switcher if 'automaticOutput' is on
79     *
80     * @author Anika Henke <anika@selfthinker.org>
81     */
82    public function _handleContent(Doku_Event $event, $param){
83        // @todo: should ideally be in showTemplateSwitcher()
84        $isOverwrittenByAdmin = !$this->getConf('preferUserChoice') && $this->_getTplPerNamespace();
85
86        if ($this->getConf('automaticOutput') && !$isOverwrittenByAdmin) {
87            $helper = $this->loadHelper('loadskin', true);
88            $event->data = $helper->showTemplateSwitcher().$event->data;
89        }
90    }
91
92    /**
93     * Checks if a given page should use a different template then the default
94     *
95     * @author Michael Klier <chi@chimeric.de>
96     * @author Anika Henke <anika@selfthinker.org>
97     */
98    private function _getTpl() {
99        $tplPerUser = $this->_getTplPerUser();
100        $tplPerNamespace = $this->_getTplPerNamespace();
101
102        if($this->getConf('preferUserChoice')) {
103            if($tplPerUser)
104                return $tplPerUser;
105            if($tplPerNamespace)
106                return $tplPerNamespace;
107        } else {
108            if($tplPerNamespace)
109                return $tplPerNamespace;
110            if($tplPerUser)
111                return $tplPerUser;
112        }
113
114        return false;
115    }
116
117    /**
118     * Get template from session and/or user config
119     *
120     * @author Anika Henke <anika@selfthinker.org>
121     */
122    private function _getTplPerUser() {
123        global $INPUT;
124
125        // get all available templates
126        $helper = $this->loadHelper('loadskin', true);
127        $tpls   = $helper->getTemplates();
128
129        $mobileSwitch = $this->getConf('mobileSwitch');
130        $user = $_SERVER['REMOTE_USER'];
131
132        $tplRequest = $INPUT->str('tpl');
133        $actSelect  = $INPUT->str('act') && ($INPUT->str('act') == 'select');
134
135        // if template switcher was used
136        if ($tplRequest && $actSelect && (in_array($tplRequest, $tpls) || ($tplRequest == '*') )) {
137            // hidden way of deleting the cookie and config values
138            if ($tplRequest == '*')
139                $tplRequest = false; // not backwards-compatible, will only work with core PR #1129
140            // store in cookie
141            set_doku_pref('loadskinTpl', $tplRequest);
142            // if registered user, store also in conf file (not for mobile switcher)
143            if ($user && !$mobileSwitch)
144                $this->_tplUserConfig('set', $user, $tplRequest);
145            return $tplRequest;
146        }
147
148        $tplUser   = $this->_tplUserConfig('get', $user);// from user conf file
149        $tplCookie = get_doku_pref('loadskinTpl', '');
150        // if logged in and user is in conf (not for mobile)
151        if ($user && $tplUser && in_array($tplUser, $tpls) && !$mobileSwitch){
152            if ($tplCookie && ($tplCookie == $tplUser))
153                return $tplCookie;
154            // store in cookie
155            set_doku_pref('loadskinTpl', $tplUser);
156            return $tplUser;
157        }
158        // if template is stored in cookie
159        if ($tplCookie && in_array($tplCookie, $tpls))
160            return $tplCookie;
161
162        // if viewed on a mobile and mobile switcher is used, set mobile template as default
163        global $INFO;
164        $mobileTpl = $this->getConf('mobileTemplate');
165        if ($mobileTpl && $INFO['ismobile']) {
166            set_doku_pref('loadskinTpl', $mobileTpl);
167            return $mobileTpl;
168        }
169
170        return false;
171    }
172
173    /**
174     * Get template from namespace/page and config
175     *
176     * @author Michael Klier <chi@chimeric.de>
177     * @author Anika Henke <anika@selfthinker.org>
178     */
179    private function _getTplPerNamespace() {
180        global $ID;
181        $config = DOKU_CONF.'loadskin.conf';
182
183        if(@file_exists($config)) {
184            $data = unserialize(io_readFile($config, false));
185            $id   = $ID;
186
187            // remove language path from $id before you check for a match (it would only be at the start)
188            if ($this->getConf('inheritInTranslations') && !plugin_isdisabled('translation')) {
189                $transplugin = &plugin_load('helper', 'translation');
190                $langPath = $transplugin->getLangPart($id).':';
191                $pos = strpos($id, $langPath);
192                if (($pos !== false) && ($pos == 0))
193                    $id = str_ireplace($langPath, '', $id);
194            }
195
196            if($data[$id]) return $data[$id];
197
198            $path  = explode(':', $id);
199
200            while(count($path) > 0) {
201                $id = implode(':', $path);
202                if($data[$id]) return $data[$id];
203                array_pop($path);
204            }
205        }
206        return false;
207    }
208
209    /**
210     * Get/set template for user in config
211     *
212     * @author Anika Henke <anika@selfthinker.org>
213     */
214    private function _tplUserConfig($act, $user, $tpl='') {
215        $data = array();
216        $userConf = DOKU_CONF.'loadskin.users.conf';
217        if(@file_exists($userConf)) {
218            $data = unserialize(io_readFile($userConf, false));
219            if ($act == 'get')
220                return $data[$user];
221            unset($data[$user]);
222        }
223        if ($act == 'get')
224            return false;
225        // keep line deleted if $tpl is empty
226        if ($tpl)
227            $data[$user] = $tpl;
228        io_saveFile($userConf, serialize($data));
229    }
230}
231
232// vim:ts=4:sw=4:
233