Completed
Branch development (176841)
by Elk
06:59
created

ManageFeatures.subs.php ➔ updateAllSignatures()   F

Complexity

Conditions 71
Paths 3602

Size

Total Lines 244

Duplication

Lines 74
Ratio 30.33 %

Code Coverage

Tests 0
CRAP Score 5112

Importance

Changes 0
Metric Value
cc 71
nc 3602
nop 1
dl 74
loc 244
ccs 0
cts 122
cp 0
crap 5112
rs 0
c 0
b 0
f 0

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
 * This file provides utility functions and db function for the profile functions,
5
 * notably, but not exclusively, deals with custom profile fields
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
/**
19
 * Loads the signature from 50 members per request
20
 * Used in ManageFeatures to apply signature settings to all members
21
 *
22
 * @param int $start_member
23
 * @return array
24
 */
25
function getSignatureFromMembers($start_member)
26
{
27
	$db = database();
28
29
	$members = array();
30
31
	$request = $db->query('', '
32
		SELECT id_member, signature
33
		FROM {db_prefix}members
34
		WHERE id_member BETWEEN ' . $start_member . ' AND ' . $start_member . ' + 49
35
			AND id_group != {int:admin_group}
36
			AND FIND_IN_SET({int:admin_group}, additional_groups) = 0',
37
		array(
38
			'admin_group' => 11,
39
		)
40
	);
41
	while ($result = $db->fetch_assoc($request))
42
	{
43
		$members[$result['id_member']]['id_member'] = $result['id_member'];
44
		$members[$result['id_member']]['signature'] = $result['signature'];
45
	}
46
47
	return $members;
48
}
49
50
/**
51
 * Updates the signature from a given member
52
 *
53
 * @param int $id_member
54
 * @param string $signature
55
 */
56
function updateSignature($id_member, $signature)
57
{
58
	require_once(SUBSDIR . '/Members.subs.php');
59
	updateMemberData($id_member, array('signature' => $signature));
60
}
61
62
/**
63
 * Update all signatures given a new set of constraints
64
 *
65
 * @param int $applied_sigs
66
 * @throws \ElkArte\Exceptions\Exception
67
 */
