Member   C
last analyzed

Complexity

Total Complexity 53

Size/Duplication

Total Lines 282
Duplicated Lines 0 %

Test Coverage

Coverage 75.97%

Importance

Changes 0
Metric Value
wmc 53
eloc 136
dl 0
loc 282
rs 6.96
c 0
b 0
f 0
ccs 98
cts 129
cp 0.7597

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A toArray() 0 5 1
A loadContext() 0 26 4
A loadBasics() 0 22 2
A prepareBasics() 0 16 4
C loadOptions() 0 53 13
A get() 0 3 1
A append() 0 7 1
D loadExtended() 0 74 26

How to fix   Complexity   

Complex Class

Complex classes like Member often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Member, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * @package   ElkArte Forum
5
 * @copyright ElkArte Forum contributors
6
 * @license   BSD http://opensource.org/licenses/BSD-3-Clause (see accompanying LICENSE.txt file)
7
 *
8
 * This file contains code covered by:
9
 * copyright: 2011 Simple Machines (http://www.simplemachines.org)
10
 *
11
 * @version 2.0 dev
12
 *
13
 */
14
15
namespace ElkArte;
16
17
use BBC\ParserWrapper;
18
use ElkArte\Helper\Util;
19
use ElkArte\Helper\ValuesContainer;
20
21
/**
22
 * This class holds all the data belonging to a certain member.
23
 */
24
class Member extends ValuesContainer
25
{
26
	/** @var bool If context has been loaded or not */
27
	protected $loaded = false;
28
29
	/** @var array Basically the content of $modSettings['displayFields'] */
30
	protected $display_fields = [];
31
32
	/**
33
	 * Constructor
34
	 *
35
	 * @param array $data
36
	 * @param string $set The set of data loaded
37
	 * @param ParserWrapper $bbc_parser
38
	 *
39
	 */
40
	public function __construct($data, protected $set, protected $bbc_parser)
41
	{
42
		parent::__construct($data);
43
	}
44
45
	/**
46
	 * Adds data to a member
47
	 *
48
	 * @param string $type
49
	 * @param array $data
50
	 * @param array $display_fields Basically the content of $modSettings['displayFields']
51
	 */
52
	public function append($type, $data, $display_fields)
53
	{
54
		$this->data[$type] = $this->data[$type] ?? [];
55 14
		$this->data[$type] = array_merge($this->data[$type], $data);
56
57 14
		$this->display_fields[$type] = $this->display_fields[$type] ?? [];
58 14
		$this->display_fields[$type] = array_merge($this->display_fields[$type], $display_fields);
59 14
	}
60 14
61
	/**
62
	 * Returns a certain data
63
	 *
64
	 * @param string $item
65
	 * @return array Anything set for that index
66
	 */
67
	public function get($item)
68
	{
69
		return $this->data[$item] ?? null;
70
	}
71
72
	/**
73
	 * Prepares some data that can be useful in the templates (and not only)
74
	 *
75
	 * @param bool $display_custom_fields
76
	 * @return bool
77
	 */
78
	public function loadContext($display_custom_fields = true)
79
	{
80
		if ($this->loaded)
81
		{
82
			return true;
83
		}
84
85
		// We can't load guests or members not loaded by loadMemberData()!
86
		if (empty($this->data['id_member']))
87
		{
88
			return false;
89
		}
90
91
		$this->prepareBasics();
92
		$this->loadBasics();
93
		$this->loadExtended();
94
		if ($display_custom_fields)
95
		{
96
			$this->loadOptions();
97
		}
98
99 6
		call_integration_hook('integrate_member_context', array($this, $display_custom_fields));
100
101 6
		$this->loaded = true;
102
103 2
		return true;
104
	}
105
106
	/**
107 4
	 * Prepares signature, icons, and few basic stuff
108
	 */
109
	protected function prepareBasics()
110
	{
111
		$this->data['signature'] = censor($this->data['signature']);
112 4
113 4
		// TODO: We should look into a censoring toggle for custom fields
114 4
115 4
		// Set things up to be used before hand.
116
		$this->data['signature'] = str_replace(array("\n", "\r"), array('<br />', ''), $this->data['signature']);
117 4
		$this->data['signature_raw'] = $this->data['signature'];
118
		$this->data['signature'] = $this->bbc_parser->parseSignature($this->data['signature'], true);
119
120 4
		$this->data['is_online'] = (!empty($this->data['show_online']) || allowedTo('moderate_forum')) && $this->data['is_online'] > 0;
121
		$this->data['icons'] = empty($this->data['icons']) ? array('', '') : explode('#', $this->data['icons']);
122 4
123
		// Setup the buddy status here (One whole in_array call saved :P)
124 4
		$this->data['buddy'] = in_array($this->data['id_member'], User::$info->buddies);
0 ignored issues
show
Bug introduced by
It seems like ElkArte\User::info->buddies can also be of type null; however, parameter $haystack of in_array() does only seem to accept array, 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

124
		$this->data['buddy'] = in_array($this->data['id_member'], /** @scrutinizer ignore-type */ User::$info->buddies);
Loading history...
Bug Best Practice introduced by
The property buddies does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
125
	}
126
127
	/**
128
	 * These minimal values are always loaded
129
	 */
130 4
	protected function loadBasics()
131
	{
132 4
		global $txt;
133
134
		$this->data['username'] = $this->data['member_name'];
135
		$this->data['name'] = $this->data['real_name'];
136
		$this->data['id'] = $this->data['id_member'];
137 4
		$this->data['href'] = getUrl('profile', ['action' => 'profile', 'u' => $this->data['id_member'], 'name' => $this->data['real_name']]);
138 4
		$this->data['link'] = '<a href="' . $this->data['href'] . '" title="' . $txt['profile_of'] . ' ' . trim($this->data['real_name']) . '">' . $this->data['real_name'] . '</a>';
139
		$this->data['email'] = $this->data['email_address'];
140 4
		$this->data['show_email'] = showEmailAddress($this->data['id_member']);
141 4
		if (empty($this->data['date_registered']))
142
		{
143
			$this->data['registered_raw'] = 0;
144 4
			$this->data['registered'] = $txt['not_applicable'];
145 4
			$this->data['registered_timestamp'] = 0;
146
		}
147
		else
148
		{
149
			$this->data['registered_raw'] = $this->data['date_registered'];
150 4
			$this->data['registered'] = standardTime($this->data['date_registered']);
151
			$this->data['registered_timestamp'] = forum_time(true, $this->data['date_registered']);
152 4
		}
153
	}
154 4
155 4
	/**
156 4
	 * Loads the huge array of content for the templates (context)
157
	 */
158 4
	protected function loadExtended()
159 4
	{
160 4
		global $modSettings, $txt, $settings, $context;
161 4
		if ($this->set !== MemberLoader::SET_MINIMAL)
162 4
		{
163
			$buddy_list = empty($this->data['buddy_list']) ? array() : explode(',', $this->data['buddy_list']);
164
			$style_color = empty($this->data['member_group_color']) ? '' : 'style="color:' . $this->data['member_group_color'] . ';"';
165
			$send_pm_url = getUrl('action', ['action' => 'pm', 'sa' => 'send', 'u' => $this->data['id_member']]);
166
			$online_status = $this->data['is_online'] ? 'online' : 'offline';
167
168
			$this->data = array_merge($this->data, array(
169
				'username_color' => '<span ' . $style_color . '>' . $this->data['member_name'] . '</span>',
170 4
				'name_color' => '<span ' . $style_color . '>' . $this->data['real_name'] . '</span>',
171 4
				'link_color' => '<a href="' . $this->data['href'] . '" title="' . $txt['profile_of'] . ' ' . $this->data['real_name'] . '" ' . $style_color . '>' . $this->data['real_name'] . '</a>',
172 4
				'is_buddy' => $this->data['buddy'],
173
				'is_reverse_buddy' => in_array(User::$info->id, $buddy_list),
0 ignored issues
show
Bug Best Practice introduced by
The property id does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
174 4
				'buddies' => $buddy_list,
175
				'title' => empty($modSettings['titlesEnable']) ? '' : $this->data['usertitle'],
176
				'website' => array(
177
					'title' => $this->data['website_title'],
178
					'url' => $this->data['website_url'],
179 4
				),
180
				'birth_date' => empty($this->data['birthdate']) || $this->data['birthdate'] === '0001-01-01' ? '0000-00-00' : (substr($this->data['birthdate'], 0, 4) === '0004' ? '0000' . substr($this->data['birthdate'], 4) : $this->data['birthdate']),
181 4
				'real_posts' => $this->data['posts'],
182 4
				'posts' => $this->data['posts'],
183
				'avatar' => determineAvatar($this->data),
184 4
				'last_login' => empty($this->data['last_login']) ? $txt['never'] : standardTime($this->data['last_login']),
185 4
				'last_login_timestamp' => empty($this->data['last_login']) ? 0 : forum_time(false, $this->data['last_login']),
186 4
				'karma' => array(
187 4
					'good' => $this->data['karma_good'],
188
					'bad' => $this->data['karma_bad'],
189 4
					'allow' => User::$info->is_guest === false && !empty($modSettings['karmaMode']) && User::$info->id != $this->data['id_member'] && allowedTo('karma_edit') &&
0 ignored issues
show
Bug Best Practice introduced by
The property is_guest does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
190 4
						(User::$info->posts >= $modSettings['karmaMinPosts'] || User::$info->is_admin),
0 ignored issues
show
Bug Best Practice introduced by
The property posts does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
Bug Best Practice introduced by
The property is_admin does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
191 4
				),
192 4
				'likes' => array(
193 4
					'given' => $this->data['likes_given'],
194 4
					'received' => $this->data['likes_received']
195 4
				),
196 4
				'ip' => htmlspecialchars($this->data['member_ip'], ENT_COMPAT, 'UTF-8'),
197
				'ip2' => htmlspecialchars($this->data['member_ip2'], ENT_COMPAT, 'UTF-8'),
198 4
				'online' => array(
199 4
					'is_online' => $this->data['is_online'],
200
					'text' => Util::htmlspecialchars($txt[$online_status]),
201 4
					'member_online_text' => sprintf($txt['member_is_' . $online_status], Util::htmlspecialchars($this->data['real_name'])),
202 4
					'href' => $send_pm_url,
203 4
					'link' => '<a href="' . $send_pm_url . '">' . $txt[$online_status] . '</a>',
204 4
					'label' => $txt[$online_status]
205 4
				),
206 4
				'language' => Util::ucwords(strtr(basename($this->data['lngfile'], '.php'), array('_' => ' '))),
207
				'is_activated' => $this->data['is_activated'] ?? 1,
208 4
				'is_banned' => isset($this->data['is_activated']) ? $this->data['is_activated'] >= 10 : 0,
209 4
				'options' => $this->data['options'],
210 4
				'is_guest' => false,
211 4
				'group' => $this->data['member_group'],
212
				'group_color' => $this->data['member_group_color'],
213
				'group_id' => $this->data['id_group'],
214 4
				'post_group' => $this->data['post_group'],
215 4
				'post_group_color' => $this->data['post_group_color'],
216
				'group_icons' => str_repeat('<img src="' . str_replace('$language', $context['user']['language'], isset($this->data['icons'][1]) ? $settings['images_url'] . '/group_icons/' . $this->data['icons'][1] : '') . '" alt="[*]" />', empty($this->data['icons'][0]) || empty($this->data['icons'][1]) ? 0 : $this->data['icons'][0]),
217 4
				'warning' => $this->data['warning'],
218 4
				'warning_status' =>
219
					!empty($modSettings['warning_mute'])
220 4
					&&
221 4
					$modSettings['warning_mute'] <= $this->data['warning']
222 4
						? 'mute'
223 4
						: (!empty($modSettings['warning_moderate']) && $modSettings['warning_moderate'] <= $this->data['warning']
224 4
							? 'moderate'
225 4
							: (!empty($modSettings['warning_watch']) && $modSettings['warning_watch'] <= $this->data['warning']
226
								? 'watch'
227 4
								: ''
228 4
						)
229 4
					),
230 4
				'local_time' => standardTime(time() + ($this->data['time_offset'] - User::$info->time_offset) * 3600, false),
0 ignored issues
show
Bug Best Practice introduced by
The property time_offset does not exist on ElkArte\Helper\ValuesContainer. Since you implemented __get, consider adding a @property annotation.
Loading history...
231
				'custom_fields' => array(),
232 4
			));
233 4
		}
234 4
	}
235 4
236 4
	/**
237 4
	 * Loads any additional data (custom fields)
238 4
	 */
239
	protected function loadOptions()
240 4
	{
241
		global $txt, $settings, $scripturl;
242 4
243
		// Are we also loading the members custom fields into context?
244 4
		if (empty($this->display_fields['options']))
245
		{
246 4
			return;
247
		}
248 4
249
		foreach ($this->display_fields['options'] as $custom)
250
		{
251 4
			if (!isset($custom['title']) || trim($custom['title']) === '' || empty($this->data['options'][$custom['colname']]))
252
			{
253
				continue;
254
			}
255 4
256
			$value = $this->data['options'][$custom['colname']];
257
258
			// BBC?
259
			if ($custom['bbc'])
260 4
			{
261
				$value = $this->bbc_parser->parseCustomFields($value);
262 4
			}
263
			// ... or checkbox?
264
			elseif (isset($custom['type']) && $custom['type'] === 'check')
265 4
			{
266
				$value = $value ? $txt['yes'] : $txt['no'];
267 4
			}
268
269
			// Enclosing the user input within some other text?
270
			if (!empty($custom['enclose']))
271
			{
272
				$replacements = array(
273
					'{SCRIPTURL}' => $scripturl,
274
					'{IMAGES_URL}' => $settings['images_url'],
275
					'{DEFAULT_IMAGES_URL}' => $settings['default_images_url'],
276
					'{INPUT}' => $value,
277
				);
278
279
				if (in_array($custom['type'], array('radio', 'select')))
280
				{
281
					$replacements['{KEY}'] = $this->data['options'][$custom['colname'] . '_key'];
282
				}
283
284
				$value = strtr($custom['enclose'], $replacements);
285
			}
286
287
			$this->data['custom_fields'][] = array(
288
				'title' => $custom['title'],
289
				'colname' => $custom['colname'],
290
				'value' => $value,
291
				'placement' => empty($custom['placement']) ? 0 : $custom['placement'],
292
			);
293
		}
294
	}
295
296
	/**
297
	 * Stores the data of the user into an array
298
	 *
299
	 * @return array
300
	 */
301
	public function toArray()
302
	{
303
		return [
304
			'set' => $this->set,
305
			'data' => $this->data,
306
		];
307
	}
308
}
309