1<?php
2/**
3 * DokuWiki Plugin jsoneditor (Helper Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Janez Paternoster <janez.paternoster@siol.net>
7 */
8
9// must be run within Dokuwiki
10if (!defined('DOKU_INC')) {
11    die();
12}
13
14class helper_plugin_jsoneditor extends helper_plugin_json {
15
16    /**
17     * Handle extension to syntax_plugin_json_define
18     *
19     * @param array $data Reference to $data, which can be further manipulated
20     */
21    public function handle(&$data) {
22        $json_o = $this->loadHelper('json');
23
24        //options for the jsoneditor
25        $data['options_default'] = $this->getConf('options');
26        if(isset($data['keys']['options'])) {
27            $data['options'] = $data['keys']['options'];
28            //replace %$ ... % snippets with data - prepare
29            $data['options_extractors'] = $json_o->extractors_handle($data['keys']['options']);
30        }
31
32        //schema for the jsoneditor
33        $schema = $data['keys']['schema'] ?? '{}';
34
35        $data['schema'] = $schema;
36        //replace %$ ... % snippets with data - prepare
37        $data['schema_extractors'] = $json_o->extractors_handle($schema);
38
39        //If 'save' attribute is set to 'all', then complete json object
40        //from jsoneditor will be saved into <json> element.
41        //Othervise only difference between original data and inline
42        //data will be saved (default).
43        $save = isset($data['keys']['save']) ? $data['keys']['save'] : '';
44        if($save !== '' && strtolower($save) === 'all') {
45            $data['saveall'] = 'true';
46        }
47        else {
48            $data['saveall'] = 'false';
49            $data['display'] .= ',orig-hidden';
50        }
51
52        //make sure, necessary json data will be there
53        $data['display'] .= ',inl-hidden,comb-hidden';
54    }
55
56
57    /**
58     * Render extension to syntax_plugin_json_define
59     *
60     * For parameters see render::syntax_plugin_json_define
61     *
62     * @param array $data from handler
63     * @param array $class definitions for parent div
64     * @param array $data_attr html data attributes
65     * @param array $tabs definitions for jQuery UI tabs widget
66     * @param array $body definitions for jQuery UI tabs widget
67     * @param array $log for reporting errors
68     * @param array $tab_no must incerment for each tab
69     * @param array $tab_number for id attribute
70     */
71    public function render(Doku_Renderer $renderer, &$data, &$class, &$data_attr, &$tabs, &$body, &$log, &$tab_no, $tab_number) {
72        //prepare options from default and optional inline options
73        $options = $data['options_default'];
74        if(isset($data['options'])) {
75            $options_inline = $data['options'];
76            //replace %$ ... % snippets with data
77            if(count($data['options_extractors']) > 0) {
78                $json_o = $this->loadHelper('json');
79                $options_inline = $json_o->extractors_replace($options_inline, $data['options_extractors']);
80            }
81            if($options === '{}') {
82                $options = $options_inline;
83            }
84            else {
85                //combine default and inline options
86                $json_options_default = json_decode($options, true);
87                if(!isset($json_options_default)) {
88                    $json_options_default = json_decode('{}', true);
89                    $log['error'] = 'internal JSON, default options '.json_last_error_msg();
90                }
91                $json_options_inline = json_decode($options_inline, true);
92                if(!isset($json_options_inline)) {
93                    $json_options_inline = json_decode('{}', true);
94                    $log['error'] = 'internal JSON, inline options '.json_last_error_msg();
95                }
96                $json_options = array_replace_recursive($json_options_default, $json_options_inline);
97                $options = json_encode($json_options);
98            }
99        }
100
101        if(count($data['schema_extractors']) > 0) {
102            $json_o = $this->loadHelper('json');
103            $schema = $json_o->extractors_replace($data['schema'], $data['schema_extractors']);
104        }
105        else {
106            $schema = $data['schema'];
107        }
108
109        $data_attr['options'] = htmlspecialchars($options);
110        $data_attr['schema'] = htmlspecialchars($schema);
111        $data_attr['saveall'] = $data['saveall'];
112
113        $class[] = 'jsoneditor-plugin';
114
115        //always display jsoneditor tab, fully shown by default
116        if(strpos($data['display'], 'jsoneditor') === false) {
117            $data['display'] .= ',jsoneditor*';
118        }
119
120        //tab for editor
121        if(strpos($data['display'], 'jsoneditor*') !== false) { $data_attr['active'] = $tab_no; }
122        $tab_no++;
123        $tabs[] = '<li><a href="#json-tab-'.$tab_number.'-editor">'.$this->getLang('json_editor').'</a></li>';
124        $body[] =      '<div id="json-tab-'.$tab_number.'-editor"><div class="json-editor-error"></div><div class="json-editor"></div></div>';
125
126        //tab for schema
127        if(strpos($data['display'], 'all') !== false || strpos($data['display'], 'schema') !== false) {
128            $tab_no++;
129            $tabs[] = '<li><a href="#json-tab-'.$tab_number.'-schema">'.$this->getLang('json_schema').'</a></li>';
130            $body[] =      '<div id="json-tab-'.$tab_number.'-schema"><pre class="lang-json">'.
131            htmlspecialchars(json_encode(json_decode($schema, true), JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE)).'</pre></div>';
132        }
133    }
134}
135