Passed
Push — master ( 92128b...d5c2c1 )
by Andreas
17:19
created

net_nemein_wiki_handler_view::_populate_toolbar()   A

Complexity

Conditions 5
Paths 12

Size

Total Lines 54
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 26
CRAP Score 5.4248

Importance

Changes 0
Metric Value
cc 5
eloc 37
c 0
b 0
f 0
nc 12
nop 0
dl 0
loc 54
ccs 26
cts 35
cp 0.7429
crap 5.4248
rs 9.0168

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
 * @package net.nemein.wiki
4
 * @author The Midgard Project, http://www.midgard-project.org
5
 * @copyright The Midgard Project, http://www.midgard-project.org
6
 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
7
 */
8
9
use midcom\datamanager\datamanager;
10
use Symfony\Component\HttpFoundation\Request;
11
12
/**
13
 * Wikipage view handler
14
 *
15
 * @package net.nemein.wiki
16
 */
17
class net_nemein_wiki_handler_view extends midcom_baseclasses_components_handler
18
{
19
    use net_nemein_wiki_handler;
0 ignored issues
show
introduced by
The trait net_nemein_wiki_handler requires some properties which are not provided by net_nemein_wiki_handler_view: $id, $extra
Loading history...
20
21
    /**
22
     * The wikipage we're viewing
23
     *
24
     * @var net_nemein_wiki_wikipage
25
     */
26
    private $_page;
27
28
    /**
29
     * The Datamanager for article to display
30
     *
31
     * @var datamanager
32
     */
33
    private $_datamanager;
34
35
    /**
36
     * Internal helper, loads the datamanager for the current wikipage. Any error triggers a 500.
37
     */
38 4
    private function _load_datamanager()
39
    {
40 4
        $this->_datamanager = datamanager::from_schemadb($this->_config->get('schemadb'))
0 ignored issues
show
Bug introduced by
It seems like $this->_config->get('schemadb') can also be of type false; however, parameter $path of midcom\datamanager\datamanager::from_schemadb() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

40
        $this->_datamanager = datamanager::from_schemadb(/** @scrutinizer ignore-type */ $this->_config->get('schemadb'))
Loading history...
41 4
            ->set_storage($this->_page);
42 4
    }
43
44 3
    private function _populate_toolbar()
45
    {
46 3
        $workflow = $this->get_workflow('datamanager');
47
        $buttons = [
48
            [
49 3
                MIDCOM_TOOLBAR_URL => "{$this->_page->name}/",
50 3
                MIDCOM_TOOLBAR_LABEL => $this->_l10n_midcom->get('view'),
51 3
                MIDCOM_TOOLBAR_GLYPHICON => 'search',
52 3
                MIDCOM_TOOLBAR_ACCESSKEY => 'v',
53
            ],
54 3
            $workflow->get_button("edit/{$this->_page->name}/", [
55 3
                MIDCOM_TOOLBAR_ACCESSKEY => 'e',
56 3
                MIDCOM_TOOLBAR_ENABLED => $this->_page->can_do('midgard:update'),
57
            ])
58
        ];
59 3
        if ($this->_page->can_do('midgard:delete')) {
60 1
            $workflow = $this->get_workflow('delete', ['object' => $this->_page]);
61 1
            $buttons[] = $workflow->get_button("delete/{$this->_page->name}/");
62
        }
63
64 3
        $buttons[] = [
65 3
            MIDCOM_TOOLBAR_URL => "whatlinks/{$this->_page->name}/",
66 3
            MIDCOM_TOOLBAR_LABEL => $this->_l10n->get('what links'),
67 3
            MIDCOM_TOOLBAR_GLYPHICON => 'link',
68
        ];
69
70 3
        if (midcom::get()->auth->user) {
71
            $user = midcom::get()->auth->user->get_storage();
72
            if ($this->_page->get_parameter('net.nemein.wiki:watch', $user->guid)) {
73
                $action = 'unsubscribe';
74
            } else {
75
                $action = 'subscribe';
76
            }
77
            $buttons[] = [
78
                MIDCOM_TOOLBAR_URL => "subscribe/{$this->_page->name}/",
79
                MIDCOM_TOOLBAR_LABEL => $this->_l10n->get($action),
80
                MIDCOM_TOOLBAR_GLYPHICON => 'envelope-o',
81
                MIDCOM_TOOLBAR_POST => true,
82
                MIDCOM_TOOLBAR_POST_HIDDENARGS => [$action => 1],
83
            ];
84
        }
85
86 3
        if ($this->_page->can_do('midgard:update')) {
87 1
            midcom::get()->head->add_link_head([
88 1
                'rel' => 'alternate',
89 1
                'type' => 'application/x-wiki',
90 1
                'title' => $this->_l10n_midcom->get('edit'),
91 1
                'href' => $this->router->generate('edit', ['wikipage' => $this->_page->name]),
92
            ]);
93
        }
94 3
        $this->_view_toolbar->add_items($buttons);
95 3
        org_openpsa_relatedto_plugin::add_button($this->_view_toolbar, $this->_page->guid);
96
97 3
        $this->bind_view_to_object($this->_page, $this->_datamanager->get_schema()->get_name());
98 3
    }
99
100 5
    private function _load_page(string $wikiword, bool $autocreate = true)
101
    {
102 5
        $qb = net_nemein_wiki_wikipage::new_query_builder();
103 5
        $qb->add_constraint('topic', '=', $this->_topic->id);
104 5
        $qb->add_constraint('name', '=', $wikiword);
105 5
        midcom::get()->auth->request_sudo($this->_component);
106 5
        $result = $qb->execute();
107 5
        midcom::get()->auth->drop_sudo();
108 5
        if (!empty($result)) {
109 4
            $this->_page = $result[0];
110 4
            $this->_page->require_do('midgard:read');
111 4
            return;
112
        }
113
114 1
        if ($wikiword == 'index') {
115
            // Autoinitialize
116 1
            $this->_topic->require_do('midgard:create');
117 1
            $this->_page = $this->initialize_index_article($this->_topic);
118 1
            return;
119
        }
120
121
        $urlized_wikiword = midcom_helper_misc::urlize($wikiword);
122
        if ($urlized_wikiword != $wikiword) {
123
            // Lets see if the page for the wikiword exists
124
            $qb = net_nemein_wiki_wikipage::new_query_builder();
125
            $qb->add_constraint('topic', '=', $this->_topic->id);
126
            $qb->add_constraint('title', '=', $wikiword);
127
            $result = $qb->execute();
128
            if (!empty($result)) {
129
                // This wiki page actually exists, so go there as "Permanent Redirect"
130
                return new midcom_response_relocate($this->router->generate('view', ['wikipage' => $result[0]->name]), 301);
131
            }
132
        }
133
        if ($autocreate) {
134
            return new midcom_response_relocate($this->router->generate('notfound', ['wikiword' => rawurlencode($wikiword)]));
135
        }
136
        throw new midcom_error_notfound('The page ' . $wikiword . ' could not be found.');
137
    }
138
139 2
    public function _handler_view(array &$data, string $wikipage = 'index')
140
    {
141 2
        if ($response = $this->_load_page($wikipage)) {
142
            return $response;
143
        }
144 2
        $this->_load_datamanager();
145
146 2
        if ($this->_datamanager->get_schema()->get_name() == 'redirect') {
147
            $qb = net_nemein_wiki_wikipage::new_query_builder();
148
            $qb->add_constraint('topic.component', '=', 'net.nemein.wiki');
149
            $qb->add_constraint('name', '=', $this->_page->url);
150
            $result = $qb->execute();
151
            if (empty($result)) {
152
                // No matching redirection page found, relocate to editing
153
                // TODO: Add UI message
154
                return new midcom_response_relocate("edit/{$this->_page->name}/");
155
            }
156
157
            if ($result[0]->topic == $this->_topic->id) {
158
                return new midcom_response_relocate("{$result[0]->name}/");
159
            }
160
            return new midcom_response_relocate(midcom::get()->permalinks->create_permalink($result[0]->guid));
161
        }
162
163 2
        $this->_populate_toolbar();
164 2
        $this->_view_toolbar->hide_item("{$this->_page->name}/");
165
166 2
        if ($this->_page->name != 'index') {
167 1
            $this->add_breadcrumb("{$this->_page->name}/", $this->_page->title);
168
        }
169
170 2
        midcom::get()->head->set_pagetitle($this->_page->title);
171 2
        midcom::get()->metadata->set_request_metadata($this->_page->metadata->revised, $this->_page->guid);
172
173 2
        $data['wikipage_view'] = $this->_datamanager->get_content_html();
174 2
        $data['wikipage'] = $this->_page;
175
176
        // Replace wikiwords
177 2
        $parser = new net_nemein_wiki_parser($this->_page);
178 2
        $data['wikipage_view']['content'] = $parser->get_markdown($data['wikipage_view']['content']);
179 2
        if ($this->_config->get('autogenerate_toc')) {
180 2
            $data['wikipage_view']['content'] = $this->_autogenerate_toc($data['wikipage_view']['content']);
181
        }
182
183 2
        return $this->show('view-wikipage');
184
    }
185
186
    /**
187
     * Parse HTML content and look for header tags, making index of them.
188
     *
189
     * It looks for all H<num> tags and converts them to named
190
     * anchors, and prepends a list of links to them to the start of HTML.
191
     */
192 2
    private function _autogenerate_toc(string $content) : string
193
    {
194 2
        if (!preg_match_all("/(<(h([1-9][0-9]*))[^>]*?>)(.*?)(<\/\\2>)/i", $content, $headings)) {
195 2
            return $content;
196
        }
197
198
        $toc = '';
199
200
        $current_tag_level = false;
201
        $current_list_level = 1;
202
        $toc .= "\n<ol class=\"midcom_helper_toc_formatter level_{$current_list_level}\">\n";
203
        foreach ($headings[4] as $key => $heading) {
204
            $anchor = 'heading-' . md5($heading);
205
            $tag_level =& $headings[3][$key];
206
            $heading_code =& $headings[0][$key];
207
            $heading_tag =& $headings[2][$key];
208
            $heading_new_code = "<a id='{$anchor}'></a>{$heading_code}";
209
            $content = str_replace($heading_code, $heading_new_code, $content);
210
            if ($current_tag_level === false) {
211
                $current_tag_level = $tag_level;
212
            } elseif ($current_tag_level == $tag_level) {
213
                $toc .= "</li>\n";
214
            } elseif ($tag_level > $current_tag_level) {
215
                for ($i = $current_tag_level; $i < $tag_level; $i++) {
216
                    $current_tag_level = $tag_level;
217
                    $current_list_level++;
218
                    $toc .= "<ol class=\"level_{$current_list_level}\">\n";
219
                    if ($tag_level > $i + 1) {
220
                        $toc .= "<li>\n";
221
                    }
222
                }
223
            } else {
224
                for ($i = $current_tag_level; $i > $tag_level; $i--) {
225
                    $toc .= "</li>\n";
226
                    $current_tag_level = $tag_level;
227
                    if ($current_list_level > 1) {
228
                        $current_list_level--;
229
                        $toc .= "</ol>\n";
230
                    }
231
                }
232
            }
233
            $toc .= "<li class='{$heading_tag}'><a href='#{$anchor}'>" . strip_tags($heading) . "</a>";
234
        }
235
        $toc .= str_repeat("</li>\n</ol>\n", $current_list_level);
236
237
        return $toc . $content;
238
    }
239
240 1
    public function _handler_raw(string $wikipage, array &$data)
241
    {
242 1
        if ($response = $this->_load_page($wikipage, false)) {
243
            return $response;
244
        }
245 1
        midcom::get()->skip_page_style = true;
246 1
        $this->_load_datamanager();
247
248 1
        $data['wikipage_view'] = $this->_datamanager->get_content_html();
249
250
        // Replace wikiwords
251 1
        $parser = new net_nemein_wiki_parser($this->_page);
252 1
        $data['wikipage_view']['content'] = $parser->get_markdown($data['wikipage_view']['content']);
253
254 1
        return $this->show('view-wikipage-raw');
255
    }
256
257 1
    public function _handler_subscribe(Request $request, string $wikipage)
258
    {
259 1
        midcom::get()->auth->require_valid_user();
260
261 1
        if ($response = $this->_load_page($wikipage, false)) {
262
            return $response;
263
        }
264
265 1
        midcom::get()->auth->request_sudo('net.nemein.wiki');
266
267 1
        $user = midcom::get()->auth->user->get_storage();
268
269 1
        if ($request->request->get('target') == 'folder') {
270
            // We're subscribing to the whole wiki
271
            $object = $this->_topic;
272
            $target = sprintf($this->_l10n->get('whole wiki %s'), $this->_topic->extra);
273
        } else {
274 1
            $object = $this->_page;
275 1
            $target = sprintf($this->_l10n->get('page %s'), $this->_page->title);
276
        }
277
278 1
        if ($request->request->has('subscribe')) {
279
            // Subscribe to page
280 1
            $object->set_parameter('net.nemein.wiki:watch', $user->guid, time());
281 1
            midcom::get()->uimessages->add($this->_l10n->get($this->_component), sprintf($this->_l10n->get('subscribed to changes in %s'), $target));
282
        } else {
283
            // Remove subscription
284
            $object->delete_parameter('net.nemein.wiki:watch', $user->guid);
285
            midcom::get()->uimessages->add($this->_l10n->get($this->_component), sprintf($this->_l10n->get('unsubscribed from changes in %s'), $target));
286
        }
287
288 1
        midcom::get()->auth->drop_sudo();
289
290
        // Redirect to editing
291 1
        if ($this->_page->name == 'index') {
292
            return new midcom_response_relocate("");
293
        }
294 1
        return new midcom_response_relocate("{$this->_page->name}/");
295
    }
296
297 1
    public function _handler_whatlinks(string $wikipage, array &$data)
298
    {
299 1
        if ($response = $this->_load_page($wikipage, false)) {
300
            return $response;
301
        }
302
303 1
        $this->_load_datamanager();
304
305 1
        $this->_populate_toolbar();
306 1
        $this->_view_toolbar->hide_item("whatlinks/{$this->_page->name}/");
307 1
        $this->add_breadcrumb("{$this->_page->name}/", $this->_page->title);
308
309 1
        $qb = net_nemein_wiki_link_dba::new_query_builder();
310 1
        $qb->add_constraint('topage', '=', $this->_page->title);
311 1
        $data['wikilinks'] = $qb->execute();
312 1
        $data['wikipage_view'] = $this->_datamanager->get_content_html();
313
314
        // Replace wikiwords
315 1
        $parser = new net_nemein_wiki_parser($this->_page);
316 1
        $data['wikipage_view']['content'] = $parser->get_markdown($data['wikipage_view']['content']);
317
318 1
        return $this->show('view-wikipage-whatlinks');
319
    }
320
321
    /**
322
     * Callback for sorting wikipages by title
323
     */
324
    public static function sort_by_title(net_nemein_wiki_wikipage $a, net_nemein_wiki_wikipage $b)
325
    {
326
        return strnatcmp($a->title, $b->title);
327
    }
328
}
329