68
function updateAllSignatures($applied_sigs)
69
{
70
	global $context, $modSettings;
71
72
	require_once(SUBSDIR . '/Members.subs.php');
73
	$sig_start = time();
74
75
	// This is horrid - but I suppose some people will want the option to do it.
76
	$done = false;
77
	$context['max_member'] = maxMemberID();
78
79
	// Load all the signature settings.
80
	list ($sig_limits, $sig_bbc) = explode(':', $modSettings['signature_settings']);
81
	$sig_limits = explode(',', $sig_limits);
82
	$disabledTags = !empty($sig_bbc) ? explode(',', $sig_bbc) : array();
83
84
	// @todo temporary since it does not work, and seriously why would you do this?
85
	$disabledTags[] = 'footnote';
86
87
	while (!$done)
88
	{
89
		// No changed signatures yet
90
		$changes = array();
91
92
		// Get a group of member signatures, 50 at a clip
93
		$update_sigs = getSignatureFromMembers($applied_sigs);
94
95
		if (empty($update_sigs))
96
			$done = true;
97
98
		foreach ($update_sigs as $row)
99
		{
100
			// Apply all the rules we can realistically do.
101
			$sig = strtr($row['signature'], array('<br />' => "\n"));
102
103
			// Max characters...
104
			if (!empty($sig_limits[1]))
105
				$sig = \ElkArte\Util::substr($sig, 0, $sig_limits[1]);
106
107
			// Max lines...
108
			if (!empty($sig_limits[2]))
109
			{
110
				$count = 0;
111
				$str_len = strlen($sig);
112
				for ($i = 0; $i < $str_len; $i++)
113
				{
114
					if ($sig[$i] == "\n")
115
					{
116
						$count++;
117
						if ($count >= $sig_limits[2])
118
							$sig = substr($sig, 0, $i) . strtr(substr($sig, $i), array("\n" => ' '));
119
					}
120
				}
121
			}
122
123
			// Max text size
124
			if (!empty($sig_limits[7]) && preg_match_all('~\[size=([\d\.]+)?(px|pt|em|x-large|larger)?~i', $sig, $matches) !== false && isset($matches[2]))
125
			{
126
				// Same as parse_bbc
127
				$sizes = array(1 => 0.7, 2 => 1.0, 3 => 1.35, 4 => 1.45, 5 => 2.0, 6 => 2.65, 7 => 3.95);
128
129
				foreach ($matches[1] as $ind => $size)
130
				{
131
					$limit_broke = 0;
132
133
					// Just specifying as [size=x]?
134 View Code Duplication
					if (empty($matches[2][$ind]))
135
					{
136
						$matches[2][$ind] = 'em';
137
						$size = isset($sizes[(int) $size]) ? $sizes[(int) $size] : 0;
138
					}
139
140
					// Attempt to allow all sizes of abuse, so to speak.
141
					if ($matches[2][$ind] == 'px' && $size > $sig_limits[7])
142
						$limit_broke = $sig_limits[7] . 'px';
143 View Code Duplication
					elseif ($matches[2][$ind] == 'pt' && $size > ($sig_limits[7] * 0.75))
144
						$limit_broke = ((int) $sig_limits[7] * 0.75) . 'pt';
145 View Code Duplication
					elseif ($matches[2][$ind] == 'em' && $size > ((float) $sig_limits[7] / 16))
146
						$limit_broke = ((float) $sig_limits[7] / 16) . 'em';
147
					elseif ($matches[2][$ind] != 'px' && $matches[2][$ind] != 'pt' && $matches[2][$ind] != 'em' && $sig_limits[7] < 18)
148
						$limit_broke = 'large';
149
150
					if ($limit_broke)
151
						$sig = str_replace($matches[0][$ind], '[size=' . $sig_limits[7] . 'px', $sig);
152
				}
153
			}
154
155
			// Stupid images - this is stupidly, stupidly challenging.
156
			if ((!empty($sig_limits[3]) || !empty($sig_limits[5]) || !empty($sig_limits[6])))
157
			{
158
				$replaces = array();
159
				$img_count = 0;
160
161
				// Get all BBC tags...
162
				preg_match_all('~\[img(\s+width=([\d]+))?(\s+height=([\d]+))?(\s+width=([\d]+))?\s*\](?:<br />)*([^<">]+?)(?:<br />)*\[/img\]~i', $sig, $matches);
163
164
				// ... and all HTML ones.
165
				preg_match_all('~&lt;img\s+src=(?:&quot;)?((?:http://|ftp://|https://|ftps://).+?)(?:&quot;)?(?:\s+alt=(?:&quot;)?(.*?)(?:&quot;)?)?(?:\s?/)?&gt;~i', $sig, $matches2, PREG_PATTERN_ORDER);
166
167
				// And stick the HTML in the BBC.
168 View Code Duplication
				if (!empty($matches2))
169
				{
170
					foreach ($matches2[0] as $ind => $dummy)
171
					{
172
						$matches[0][] = $matches2[0][$ind];
173
						$matches[1][] = '';
174
						$matches[2][] = '';
175
						$matches[3][] = '';
176
						$matches[4][] = '';
177
						$matches[5][] = '';
178
						$matches[6][] = '';
179
						$matches[7][] = $matches2[1][$ind];
180
					}
181
				}
182
183
				// Try to find all the images!
184
				if (!empty($matches))
185
				{
186
					$image_count_holder = array();
187
					foreach ($matches[0] as $key => $image)
188
					{
189
						$width = -1;
190
						$height = -1;
191
						$img_count++;
192
193
						// Too many images?
194
						if (!empty($sig_limits[3]) && $img_count > $sig_limits[3])
195
						{
196
							// If we've already had this before we only want to remove the excess.
197
							if (isset($image_count_holder[$image]))
198
							{
199
								$img_offset = -1;
200
								$rep_img_count = 0;
201
								while ($img_offset !== false)
202
								{
203
									$img_offset = strpos($sig, $image, $img_offset + 1);
204
									$rep_img_count++;
205
									if ($rep_img_count > $image_count_holder[$image])
206
									{
207
										// Only replace the excess.
208
										$sig = substr($sig, 0, $img_offset) . str_replace($image, '', substr($sig, $img_offset));
209
210
										// Stop looping.
211
										$img_offset = false;
212
									}
213
								}
214
							}
215
							else
216
								$replaces[$image] = '';
217
218
							continue;
219
						}
220
221
						// Does it have predefined restraints? Width first.
222 View Code Duplication
						if ($matches[6][$key])
223
							$matches[2][$key] = $matches[6][$key];
224
225 View Code Duplication
						if ($matches[2][$key] && $sig_limits[5] && $matches[2][$key] > $sig_limits[5])
226
						{
227
							$width = $sig_limits[5];
228
							$matches[4][$key] = $matches[4][$key] * ($width / $matches[2][$key]);
229
						}
230
						elseif ($matches[2][$key])
231
							$width = $matches[2][$key];
232
233
						// ... and height.
234 View Code Duplication
						if ($matches[4][$key] && $sig_limits[6] && $matches[4][$key] > $sig_limits[6])
235
						{
236
							$height = $sig_limits[6];
237
							if ($width != -1)
238
								$width = $width * ($height / $matches[4][$key]);
239
						}
240
						elseif ($matches[4][$key])
241
							$height = $matches[4][$key];
242
243
						// If the dimensions are still not fixed - we need to check the actual image.
244 View Code Duplication
						if (($width == -1 && $sig_limits[5]) || ($height == -1 && $sig_limits[6]))
245
						{
246
							// We'll mess up with images, who knows.
247
							require_once(SUBSDIR . '/Attachments.subs.php');
248
249
							$sizes = url_image_size($matches[7][$key]);
250
							if (is_array($sizes))
251
							{
252
								// Too wide?
253
								if ($sizes[0] > $sig_limits[5] && $sig_limits[5])
254
								{
255
									$width = $sig_limits[5];
256
									$sizes[1] = $sizes[1] * ($width / $sizes[0]);
257
								}
258
259
								// Too high?
260
								if ($sizes[1] > $sig_limits[6] && $sig_limits[6])
261
								{
262
									$height = $sig_limits[6];
263
									if ($width == -1)
264
										$width = $sizes[0];
265
									$width = $width * ($height / $sizes[1]);
266
								}
267
								elseif ($width != -1)
268
									$height = $sizes[1];
269
							}
270
						}
271
272
						// Did we come up with some changes? If so remake the string.
273 View Code Duplication
						if ($width != -1 || $height != -1)
274
							$replaces[$image] = '[img' . ($width != -1 ? ' width=' . round($width) : '') . ($height != -1 ? ' height=' . round($height) : '') . ']' . $matches[7][$key] . '[/img]';
275
276
						// Record that we got one.
277
						$image_count_holder[$image] = isset($image_count_holder[$image]) ? $image_count_holder[$image] + 1 : 1;
278
					}
279
280
					if (!empty($replaces))
281
						$sig = str_replace(array_keys($replaces), array_values($replaces), $sig);
282
				}
283
			}
284
285
			// Try to fix disabled tags.
286 View Code Duplication
			if (!empty($disabledTags))
287
			{
288
				$sig = preg_replace('~\[(?:' . implode('|', $disabledTags) . ').+?\]~i', '', $sig);
289
				$sig = preg_replace('~\[/(?:' . implode('|', $disabledTags) . ')\]~i', '', $sig);
290
			}
291
292
			$sig = strtr($sig, array("\n" => '<br />'));
293
			call_integration_hook('integrate_apply_signature_settings', array(&$sig, $sig_limits, $disabledTags));
294
			if ($sig != $row['signature'])
295
				$changes[$row['id_member']] = $sig;
296
		}
297
298
		// Do we need to delete what we have?
299
		if (!empty($changes))
300
		{
301
			foreach ($changes as $id => $sig)
302
				updateSignature($id, $sig);
303
		}
304
305
		$applied_sigs += 50;
306
		if (!$done)
307
		{
308
			pauseSignatureApplySettings($applied_sigs, $sig_start);
309
		}
310
	}
311
}
312
313
/**
314
 * Callback for createList() in displaying profile fields
315
 * Can be used to load standard or custom fields by setting the $standardFields flag
316
 *
317
 * @param int $start The item to start with (for pagination purposes)
318
 * @param int $items_per_page The number of items to show per page
319
 * @param string $sort A string indicating how to sort the results
320
 * @param boolean $standardFields
321
 *
322
 * @return array
323
 */
