Passed
Push — master ( 00519f...366a1b )
by Andreas
17:30
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
    private $custom_view;
71
72
    /**
73
     * Prepares the request data
74
     */
75 2
    private function _prepare_request_data()
76
    {
77 2
        $this->_request_data['comments'] = $this->_comments;
78 2
        $this->_request_data['objectguid'] = $this->_objectguid;
79 2
        $this->_request_data['post_controller'] = $this->_post_controller;
80 2
        $this->_request_data['display_datamanager'] = $this->_display_datamanager;
81 2
        $this->_request_data['custom_view'] = $this->custom_view;
82 2
    }
83
84
    /**
85
     * Prepares the _display_datamanager member.
86
     */
87
    private function _init_display_datamanager()
88
    {
89
        $this->_load_schemadb();
90
        $this->_display_datamanager = new datamanager($this->_schemadb);
91
    }
92
93
    /**
94
     * Loads the schemadb (unless it has already been loaded).
95
     */
96 2
    private function _load_schemadb()
97
    {
98 2
        if (!$this->_schemadb) {
99 2
            $this->_schemadb = schemadb::from_path($this->_config->get('schemadb'));
100
101 2
            if (   $this->_config->get('use_captcha')
102 2
                || (   !midcom::get()->auth->user
103 2
                    && $this->_config->get('use_captcha_if_anonymous'))) {
104
                $fields = $this->_schemadb->get('comment')->get('fields');
105
                $fields['captcha'] = [
106
                    'title' => $this->_l10n_midcom->get('captcha field title'),
107
                    'storage' => null,
108
                    'type' => 'captcha',
109
                    'widget' => 'captcha',
110
                    'widget_config' => $this->_config->get('captcha_config'),
111
                ];
112
                $this->_schemadb->get('comment')->set('fields', $fields);
113
            }
114
115 2
            if (   $this->_config->get('ratings_enable')
116 2
                && $this->_schemadb->get('comment')->has_field('rating')) {
117
                $this->_schemadb->get('comment')->get_field('rating')['hidden'] = false;
118
            }
119
        }
120 2
    }
121
122
    /**
123
     * Initializes a DM for posting.
124
     *
125
     * @param Request $request The request object
126
     */
127 2
    private function _init_post_controller(Request $request)
128
    {
129 2
        $this->_load_schemadb();
130
131 2
        $defaults = [];
132 2
        if (midcom::get()->auth->user) {
133 2
            $defaults['author'] = midcom::get()->auth->user->name;
134
        }
135
136 2
        $this->_new_comment = new net_nehmer_comments_comment();
137 2
        $this->_new_comment->objectguid = $this->_objectguid;
138 2
        $this->_new_comment->ip = $request->getClientIp();
139
140 2
        if (midcom::get()->auth->user) {
141 2
            $this->_new_comment->status = net_nehmer_comments_comment::NEW_USER;
142 2
            $this->_new_comment->author = midcom::get()->auth->user->name;
143
        } else {
144
            $this->_new_comment->status = net_nehmer_comments_comment::NEW_ANONYMOUS;
145
        }
146
147 2
        if ($this->_config->get('enable_notify')) {
148 2
            $this->_new_comment->_send_notification = true;
149
        }
150
151 2
        $dm = new datamanager($this->_schemadb);
152 2
        $this->_post_controller = $dm
153 2
            ->set_defaults($defaults)
154 2
            ->set_storage($this->_new_comment)
155 2
            ->get_controller();
156 2
    }
157
158
    /**
159
     * Loads the comments, does any processing according to the state of the GET list.
160
     * On successful processing we relocate once to ourself.
161
     *
162
     * @param Request $request The request object
163
     * @param mixed $handler_id The ID of the handler.
164
     * @param array $data The local request data.
165
     * @param string $guid The object's GUID
166
     * @param string $view The custom view identifier
167
     */
168 2
    public function _handler_comments(Request $request, string $handler_id, array &$data, string $guid, $view = null)
169
    {
170 2
        $this->_objectguid = $guid;
171 2
        midcom::get()->cache->content->register($this->_objectguid);
172
173 2
        if ($handler_id == 'view-comments-nonempty') {
174 1
            $this->_comments = net_nehmer_comments_comment::list_by_objectguid_filter_anonymous(
175 1
                $this->_objectguid,
176 1
                $this->_config->get('items_to_show'),
177 1
                $this->_config->get('item_ordering'),
178 1
                $this->_config->get('paging')
179
            );
180
        } else {
181 1
            $this->_comments = net_nehmer_comments_comment::list_by_objectguid(
182 1
                $this->_objectguid,
183 1
                $this->_config->get('items_to_show'),
184 1
                $this->_config->get('item_ordering'),
185 1
                $this->_config->get('paging')
186
            );
187
        }
188
189 2
        if ($this->_config->get('paging') !== false) {
190
            $data['qb_pager'] = $this->_comments;
191
            $this->_comments = $this->_comments->execute();
192
        }
193
194 2
        if (   midcom::get()->auth->user
195 2
            || $this->_config->get('allow_anonymous')) {
196 2
            $this->_init_post_controller($request);
197 2
            if ($response = $this->_process_post($request)) {
198
                return $response;
199
            }
200
        }
201 2
        if ($this->_comments) {
202
            $this->_init_display_datamanager();
203
        }
204
205 2
        if ($handler_id == 'view-comments-custom') {
206
            midcom::get()->skip_page_style = true;
207
            $this->custom_view = $view;
208
        }
209
210 2
        $this->_prepare_request_data();
211 2
        midcom::get()->metadata->set_request_metadata($this->_get_last_modified(), $this->_objectguid);
212
213 2
        if ($request->isXmlHttpRequest()) {
214
            midcom::get()->skip_page_style = true;
215
        }
216 2
    }
217
218
    /**
219
     * Checks if a new post has been submitted.
220
     *
221
     * @param Request $request The request object
222
     */
223 2
    private function _process_post(Request $request)
224
    {
225 2
        if (   !midcom::get()->auth->user
226 2
            && !midcom::get()->auth->request_sudo('net.nehmer.comments')) {
227
            throw new midcom_error('We were anonymous but could not acquire SUDO privileges, aborting');
228
        }
229
230 2
        switch ($this->_post_controller->handle($request)) {
231 2
            case 'save':
232
                // Check against comment spam
233
                if ($this->_config->get('enable_spam_check')) {
234
                    $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

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