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

net_nehmer_comments_handler_view::_show_comments()   B

Complexity

Conditions 8
Paths 4

Size

Total Lines 29
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 21.8238

Importance

Changes 0
Metric Value
cc 8
eloc 21
nc 4
nop 2
dl 0
loc 29
ccs 8
cts 20
cp 0.4
crap 21.8238
rs 8.4444
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, $user
Loading history...
26
27
    /**
28
     * The schema database to use.
29
     *
30
     * @var schemadb
31
     */
32
    private $_schemadb;
33
34
    /**
35
     * List of comments we are currently working with.
36
     *
37
     * @var Array
38
     */
39
    private $_comments = [];
40
41
    /**
42
     * A new comment just created for posting.
43
     *
44
     * @var net_nehmer_comments_comment
45
     */
46
    private $_new_comment;
47
48
    /**
49
     * The GUID of the object we're bound to.
50
     *
51
     * @var string GUID
52
     */
53
    private $_objectguid;
54
55
    /**
56
     * The controller used to post a new comment. Only set if we have a valid user.
57
     *
58
     * @var controller
59
     */
60
    private $_post_controller;
61
62
    /**
63
     * This datamanager instance is used to display an existing comment. only set
64
     * if there are actually comments to display.
65
     *
66
     * @var datamanager
67
     */
68
    private $_display_datamanager;
69
70
    /**
71
     * Prepares the request data
72
     */
73 2
    private function _prepare_request_data()
74
    {
75 2
        $this->_request_data['objectguid'] = $this->_objectguid;
76 2
        $this->_request_data['post_controller'] = $this->_post_controller;
77 2
        $this->_request_data['display_datamanager'] = $this->_display_datamanager;
78 2
    }
79
80
    /**
81
     * Prepares the _display_datamanager member.
82
     */
83
    private function _init_display_datamanager()
84
    {
85
        $this->_load_schemadb();
86
        $this->_display_datamanager = new datamanager($this->_schemadb);
87
    }
88
89
    /**
90
     * Loads the schemadb (unless it has already been loaded).
91
     */
92 2
    private function _load_schemadb()
93
    {
94 2
        if (!$this->_schemadb) {
95 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

95
            $this->_schemadb = schemadb::from_path(/** @scrutinizer ignore-type */ $this->_config->get('schemadb'));
Loading history...
96
97 2
            if (   $this->_config->get('use_captcha')
98 2
                || (   !midcom::get()->auth->user
99 2
                    && $this->_config->get('use_captcha_if_anonymous'))) {
100
                $fields = $this->_schemadb->get('comment')->get('fields');
101
                $fields['captcha'] = [
102
                    'title' => $this->_l10n_midcom->get('captcha field title'),
103
                    'storage' => null,
104
                    'type' => 'captcha',
105
                    'widget' => 'captcha',
106
                    'widget_config' => $this->_config->get('captcha_config'),
107
                ];
108
                $this->_schemadb->get('comment')->set('fields', $fields);
109
            }
110
111 2
            if (   $this->_config->get('ratings_enable')
112 2
                && $this->_schemadb->get('comment')->has_field('rating')) {
113
                $this->_schemadb->get('comment')->get_field('rating')['hidden'] = false;
114
            }
115
        }
116 2
    }
117
118
    /**
119
     * Initializes a DM for posting.
120
     *
121
     * @param Request $request The request object
122
     */
123 2
    private function _init_post_controller(Request $request)
124
    {
125 2
        $this->_load_schemadb();
126
127 2
        $defaults = [];
128 2
        if (midcom::get()->auth->user) {
129 2
            $defaults['author'] = midcom::get()->auth->user->name;
130
        }
131
132 2
        $this->_new_comment = new net_nehmer_comments_comment();
133 2
        $this->_new_comment->objectguid = $this->_objectguid;
134 2
        $this->_new_comment->ip = $request->getClientIp();
135
136 2
        if (midcom::get()->auth->user) {
137 2
            $this->_new_comment->status = net_nehmer_comments_comment::NEW_USER;
138 2
            $this->_new_comment->author = midcom::get()->auth->user->name;
139
        } else {
140
            $this->_new_comment->status = net_nehmer_comments_comment::NEW_ANONYMOUS;
141
        }
142
143 2
        if ($this->_config->get('enable_notify')) {
144 2
            $this->_new_comment->_send_notification = true;
145
        }
146
147 2
        $dm = new datamanager($this->_schemadb);
148 2
        $this->_post_controller = $dm
149 2
            ->set_defaults($defaults)
150 2
            ->set_storage($this->_new_comment)
151 2
            ->get_controller();
152 2
    }
153
154
    /**
155
     * Loads the comments, does any processing according to the state of the GET list.
156
     * On successful processing we relocate once to ourself.
157
     */
158 2
    public function _handler_comments(Request $request, string $handler_id, array &$data, string $guid, string $view = null)