324
function list_getProfileFields($start, $items_per_page, $sort, $standardFields)
325
{
326
	global $txt, $modSettings;
327
328
	$db = database();
329
330
	$list = array();
331
332
	if ($standardFields)
333
	{
334
		$standard_fields = array('website', 'posts', 'warning_status', 'date_registered');
335
		$fields_no_registration = array('posts', 'warning_status', 'date_registered');
336
		$disabled_fields = isset($modSettings['disabled_profile_fields']) ? explode(',', $modSettings['disabled_profile_fields']) : array();
337
		$registration_fields = isset($modSettings['registration_fields']) ? explode(',', $modSettings['registration_fields']) : array();
338
339
		foreach ($standard_fields as $field)
340
			$list[] = array(
341
				'id' => $field,
342
				'label' => isset($txt['standard_profile_field_' . $field]) ? $txt['standard_profile_field_' . $field] : (isset($txt[$field]) ? $txt[$field] : $field),
343
				'disabled' => in_array($field, $disabled_fields),
344
				'on_register' => in_array($field, $registration_fields) && !in_array($field, $fields_no_registration),
345
				'can_show_register' => !in_array($field, $fields_no_registration),
346
			);
347
	}
348
	else
349
	{
350
		// Load all the fields.
351
		$request = $db->query('', '
352
			SELECT 
353
				id_field, col_name, field_name, field_desc, field_type, active, placement, vieworder
354
			FROM {db_prefix}custom_fields
355
			ORDER BY {raw:sort}, vieworder ASC
356
			LIMIT {int:start}, {int:items_per_page}',
357
			array(
358
				'sort' => $sort,
359
				'start' => $start,
360
				'items_per_page' => $items_per_page,
361
			)
362
		);
363
		while ($row = $db->fetch_assoc($request))
364
		{
365
			$list[$row['id_field']] = $row;
366
		}
367
		$db->free_result($request);
368
	}
369
370
	return $list;
371
}
372
373
/**
374
 * Callback for createList().
375
 */
