1<?php
2/**
3 * DokuWiki Plugin SketchCanvas (Action Component)
4 *
5 * @license ???
6 * @author  Masahiro Sakuta
7 */
8
9// must be run within Dokuwiki
10if (!defined('DOKU_INC')) die();
11
12require_once("CanvasElement.php");
13
14/**
15 * Add scripts via an event handler
16 */
17class action_plugin_sketchcanvas extends DokuWiki_Action_Plugin {
18
19    /**
20     * Register handler for the TPL_METAHEADER_OUTPUT event
21     */
22    public function register(Doku_Event_Handler $controller) {
23       $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, 'metaheader');
24
25       $controller->register_hook('HTML_SECEDIT_BUTTON', 'BEFORE', $this, 'editButton');
26       $controller->register_hook('HTML_EDIT_FORMSELECTION', 'BEFORE', $this, 'editForm');
27       // After Igor
28       $controller->register_hook('EDIT_FORM_ADDTEXTAREA', 'BEFORE', $this, 'editFormNew');
29       $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_newfigure');
30
31       $controller->register_hook('TOOLBAR_DEFINE', 'AFTER', $this, 'toolbarDefine');
32    }
33
34    /**
35     * Add <script> blocks to the headers
36     *
37     * Scripts are ought to be included via script.js on the plugin root directory, but
38     * it doesn't work if compress option (discarding whitespaces) is ative, so we have to
39     * include the necessary scripts individually in the header.
40     *
41     * @param Doku_Event $event
42     * @param            $param
43     */
44    public function metaheader(Doku_Event &$event, $param) {
45        $event->data['link'][] = array(
46            'type'   => 'text/css',
47            "rel" => "stylesheet",
48            "href" => (is_ssl() ? "https" : "http") . "://fonts.googleapis.com/earlyaccess/notosansjapanese.css",
49             );
50        $event->data['script'][] = array(
51            'type'    => 'text/javascript',
52            'charset' => 'utf-8',
53            'src'     => DOKU_BASE . 'lib/plugins/' . $this->getPluginName() . '/bundle/SketchCanvas.js',
54            '_data'   => '',
55                );
56        $files = array('draw.js', /*'i18next-1.7.2.min.js', 'js-yaml.min.js',*/ );
57        foreach($files as $file)
58            $event->data['script'][] = array(
59                'type'    => 'text/javascript',
60                'charset' => 'utf-8',
61                'src'     => DOKU_BASE . 'lib/plugins/' . $this->getPluginName() . '/script/' . $file,
62                '_data'   => '',
63    	           );
64        $event->data['script'][] = array(
65            'type'    => 'text/javascript',
66            'charset' => 'utf-8',
67            '_data'   => <<<EOT
68document.addEventListener('DOMContentLoaded', function(){
69    var canvas;
70    for(var i = 1; (canvas = document.getElementById("__sketchcanvas" + i)); i++) {
71        var text = document.getElementById("__sketchcanvas_text" + i);
72        if(text) {
73            var skcanvas = new SketchCanvas.SketchCanvas(canvas);
74            skcanvas.loadData(text.innerHTML);
75            var form = document.forms['__sketchcanvas_form' + i];
76            if(form){
77                var input = document.createElement('input');
78                input.type = 'hidden';
79                input.name = "data";
80                input.value = text.innerHTML;
81                form.appendChild(input);
82            }
83        }
84    }
85});
86EOT
87               );
88    }
89
90    public function editButton(Doku_Event $event, $param){
91        if($event->data['target'] !== 'plugin_sketchcanvas')
92            return;
93
94        $event->data['name'] = /*$this->getLang*/('Edit Figure');
95    }
96
97    public function editForm(Doku_Event $event, $param){
98        global $TEXT;
99        if($event->data['target'] !== 'plugin_sketchcanvas')
100            return;
101        $event->preventDefault();
102
103        $event->data['media_manager'] = false;
104
105        $escText = '"' . str_replace(array("\r", "\n"), array('\r', '\n'), addslashes($TEXT)) . '"';
106
107        $form =& $event->data['form'];
108        $canvasText = <<<EOT
109<canvas id="editcanvas"></canvas>
110<script type="text/javascript"><!--
111var skcanvas;
112document.addEventListener('DOMContentLoaded', function(){
113    skcanvas = new SketchCanvas.SketchCanvas(document.getElementById('editcanvas'), {editmode: true});
114    skcanvas.loadData($escText);
115    skcanvas.onUpdateData = function(data){
116        var wikitext = document.getElementById('wiki__text');
117        wikitext.value = data;
118    }
119});
120--></script>
121<input type="button" value="Load data from text" onclick="skcanvas.loadData(document.getElementById('wiki__text').value)">
122<textarea name="wikitext" id="wiki__text" class="edit" cols="80" rows="10">$TEXT</textarea>
123EOT;
124        $form->addElement($canvasText);
125
126        // Pass wikitext through POSTs for previewing and saving
127        if(isset($_POST['editfigure__new'])) {
128            foreach($_POST['editfigure__new'] as $k => $v) {
129                $form->addHidden("editfigure__new[$k]", $v);
130            }
131        }
132    }
133
134    /**
135     * An event handler for newer versions of DokuWiki, starting from Igor.
136     *
137     * @param Doku_Event $event
138     */
139    public function editFormNew(Doku_Event $event, $param){
140        global $TEXT;
141        if($event->data['target'] !== 'plugin_sketchcanvas')
142            return;
143        $event->preventDefault();
144
145        $event->data['media_manager'] = false;
146
147        $form =& $event->data['form'];
148        $canvasElem = new CanvasElement();
149        $canvasElem->val($TEXT);
150        $form->addElement($canvasElem);
151
152        // Pass wikitext through POSTs for previewing and saving
153        if(isset($_POST['editfigure__new'])) {
154            foreach($_POST['editfigure__new'] as $k => $v) {
155                $form->setHiddenField("editfigure__new[$k]", $v);
156            }
157        }
158    }
159
160    /**
161     * Add a toolbar button to add a new figure
162     *
163     * @param Doku_Event $event
164     */
165    public function toolbarDefine(Doku_Event $event, $param){
166        $event->data[] = array(
167            'type' => 'NewFigure',
168            'title' => 'New Figure',
169            'icon' => '../../plugins/' . $this->getPluginName() . '/images/figure.png',
170            'block' => true);
171    }
172
173    /**
174     * Handle the click on the new figure button in the toolbar
175     *
176     * @param Doku_Event $event
177     */
178    function handle_newfigure($event) {
179        global $INPUT;
180        global $TEXT;
181        global $ACT;
182
183        if(!$INPUT->post->has('editfigure__new')) return;
184
185        /*
186         * $fields['pre']  has all data before the selection when the "Insert table" button was clicked
187         * $fields['text'] has all data inside the selection when the "Insert table" button was clicked
188         * $fields['suf']  has all data after the selection when the "Insert table" button was clicked
189         * $TEXT has the table created by the editor (from action_plugin_edittable_editor::handle_table_post())
190         */
191        $fields = $INPUT->post->arr('editfigure__new');
192
193        // clean the fields (undos formText()) and update the post and request arrays
194        $fields['pre'] = cleanText($fields['pre']);
195        $fields['text'] = cleanText($fields['text']);
196        $fields['suf'] = cleanText($fields['suf']);
197        $INPUT->post->set('editfigure__new', $fields);
198
199
200        $ACT = act_clean($ACT);
201        switch($ACT){
202            case 'preview':
203                // preview view of a table edit
204                $INPUT->post->set('target', 'plugin_sketchcanvas');
205                break;
206            case 'edit':
207                // edit view of a table (first edit)
208                $INPUT->post->set('target', 'plugin_sketchcanvas');
209                $TEXT = "";
210                $lines = explode("\n", $fields['text']);
211
212                // Delete opening and closing <skcanvas> tags from the input because they're not part of
213                // the figure source and the tags will be added on the save button anyway
214                if(preg_match('/^<skcanvas.*?>/', $lines[0]))
215                    array_shift($lines);
216                if(preg_match('/^<\/skcanvas>/', end($lines)))
217                    array_pop($lines);
218
219                foreach($lines as $line) {
220                    $TEXT .= "$line\n";
221                }
222                break;
223            case 'draftdel':
224                // not sure if/how this would happen, we restore all data and hand over to section edit
225                $INPUT->post->set('target', 'section');
226                $TEXT = $fields['pre'].$fields['text'].$fields['suf'];
227                $INPUT->post->set('wikitext', $TEXT);
228                $event->data  = 'edit';
229                break;
230            case 'save':
231                // return to edit page
232                $INPUT->post->set('target', 'section');
233                $TEXT = $fields['pre']."<skcanvas>\n".$TEXT."</skcanvas>".$fields['suf'];
234                $INPUT->post->set('wikitext', $TEXT);
235                $ACT  = 'edit';
236                break;
237        }
238    }
239}
240