Passed
Push — master ( 32796f...7ac5bb )
by Andreas
12:42
created

net_nehmer_comments_handler_view::_load_schemadb()   B

Complexity

Conditions 7
Paths 5

Size

Total Lines 22
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 15.4039

Importance

Changes 0
Metric Value
cc 7
eloc 16
nc 5
nop 0
dl 0
loc 22
ccs 8
cts 18
cp 0.4444
crap 15.4039
rs 8.8333
c 0
b 0
f 0
1
<?php
2
/**
3
 * @package net.nehmer.comments
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\schemadb;
10
use midcom\datamanager\datamanager;
11
use midcom\datamanager\controller;
12
use Symfony\Component\HttpFoundation\Request;
13
14
/**
15
 * Comments view handler.
16
 *
17
 * This handler is a single handler which displays the thread for a given object GUID.
18
 * It checks for various commands in the request during startup and processes them
19
 * if applicable. It relocates to the same page to prevent duplicate request runs.
20
 *
21
 * @package net.nehmer.comments
22
 */
23
class net_nehmer_comments_handler_view extends midcom_baseclasses_components_handler
24
{
25
    use net_nehmer_comments_handler;
0 ignored issues
show
introduced by
The trait net_nehmer_comments_handler requires some properties which are not provided by net_nehmer_comments_handler_view: $auth, $guid
Loading history...
26
27
    private ?schemadb $_schemadb = null;
28
29
    /**
30
     * @var net_nehmer_comments_comment[]
31
     */
32
    private array $_comments = [];
33
34
    private net_nehmer_comments_comment $_new_comment;
35
36
    private string $_objectguid;
37
38
    private controller $_post_controller;
39
40
    private datamanager $_display_datamanager;
41
42
    /**
43
     * Prepares the request data
44
     */
45 2
    private function _prepare_request_data()
46
    {
47 2
        $this->_request_data['objectguid'] = $this->_objectguid;
48 2
        $this->_request_data['post_controller'] = $this->_post_controller;
49
    }
50
51
    /**
52
     * Prepares the _display_datamanager member.
53
     */
54
    private function _init_display_datamanager()
55
    {
56
        $this->_load_schemadb();
57
        $this->_display_datamanager = new datamanager($this->_schemadb);
58
        $this->_request_data['display_datamanager'] = $this->_display_datamanager;
59
    }
60
61
    /**
62
     * Loads the schemadb (unless it has already been loaded).
63
     */
64 2
    private function _load_schemadb()
65
    {
66 2
        if (!$this->_schemadb) {
67 2
            $this->_schemadb = schemadb::from_path($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\schemadb::from_path() 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

67
            $this->_schemadb = schemadb::from_path(/** @scrutinizer ignore-type */ $this->_config->get('schemadb'));
Loading history...
68
69 2
            if (   $this->_config->get('use_captcha')
70 2
                || (   !midcom::get()->auth->user
71 2
                    && $this->_config->get('use_captcha_if_anonymous'))) {
72
                $fields = $this->_schemadb->get('comment')->get('fields');
73
                $fields['captcha'] = [
74
                    'title' => $this->_l10n_midcom->get('captcha field title'),
75
                    'storage' => null,
76
                    'type' => 'captcha',
77
                    'widget' => 'captcha',
78
                    'widget_config' => $this->_config->get_array('captcha_config'),
79
                ];
80
                $this->_schemadb->get('comment')->set('fields', $fields);
81
            }
82
83 2
            if (   $this->_config->get('ratings_enable')
84 2
                && $this->_schemadb->get('comment')->has_field('rating')) {
85
                $this->_schemadb->get('comment')->get_field('rating')['hidden'] = false;
86
            }
87
        }
88
    }
89
90
    /**
91
     * Initializes a DM for posting.
92
     */
93 2
    private function _init_post_controller(Request $request)
94
    {
95 2
        $this->_load_schemadb();
96
97 2
        $defaults = [];
98 2
        if (midcom::get()->auth->user) {
99 2
            $defaults['author'] = midcom::get()->auth->user->name;
100
        }
101
102 2
        $this->_new_comment = new net_nehmer_comments_comment();
103 2
        $this->_new_comment->objectguid = $this->_objectguid;
104 2
        $this->_new_comment->ip = $request->getClientIp();
105
106 2
        if (midcom::get()->auth->user) {
107 2
            $this->_new_comment->status = net_nehmer_comments_comment::NEW_USER;
108 2
            $this->_new_comment->author = midcom::get()->auth->user->name;
109
        } else {
110
            $this->_new_comment->status = net_nehmer_comments_comment::NEW_ANONYMOUS;
111
        }
112
113 2
        if ($this->_config->get('enable_notify')) {
114 2
            $this->_new_comment->_send_notification = true;
115
        }
116
117 2
        $dm = new datamanager($this->_schemadb);
118 2
        $this->_post_controller = $dm
119 2
            ->set_defaults($defaults)
120 2
            ->set_storage($this->_new_comment)
121 2
            ->get_controller();
122
    }
123
124
    /**
125
     * Loads the comments, does any processing according to the state of the GET list.
126
     * On successful processing we relocate once to ourself.
127
     */
128 2
    public function _handler_comments(Request $request, string $handler_id, array &$data, string $guid, string $view = null)
129
    {
130 2
        $this->_objectguid = $guid;
131 2
        midcom::get()->cache->content->register($this->_objectguid);
132
133 2
        if ($handler_id == 'view-comments-nonempty') {
134 1
            $this->_comments = net_nehmer_comments_comment::list_by_objectguid_filter_anonymous(
135 1
                $this->_objectguid,
136 1
                $this->_config->get('items_to_show'),
137 1
                $this->_config->get('item_ordering'),
0 ignored issues
show
Bug introduced by
It seems like $this->_config->get('item_ordering') can also be of type false; however, parameter $order of net_nehmer_comments_comm...guid_filter_anonymous() 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

137
                /** @scrutinizer ignore-type */ $this->_config->get('item_ordering'),
Loading history...
138 1
                $this->_config->get('paging')
139 1
            );
140
        } else {
141 1
            $this->_comments = net_nehmer_comments_comment::list_by_objectguid(
142 1
                $this->_objectguid,
143 1
                $this->_config->get('items_to_show'),
144 1
                $this->_config->get('item_ordering'),
0 ignored issues
show
Bug introduced by
It seems like $this->_config->get('item_ordering') can also be of type false; however, parameter $order of net_nehmer_comments_comment::list_by_objectguid() 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

144
                /** @scrutinizer ignore-type */ $this->_config->get('item_ordering'),
Loading history...
145 1
                $this->_config->get('paging')
146 1
            );
147
        }
148
149 2
        if ($this->_config->get('paging') !== false) {
150
            $data['qb_pager'] = $this->_comments;
151
            $this->_comments = $this->_comments->execute();
152
        }
153
154 2
        if (   midcom::get()->auth->user
155 2
            || $this->_config->get('allow_anonymous')) {
156 2
            $this->_init_post_controller($request);
157 2
            if ($response = $this->_process_post($request)) {
158
                return $response;
159
            }
160
        }
161 2
        if ($this->_comments) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->_comments of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
162
            $this->_init_display_datamanager();
163
        }
164
165 2
        if ($handler_id == 'view-comments-custom') {
166
            midcom::get()->skip_page_style = true;
167
            $data['custom_view'] = $view;
168
        }
169
170 2
        $this->_prepare_request_data();
171 2
        midcom::get()->metadata->set_request_metadata($this->_get_last_modified(), $this->_objectguid);
172
173 2
        if ($request->isXmlHttpRequest()) {
174
            midcom::get()->skip_page_style = true;
175
        }
176
    }
177
178
    /**
179
     * Checks if a new post has been submitted.
180
     */
181 2
    private function _process_post(Request $request)
182
    {
183 2
        if (   !midcom::get()->auth->user
184 2
            && !midcom::get()->auth->request_sudo('net.nehmer.comments')) {
185
            throw new midcom_error('We were anonymous but could not acquire SUDO privileges, aborting');
186
        }
187
188 2
        switch ($this->_post_controller->handle($request)) {
189 2
            case 'save':
190
                // Check against comment spam
191
                if ($this->_config->get('enable_spam_check')) {
192
                    net_nehmer_comments_spamchecker::check($this->_new_comment);
193
                }
194
195
                $formdata = $this->_post_controller->get_form_values();
196
                if (   $formdata['subscribe']
197
                    && midcom::get()->auth->user) {
198
                    // User wants to subscribe to receive notifications about this comments thread
199
200
                    // Get the object we're commenting
201
                    $parent = midcom::get()->dbfactory->get_object_by_guid($this->_objectguid);
202
203
                    // Sudo so we can update the parent object
204
                    if (midcom::get()->auth->request_sudo($this->_component)) {
205
                        // Save the subscription
206
                        $parent->set_parameter('net.nehmer.comments:subscription', midcom::get()->auth->user->guid, time());
207
208
                        // Return back from the sudo state
209
                        midcom::get()->auth->drop_sudo();
210
                    }
211
                }
212
213
                midcom::get()->cache->invalidate($this->_objectguid);
214
                // Fall-through intentional
215
216 2
            case 'cancel':
217
                if (!midcom::get()->auth->user) {
218
                    midcom::get()->auth->drop_sudo();
219
                }
220
                return new midcom_response_relocate($request->getRequestUri());
221
        }
222
    }
223
224
    /**
225
     * Determines the last modified timestamp. It is the max out of all revised timestamps
226
     * of the comments (or 0 in case nothing was found).
227
     */
228 2
    private function _get_last_modified() : int
229
    {
230 2
        return array_reduce($this->_comments, function ($carry, net_nehmer_comments_comment $item) {
231
            return max($item->metadata->revised, $carry);
232 2
        }, 0);
233
    }
234
235
    /**
236
     * Display the comment list and the submit-comment form.
237
     */
238 2
    public function _show_comments(string $handler_id, array &$data)
239
    {
240 2
        midcom_show_style('comments-header');
241 2
        if ($this->_comments) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->_comments of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
242
            midcom_show_style('comments-start');
243
            foreach ($this->_comments as $comment) {
244
                $this->_display_datamanager->set_storage($comment);
245
                $data['comment'] = $comment;
246
                $data['comment_toolbar'] = $this->populate_post_toolbar($comment);
247
                midcom_show_style('comments-item');
248
249
                if (   midcom::get()->auth->admin
250
                    || (   midcom::get()->auth->user
251
                        && $comment->can_do('midgard:delete'))) {
252
                    midcom_show_style('comments-admintoolbar');
253
                }
254
            }
255
            midcom_show_style('comments-end');
256
        } else {
257 2
            midcom_show_style('comments-nonefound');
258
        }
259
260 2
        if (   midcom::get()->auth->user
261 2
            || $this->_config->get('allow_anonymous')) {
262 2
            midcom_show_style('post-comment');
263
        } else {
264
            midcom_show_style('post-denied');
265
        }
266 2
        midcom_show_style('comments-footer');
267
    }
268
}
269