376
function list_getProfileFieldSize()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
377
{
378
	$db = database();
379
380
	$request = $db->query('', '
381
		SELECT COUNT(*)
382
		FROM {db_prefix}custom_fields',
383
		array(
384
		)
385
	);
386
387
	list ($numProfileFields) = $db->fetch_row($request);
388
	$db->free_result($request);
389
390
	return $numProfileFields;
391
}
392
393
/**
394
 * Loads the profile field properties from a given field id
395
 *
396
 * @param int $id_field
397
 * @return array $field
398
 */
399
function getProfileField($id_field)
400
{
401
	$db = database();
402
403
	$field = array();
404
405
	// The fully-qualified name for rows is here because it's a reserved word in Mariadb 10.2.4+ and quoting would be different for MySQL/Mariadb and PSQL
406
	$request = $db->query('', '
407
		SELECT
408
			id_field, col_name, field_name, field_desc, field_type, field_length, field_options,
409
			show_reg, show_display, show_memberlist, show_profile, private, active, default_value, can_search,
410
			bbc, mask, enclose, placement, vieworder, {db_prefix}custom_fields.rows, cols
411
		FROM {db_prefix}custom_fields
412
		WHERE id_field = {int:current_field}',
413
		array(
414
			'current_field' => $id_field,
415
		)
416
	);
417
	while ($row = $db->fetch_assoc($request))
418
	{
419
		$field = array(
420
			'name' => $row['field_name'],
421
			'desc' => $row['field_desc'],
422
			'colname' => $row['col_name'],
423
			'profile_area' => $row['show_profile'],
424
			'reg' => $row['show_reg'],
425
			'display' => $row['show_display'],
426
			'memberlist' => $row['show_memberlist'],
427
			'type' => $row['field_type'],
428
			'max_length' => $row['field_length'],
429
			'rows' => $row['rows'],
430
			'cols' => $row['cols'],
431
			'bbc' => $row['bbc'] ? true : false,
432
			'default_check' => $row['field_type'] == 'check' && $row['default_value'] ? true : false,
433
			'default_select' => $row['field_type'] == 'select' || $row['field_type'] == 'radio' ? $row['default_value'] : '',
434
			'show_nodefault' => $row['field_type'] == 'select' || $row['field_type'] == 'radio',
435
			'default_value' => $row['default_value'],
436
			'options' => strlen($row['field_options']) > 1 ? explode(',', $row['field_options']) : array('', '', ''),
437
			'active' => $row['active'],
438
			'private' => $row['private'],
439
			'can_search' => $row['can_search'],
440
			'mask' => $row['mask'],
441
			'regex' => substr($row['mask'], 0, 5) == 'regex' ? substr($row['mask'], 5) : '',
442
			'enclose' => $row['enclose'],
443
			'placement' => $row['placement'],
444
		);
445
	}
446
	$db->free_result($request);
447
448
	return($field);
449
}
450
451
/**
452
 * Make sure a profile field is unique
453
 *
454
 * @param string $colname
455
 * @param string $initial_colname
456
 * @param boolean $unique
457
 * @return boolean
458
 */