159
    {
160 2
        $this->_objectguid = $guid;
161 2
        midcom::get()->cache->content->register($this->_objectguid);
162
163 2
        if ($handler_id == 'view-comments-nonempty') {
164 1
            $this->_comments = net_nehmer_comments_comment::list_by_objectguid_filter_anonymous(
165 1
                $this->_objectguid,
166 1
                $this->_config->get('items_to_show'),
167 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

167
                /** @scrutinizer ignore-type */ $this->_config->get('item_ordering'),
Loading history...
168 1
                $this->_config->get('paging')
169
            );
170
        } else {
171 1
            $this->_comments = net_nehmer_comments_comment::list_by_objectguid(
172 1
                $this->_objectguid,
173 1
                $this->_config->get('items_to_show'),
174 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

174
                /** @scrutinizer ignore-type */ $this->_config->get('item_ordering'),
Loading history...
175 1
                $this->_config->get('paging')
176
            );
177
        }
178
179 2
        if ($this->_config->get('paging') !== false) {
180
            $data['qb_pager'] = $this->_comments;
181
            $this->_comments = $this->_comments->execute();
182
        }
183
184 2
        if (   midcom::get()->auth->user
185 2
            || $this->_config->get('allow_anonymous')) {
186 2
            $this->_init_post_controller($request);
187 2
            if ($response = $this->_process_post($request)) {
188
                return $response;
189
            }
190
        }
191 2
        if ($this->_comments) {
192
            $this->_init_display_datamanager();
193
        }
194
195 2
        if ($handler_id == 'view-comments-custom') {
196
            midcom::get()->skip_page_style = true;
197
            $data['custom_view'] = $view;
198
        }
199
200 2
        $this->_prepare_request_data();
201 2
        midcom::get()->metadata->set_request_metadata($this->_get_last_modified(), $this->_objectguid);
202
203 2
        if ($request->isXmlHttpRequest()) {
204
            midcom::get()->skip_page_style = true;
205
        }
206 2
    }
207
208
    /**
209
     * Checks if a new post has been submitted.
210
     *
211
     * @param Request $request The request object
212
     */
213 2
    private function _process_post(Request $request)
214
    {
215 2
        if (   !midcom::get()->auth->user
216 2
            && !midcom::get()->auth->request_sudo('net.nehmer.comments')) {
217
            throw new midcom_error('We were anonymous but could not acquire SUDO privileges, aborting');
218
        }
219
220 2
        switch ($this->_post_controller->handle($request)) {
221 2
            case 'save':
222
                // Check against comment spam
223
                if ($this->_config->get('enable_spam_check')) {
224
                    $this->check_spam($this->_new_comment);
0 ignored issues
show
Bug introduced by
The method check_spam() does not exist on net_nehmer_comments_handler_view. ( Ignorable by Annotation )

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

224
                    $this->/** @scrutinizer ignore-call */ 
225
                           check_spam($this->_new_comment);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
225
                }
226
227
                $formdata = $this->_post_controller->get_form_values();
228
                if (   $formdata['subscribe']
229
                    && midcom::get()->auth->user) {
230
                    // User wants to subscribe to receive notifications about this comments thread
231
232
                    // Get the object we're commenting
233
                    $parent = midcom::get()->dbfactory->get_object_by_guid($this->_objectguid);
234
235
                    // Sudo so we can update the parent object
236
                    if (midcom::get()->auth->request_sudo($this->_component)) {
237
                        // Save the subscription
238
                        $parent->set_parameter('net.nehmer.comments:subscription', midcom::get()->auth->user->guid, time());
239
240
                        // Return back from the sudo state
241
                        midcom::get()->auth->drop_sudo();
242
                    }
243
                }
244
245
                midcom::get()->cache->invalidate($this->_objectguid);
246
                // Fall-through intentional
247
248 2
            case 'cancel':
249
                if (!midcom::get()->auth->user) {
250
                    midcom::get()->auth->drop_sudo();
251
                }
252
                return new midcom_response_relocate($request->getRequestUri());
253
        }
254 2
    }
255
256
    /**
257
     * Determines the last modified timestamp. It is the max out of all revised timestamps
258
     * of the comments (or 0 in case nothing was found).
259
     */
260 2
    private function _get_last_modified() : int
261
    {
262
        return array_reduce($this->_comments, function ($carry, net_nehmer_comments_comment $item) {
263
            return max($item->metadata->revised, $carry);
264 2
        }, 0);
265
    }
266
267
    /**
268
     * Display the comment list and the submit-comment form.
269
     *
270
     * @param array $data The local request data.
271
     */
272 2
    public function _show_comments(string $handler_id, array &$data)
273
    {
274 2
        midcom_show_style('comments-header');
275 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...
276
            midcom_show_style('comments-start');
277
            foreach ($this->_comments as $comment) {
278
                $this->_display_datamanager->set_storage($comment);
279
                $data['comment'] = $comment;
280
                $data['comment_toolbar'] = $this->populate_post_toolbar($comment);
281
                midcom_show_style('comments-item');
282
283
                if (   midcom::get()->auth->admin
284
                    || (   midcom::get()->auth->user
285
                        && $comment->can_do('midgard:delete'))) {
286
                    midcom_show_style('comments-admintoolbar');
287
                }
288
            }
289
            midcom_show_style('comments-end');
290
        } else {
291 2
            midcom_show_style('comments-nonefound');
292
        }
293
294 2
        if (   midcom::get()->auth->user
295 2
            || $this->_config->get('allow_anonymous')) {
296 2
            midcom_show_style('post-comment');
297
        } else {
298
            midcom_show_style('post-denied');
299
        }
300 2
        midcom_show_style('comments-footer');
301 2
    }
302
}
303