action_plugin_prosemirror_ajax::switchEditors()   B
last analyzed

Complexity

Conditions 7
Paths 7

Size

Total Lines 64
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 45
c 1
b 0
f 0
nc 7
nop 1
dl 0
loc 64
rs 8.2666

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * DokuWiki Plugin prosemirror (Action Component)
5
 *
6
 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
7
 * @author  Andreas Gohr <[email protected]>
8
 */
9
10
use dokuwiki\Extension\ActionPlugin;
11
use dokuwiki\Extension\EventHandler;
12
use dokuwiki\Extension\Event;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Event. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
13
use dokuwiki\plugin\prosemirror\parser\ImageNode;
14
use dokuwiki\plugin\prosemirror\parser\RSSNode;
15
use dokuwiki\plugin\prosemirror\parser\LocalLinkNode;
16
use dokuwiki\plugin\prosemirror\parser\InternalLinkNode;
17
use dokuwiki\plugin\prosemirror\parser\LinkNode;
18
19
class action_plugin_prosemirror_ajax extends ActionPlugin
20
{
21
    /**
22
     * Registers a callback function for a given event
23
     *
24
     * @param EventHandler $controller DokuWiki's event controller object
25
     *
26
     * @return void
27
     */
28
    public function register(EventHandler $controller)
29
    {
30
        $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleAjax');
31
        $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'switchEditors');
32
    }
33
34
    /**
35
     * [Custom event handler which performs action]
36
     *
37
     * Event: AJAX_CALL_UNKNOWN
38
     *
39
     * @param Event $event event object by reference
40
     *
41
     * @return void
42
     */
43
    public function handleAjax(Event $event)
44
    {
45
        if ($event->data !== 'plugin_prosemirror') {
46
            return;
47
        }
48
        $event->preventDefault();
49
        $event->stopPropagation();
50
51
        global $INPUT, $ID;
52
        $ID = $INPUT->str('id');
53
        $responseData = [];
54
        foreach ($INPUT->arr('actions') as $action) {
55
            switch ($action) {
56
                case 'resolveInternalLink':
57
                    $inner = $INPUT->str('inner');
58
                    $responseData[$action] = $this->resolveInternalLink($inner, $ID);
59
                    break;
60
                case 'resolveInterWikiLink':
61
                    $inner = $INPUT->str('inner');
62
                    [$shortcut, $reference] = explode('>', $inner);
63
                    $responseData[$action] = $this->resolveInterWikiLink($shortcut, $reference);
64
                    break;
65
                case 'resolveMedia':
66
                    $attrs = $INPUT->arr('attrs');
67
                    $responseData[$action] = [
68
                        'data-resolvedHtml' => ImageNode::resolveMedia(
69
                            $attrs['id'],
70
                            $attrs['title'],
71
                            $attrs['align'],
72
                            $attrs['width'],
73
                            $attrs['height'],
74
                            $attrs['cache'],
75
                            $attrs['linking']
76
                        )
77
                    ];
78
                    break;
79
                case 'resolveImageTitle':
80
                    $image = $INPUT->arr('image');
81
                    $responseData[$action] = [];
82
                    $responseData[$action]['data-resolvedImage'] = LinkNode::resolveImageTitle(
83
                        $ID,
84
                        $image['id'],
85
                        $image['title'],
86
                        $image['align'],
87
                        $image['width'],
88
                        $image['height'],
89
                        $image['cache']
90
                    );
91
                    break;
92
                case 'resolveRSS':
93
                    $attrs = json_decode($INPUT->str('attrs'), true);
94
                    $responseData[$action] = RSSNode::renderAttrsToHTML($attrs);
95
                    break;
96
                default:
97
                    dokuwiki\Logger::getInstance(dokuwiki\Logger::LOG_DEBUG)->log(
98
                        __FILE__ . ': ' . __LINE__,
99
                        'Unknown action: ' . $action
100
                    );
101
                    http_status(400, 'unknown action');
102
                    return;
103
            }
104
        }
105
106
        header('Content-Type: application/json');
107
        echo json_encode($responseData);
108
    }
109
110
    protected function resolveInterWikiLink($shortcut, $reference)
111
    {
112
        $xhtml_renderer = p_get_renderer('xhtml');
113
        $xhtml_renderer->interwiki = getInterwiki();
114
        $url = $xhtml_renderer->_resolveInterWiki($shortcut, $reference, $exits);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $exits seems to be never defined.
Loading history...
115
        return [
116
            'url' => $url,
117
            'resolvedClass' => 'interwikilink interwiki iw_' . $shortcut,
118
        ];
119
    }
120
121
    protected function resolveInternalLink($inner, $curId)
122
    {
123
        if ($inner[0] === '#') {
124
            return LocalLinkNode::resolveLocalLink($inner, $curId);
125
        }
126
        return InternalLinkNode::resolveLink($inner, $curId);
127
    }
128
129
    /**
130
     * [Custom event handler which performs action]
131
     *
132
     * Event: AJAX_CALL_UNKNOWN
133
     *
134
     * @param Event $event event object by reference
135
     *
136
     * @return void
137
     */
138
    public function switchEditors(Event $event)
139
    {
140
        if ($event->data !== 'plugin_prosemirror_switch_editors') {
141
            return;
142
        }
143
        $event->preventDefault();
144
        $event->stopPropagation();
145
146
        global $INPUT, $ID;
147
        $ID = $INPUT->str('id');
148
149
        if ($INPUT->bool('getJSON')) {
150
            $text = $INPUT->str('data');
151
            $instructions = p_get_instructions($text);
152
            try {
153
                $prosemirrorJSON = p_render('prosemirror', $instructions, $info);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $info seems to be never defined.
Loading history...
154
            } catch (Throwable $e) {
155
                $errorMsg = 'Rendering the page\'s syntax for the WYSIWYG editor failed: ';
156
                $errorMsg .= $e->getMessage();
157
158
                /** @var \helper_plugin_prosemirror $helper */
159
                $helper = plugin_load('helper', 'prosemirror');
160
                if ($helper->tryToLogErrorToSentry($e, ['text' => $text])) {
161
                    $errorMsg .= ' -- The error has been logged to Sentry.';
162
                } else {
163
                    $errorMsg .= '<code>' . $e->getFile() . ':' . $e->getLine() . '</code>';
164
                    $errorMsg .= '<pre>' . $e->getTraceAsString() . '</pre>';
165
                }
166
167
                http_status(500);
168
                header('Content-Type: application/json');
169
                echo json_encode(['error' => $errorMsg]);
170
                return;
171
            }
172
            $responseData = [
173
                'json' => $prosemirrorJSON,
174
            ];
175
        } else {
176
            /** @var \helper_plugin_prosemirror $helper */
177
            $helper = plugin_load('helper', 'prosemirror');
178
            $json = $INPUT->str('data');
179
            try {
180
                $syntax = $helper->getSyntaxFromProsemirrorData($json);
181
            } catch (Throwable $e) {
182
                $errorMsg = 'Parsing the data generated by Prosemirror failed with message: "';
183
                $errorMsg .= $e->getMessage();
184
                $errorMsg .= '"';
185
186
                if ($helper->tryToLogErrorToSentry($e, ['json' => $json])) {
187
                    $errorMsg .= ' -- The error has been logged to Sentry.';
188
                }
189
190
                http_status(500);
191
                header('Content-Type: application/json');
192
                echo json_encode(['error' => $errorMsg]);
193
                return;
194
            }
195
            $responseData = [
196
                'text' => $syntax,
197
            ];
198
        }
199
200
        header('Content-Type: application/json');
201
        echo json_encode($responseData);
202
    }
203
}
204