459
function ensureUniqueProfileField($colname, $initial_colname, $unique = false)
460
{
461
	$db = database();
462
	// Make sure this is unique.
463
	// @todo This may not be the most efficient way to do this.
464
	for ($i = 0; !$unique && $i < 9; $i++)
465
	{
466
		$request = $db->query('', '
467
			SELECT id_field
468
			FROM {db_prefix}custom_fields
469
			WHERE col_name = {string:current_column}',
470
			array(
471
				'current_column' => $colname,
472
			)
473
		);
474
		if ($db->num_rows($request) == 0)
475
			$unique = true;
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $unique. This often makes code more readable.
Loading history...
476
		else
477
			$colname = $initial_colname . $i;
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $colname. This often makes code more readable.
Loading history...
478
			$db->free_result($request);
479
	}
480
481
	return $unique;
482
}
483
484
/**
485
 * Update the profile fields name
486
 *
487
 * @param string $key
488
 * @param mixed[] $newOptions
489
 * @param string $name
490
 * @param string $option
491
 */
492
function updateRenamedProfileField($key, $newOptions, $name, $option)
493
{
494
	$db = database();
495
496
	$db->query('', '
497
		UPDATE {db_prefix}custom_fields_data
498
		SET value = {string:new_value}
499
		WHERE variable = {string:current_column}
500
			AND value = {string:old_value}
501
			AND id_member > {int:no_member}',
502
		array(
503
			'no_member' => 0,
504
			'new_value' => $newOptions[$key],
505
			'current_column' => $name,
506
			'old_value' => $option,
507
		)
508
	);
509
}
510
511
/**
512
 * Update the custom profile fields active status on/off
513
 *
514
 * @param int[] $enabled
515
 */
516
function updateRenamedProfileStatus($enabled)
517
{
518
	$db = database();
519
520
	// Do the updates
521
	$db->query('', '
522
		UPDATE {db_prefix}custom_fields
523
		SET active = CASE WHEN id_field IN ({array_int:id_cust_enable}) THEN 1 ELSE 0 END',
524
		array(
525
			'id_cust_enable' => $enabled,
526
		)
527
	);
528
}
529
530
/**
531
 * Update the profile field
532
 *
533
 * @param mixed[] $field_data
534
 */
