1<?php
2/**
3 * DokuWiki Plugin lightweightscript (Action Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  i-net /// software <tools@inetsoftware.de>
7 */
8
9// must be run within Dokuwiki
10if(!defined('DOKU_INC')) die();
11
12class action_plugin_lightweightscript extends DokuWiki_Action_Plugin {
13
14    /**
15     * Registers a callback function for a given event
16     *
17     * @param Doku_Event_Handler $controller DokuWiki's event controller object
18     * @return void
19     */
20    public function register(Doku_Event_Handler $controller) {
21       $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'handle_tpl_metaheader_output');
22       $controller->register_hook('JS_SCRIPT_LIST', 'BEFORE', $this, 'handle_js_script_list');
23       $controller->register_hook('TOOLBAR_DEFINE', 'BEFORE', $this, 'handle_js_toolbar');
24
25       // $controller->register_hook('JS_CACHE_USE', 'BEFORE', $this, 'handle_use_cache');
26    }
27
28    /**
29     * Insert an extra script tag for users that have AUTH_EDIT or better
30     *
31     * @param Doku_Event $event  event object by reference
32     * @param mixed      $param  [the parameters passed as fifth argument to register_hook() when this
33     *                           handler was registered]
34     * @return void
35     */
36    public function handle_tpl_metaheader_output(Doku_Event &$event, $param) {
37        global $ID;
38        global $conf;
39
40        // add script if user has better auth than AUTH_EDIT
41        if ( auth_quickaclcheck( $ID ) >= AUTH_EDIT ) {
42            $event->data['script'][] = array(
43                'type'=> 'text/javascript', 'charset'=> 'utf-8', '_data'=> '',
44                'src' => DOKU_BASE.'lib/exe/js.php'.'?t='.rawurlencode($conf['template']).'&type=admin&tseed='.$tseed
45            )  + ($conf['defer_js'] ? [ 'defer' => 'defer'] : []);
46        }
47
48        // The first one is the static JavaScript block. PageSpeed says it would be good to print this first.
49        _tpl_metaheaders_action( array( 'script' => array( array_shift($event->data['script']) ) ) );
50    }
51
52    /**
53     * Hacking the toolbar for the requested script.
54     * If it is NOT the previously added admin script, remove the toolbar
55     * because the user has no edit rights.
56     *
57     * @param Doku_Event $event  event object by reference
58     * @param mixed      $param  [the parameters passed as fifth argument to register_hook() when this
59     *                           handler was registered]
60     * @return void
61     */
62    public function handle_js_toolbar(Doku_Event &$event, $param) {
63        global $INPUT;
64
65        if ( $INPUT->str('type')  != 'admin' ) {
66            $data = array();
67
68            // Remove the toolbar and do not add (which is done after this function) the default buttons
69            $event->data = &$data;
70            $event->preventDefault();
71
72            return false;
73        } else {
74            // Only defaults if admin, the whole header part will be removed.
75            // This is a bit hacky ...
76            ob_clean();
77        }
78    }
79
80    /**
81     * This function serves debugging purposes and has to be enabled in the register phase
82     *
83     * @param Doku_Event $event  event object by reference
84     * @param mixed      $param  [the parameters passed as fifth argument to register_hook() when this
85     *                           handler was registered]
86     * @return void
87     */
88    public function handle_use_cache(Doku_Event &$event, $param) {
89        $event->preventDefault();
90        return false;
91    }
92
93    /**
94     * Finally, handle the JS script list. The script would be fit to do even more stuff / types
95     * but handles only admin and default currently.
96     *
97     * @param Doku_Event $event  event object by reference
98     * @param mixed      $param  [the parameters passed as fifth argument to register_hook() when this
99     *                           handler was registered]
100     * @return void
101     */
102    public function handle_js_script_list(Doku_Event &$event, $param) {
103        global $INPUT;
104
105        switch( $INPUT->str('type') ) {
106
107            case 'admin':
108                // Filter for admin scripts
109                $event->data = array_filter( $event->data, array($this, 'filter_admin_scripts') );
110                break;
111
112            default:
113                // Filter for the-rest-if-us scripts
114                $event->data = array_filter( $event->data, array($this, 'filter_user_scripts') );
115        }
116    }
117
118    /**
119     * A simple filter function to check the input string against a list of path-parts that are allowed
120     *
121     * @param string    $str   the script file to check against the list
122     * @param mixed     $list  the list of path parts to test
123     * @return boolean
124     */
125    private function includeFilter( $str, $list ) {
126
127        foreach( $list as $entry ) {
128            if ( strpos( $str, $entry ) ) return true;
129        }
130
131        return false;
132    }
133
134    /**
135     * A simple filter function to check the input string against a list of path-parts that are allowed
136     * Is the inversion of includeFilter( $str, $list )
137     *
138     * @param string    $str   the script file to check against the list
139     * @param mixed     $list  the list of path parts to test
140     * @return boolean
141     */
142    private function excludeFilter( $str, $list ) {
143        return !$this->includeFilter( $str, $list );
144    }
145
146    /**
147     * Filters scripts that are intended for admins only
148     *
149     * @param string    $script   the script file to check against the list
150     * @return boolean
151     */
152    private function filter_admin_scripts( $script ) {
153        return $this->includeFilter( $script, array(
154
155            '/lib/scripts/fileuploader',
156            'jquery.ui.datepicker.js',
157            '/lib/scripts/',
158
159            // Plugins
160            '/lib/plugins/tag/',
161            '/lib/plugins/extension/',
162            '/lib/plugins/move/',
163            '/lib/plugins/styling/',
164            '/lib/plugins/sectionedit/',
165            '/lib/plugins/searchindex/',
166            '/lib/plugins/acl/',
167            '/lib/plugins/pagequery/',
168            '/lib/plugins/colorpicker/',
169            '/lib/plugins/sync/',
170            '/lib/plugins/multiorphan/',
171            '/lib/plugins/color/',
172            '/lib/plugins/usermanager/',
173            '/lib/plugins/edittable/',
174            '/lib/plugins/edittable/',
175            '/lib/plugins/include/',
176            '/lib/plugins/toctweak/',
177            '/lib/plugins/searchindex/',
178            '/lib/plugins/fastwiki/',
179
180        )) && $this->excludeFilter( $script, array(
181            '/lib/scripts/script.js', // a core script
182            '/lib/scripts/page.js', // a core script for footnotes
183            'jquery.cookie.js',
184        ));
185    }
186
187    /**
188     * Filters scripts that are intended for users only
189     *
190     * @param string    $script   the script file to check against the list
191     * @return boolean
192     */
193    private function filter_user_scripts( $script ) {
194        return !$this->filter_admin_scripts( $script );
195    }
196}
197
198// vim:ts=4:sw=4:et:
199