1<?php
2
3/**
4 * DataTables Action Plugin
5 *
6 * Add DataTables support to DokuWiki
7 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
8 * @author     Giuseppe Di Terlizzi <giuseppe.diterlizzi@gmail.com>
9 * @copyright  (C) 2015-2020, Giuseppe Di Terlizzi
10 */
11class action_plugin_datatables extends DokuWiki_Action_Plugin
12{
13    const ASSET_DIR = __DIR__ . '/assets';
14    const ASSET_URL = DOKU_BASE . 'lib/plugins/datatables/assets';
15
16
17    /**
18     * Register events
19     *
20     * @param Doku_Event_Handler $controller
21     */
22    public function register(Doku_Event_Handler $controller)
23    {
24        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'datatables');
25        $controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, 'jsinfo');
26    }
27
28    /**
29     * Set config for DataTables in JSINFO
30     *
31     * @param Doku_Event $event DOKUWIKI_STARTED
32     * @param mixed $param
33     * @return void
34     */
35    public function jsinfo(Doku_Event $event, $param)
36    {
37        global $JSINFO;
38
39        // default config
40        $datatables_config = [
41            'config' => [
42                'dom' => 'lBfrtip'
43            ],
44            'enableForAllTables' => $this->getConf('enableForAllTables'),
45        ];
46
47        // find a matching language file
48        foreach ($this->getLangPath() as $path) {
49            if (file_exists(self::ASSET_DIR . '/' . $path)) {
50                $datatables_config['config']['language']['url'] = self::ASSET_URL . '/' . $path;
51                break;
52            }
53        }
54
55        $JSINFO['plugin']['datatables'] = $datatables_config;
56    }
57
58    /**
59     * Add DataTables scripts and styles
60     *
61     * @param Doku_Event $event TPL_METAHEADER_OUTPUT
62     */
63    public function datatables(Doku_Event $event, $param)
64    {
65
66        global $ID;
67        global $conf;
68
69        $excluded_pages = $this->getConf('excludedPages');
70
71        if (!empty($excluded_pages) && (bool)preg_match("/$excluded_pages/", $ID)) {
72            return;
73        }
74
75        $base_url = self::ASSET_URL;
76
77        $dt_scripts[] = "$base_url/datatables.net/js/jquery.dataTables.min.js";
78
79        $dt_scripts[] = "$base_url/datatables.net-fixedheader-dt/js/fixedHeader.dataTables.min.js";
80        $dt_styles[] = "$base_url/datatables.net-fixedheader-dt/css/fixedHeader.dataTables.min.css";
81
82        $dt_scripts[] = "$base_url/datatables.net-fixedcolumns-dt/js/fixedColumns.dataTables.min.js";
83        $dt_styles[] = "$base_url/datatables.net-fixedcolumns-dt/css/fixedColumns.dataTables.min.css";
84
85        $dt_scripts[] = "$base_url/datatables.net-buttons/js/dataTables.buttons.min.js";
86        $dt_scripts[] = "$base_url/datatables.net-buttons/js/buttons.html5.min.js";
87        $dt_scripts[] = "$base_url/datatables.net-buttons/js/buttons.print.min.js";
88
89        $dt_scripts[] = "$base_url/jszip/jszip.min.js";
90        $dt_scripts[] = "$base_url/pdfmake/pdfmake.min.js";
91        $dt_scripts[] = "$base_url/pdfmake/vfs_fonts.js";
92
93        switch ($conf['template']) {
94            case 'bootstrap3':
95                $dt_scripts[] = "$base_url/datatables.net/js/dataTables.bootstrap.min.js";
96                $dt_styles[] = "$base_url/datatables.net/css/dataTables.bootstrap.min.css";
97                $dt_scripts[] = "$base_url/datatables.net-buttons/js/buttons.bootstrap.min.js";
98                $dt_styles[] = "$base_url/datatables.net-buttons/css/buttons.bootstrap.min.css";
99                break;
100            default:
101                $dt_scripts[] = "$base_url/datatables.net/js/dataTables.jqueryui.min.js";
102                $dt_styles[] = "$base_url/datatables.net/css/dataTables.jqueryui.min.css";
103                $dt_scripts[] = "$base_url/datatables.net-buttons/js/buttons.jqueryui.min.js";
104                $dt_styles[] = "$base_url/datatables.net-buttons/css/buttons.jqueryui.min.css";
105        }
106
107        foreach ($dt_scripts as $script) {
108            $event->data['script'][] = [
109                'type' => 'text/javascript',
110                'src' => $script,
111                'defer' => 'defer',
112                '_data' => null,
113            ];
114        }
115
116        foreach ($dt_styles as $style) {
117            $event->data['link'][] = [
118                'type' => 'text/css',
119                'rel' => 'stylesheet',
120                'href' => $style,
121            ];
122        }
123    }
124
125    /**
126     * Get possible language file paths for the current language
127     *
128     * @return Generator<string> Path relative to the asset locations
129     */
130    protected function getLangPath()
131    {
132        global $conf;
133        [$lang, $dialect] = array_pad(explode('-', $conf['lang'], 2), 2, null);
134        $dialect = strtoupper($dialect);
135
136        // exact match with dialect
137        if ($dialect) {
138            yield "datatables.net-i18n/{$lang}-{$dialect}.json";
139        }
140
141        // exact match with language only
142        yield "datatables.net-i18n/{$lang}.json";
143
144        // fake dialect
145        $dialect = strtoupper($lang);
146        yield "datatables.net-i18n/{$lang}-{$dialect}.json";
147
148        // any matching language
149        $glob = self::ASSET_DIR . '/datatables.net-i18n/' . $lang . '*.json';
150        $result = glob($glob);
151        if ($result) {
152            yield 'datatables.net-i18n/' . basename($result[0]);
153        }
154    }
155}
156