535
function updateProfileField($field_data)
536
{
537
	$db = database();
538
539
	// The fully-qualified name for rows is here because it's a reserved word in Mariadb 10.2.4+ and quoting would be different for MySQL/Mariadb and PSQL
540
	$db->query('', '
541
		UPDATE {db_prefix}custom_fields
542
		SET
543
			field_name = {string:field_name}, field_desc = {string:field_desc},
544
			field_type = {string:field_type}, field_length = {int:field_length},
545
			field_options = {string:field_options}, show_reg = {int:show_reg},
546
			show_display = {int:show_display}, show_memberlist = {int:show_memberlist},
547
			show_profile = {string:show_profile}, private = {int:private},
548
			active = {int:active}, default_value = {string:default_value},
549
			can_search = {int:can_search}, bbc = {int:bbc}, mask = {string:mask},
550
			enclose = {string:enclose}, placement = {int:placement}, {db_prefix}custom_fields.rows = {int:rows},
551
			cols = {int:cols}
552
		WHERE id_field = {int:current_field}',
553
		array(
554
			'field_length' => $field_data['field_length'],
555
			'show_reg' => $field_data['show_reg'],
556
			'show_display' => $field_data['show_display'],
557
			'show_memberlist' => $field_data['show_memberlist'],
558
			'private' => $field_data['private'],
559
			'active' => $field_data['active'],
560
			'can_search' => $field_data['can_search'],
561
			'bbc' => $field_data['bbc'],
562
			'current_field' => $field_data['current_field'],
563
			'field_name' => $field_data['field_name'],
564
			'field_desc' => $field_data['field_desc'],
565
			'field_type' => $field_data['field_type'],
566
			'field_options' => $field_data['field_options'],
567
			'show_profile' => $field_data['show_profile'],
568
			'default_value' => $field_data['default_value'],
569
			'mask' => $field_data['mask'],
570
			'enclose' => $field_data['enclose'],
571
			'placement' => $field_data['placement'],
572
			'rows' => $field_data['rows'],
573
			'cols' => $field_data['cols'],
574
		)
575
	);
576
}
577
578
/**
579
 * Updates the viewing order for profile fields
580
 * Done as a CASE WHEN one two three ELSE 0 END in place of many updates
581
 *
582
 * @param string $replace constructed as WHEN fieldname=value THEN new viewvalue WHEN .....
583
 */
584
function updateProfileFieldOrder($replace)
585
{
586
	$db = database();
587
588
	$db->query('', '
589
		UPDATE {db_prefix}custom_fields
590
		SET vieworder = CASE ' . $replace . ' ELSE 0 END',
591
		array('')
592
	);
593
}
594
595
/**
596
 * Deletes selected values from old profile field selects
597
 *
598
 * @param string[] $newOptions
599
 * @param string $fieldname
600
 */
601
function deleteOldProfileFieldSelects($newOptions, $fieldname)
602
{
603
	$db = database();
604
605
	$db->query('', '
606
		DELETE FROM {db_prefix}custom_fields_data
607
		WHERE variable = {string:current_column}
608
			AND value NOT IN ({array_string:new_option_values})
609
			AND id_member > {int:no_member}',
610
		array(
611
			'no_member' => 0,
612
			'new_option_values' => $newOptions,
613
			'current_column' => $fieldname,
614
		)
615
	);
616
}
617
618
/**
619
 * Used to add a new custom profile field
620
 *
621
 * @param mixed[] $field
622
 */
623
function addProfileField($field)
624
{
625
	$db = database();
626
627
	$db->insert('',
628
		'{db_prefix}custom_fields',
629
		array(
630
			'col_name' => 'string', 'field_name' => 'string', 'field_desc' => 'string',
631
			'field_type' => 'string', 'field_length' => 'string', 'field_options' => 'string',
632
			'show_reg' => 'int', 'show_display' => 'int', 'show_memberlist' => 'int', 'show_profile' => 'string',
633
			'private' => 'int', 'active' => 'int', 'default_value' => 'string', 'can_search' => 'int',
634
			'bbc' => 'int', 'mask' => 'string', 'enclose' => 'string', 'placement' => 'int', 'vieworder' => 'int',
635
			'rows' => 'int', 'cols' => 'int'
636
		),
637
		array(
638
			$field['col_name'], $field['field_name'], $field['field_desc'],
639
			$field['field_type'], $field['field_length'], $field['field_options'],
640
			$field['show_reg'], $field['show_display'], $field['show_memberlist'], $field['show_profile'],
641
			$field['private'], $field['active'], $field['default_value'], $field['can_search'],
642
			$field['bbc'], $field['mask'], $field['enclose'], $field['placement'], $field['vieworder'],
643
			$field['rows'], $field['cols']
644
		),
645
		array('id_field')
646
	);
647
}
648
649
/**
650
 * Delete all user data for a specified custom profile field
651
 *
652
 * @param string $name
653
 */
