DisplayRenderer::_buildOutputArray()   F
last analyzed

Complexity

Conditions 27
Paths > 20000

Size

Total Lines 52
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 27
CRAP Score 28.5649

Importance

Changes 0
Metric Value
cc 27
eloc 36
nc 829440
nop 0
dl 0
loc 52
rs 0
c 0
b 0
f 0
ccs 27
cts 31
cp 0.871
crap 28.5649

How to fix   Long Method    Complexity   

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
 * Part of the files dealing with preparing the content for display posts
5
 * via callbacks (Display, PM, Search).
6
 *
7
 * @package   ElkArte Forum
8
 * @copyright ElkArte Forum contributors
9
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file)
10
 *
11
 * This file contains code covered by:
12
 * copyright: 2011 Simple Machines (http://www.simplemachines.org)
13
 *
14
 * @version 2.0 dev
15
 *
16
 */
17
18
namespace ElkArte\MessagesCallback;
19
20
use ElkArte\MembersList;
21
22
/**
23
 * DisplayRenderer
24
 * The class prepares the details of a message so that they can be used
25
 * to display it in the template.
26
 */
27
class DisplayRenderer extends Renderer
28
{
29
	public const BEFORE_PREPARE_HOOK = 'integrate_before_prepare_display_context';
30
31
	public const CONTEXT_HOOK = 'integrate_prepare_display_context';
32
33
	/**
34
	 * {@inheritDoc}
35 2
	 */
36
	protected function _setupPermissions()
37 2
	{
38
		global $context, $modSettings;
39
40 2
		// Are you allowed to remove at least a single reply?
41
		$context['can_remove_post'] |= allowedTo('delete_own')
42
			&& (empty($modSettings['edit_disable_time']) || $this->_this_message['poster_time'] + $modSettings['edit_disable_time'] * 60 >= time())
43 2
			&& (int) $this->_this_message['id_member'] === (int) $this->user->id;
44
45 2
		// Have you liked this post, can you?
46 2
		$this->_this_message['you_liked'] = !empty($context['likes'][$this->_this_message['id_msg']]['member'])
47 2
			&& isset($context['likes'][$this->_this_message['id_msg']]['member'][$this->user->id]);
48 2
		$this->_this_message['use_likes'] = allowedTo('like_posts') && empty($context['is_locked'])
49 2
			&& ($this->_this_message['id_member'] != $this->user->id || !empty($modSettings['likeAllowSelf']))
50
			&& (empty($modSettings['likeMinPosts']) || $modSettings['likeMinPosts'] <= $this->user->posts);
51
		$this->_this_message['like_count'] = empty($context['likes'][$this->_this_message['id_msg']]['count']) ? 0 : $context['likes'][$this->_this_message['id_msg']]['count'];
52
	}
53
54 2
	/**
55
	 * {@inheritDoc}
56 2
	 */
57
	protected function _adjustAllMembers($member_context)
58 2
	{
59 2
		global $context;
60 2
61
		$id_member = $this->_this_message[$this->_idx_mapper->id_member];
0 ignored issues
show
Bug Best Practice introduced by
The property id_member does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
62 2
		$this_member = MembersList::get($id_member);
63 2
		$this_member->loadContext();
64
65 2
		$this_member['ip'] = $this->_this_message['poster_ip'] ?? '';
66 2
		$this_member['show_profile_buttons'] = (!empty($this_member['can_view_profile'])
67
			|| (!empty($this_member['website']['url']) && !isset($context['disabled_fields']['website']))
68
			|| $this_member['show_email']
69
			|| $context['can_send_pm']);
70
71 2
		$context['id_msg'] = $this->_this_message['id_msg'] ?? '';
72
	}
73 2
74
	/**
75 2
	 * {@inheritDoc}
76
	 */
77 2
	protected function _buildOutputArray()
78 2
	{
79
		global $topic, $context, $modSettings, $txt;
80 2
81 2
		require_once(SUBSDIR . '/Attachments.subs.php');
82 2
83 2
		$output = parent::_buildOutputArray();
84 2
		$href = getUrl('topic', ['topic' => $topic, 'start' => 'msg' . $this->_this_message['id_msg'], 'subject' => $this->_this_message['subject']]) . '#msg' . $this->_this_message['id_msg'];
85
		$output += [
86 2
			'href' => $href,
87 2
			'link' => '<a href="' . $href . '" rel="nofollow">' . $this->_this_message['subject'] . '</a>',
88 2
			'icon' => $this->_options->icon_sources->getIconValue($this->_this_message['icon']),
0 ignored issues
show
Bug introduced by
The method getIconValue() does not exist on null. ( Ignorable by Annotation )

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

88
			'icon' => $this->_options->icon_sources->/** @scrutinizer ignore-call */ getIconValue($this->_this_message['icon']),

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...
Bug Best Practice introduced by
The property icon_sources does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
89 2
			'icon_url' => $this->_options->icon_sources->getIconURL($this->_this_message['icon']),
90
			'modified' => [
91 2
				'time' => standardTime($this->_this_message['modified_time']),
92 2
				'html_time' => htmlTime($this->_this_message['modified_time']),
93 2
				'timestamp' => forum_time(true, $this->_this_message['modified_time']),
94 2
				'name' => $this->_this_message['modified_name']
95 2
			],
96 2
			'new' => empty($this->_this_message['is_read']),
97 2
			'approved' => $this->_this_message['approved'],
98 2
			'first_new' => isset($context['start_from']) && $context['start_from'] == $this->_counter,
99 2
			'is_ignored' => !empty($modSettings['enable_buddylist']) && in_array($this->_this_message['id_member'], $context['user']['ignoreusers']),
100 2
			'is_message_author' => (int) $this->_this_message['id_member'] === (int) $this->user->id,
101 2
			'can_approve' => !$this->_this_message['approved'] && $context['can_approve'],
102 2
			'can_unapprove' => !empty($modSettings['postmod_active']) && $context['can_approve'] && $this->_this_message['approved'],
103 2
			'can_modify' => (!$context['is_locked'] || allowedTo('moderate_board')) && (allowedTo('modify_any') || (allowedTo('modify_replies') && $context['user']['started']) || (allowedTo('modify_own') && $this->_this_message['id_member'] == $this->user->id && (empty($modSettings['edit_disable_time']) || !$this->_this_message['approved'] || $this->_this_message['poster_time'] + $modSettings['edit_disable_time'] * 60 > time()))),
104
			'can_remove' => allowedTo('delete_any') || (allowedTo('delete_replies') && $context['user']['started']) || (allowedTo('delete_own') && $this->_this_message['id_member'] == $this->user->id && (empty($modSettings['edit_disable_time']) || $this->_this_message['poster_time'] + $modSettings['edit_disable_time'] * 60 > time())),
105
			'can_like' => $this->_this_message['use_likes'] && !$this->_this_message['you_liked'],
106
			'can_unlike' => $this->_this_message['use_likes'] && $this->_this_message['you_liked'],
107 2
			'like_counter' => $this->_this_message['like_count'],
108
			'likes_enabled' => !empty($modSettings['likes_enabled']) && ($this->_this_message['use_likes'] || ($this->_this_message['like_count'] != 0)),
109
			'classes' => [],
110
		];
111
112 2
		if (!empty($output['modified']['name']))
113
		{
114
			$output['modified']['last_edit_text'] = sprintf($txt['last_edit_by'], $output['modified']['time'], $output['modified']['name'], standardTime($output['modified']['timestamp']));
115
		}
116
117
		if (!empty($output['member']['karma']['allow']))
118
		{
119
			$output['member']['karma'] += [
120 2
				'applaud_url' => getUrl('action', ['action' => 'karma', 'sa' => 'applaud', 'uid' => $output['member']['id'], 'topic' => $context['current_topic'] . '.' . $context['start'], 'm' => $output['id'], '{session_data}']),
121
				'smite_url' => getUrl('action', ['action' => 'karma', 'sa' => 'smite', 'uid' => $output['member']['id'], 'topic' => $context['current_topic'] . '.' . $context['start'], 'm' => $output['id'], '{session_data}'])
122
			];
123
		}
124
125
		// Build the per post buttons!
126
		$output += $this->_buildPostButtons($output);
127
128
		return $output;
129
	}
130
131
	/**
132
	 * Generates the available button array suitable for consumption by template_button_strip
133
	 *
134
	 * @param array $output The output array containing post details.
135
	 *
136
	 * @return array The array containing all the post buttons.
137
	 */
138
	protected function _buildPostButtons($output)
139
	{
140
		global $context, $txt, $topic, $options, $board;
141
142
		$postButtons = [
143
			// Can they reply? Have they turned on quick reply?
144
			'quote' => [
145
				'text' => 'quote',
146
				'url' => empty($options['display_quick_reply']) ? getUrl('action', ['action' => 'post', 'topic' => $topic . '.' . $context['start'], 'quote' => $output['id'], 'last_msg' => $context['topic_last_message']]) : null,
147
				'custom' => empty($options['display_quick_reply']) ? '' : 'onclick="return oQuickReply.quote(' . $output['id'] . ');"',
148
				'class' => 'quote_button last',
149
				'icon' => 'quote',
150
				'enabled' => !empty($context['can_quote']),
151
			],
152
			// Can the user quick modify the contents of this post?  Show the quick (inline) modify button.
153
			'quick_edit' => [
154
				'text' => 'quick_edit',
155
				'url' => 'javascript:void(0);',
156
				'custom' => 'onclick="oQuickModify.modifyMsg(\'' . $output['id'] . '\')"',
157
				'icon' => 'modify',
158
				'enabled' => $output['can_modify'],
159
			],
160
			// Can they like/unlike or just view counts
161
			'react' => [
162
				'text' => 'like_post',
163
				'url' => 'javascript:void(0);',
164
				'custom' => 'onclick="likePosts.prototype.likeUnlikePosts(event,' . $output['id'] . ',' . $context['current_topic'] . '); return false;"',
165
				'linkclass' => 'react_button',
166
				'icon' => 'thumbsup',
167
				'enabled' => $output['likes_enabled'] && $output['can_like'],
168
				'counter' => $output['like_counter'] ?? 0,
169
			],
170
			'unreact' => [
171
				'text' => 'unlike_post',
172
				'url' => 'javascript:void(0);',
173
				'custom' => 'onclick="likePosts.prototype.likeUnlikePosts(event,' . $output['id'] . ',' . $context['current_topic'] . '); return false;"',
174
				'linkclass' => 'unreact_button',
175
				'icon' => 'thumbsdown',
176
				'enabled' => $output['likes_enabled'] && $output['can_unlike'],
177
				'counter' => $output['like_counter'] ?? 0,
178
			],
179
			'liked' => [
180
				'text' => 'likes',
181
				'url' => 'javascript:void(0);',
182
				'custom' => 'onclick="this.blur();"',
183
				'icon' => 'thumbsup',
184
				'enabled' => $output['likes_enabled'] && !$output['can_unlike'] && !$output['can_like'],
185
				'counter' => $output['like_counter'] ?? 0,
186
			],
187
			// *** Submenu, aka "more", button items
188
			//
189
			// Can the user modify the contents of this post?
190
			'modify' => [
191
				'text' => 'modify',
192
				'url' => getUrl('action', ['action' => 'post', 'msg' => $output['id'], 'topic' => $context['current_topic'] . '.' . $context['start']]),
193
				'icon' => 'modify',
194
				'enabled' => $output['can_modify'],
195
				'submenu' => true,
196
			],
197
			// How about... even... remove it entirely?!
198
			'remove_topic' => [
199
				'text' => 'remove_topic',
200
				'url' => getUrl('action', ['action' => 'removetopic2', 'topic' => $topic . '.' . $context['start'], '{session_data}']),
201
				'custom' => 'onclick="return confirm(\'' . $txt['are_sure_remove_topic'] . '\');"',
202
				'icon' => 'warn',
203
				'enabled' => $context['can_delete'] && $context['topic_first_message'] === $output['id'],
204
				'submenu' => true,
205
			],
206
			// How about... remove the message
207
			'remove' => [
208
				'text' => 'remove',
209
				'url' => getUrl('action', ['action' => 'deletemsg', 'topic' => $topic . '.' . $context['start'], 'msg' => $output['id'], '{session_data}']),
210
				'custom' => 'onclick="return confirm(\'' . $txt['remove_message'] . '?\');"',
211
				'icon' => 'delete',
212
				'enabled' => $output['can_remove'] && ($context['topic_first_message'] !== $output['id']),
213
				'submenu' => true,
214
			],
215
			// Can they quote to a new topic? @todo - This needs rethinking for GUI layout.
216
			'followup' => [
217
				'text' => 'quote_new',
218
				'url' => getUrl('action', ['action' => 'post', 'board' => $board, 'quote' => $output['id'], 'followup' => $output['id']]),
219
				'icon' => 'quote',
220
				'enabled' => !empty($context['can_follow_up']),
221
				'submenu' => true,
222
			],
223
			// What about splitting it off the rest of the topic?
224
			'split' => [
225
				'text' => 'split_topic',
226
				'url' => getUrl('action', ['action' => 'splittopics', 'topic' => $topic . '.0', 'at' => $output['id']]),
227
				'icon' => 'split',
228
				'enabled' => $context['can_split'] && !empty($context['real_num_replies']) && $context['topic_first_message'] !== $output['id'],
229
				'submenu' => true,
230
			],
231
			// Can we restore topics?
232
			'restore' => [
233
				'text' => 'restore_message',
234
				'url' => getUrl('action', ['action' => 'restoretopic', 'msgs' => $output['id'], '{session_data}']),
235
				'icon' => 'recycle',
236
				'enabled' => $context['can_restore_msg'],
237
				'submenu' => true,
238
			],
239
			// Maybe we can approve it, maybe we should?
240
			'approve' => [
241
				'text' => 'approve',
242
				'url' => getUrl('action', ['action' => 'moderate', 'area' => 'postmod', 'sa' => 'approve', 'topic' =>  $topic . '.' . $context['start'], 'msg' => $output['id'], '{session_data}']),
243
				'icon' => 'check',
244
				'enabled' => $output['can_approve'],
245
				'submenu' => true,
246
			],
247
			// Maybe we can unapprove it?
248
			'unapprove' => [
249
				'text' => 'unapprove',
250
				'url' => getUrl('action', ['action' => 'moderate', 'area' => 'postmod', 'sa' => 'approve', 'topic' =>  $topic . '.' . $context['start'], 'msg' => $output['id'], '{session_data}']),
251
				'icon' => 'remove',
252
				'enabled' => $output['can_unapprove'],
253
				'submenu' => true,
254
			],
255
			// Maybe they want to report this post to the moderator(s)?
256
			'report' => [
257
				'text' => 'report_to_mod',
258
				'url' => getUrl('action', ['action' => 'reporttm', 'topic' =>  $topic . '.' . $output['counter'], 'msg' => $output['id']]),
259
				'icon' => 'comment',
260
				'enabled' => $context['can_report_moderator'],
261
				'submenu' => true,
262
			],
263
			// Can we issue a warning because of this post?
264
			'warn' => [
265
				'text' => 'issue_warning',
266
				'url' => getUrl('action', ['action' => 'profile', 'area' => 'issuewarning', 'u' =>  $output['member']['id'], 'msg' => $output['id']]),
267
				'icon' => 'warn',
268
				'enabled' => $context['can_issue_warning'] && !$output['is_message_author'] && !$output['member']['is_guest'],
269
				'submenu' => true,
270
			],
271
			// Quick Moderation Checkbox
272
			'inline_mod_check' => [
273
				'id' => 'in_topic_mod_check_' . $output['id'],
274
				'class' => 'inline_mod_check hide',
275
				'enabled' => !empty($options['display_quick_mod']) && $output['can_remove'],
276
				'checkbox' => 'check',
277
			]
278
		];
279
280
		// Drop any non-enabled ones
281
		$postButtons = array_filter($postButtons, static fn($button) => !isset($button['enabled']) || (bool) $button['enabled']);
282
283
		return ['postbuttons' => $postButtons];
284
	}
285
}
286