1<?php
2
3use dokuwiki\Extension\ActionPlugin;
4use dokuwiki\Extension\EventHandler;
5use dokuwiki\Extension\Event;
6use dokuwiki\plugin\gallery\classes\Options;
7use dokuwiki\plugin\gallery\GalleryNode;
8use dokuwiki\plugin\prosemirror\parser\RootNode;
9use dokuwiki\plugin\prosemirror\schema\Node;
10
11class action_plugin_gallery_prosemirror extends ActionPlugin
12{
13    /**
14     * Registers a callback function for a given event
15     *
16     * @param EventHandler $controller DokuWiki's event controller object
17     *
18     * @return void
19     */
20    public function register(EventHandler $controller)
21    {
22        // check if prosemirror is installed
23        if (!class_exists('\dokuwiki\plugin\prosemirror\schema\Node')) return;
24
25        $controller->register_hook('DOKUWIKI_STARTED', 'BEFORE', $this, 'writeDefaultsToJSINFO');
26        $controller->register_hook('PROSEMIRROR_RENDER_PLUGIN', 'BEFORE', $this, 'renderFromInstructions');
27        $controller->register_hook('PROSEMIRROR_PARSE_UNKNOWN', 'BEFORE', $this, 'parseToSyntax');
28        $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'renderAttributesToHTML');
29    }
30
31    /**
32     * Render our syntax instructions for prosemirror
33     *
34     * Triggered by event: DOKUWIKI_STARTED
35     *
36     * @param Event $event event object
37     * @param mixed $param [the parameters passed as fifth argument to register_hook() when this
38     *                           handler was registered]
39     *
40     * @return void
41     */
42    public function writeDefaultsToJSINFO(Event $event, $param)
43    {
44        global $JSINFO;
45
46        $defaults = $this->getDefaults();
47
48        if (!isset($JSINFO['plugins'])) {
49            $JSINFO['plugins'] = [];
50        }
51        $JSINFO['plugins']['gallery'] = [
52            'defaults' => array_map(function ($default) {
53                return ['default' => $default,];
54            }, $defaults),
55        ];
56        $JSINFO['plugins']['gallery']['defaults']['namespace'] = ['default' => ''];
57    }
58
59
60    /**
61     * Render our syntax instructions for prosemirror
62     *
63     * Triggered by event: PROSEMIRROR_RENDER_PLUGIN
64     *
65     * @param Event $event event object
66     * @param mixed $param [the parameters passed as fifth argument to register_hook() when this
67     *                           handler was registered]
68     *
69     * @return void
70     */
71    public function renderFromInstructions(Event $event, $param)
72    {
73        if ($event->data['name'] !== 'gallery_main') {
74            return;
75        }
76        $event->preventDefault();
77        $event->stopPropagation();
78
79        $node = new Node('dwplugin_gallery');
80        $data = $event->data['data'];
81        // FIXME source can be something other than namespace
82        [$ns, $options] = $data;
83
84        if (cleanID($ns) === $ns) {
85            $ns = ':' . $ns;
86        }
87        $node->attr('namespace', $ns);
88
89        $attrs = $this->optionsToAttrs($options);
90        foreach ($attrs as $name => $value) {
91            $node->attr($name, $value);
92        }
93        $event->data['renderer']->nodestack->add($node);
94    }
95
96    /**
97     * Render our syntax instructions for prosemirror
98     *
99     * Triggered by event: PROSEMIRROR_PARSE_UNKNOWN
100     *
101     * @param Event $event event object
102     * @param mixed $param [the parameters passed as fifth argument to register_hook() when this
103     *                           handler was registered]
104     *
105     * @return void
106     */
107    public function parseToSyntax(Event $event, $param)
108    {
109        if ($event->data['node']['type'] !== 'dwplugin_gallery') {
110            return;
111        }
112        $event->preventDefault();
113        $event->stopPropagation();
114
115        $event->data['newNode'] = new GalleryNode($event->data['node'], $event->data['parent']);
116    }
117
118    /**
119     * Render the nodes attributes to html so it can be displayed in the editor
120     *
121     * Triggered by event: AJAX_CALL_UNKNOQN
122     *
123     * @param Event $event event object
124     * @param mixed $param [the parameters passed as fifth argument to register_hook() when this
125     *                           handler was registered]
126     *
127     * @return void
128     */
129    public function renderAttributesToHTML(Event $event, $param)
130    {
131        if ($event->data !== 'plugin_gallery_prosemirror') {
132            return;
133        }
134        $event->preventDefault();
135        $event->stopPropagation();
136
137        global $INPUT;
138        $node = new GalleryNode(['attrs' => json_decode($INPUT->str('attrs'), true)], new RootNode([]));
139        $syntax = $node->toSyntax();
140        $html = p_render('xhtml', p_get_instructions($syntax), $info);
141        echo $html;
142    }
143
144    /**
145     * Get default node attributes from gallery Options object
146     */
147    public function getDefaults(): array
148    {
149        $options = new Options();
150
151        return [
152            'thumbnailsize' => $options->thumbnailWidth . 'x' . $options->thumbnailHeight,
153            'imagesize' => $options->lightboxWidth . 'X' . $options->lightboxHeight,
154            'cache' => $options->cache,
155            'filter' => $options->filter,
156            'showname' => $options->showname,
157            'showtitle' => $options->showtitle,
158            'crop' => $options->crop,
159            'direct' => $options->direct,
160            'reverse' => $options->reverse,
161            'recursive' => $options->recursive,
162            'align' => $options->align,
163            'cols' => $options->columns,
164            'limit' => $options->limit,
165            'offset' => $options->offset,
166            'paginate' => $options->paginate,
167            'sort' => $options->sort,
168        ];
169    }
170
171    /**
172     * Convert gallery options to node attributes
173     *
174     * @param Options $options
175     * @return array
176     */
177    protected function optionsToAttrs($options)
178    {
179        $attrs = (array)$options;
180
181        $attrs['thumbnailsize'] = $options->thumbnailWidth . 'x' . $options->thumbnailHeight;
182        $attrs['imagesize'] = $options->lightboxWidth . 'X' . $options->lightboxHeight;
183        $attrs['cols'] = $options->columns;
184
185        unset($attrs['thumbnailWidth']);
186        unset($attrs['thumbnailHeight']);
187        unset($attrs['lightboxWidth']);
188        unset($attrs['lightboxHeight']);
189        unset($attrs['columns']);
190
191        return $attrs;
192    }
193}
194