654
function deleteProfileFieldUserData($name)
655
{
656
	$db = database();
657
658
	// Delete the user data first.
659
	$db->query('', '
660
		DELETE FROM {db_prefix}custom_fields_data
661
		WHERE variable = {string:current_column}
662
			AND id_member > {int:no_member}',
663
		array(
664
			'no_member' => 0,
665
			'current_column' => $name,
666
		)
667
	);
668
}
669
670
/**
671
 * Deletes a custom profile field.
672
 *
673
 * @param int $id
674
 */
675
function deleteProfileField($id)
676
{
677
	$db = database();
678
679
	$db->query('', '
680
		DELETE FROM {db_prefix}custom_fields
681
		WHERE id_field = {int:current_field}',
682
		array(
683
			'current_field' => $id,
684
		)
685
	);
686
}
687
688
/**
689
 * Update the display cache, needed after editing or deleting a custom profile field
690
 */
691
function updateDisplayCache()
692
{
693
	$db = database();
694
695
	$fields = $db->fetchQuery('
0 ignored issues
show
Bug introduced by
The method fetch_callback cannot be called on $db->fetchQuery(' SELE...'not_admin_only' => 3)) (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
696
		SELECT col_name, field_name, field_type, bbc, enclose, placement, vieworder
697
		FROM {db_prefix}custom_fields
698
		WHERE show_display = {int:is_displayed}
699
			AND active = {int:active}
700
			AND private != {int:not_owner_only}
701
			AND private != {int:not_admin_only}
702
		ORDER BY vieworder',
703
		array(
704
			'is_displayed' => 1,
705
			'active' => 1,
706
			'not_owner_only' => 2,
707
			'not_admin_only' => 3,
708
		)
709
	)->fetch_callback(
710
		function ($row)
711
		{
712
			return array(
713
				'colname' => strtr($row['col_name'], array('|' => '', ';' => '')),
714
				'title' => strtr($row['field_name'], array('|' => '', ';' => '')),
715
				'type' => $row['field_type'],
716
				'bbc' => $row['bbc'] ? 1 : 0,
717
				'placement' => !empty($row['placement']) ? $row['placement'] : 0,
718
				'enclose' => !empty($row['enclose']) ? $row['enclose'] : '',
719
			);
720
		}
721
	);
722
723
	updateSettings(array('displayFields' => serialize($fields)));
724
}
725
726
/**
727
 * Loads all the custom fields in the system, active or not
728
 */
729 View Code Duplication
function loadAllCustomFields()
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
730
{
731
	$db = database();
732
733
	// Get the names of any custom fields.
734
	$request = $db->query('', '
735
		SELECT
736
			col_name, field_name, bbc
737
		FROM {db_prefix}custom_fields',
738
		array(
739
		)
740
	);
741
	$custom_field_titles = array();
742
	while ($row = $db->fetch_assoc($request))
743
	{
744
		$custom_field_titles['customfield_' . $row['col_name']] = array(
745
			'title' => $row['field_name'],
746
			'parse_bbc' => $row['bbc'],
747
		);
748
	}
749
	$db->free_result($request);
750
751
	return $custom_field_titles;
752
}
753
754
/**
755
 * Load all the available mention types
756
 *
757
 * What it does:
758
 *
759
 * - Scans teh subs\MentionType directory for files
760
 * - Calls its getType method
761
 *
762
 * @return array
763
 */
764
function getNotificationTypes()
765
{
766 2
	$glob = new \GlobIterator(SOURCEDIR . '/ElkArte/Mentions/MentionType/*Mention.php', \FilesystemIterator::SKIP_DOTS);
767 2
	$types = array();
768
769
	// For each file found, call its getType method
770 2
	foreach ($glob as $file)
771
	{
772
		$class_name = '\\ElkArte\\Mentions\\MentionType\\' . $file->getBasename('.php');
773
		$types[] = $class_name::getType();
774
	}
775
776 2
	return $types;
777
}
778
779
/**
780
 * Returns the modules for the given mentions
781
 *
782
 * What it does:
783
 *
784
 * - Calls each modules static function ::getModules
785
 * - Called from ManageFeatures.controller as part of notification settings
786
 *
787
 * @param string[] $enabled_mentions
788
 *
789
 * @return array
790
 */
791
function getMentionsModules($enabled_mentions)
792
{
793
	$modules = array();
794
795
	foreach ($enabled_mentions as $mention)
796
	{
797
		$class_name = '\\ElkArte\\Mentions\\MentionType\\' . ucfirst($mention);
798
		$modules = $class_name::getModules($modules);
799
	}
800
801
	return $modules;
802
}
803
804
/**
805
 * Loads available frontpage controllers for selection in the look/layout area of the ACP
806
 *
807
 * What it does:
808
 *
809
 * - Scans controllerdir and addonsdir for .controller.php files
810
 * - Checks if found files have a static frontPageOptions method
811
 *
812
 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string|array>[].

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
813
 */
814
function getFrontPageControllers()
815
{
816 2
	global $txt;
817
818 2
	$classes = array();
819
820 2
	$glob = new \GlobIterator(CONTROLLERDIR . '/*.controller.php', \FilesystemIterator::SKIP_DOTS);
821 2
	$classes += scanFileSystemForControllers($glob);
822
823 2
	$glob = new \GlobIterator(ADDONSDIR . '/*/controllers/*.controller.php', \FilesystemIterator::SKIP_DOTS);
824 2
	$classes += scanFileSystemForControllers($glob, '\\ElkArte\\Addon\\');
825
826 2
	$config_vars = array(array('select', 'front_page', $classes));
827 2
	array_unshift($config_vars[0][2], $txt['default']);
828
829 2
	foreach (array_keys($classes) as $class_name)
830
	{
831
		$options = $class_name::frontPageOptions();
832
		if (!empty($options))
833
			$config_vars = array_merge($config_vars, $options);
834
	}
835
836 2
	return $config_vars;
837
}
838
839
/**
840
 *
841
 * @param \GlobIterator $iterator
842
 * @param string $namespace
843
 *
844
 * @return array
845
 */
846
function scanFileSystemForControllers($iterator, $namespace = '')
847
{
848 2
	global $txt;
849
850 2
	$types = array();
851
852 2
	foreach ($iterator as $file)
853
	{
854
		$class_name = $namespace . $file->getBasename('.php');
855
856
		if (!class_exists($class_name))
857
		{
858
			continue;
859
		}
860
861
		if (is_subclass_of($class_name, '\\ElkArte\\AbstractController') && $class_name::canFrontPage())
862
		{
863
			// Temporary
864
			if (!isset($txt[$class_name]))
865
			{
866
				continue;
867
			}
868
869
			$types[$class_name] = $txt[$class_name];
870
		}
871
	}
872
873 2
	return $types;
874
}
875
876
/**
877
 * Just pause the signature applying thing.
878
 *
879
 * @todo Move to subs file
880
 * @todo Merge with other pause functions?
881
 *    pausePermsSave(), pauseAttachmentMaintenance(), pauseRepairProcess()
882
 *
883
 * @param int $applied_sigs
884
 * @param int $sig_start
885
 * @throws \ElkArte\Exceptions\Exception
886
 */
887
function pauseSignatureApplySettings($applied_sigs, $sig_start)
888
{
889
	global $context, $txt;
890
891
	// Try get more time...
892
	detectServer()->setTimeLimit(600);
893
894
	// Have we exhausted all the time we allowed?
895
	if (time() - array_sum(explode(' ', $sig_start)) < 3)
896
		return;
897
898
	$context['continue_get_data'] = '?action=admin;area=featuresettings;sa=sig;apply;step=' . $applied_sigs . ';' . $context['session_var'] . '=' . $context['session_id'];
899
	$context['page_title'] = $txt['not_done_title'];
900
	$context['continue_post_data'] = '';
901
	$context['continue_countdown'] = '2';
902
	$context['sub_template'] = 'not_done';
903
904
	// Specific stuff to not break this template!
905
	$context[$context['admin_menu_name']]['current_subsection'] = 'sig';
906
907
	// Get the right percent.
908
	$context['continue_percent'] = round(($applied_sigs / $context['max_member']) * 100);
909
910
	// Never more than 100%!
911
	$context['continue_percent'] = min($context['continue_percent'], 100);
912
913
	obExit();
914
}
915