1<?php
2/**
3 * MoaiEditor plugin for DokuWiki
4 */
5# Constants
6const MOAIED_FAKE_MESSAGES = false;     # Create fake messages (info, error, success, notify) to test template compatibilty
7
8//include_once('/var/www/html/zdebug/inc.php');
9
10use dokuwiki\Extension\Plugin;
11
12if(!defined('DOKU_INC')) die();
13
14class action_plugin_moaieditor extends DokuWiki_Action_Plugin {
15
16    // Register hook function
17    public function register(Doku_Event_Handler $controller) {
18        $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'moaieditor_main');
19    }
20    // Main function
21    public function moaieditor_main (Doku_Event &$event, $param) {
22        global $ACT, $INFO, $conf, $lang;
23
24        // Exit if not in edit mode
25        if (!in_array($ACT, ['edit'])) {
26            return;
27        }
28        // Load the JS files in 'templates/' and 'user_templates/'
29        $info = $this->getInfo();
30        $version = str_replace('-', '', $info['date']);
31        $plugin_path = DOKU_PLUGIN.'moaieditor';
32        $plugin_url  = DOKU_BASE.'lib/plugins/moaieditor';
33        $t = $this->scanTemplateDir ($plugin_url, $plugin_path, "templates");
34        $u = $this->scanTemplateDir ($plugin_url, $plugin_path, "user_templates");
35        $templates = array_merge($t, $u);
36        foreach ($templates as $template)
37            $event->data['script'][] = array(
38                'type' => 'text/javascript',
39                'charset' => 'utf-8',
40                'src' => $plugin_url.'/'.$template['folder'].'/'.$template['name'].".js?v=$version",
41                'defer' => 'defer',
42            );
43        // Pass some data to Javascript
44        $jsinfo = array(
45            // Configuration options
46            'base_url'                  => $plugin_url,
47            'templates'                 => $templates,
48            'hide_editor_by_default'    => $this->getConf('hide_editor_by_default'),
49            'editor_width_side_by_side' => $this->getConf('editor_width_side_by_side'),
50            'editor_width_top_bottom'   => $this->getConf('editor_width_top_bottom'),
51            'editor_width_single_pane'  => $this->getConf('editor_width_single_pane'),
52            // Docinfo
53            'docinfo'                   => $this->getDocinfo(),
54            // Editor intro message
55            'intromsg'                  => $this->getEditorIntroMessage(),
56        );
57        $event->data['script'][] = array(
58            'type' => 'text/javascript',
59            '_data' => 'JSINFO.plugin_moaieditor = ' . json_encode($jsinfo),
60        );
61        // Simulate template messages (for testing template compatibility)
62        if( isset($_GET['fakemsg']) || MOAIED_FAKE_MESSAGES)
63            $this->simulate_template_messages();
64    }
65    // ───────────────────────────────────────────
66    // Scan template dir
67    public function scanTemplateDir ($plugin_url, $plugin_path, $folder) {
68        $files = [];
69        foreach (scandir("$plugin_path/$folder") as $filename)
70            if (str_ends_with($filename, '.js'))
71                if (!str_ends_with($filename, 'default.js')) {
72                    $name = pathinfo($filename, PATHINFO_FILENAME);
73                    $css = Null;
74                    if (file_exists("$plugin_path/$folder/$name.css"))
75                        $css = "$plugin_url/$folder/$name.css";
76                    $files[] = ['name'=>$name, 'folder'=>$folder, 'css'=>$css];
77                }
78        return $files;
79    }
80    // ───────────────────────────────────────────
81    // Get the intro message shown by DokuWiki in editor mode (whether we show it or not will depend on user settings)
82    public function getEditorIntroMessage () {
83        # The editor intro message is rendered here: inc/Ui/Editor.php -> show()
84        # In editor mode, it can be of two types: 'editrev' or 'edit'
85        #      /inc/lang/en/edit.txt       "**You've loaded an old revision of the document!** If you save it, you will create a new version with this data."
86        #      /inc/lang/en/editrev.txt    "Edit the page and hit ''Save''. See [[wiki:syntax]] for Wiki syntax. Please edit the page only if you can **improve** it. If you want to test some things, learn to make your first steps on the [[playground:playground|playground]]."
87        global $REV;
88        global $INFO;
89        $wr = $INFO['writable'] && !$INFO['locked'];
90        if (!$wr)
91            return null;
92        $type = ($REV) ? 'editrev' : 'edit';   // intro locale text (edit, rditrev, or read)
93        $html = p_locale_xhtml($type);
94        return ['type'=>$type, 'html'=>$html];
95    }
96    // ───────────────────────────────────────────
97    // Get document info (mostly copied from 'tpl_pageinfo' but we want to format the data differently)
98    public function getDocinfo () {
99        global $conf, $lang, $INFO, $ID;
100
101        // Document info will not exist when creating a new page
102        if (!$INFO['exists'])
103            return null;
104
105        // Document path on disk
106        $fn = $INFO['filepath'];
107        if (!$conf['fullpath']) {
108            if ($INFO['rev'])
109                $fn = str_replace($conf['olddir'] . '/', '', $fn);
110            else
111                $fn = str_replace($conf['datadir'] . '/', '', $fn);
112        }
113        $fn = utf8_decodeFN($fn);
114
115        // Last modification time
116        $dateLocal = dformat($INFO['lastmod']);
117        $dateIso = date(DATE_ISO8601, $INFO['lastmod']);
118
119        // Edited by
120        if ($INFO['editor'])
121            $by = $lang['by'].' <bdi><b>'.editorinfo($INFO['editor']).'</b></bdi>';
122        else
123            $by = '('.$lang['external_edit'].')';
124
125        // Return it
126        return [
127            'labelPath' => 'Document path on disk',
128            'labelMod'  => $lang['lastmod'],
129            'path'      => "<bdi><i>data/pages/</i><b>$fn</b></bdi>",
130            'time'      => "<time datetime='$dateIso'><b>$dateLocal</b></time>",
131            'by'        => $by
132        ];
133    }
134    // ───────────────────────────────────────────
135    // Function to create fake messages intended to facilitate testing of templates
136    public function simulate_template_messages () {
137        global $MSG;
138        $MSG[] = ['msg'=>'Error message (-1)',  'lvl'=>'error',   'allow'=>0, 'line'=>'', 'file'=>''];
139        $MSG[] = ['msg'=>'Info message (0)',    'lvl'=>'info',    'allow'=>0, 'line'=>'', 'file'=>''];
140        $MSG[] = ['msg'=>'Success message (1)', 'lvl'=>'success', 'allow'=>0, 'line'=>'', 'file'=>''];
141        $MSG[] = ['msg'=>'Notify message (2)',  'lvl'=>'notify',  'allow'=>0, 'line'=>'', 'file'=>''];
142    }
143
144} // End class
145