ViewSubscribedUsers()   B
last analyzed

Complexity

Conditions 6
Paths 16

Size

Total Lines 186
Code Lines 118

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 118
nop 0
dl 0
loc 186
rs 7.3777
c 0
b 0
f 0
nc 16

How to fix   Long Method   

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 contains all the administration functions for subscriptions.
5
 * (and some more than that :P)
6
 *
7
 * Simple Machines Forum (SMF)
8
 *
9
 * @package SMF
10
 * @author Simple Machines http://www.simplemachines.org
11
 * @copyright 2019 Simple Machines and individual contributors
12
 * @license http://www.simplemachines.org/about/smf/license.php BSD
13
 *
14
 * @version 2.1 RC2
15
 */
16
17
if (!defined('SMF'))
18
	die('No direct access...');
19
20
/**
21
 * The main entrance point for the 'Paid Subscription' screen, calling
22
 * the right function based on the given sub-action.
23
 * It defaults to sub-action 'view'.
24
 * Accessed from ?action=admin;area=paidsubscribe.
25
 * It requires admin_forum permission for admin based actions.
26
 */
27
function ManagePaidSubscriptions()
28
{
29
	global $context, $txt, $modSettings;
30
31
	// Load the required language and template.
32
	loadLanguage('ManagePaid');
33
	loadTemplate('ManagePaid');
34
35
	if (!empty($modSettings['paid_enabled']))
36
		$subActions = array(
37
			'modify' => array('ModifySubscription', 'admin_forum'),
38
			'modifyuser' => array('ModifyUserSubscription', 'admin_forum'),
39
			'settings' => array('ModifySubscriptionSettings', 'admin_forum'),
40
			'view' => array('ViewSubscriptions', 'admin_forum'),
41
			'viewsub' => array('ViewSubscribedUsers', 'admin_forum'),
42
		);
43
	else
44
		$subActions = array(
45
			'settings' => array('ModifySubscriptionSettings', 'admin_forum'),
46
		);
47
48
	// Default the sub-action to 'view subscriptions', but only if they have already set things up..
49
	$_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : (!empty($modSettings['paid_currency_symbol']) && !empty($modSettings['paid_enabled']) ? 'view' : 'settings');
50
51
	// Make sure you can do this.
52
	isAllowedTo($subActions[$_REQUEST['sa']][1]);
53
54
	$context['page_title'] = $txt['paid_subscriptions'];
55
56
	// Tabs for browsing the different subscription functions.
57
	$context[$context['admin_menu_name']]['tab_data'] = array(
58
		'title' => $txt['paid_subscriptions'],
59
		'help' => '',
60
		'description' => $txt['paid_subscriptions_desc'],
61
	);
62
	if (!empty($modSettings['paid_enabled']))
63
		$context[$context['admin_menu_name']]['tab_data']['tabs'] = array(
64
			'view' => array(
65
				'description' => $txt['paid_subs_view_desc'],
66
			),
67
			'settings' => array(
68
				'description' => $txt['paid_subs_settings_desc'],
69
			),
70
		);
71
72
	call_integration_hook('integrate_manage_subscriptions', array(&$subActions));
73
74
	// Call the right function for this sub-action.
75
	call_helper($subActions[$_REQUEST['sa']][0]);
76
}
77
78
/**
79
 * Set any setting related to paid subscriptions, i.e.
80
 * modify which payment methods are to be used.
81
 * It requires the moderate_forum permission
82
 * Accessed from ?action=admin;area=paidsubscribe;sa=settings.
83
 *
84
 * @param bool $return_config Whether or not to return the $config_vars array (used for admin search)
85
 * @return void|array Returns nothing or returns the config_vars array if $return_config is true
86
 */
87
function ModifySubscriptionSettings($return_config = false)
88
{
89
	global $context, $txt, $modSettings, $sourcedir, $smcFunc, $scripturl;
90
91
	if (!empty($modSettings['paid_enabled']))
92
	{
93
		// If the currency is set to something different then we need to set it to other for this to work and set it back shortly.
94
		$modSettings['paid_currency'] = !empty($modSettings['paid_currency_code']) ? $modSettings['paid_currency_code'] : '';
95
		if (!empty($modSettings['paid_currency_code']) && !in_array($modSettings['paid_currency_code'], array('usd', 'eur', 'gbp', 'cad', 'aud')))
96
			$modSettings['paid_currency'] = 'other';
97
98
		// These are all the default settings.
99
		$config_vars = array(
100
			array(
101
				'check',
102
				'paid_enabled'
103
			),
104
			'',
105
106
			array(
107
				'select',
108
				'paid_email',
109
				array(
110
					0 => $txt['paid_email_no'],
111
					1 => $txt['paid_email_error'],
112
					2 => $txt['paid_email_all']
113
				),
114
				'subtext' => $txt['paid_email_desc']
115
			),
116
			array(
117
				'email',
118
				'paid_email_to',
119
				'subtext' => $txt['paid_email_to_desc'],
120
				'size' => 60
121
			),
122
			'',
123
124
			'dummy_currency' => array(
125
				'select',
126
				'paid_currency',
127
				array(
128
					'usd' => $txt['usd'],
129
					'eur' => $txt['eur'],
130
					'gbp' => $txt['gbp'],
131
					'cad' => $txt['cad'],
132
					'aud' => $txt['aud'],
133
					'other' => $txt['other']
134
				),
135
				'javascript' => 'onchange="toggleOther();"'
136
			),
137
			array(
138
				'text',
139
				'paid_currency_code',
140
				'subtext' => $txt['paid_currency_code_desc'],
141
				'size' => 5,
142
				'force_div_id' => 'custom_currency_code_div'
143
			),
144
			array(
145
				'text',
146
				'paid_currency_symbol',
147
				'subtext' => $txt['paid_currency_symbol_desc'],
148
				'size' => 8,
149
				'force_div_id' => 'custom_currency_symbol_div'
150
			),
151
			array(
152
				'check',
153
				'paidsubs_test',
154
				'subtext' => $txt['paidsubs_test_desc'],
155
				'onclick' => 'return document.getElementById(\'paidsubs_test\').checked ? confirm(\'' . $txt['paidsubs_test_confirm'] . '\') : true;'
156
			),
157
		);
158
159
		// Now load all the other gateway settings.
160
		$gateways = loadPaymentGateways();
161
		foreach ($gateways as $gateway)
162
		{
163
			$gatewayClass = new $gateway['display_class']();
164
			$setting_data = $gatewayClass->getGatewaySettings();
165
			if (!empty($setting_data))
166
			{
167
				$config_vars[] = array('title', $gatewayClass->title, 'text_label' => (isset($txt['paidsubs_gateway_title_' . $gatewayClass->title]) ? $txt['paidsubs_gateway_title_' . $gatewayClass->title] : $gatewayClass->title));
168
				$config_vars = array_merge($config_vars, $setting_data);
169
			}
170
		}
171
172
		$context['settings_message'] = $txt['paid_note'];
173
		$context[$context['admin_menu_name']]['current_subsection'] = 'settings';
174
		$context['settings_title'] = $txt['settings'];
175
176
		// We want javascript for our currency options.
177
		addInlineJavaScript('
178
		function toggleOther()
179
		{
180
			var otherOn = document.getElementById("paid_currency").value == \'other\';
181
			var currencydd = document.getElementById("custom_currency_code_div_dd");
182
183
			if (otherOn)
184
			{
185
				document.getElementById("custom_currency_code_div").style.display = "";
186
				document.getElementById("custom_currency_symbol_div").style.display = "";
187
188
				if (currencydd)
189
				{
190
					document.getElementById("custom_currency_code_div_dd").style.display = "";
191
					document.getElementById("custom_currency_symbol_div_dd").style.display = "";
192
				}
193
			}
194
			else
195
			{
196
				document.getElementById("custom_currency_code_div").style.display = "none";
197
				document.getElementById("custom_currency_symbol_div").style.display = "none";
198
199
				if (currencydd)
200
				{
201
					document.getElementById("custom_currency_symbol_div_dd").style.display = "none";
202
					document.getElementById("custom_currency_code_div_dd").style.display = "none";
203
				}
204
			}
205
		}
206
		toggleOther();', true);
207
	}
208
	else
209
	{
210
		$config_vars = array(
211
			array('check', 'paid_enabled'),
212
		);
213
		$context['settings_title'] = $txt['paid_subscriptions'];
214
	}
215
216
	// Just searching?
217
	if ($return_config)
218
		return $config_vars;
219
220
	// Get the settings template fired up.
221
	require_once($sourcedir . '/ManageServer.php');
222
223
	// Some important context stuff
224
	$context['page_title'] = $txt['settings'];
225
	$context['sub_template'] = 'show_settings';
226
227
	// Get the final touches in place.
228
	$context['post_url'] = $scripturl . '?action=admin;area=paidsubscribe;save;sa=settings';
229
230
	// Saving the settings?
231
	if (isset($_GET['save']))
232
	{
233
		checkSession();
234
235
		$old = !empty($modSettings['paid_enabled']);
236
		$new = !empty($_POST['paid_enabled']);
237
		if ($old != $new)
238
		{
239
			// So we're changing this fundamental status. Great.
240
			$smcFunc['db_query']('', '
241
				UPDATE {db_prefix}scheduled_tasks
242
				SET disabled = {int:disabled}
243
				WHERE task = {string:task}',
244
				array(
245
					'disabled' => $new ? 0 : 1,
246
					'task' => 'paid_subscriptions',
247
				)
248
			);
249
250
			// This may well affect the next trigger, whether we're enabling or not.
251
			require_once($sourcedir . '/ScheduledTasks.php');
252
			CalculateNextTrigger('paid_subscriptions');
253
		}
254
255
		// Check the email addresses were actually email addresses.
256
		if (!empty($_POST['paid_email_to']))
257
		{
258
			$email_addresses = array();
259
			foreach (explode(',', $_POST['paid_email_to']) as $email)
260
			{
261
				$email = trim($email);
262
				if (!empty($email) && filter_var($email, FILTER_VALIDATE_EMAIL))
263
					$email_addresses[] = $email;
264
				$_POST['paid_email_to'] = implode(',', $email_addresses);
265
			}
266
		}
267
268
		// Can only handle this stuff if it's already enabled...
269
		if (!empty($modSettings['paid_enabled']))
270
		{
271
			// Sort out the currency stuff.
272
			if ($_POST['paid_currency'] != 'other')
273
			{
274
				$_POST['paid_currency_code'] = $_POST['paid_currency'];
275
				$_POST['paid_currency_symbol'] = $txt[$_POST['paid_currency'] . '_symbol'];
276
			}
277
			unset($config_vars['dummy_currency']);
278
		}
279
280
		saveDBSettings($config_vars);
281
		$_SESSION['adm-save'] = true;
282
283
		redirectexit('action=admin;area=paidsubscribe;sa=settings');
284
	}
285
286
	// Prepare the settings...
287
	prepareDBSettingContext($config_vars);
288
}
289
290
/**
291
 * View a list of all the current subscriptions
292
 * Requires the admin_forum permission.
293
 * Accessed from ?action=admin;area=paidsubscribe;sa=view.
294
 */
295
function ViewSubscriptions()
296
{
297
	global $context, $txt, $modSettings, $sourcedir, $scripturl;
298
299
	// Not made the settings yet?
300
	if (empty($modSettings['paid_currency_symbol']))
301
		fatal_lang_error('paid_not_set_currency', false, $scripturl . '?action=admin;area=paidsubscribe;sa=settings');
0 ignored issues
show
Bug introduced by
$scripturl . '?action=ad...dsubscribe;sa=settings' of type string is incompatible with the type array expected by parameter $sprintf of fatal_lang_error(). ( Ignorable by Annotation )

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

301
		fatal_lang_error('paid_not_set_currency', false, /** @scrutinizer ignore-type */ $scripturl . '?action=admin;area=paidsubscribe;sa=settings');
Loading history...
302
303
	// Some basic stuff.
304
	$context['page_title'] = $txt['paid_subs_view'];
305
	loadSubscriptions();
306
307
	$listOptions = array(
308
		'id' => 'subscription_list',
309
		'title' => $txt['subscriptions'],
310
		'items_per_page' => $modSettings['defaultMaxListItems'],
311
		'base_href' => $scripturl . '?action=admin;area=paidsubscribe;sa=view',
312
		'get_items' => array(
313
			'function' => function($start, $items_per_page) use ($context)
314
			{
315
				$subscriptions = array();
316
				$counter = 0;
317
				$start++;
318
319
				foreach ($context['subscriptions'] as $data)
320
				{
321
					if (++$counter < $start)
322
						continue;
323
					elseif ($counter == $start + $items_per_page)
324
						break;
325
326
					$subscriptions[] = $data;
327
				}
328
				return $subscriptions;
329
			},
330
		),
331
		'get_count' => array(
332
			'function' => function() use ($context)
333
			{
334
				return count($context['subscriptions']);
335
			},
336
		),
337
		'no_items_label' => $txt['paid_none_yet'],
338
		'columns' => array(
339
			'name' => array(
340
				'header' => array(
341
					'value' => $txt['paid_name'],
342
					'style' => 'width: 35%;',
343
				),
344
				'data' => array(
345
					'function' => function($rowData) use ($scripturl)
346
					{
347
						return sprintf('<a href="%1$s?action=admin;area=paidsubscribe;sa=viewsub;sid=%2$s">%3$s</a>', $scripturl, $rowData['id'], $rowData['name']);
348
					},
349
				),
350
			),
351
			'cost' => array(
352
				'header' => array(
353
					'value' => $txt['paid_cost'],
354
				),
355
				'data' => array(
356
					'function' => function($rowData) use ($txt)
357
					{
358
						return $rowData['flexible'] ? '<em>' . $txt['flexible'] . '</em>' : $rowData['cost'] . ' / ' . $rowData['length'];
359
					},
360
				),
361
			),
362
			'pending' => array(
363
				'header' => array(
364
					'value' => $txt['paid_pending'],
365
					'style' => 'width: 18%;',
366
					'class' => 'centercol',
367
				),
368
				'data' => array(
369
					'db_htmlsafe' => 'pending',
370
					'class' => 'centercol',
371
				),
372
			),
373
			'finished' => array(
374
				'header' => array(
375
					'value' => $txt['paid_finished'],
376
					'class' => 'centercol',
377
				),
378
				'data' => array(
379
					'db_htmlsafe' => 'finished',
380
					'class' => 'centercol',
381
				),
382
			),
383
			'total' => array(
384
				'header' => array(
385
					'value' => $txt['paid_active'],
386
					'class' => 'centercol',
387
				),
388
				'data' => array(
389
					'db_htmlsafe' => 'total',
390
					'class' => 'centercol',
391
				),
392
			),
393
			'is_active' => array(
394
				'header' => array(
395
					'value' => $txt['paid_is_active'],
396
					'class' => 'centercol',
397
				),
398
				'data' => array(
399
					'function' => function($rowData) use ($txt)
400
					{
401
						return '<span style="color: ' . ($rowData['active'] ? 'green' : 'red') . '">' . ($rowData['active'] ? $txt['yes'] : $txt['no']) . '</span>';
402
					},
403
					'class' => 'centercol',
404
				),
405
			),
406
			'modify' => array(
407
				'data' => array(
408
					'function' => function($rowData) use ($txt, $scripturl)
409
					{
410
						return '<a href="' . $scripturl . '?action=admin;area=paidsubscribe;sa=modify;sid=' . $rowData['id'] . '">' . $txt['modify'] . '</a>';
411
					},
412
					'class' => 'centercol',
413
				),
414
			),
415
			'delete' => array(
416
				'data' => array(
417
					'function' => function($rowData) use ($scripturl, $txt)
418
					{
419
						return '<a href="' . $scripturl . '?action=admin;area=paidsubscribe;sa=modify;delete;sid=' . $rowData['id'] . '">' . $txt['delete'] . '</a>';
420
					},
421
					'class' => 'centercol',
422
				),
423
			),
424
		),
425
		'form' => array(
426
			'href' => $scripturl . '?action=admin;area=paidsubscribe;sa=modify',
427
		),
428
		'additional_rows' => array(
429
			array(
430
				'position' => 'above_table_headers',
431
				'value' => '<input type="submit" name="add" value="' . $txt['paid_add_subscription'] . '" class="button">',
432
			),
433
			array(
434
				'position' => 'below_table_data',
435
				'value' => '<input type="submit" name="add" value="' . $txt['paid_add_subscription'] . '" class="button">',
436
			),
437
		),
438
	);
439
440
	require_once($sourcedir . '/Subs-List.php');
441
	createList($listOptions);
442
443
	$context['sub_template'] = 'show_list';
444
	$context['default_list'] = 'subscription_list';
445
}
446
447
/**
448
 * Adding, editing and deleting subscriptions.
449
 * Accessed from ?action=admin;area=paidsubscribe;sa=modify.
450
 */
451
function ModifySubscription()
452
{
453
	global $context, $txt, $smcFunc;
454
455
	$context['sub_id'] = isset($_REQUEST['sid']) ? (int) $_REQUEST['sid'] : 0;
456
	$context['action_type'] = $context['sub_id'] ? (isset($_REQUEST['delete']) ? 'delete' : 'edit') : 'add';
457
458
	// Setup the template.
459
	$context['sub_template'] = $context['action_type'] == 'delete' ? 'delete_subscription' : 'modify_subscription';
460
	$context['page_title'] = $txt['paid_' . $context['action_type'] . '_subscription'];
461
462
	// Delete it?
463
	if (isset($_POST['delete_confirm']) && isset($_REQUEST['delete']))
464
	{
465
		checkSession();
466
		validateToken('admin-pmsd');
467
468
		// Before we delete the subscription we need to find out if anyone currently has said subscription.
469
		$request = $smcFunc['db_query']('', '
470
			SELECT ls.id_member, ls.old_id_group, mem.id_group, mem.additional_groups
471
			FROM {db_prefix}log_subscribed AS ls
472
				INNER JOIN {db_prefix}members AS mem ON (ls.id_member = mem.id_member)
473
			WHERE id_subscribe = {int:current_subscription}
474
				AND status = {int:is_active}',
475
			array(
476
				'current_subscription' => $context['sub_id'],
477
				'is_active' => 1,
478
			)
479
		);
480
		$members = array();
481
		while ($row = $smcFunc['db_fetch_assoc']($request))
482
		{
483
			$id_member = array_shift($row);
484
			$members[$id_member] = $row;
485
		}
486
		$smcFunc['db_free_result']($request);
487
488
		// If there are any members with this subscription, we have to do some more work before we go any further.
489
		if (!empty($members))
490
		{
491
			$request = $smcFunc['db_query']('', '
492
				SELECT id_group, add_groups
493
				FROM {db_prefix}subscriptions
494
				WHERE id_subscribe = {int:current_subscription}',
495
				array(
496
					'current_subscription' => $context['sub_id'],
497
				)
498
			);
499
			$id_group = 0;
500
			$add_groups = '';
501
			if ($smcFunc['db_num_rows']($request))
502
				list ($id_group, $add_groups) = $smcFunc['db_fetch_row']($request);
503
			$smcFunc['db_free_result']($request);
504
505
			$changes = array();
506
507
			// Is their group changing? This subscription may not have changed primary group.
508
			if (!empty($id_group))
509
			{
510
				foreach ($members as $id_member => $member_data)
511
				{
512
					// If their current primary group isn't what they had before the subscription, and their current group was
513
					// granted by the sub, remove it.
514
					if ($member_data['old_id_group'] != $member_data['id_group'] && $member_data['id_group'] == $id_group)
515
						$changes[$id_member]['id_group'] = $member_data['old_id_group'];
516
				}
517
			}
518
519
			// Did this subscription add secondary groups?
520
			if (!empty($add_groups))
521
			{
522
				$add_groups = explode(',', $add_groups);
523
				foreach ($members as $id_member => $member_data)
524
				{
525
					// First let's get their groups sorted.
526
					$current_groups = explode(',', $member_data['additional_groups']);
527
					$new_groups = implode(',', array_diff($current_groups, $add_groups));
528
					if ($new_groups != $member_data['additional_groups'])
529
						$changes[$id_member]['additional_groups'] = $new_groups;
530
				}
531
			}
532
533
			// We're going through changes...
534
			if (!empty($changes))
535
				foreach ($changes as $id_member => $new_values)
536
					updateMemberData($id_member, $new_values);
537
		}
538
539
		// Delete the subscription
540
		$smcFunc['db_query']('', '
541
			DELETE FROM {db_prefix}subscriptions
542
			WHERE id_subscribe = {int:current_subscription}',
543
			array(
544
				'current_subscription' => $context['sub_id'],
545
			)
546
		);
547
548
		// And delete any subscriptions to it to clear the phantom data too.
549
		$smcFunc['db_query']('', '
550
			DELETE FROM {db_prefix}log_subscribed
551
			WHERE id_subscribe = {int:current_subscription}',
552
			array(
553
				'current_subscription' => $context['sub_id'],
554
			)
555
		);
556
557
		call_integration_hook('integrate_delete_subscription', array($context['sub_id']));
558
559
		redirectexit('action=admin;area=paidsubscribe;view');
560
	}
561
562
	// Saving?
563
	if (isset($_POST['save']))
564
	{
565
		checkSession();
566
567
		// Some cleaning...
568
		$isActive = isset($_POST['active']) ? 1 : 0;
569
		$isRepeatable = isset($_POST['repeatable']) ? 1 : 0;
570
		$allowpartial = isset($_POST['allow_partial']) ? 1 : 0;
571
		$reminder = isset($_POST['reminder']) ? (int) $_POST['reminder'] : 0;
572
		$emailComplete = strlen($_POST['emailcomplete']) > 10 ? trim($_POST['emailcomplete']) : '';
573
574
		// Is this a fixed one?
575
		if ($_POST['duration_type'] == 'fixed')
576
		{
577
			// There are sanity check limits on these things.
578
			$limits = array(
579
				'D' => 90,
580
				'W' => 52,
581
				'M' => 24,
582
				'Y' => 5,
583
			);
584
			if (empty($_POST['span_unit']) || empty($limits[$_POST['span_unit']]) || empty($_POST['span_value']) || $_POST['span_value'] < 1)
585
				fatal_lang_error('paid_invalid_duration', false);
586
587
			if ($_POST['span_value'] > $limits[$_POST['span_unit']])
588
				fatal_lang_error('paid_invalid_duration_' . $_POST['span_unit'], false);
589
590
			// Clean the span.
591
			$span = $_POST['span_value'] . $_POST['span_unit'];
592
593
			// Sort out the cost.
594
			$cost = array('fixed' => sprintf('%01.2f', strtr($_POST['cost'], ',', '.')));
595
596
			// There needs to be something.
597
			if (empty($_POST['span_value']) || empty($_POST['cost']))
598
				fatal_lang_error('paid_no_cost_value');
599
		}
600
		// Flexible is harder but more fun ;)
601
		else
602
		{
603
			$span = 'F';
604
605
			$cost = array(
606
				'day' => sprintf('%01.2f', strtr($_POST['cost_day'], ',', '.')),
607
				'week' => sprintf('%01.2f', strtr($_POST['cost_week'], ',', '.')),
608
				'month' => sprintf('%01.2f', strtr($_POST['cost_month'], ',', '.')),
609
				'year' => sprintf('%01.2f', strtr($_POST['cost_year'], ',', '.')),
610
			);
611
612
			if (empty($_POST['cost_day']) && empty($_POST['cost_week']) && empty($_POST['cost_month']) && empty($_POST['cost_year']))
613
				fatal_lang_error('paid_all_freq_blank');
614
		}
615
		$cost = $smcFunc['json_encode']($cost);
616
617
		// Having now validated everything that might throw an error, let's also now deal with the token.
618
		validateToken('admin-pms');
619
620
		// Yep, time to do additional groups.
621
		$addgroups = array();
622
		if (!empty($_POST['addgroup']))
623
			foreach ($_POST['addgroup'] as $id => $dummy)
624
				$addgroups[] = (int) $id;
625
		$addgroups = implode(',', $addgroups);
626
627
		// Is it new?!
628
		if ($context['action_type'] == 'add')
629
		{
630
			$id_subscribe = $smcFunc['db_insert']('',
631
				'{db_prefix}subscriptions',
632
				array(
633
					'name' => 'string-60', 'description' => 'string-255', 'active' => 'int', 'length' => 'string-4', 'cost' => 'string',
634
					'id_group' => 'int', 'add_groups' => 'string-40', 'repeatable' => 'int', 'allow_partial' => 'int', 'email_complete' => 'string',
635
					'reminder' => 'int',
636
				),
637
				array(
638
					$_POST['name'], $_POST['desc'], $isActive, $span, $cost,
639
					$_POST['prim_group'], $addgroups, $isRepeatable, $allowpartial, $emailComplete,
640
					$reminder,
641
				),
642
				array('id_subscribe'),
643
				1
644
			);
645
		}
646
		// Otherwise must be editing.
647
		else
648
		{
649
			// Don't do groups if there are active members
650
			$request = $smcFunc['db_query']('', '
651
				SELECT COUNT(*)
652
				FROM {db_prefix}log_subscribed
653
				WHERE id_subscribe = {int:current_subscription}
654
					AND status = {int:is_active}',
655
				array(
656
					'current_subscription' => $context['sub_id'],
657
					'is_active' => 1,
658
				)
659
			);
660
			list ($disableGroups) = $smcFunc['db_fetch_row']($request);
661
			$smcFunc['db_free_result']($request);
662
663
			$smcFunc['db_query']('substring', '
664
				UPDATE {db_prefix}subscriptions
665
					SET name = SUBSTRING({string:name}, 1, 60), description = SUBSTRING({string:description}, 1, 255), active = {int:is_active},
666
					length = SUBSTRING({string:length}, 1, 4), cost = {string:cost}' . ($disableGroups ? '' : ', id_group = {int:id_group},
667
					add_groups = {string:additional_groups}') . ', repeatable = {int:repeatable}, allow_partial = {int:allow_partial},
668
					email_complete = {string:email_complete}, reminder = {int:reminder}
669
				WHERE id_subscribe = {int:current_subscription}',
670
				array(
671
					'is_active' => $isActive,
672
					'id_group' => !empty($_POST['prim_group']) ? $_POST['prim_group'] : 0,
673
					'repeatable' => $isRepeatable,
674
					'allow_partial' => $allowpartial,
675
					'reminder' => $reminder,
676
					'current_subscription' => $context['sub_id'],
677
					'name' => $_POST['name'],
678
					'description' => $_POST['desc'],
679
					'length' => $span,
680
					'cost' => $cost,
681
					'additional_groups' => !empty($addgroups) ? $addgroups : '',
682
					'email_complete' => $emailComplete,
683
				)
684
			);
685
		}
686
		call_integration_hook('integrate_save_subscription', array(($context['action_type'] == 'add' ? $id_subscribe : $context['sub_id']), $_POST['name'], $_POST['desc'], $isActive, $span, $cost, $_POST['prim_group'], $addgroups, $isRepeatable, $allowpartial, $emailComplete, $reminder));
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $id_subscribe does not seem to be defined for all execution paths leading up to this point.
Loading history...
687
688
		redirectexit('action=admin;area=paidsubscribe;view');
689
	}
690
691
	// Defaults.
692
	if ($context['action_type'] == 'add')
693
	{
694
		$context['sub'] = array(
695
			'name' => '',
696
			'desc' => '',
697
			'cost' => array(
698
				'fixed' => 0,
699
			),
700
			'span' => array(
701
				'value' => '',
702
				'unit' => 'D',
703
			),
704
			'prim_group' => 0,
705
			'add_groups' => array(),
706
			'active' => 1,
707
			'repeatable' => 1,
708
			'allow_partial' => 0,
709
			'duration' => 'fixed',
710
			'email_complete' => '',
711
			'reminder' => 0,
712
		);
713
	}
714
	// Otherwise load up all the details.
715
	else
716
	{
717
		$request = $smcFunc['db_query']('', '
718
			SELECT name, description, cost, length, id_group, add_groups, active, repeatable, allow_partial, email_complete, reminder
719
			FROM {db_prefix}subscriptions
720
			WHERE id_subscribe = {int:current_subscription}
721
			LIMIT 1',
722
			array(
723
				'current_subscription' => $context['sub_id'],
724
			)
725
		);
726
		while ($row = $smcFunc['db_fetch_assoc']($request))
727
		{
728
			// Sort the date.
729
			preg_match('~(\d*)(\w)~', $row['length'], $match);
730
			if (isset($match[2]))
731
			{
732
				$span_value = $match[1];
733
				$span_unit = $match[2];
734
			}
735
			else
736
			{
737
				$span_value = 0;
738
				$span_unit = 'D';
739
			}
740
741
			// Is this a flexible one?
742
			if ($row['length'] == 'F')
743
				$isFlexible = true;
744
			else
745
				$isFlexible = false;
746
747
			$context['sub'] = array(
748
				'name' => $row['name'],
749
				'desc' => $row['description'],
750
				'cost' => $smcFunc['json_decode']($row['cost'], true),
751
				'span' => array(
752
					'value' => $span_value,
753
					'unit' => $span_unit,
754
				),
755
				'prim_group' => $row['id_group'],
756
				'add_groups' => explode(',', $row['add_groups']),
757
				'active' => $row['active'],
758
				'repeatable' => $row['repeatable'],
759
				'allow_partial' => $row['allow_partial'],
760
				'duration' => $isFlexible ? 'flexible' : 'fixed',
761
				'email_complete' => $smcFunc['htmlspecialchars']($row['email_complete']),
762
				'reminder' => $row['reminder'],
763
			);
764
		}
765
		$smcFunc['db_free_result']($request);
766
767
		// Does this have members who are active?
768
		$request = $smcFunc['db_query']('', '
769
			SELECT COUNT(*)
770
			FROM {db_prefix}log_subscribed
771
			WHERE id_subscribe = {int:current_subscription}
772
				AND status = {int:is_active}',
773
			array(
774
				'current_subscription' => $context['sub_id'],
775
				'is_active' => 1,
776
			)
777
		);
778
		list ($context['disable_groups']) = $smcFunc['db_fetch_row']($request);
779
		$smcFunc['db_free_result']($request);
780
	}
781
782
	// Load up all the groups.
783
	$request = $smcFunc['db_query']('', '
784
		SELECT id_group, group_name
785
		FROM {db_prefix}membergroups
786
		WHERE id_group != {int:moderator_group}
787
			AND min_posts = {int:min_posts}',
788
		array(
789
			'moderator_group' => 3,
790
			'min_posts' => -1,
791
		)
792
	);
793
	$context['groups'] = array();
794
	while ($row = $smcFunc['db_fetch_assoc']($request))
795
		$context['groups'][$row['id_group']] = $row['group_name'];
796
	$smcFunc['db_free_result']($request);
797
798
	// This always happens.
799
	createToken($context['action_type'] == 'delete' ? 'admin-pmsd' : 'admin-pms');
800
}
801
802
/**
803
 * View all the users subscribed to a particular subscription.
804
 * Requires the admin_forum permission.
805
 * Accessed from ?action=admin;area=paidsubscribe;sa=viewsub.
806
 *
807
 * Subscription ID is required, in the form of $_GET['sid'].
808
 */
809
function ViewSubscribedUsers()
810
{
811
	global $context, $txt, $scripturl, $smcFunc, $sourcedir, $modSettings;
812
813
	// Setup the template.
814
	$context['page_title'] = $txt['viewing_users_subscribed'];
815
816
	// ID of the subscription.
817
	$context['sub_id'] = (int) $_REQUEST['sid'];
818
819
	// Load the subscription information.
820
	$request = $smcFunc['db_query']('', '
821
		SELECT id_subscribe, name, description, cost, length, id_group, add_groups, active
822
		FROM {db_prefix}subscriptions
823
		WHERE id_subscribe = {int:current_subscription}',
824
		array(
825
			'current_subscription' => $context['sub_id'],
826
		)
827
	);
828
	// Something wrong?
829
	if ($smcFunc['db_num_rows']($request) == 0)
830
		fatal_lang_error('no_access', false);
831
	// Do the subscription context.
832
	$row = $smcFunc['db_fetch_assoc']($request);
833
	$context['subscription'] = array(
834
		'id' => $row['id_subscribe'],
835
		'name' => $row['name'],
836
		'desc' => $row['description'],
837
		'active' => $row['active'],
838
	);
839
	$smcFunc['db_free_result']($request);
840
841
	// Are we searching for people?
842
	$search_string = isset($_POST['ssearch']) && !empty($_POST['sub_search']) ? ' AND COALESCE(mem.real_name, {string:guest}) LIKE {string:search}' : '';
843
	$search_vars = empty($_POST['sub_search']) ? array() : array('search' => '%' . $_POST['sub_search'] . '%', 'guest' => $txt['guest']);
844
845
	$listOptions = array(
846
		'id' => 'subscribed_users_list',
847
		'title' => sprintf($txt['view_users_subscribed'], $row['name']),
848
		'items_per_page' => $modSettings['defaultMaxListItems'],
849
		'base_href' => $scripturl . '?action=admin;area=paidsubscribe;sa=viewsub;sid=' . $context['sub_id'],
850
		'default_sort_col' => 'name',
851
		'get_items' => array(
852
			'function' => 'list_getSubscribedUsers',
853
			'params' => array(
854
				$context['sub_id'],
855
				$search_string,
856
				$search_vars,
857
			),
858
		),
859
		'get_count' => array(
860
			'function' => 'list_getSubscribedUserCount',
861
			'params' => array(
862
				$context['sub_id'],
863
				$search_string,
864
				$search_vars,
865
			),
866
		),
867
		'no_items_label' => $txt['no_subscribers'],
868
		'columns' => array(
869
			'name' => array(
870
				'header' => array(
871
					'value' => $txt['who_member'],
872
					'style' => 'width: 20%;',
873
				),
874
				'data' => array(
875
					'function' => function($rowData) use ($scripturl, $txt)
876
					{
877
						return $rowData['id_member'] == 0 ? $txt['guest'] : '<a href="' . $scripturl . '?action=profile;u=' . $rowData['id_member'] . '">' . $rowData['name'] . '</a>';
878
					},
879
				),
880
				'sort' => array(
881
					'default' => 'name',
882
					'reverse' => 'name DESC',
883
				),
884
			),
885
			'status' => array(
886
				'header' => array(
887
					'value' => $txt['paid_status'],
888
					'style' => 'width: 10%;',
889
				),
890
				'data' => array(
891
					'db_htmlsafe' => 'status_text',
892
				),
893
				'sort' => array(
894
					'default' => 'status',
895
					'reverse' => 'status DESC',
896
				),
897
			),
898
			'payments_pending' => array(
899
				'header' => array(
900
					'value' => $txt['paid_payments_pending'],
901
					'style' => 'width: 15%;',
902
				),
903
				'data' => array(
904
					'db_htmlsafe' => 'pending',
905
				),
906
				'sort' => array(
907
					'default' => 'payments_pending',
908
					'reverse' => 'payments_pending DESC',
909
				),
910
			),
911
			'start_time' => array(
912
				'header' => array(
913
					'value' => $txt['start_date'],
914
					'style' => 'width: 20%;',
915
				),
916
				'data' => array(
917
					'db_htmlsafe' => 'start_date',
918
					'class' => 'smalltext',
919
				),
920
				'sort' => array(
921
					'default' => 'start_time',
922
					'reverse' => 'start_time DESC',
923
				),
924
			),
925
			'end_time' => array(
926
				'header' => array(
927
					'value' => $txt['end_date'],
928
					'style' => 'width: 20%;',
929
				),
930
				'data' => array(
931
					'db_htmlsafe' => 'end_date',
932
					'class' => 'smalltext',
933
				),
934
				'sort' => array(
935
					'default' => 'end_time',
936
					'reverse' => 'end_time DESC',
937
				),
938
			),
939
			'modify' => array(
940
				'header' => array(
941
					'style' => 'width: 10%;',
942
					'class' => 'centercol',
943
				),
944
				'data' => array(
945
					'function' => function($rowData) use ($scripturl, $txt)
946
					{
947
						return '<a href="' . $scripturl . '?action=admin;area=paidsubscribe;sa=modifyuser;lid=' . $rowData['id'] . '">' . $txt['modify'] . '</a>';
948
					},
949
					'class' => 'centercol',
950
				),
951
			),
952
			'delete' => array(
953
				'header' => array(
954
					'style' => 'width: 4%;',
955
					'class' => 'centercol',
956
				),
957
				'data' => array(
958
					'function' => function($rowData)
959
					{
960
						return '<input type="checkbox" name="delsub[' . $rowData['id'] . ']">';
961
					},
962
					'class' => 'centercol',
963
				),
964
			),
965
		),
966
		'form' => array(
967
			'href' => $scripturl . '?action=admin;area=paidsubscribe;sa=modifyuser;sid=' . $context['sub_id'],
968
		),
969
		'additional_rows' => array(
970
			array(
971
				'position' => 'below_table_data',
972
				'value' => '
973
					<input type="submit" name="add" value="' . $txt['add_subscriber'] . '" class="button">
974
					<input type="submit" name="finished" value="' . $txt['complete_selected'] . '" data-confirm="' . $txt['complete_are_sure'] . '" class="button you_sure">
975
					<input type="submit" name="delete" value="' . $txt['delete_selected'] . '" data-confirm="' . $txt['delete_are_sure'] . '" class="button you_sure">
976
				',
977
			),
978
			array(
979
				'position' => 'top_of_list',
980
				'value' => '
981
					<div class="flow_auto">
982
						<input type="submit" name="ssearch" value="' . $txt['search_sub'] . '" class="button" style="margin-top: 3px;">
983
						<input type="text" name="sub_search" value="" class="floatright">
984
					</div>
985
				',
986
			),
987
		),
988
	);
989
990
	require_once($sourcedir . '/Subs-List.php');
991
	createList($listOptions);
992
993
	$context['sub_template'] = 'show_list';
994
	$context['default_list'] = 'subscribed_users_list';
995
}
996
997
/**
998
 * Returns how many people are subscribed to a paid subscription.
999
 *
1000
 * @todo refactor away
1001
 *
1002
 * @param int $id_sub The ID of the subscription
1003
 * @param string $search_string A search string
1004
 * @param array $search_vars An array of variables for the search string
1005
 * @return int The number of subscribed users matching the given parameters
1006
 */
1007
function list_getSubscribedUserCount($id_sub, $search_string, $search_vars = array())
1008
{
1009
	global $smcFunc;
1010
1011
	// Get the total amount of users.
1012
	$request = $smcFunc['db_query']('', '
1013
		SELECT COUNT(*) AS total_subs
1014
		FROM {db_prefix}log_subscribed AS ls
1015
			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = ls.id_member)
1016
		WHERE ls.id_subscribe = {int:current_subscription} ' . $search_string . '
1017
			AND (ls.end_time != {int:no_end_time} OR ls.payments_pending != {int:no_pending_payments})',
1018
		array_merge($search_vars, array(
1019
			'current_subscription' => $id_sub,
1020
			'no_end_time' => 0,
1021
			'no_pending_payments' => 0,
1022
		))
1023
	);
1024
	list ($memberCount) = $smcFunc['db_fetch_row']($request);
1025
	$smcFunc['db_free_result']($request);
1026
1027
	return $memberCount;
1028
}
1029
1030
/**
1031
 * Return the subscribed users list, for the given parameters.
1032
 *
1033
 * @todo refactor outta here
1034
 *
1035
 * @param int $start The item to start with (for pagination purposes)
1036
 * @param int $items_per_page How many items to show on each page
1037
 * @param string $sort A string indicating how to sort the results
1038
 * @param int $id_sub The ID of the subscription
1039
 * @param string $search_string A search string
1040
 * @param array $search_vars The variables for the search string
1041
 * @return array An array of information about the subscribed users matching the given parameters
1042
 */
1043
function list_getSubscribedUsers($start, $items_per_page, $sort, $id_sub, $search_string, $search_vars = array())
1044
{
1045
	global $smcFunc, $txt;
1046
1047
	$request = $smcFunc['db_query']('', '
1048
		SELECT ls.id_sublog, COALESCE(mem.id_member, 0) AS id_member, COALESCE(mem.real_name, {string:guest}) AS name, ls.start_time, ls.end_time,
1049
			ls.status, ls.payments_pending
1050
		FROM {db_prefix}log_subscribed AS ls
1051
			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = ls.id_member)
1052
		WHERE ls.id_subscribe = {int:current_subscription} ' . $search_string . '
1053
			AND (ls.end_time != {int:no_end_time} OR ls.payments_pending != {int:no_payments_pending})
1054
		ORDER BY {raw:sort}
1055
		LIMIT {int:start}, {int:max}',
1056
		array_merge($search_vars, array(
1057
			'current_subscription' => $id_sub,
1058
			'no_end_time' => 0,
1059
			'no_payments_pending' => 0,
1060
			'guest' => $txt['guest'],
1061
			'sort' => $sort,
1062
			'start' => $start,
1063
			'max' => $items_per_page,
1064
		))
1065
	);
1066
	$subscribers = array();
1067
	while ($row = $smcFunc['db_fetch_assoc']($request))
1068
		$subscribers[] = array(
1069
			'id' => $row['id_sublog'],
1070
			'id_member' => $row['id_member'],
1071
			'name' => $row['name'],
1072
			'start_date' => timeformat($row['start_time'], false),
1073
			'end_date' => $row['end_time'] == 0 ? 'N/A' : timeformat($row['end_time'], false),
1074
			'pending' => $row['payments_pending'],
1075
			'status' => $row['status'],
1076
			'status_text' => $row['status'] == 0 ? ($row['payments_pending'] == 0 ? $txt['paid_finished'] : $txt['paid_pending']) : $txt['paid_active'],
1077
		);
1078
	$smcFunc['db_free_result']($request);
1079
1080
	return $subscribers;
1081
}
1082
1083
/**
1084
 * Edit or add a user subscription.
1085
 * Accessed from ?action=admin;area=paidsubscribe;sa=modifyuser.
1086
 */
1087
function ModifyUserSubscription()
1088
{
1089
	global $context, $txt, $modSettings, $smcFunc;
1090
1091
	loadSubscriptions();
1092
1093
	$context['log_id'] = isset($_REQUEST['lid']) ? (int) $_REQUEST['lid'] : 0;
1094
	$context['sub_id'] = isset($_REQUEST['sid']) ? (int) $_REQUEST['sid'] : 0;
1095
	$context['action_type'] = $context['log_id'] ? 'edit' : 'add';
1096
1097
	// Setup the template.
1098
	$context['sub_template'] = 'modify_user_subscription';
1099
	$context['page_title'] = $txt[$context['action_type'] . '_subscriber'];
1100
1101
	// If we haven't been passed the subscription ID get it.
1102
	if ($context['log_id'] && !$context['sub_id'])
1103
	{
1104
		$request = $smcFunc['db_query']('', '
1105
			SELECT id_subscribe
1106
			FROM {db_prefix}log_subscribed
1107
			WHERE id_sublog = {int:current_log_item}',
1108
			array(
1109
				'current_log_item' => $context['log_id'],
1110
			)
1111
		);
1112
		if ($smcFunc['db_num_rows']($request) == 0)
1113
			fatal_lang_error('no_access', false);
1114
		list ($context['sub_id']) = $smcFunc['db_fetch_row']($request);
1115
		$smcFunc['db_free_result']($request);
1116
	}
1117
1118
	if (!isset($context['subscriptions'][$context['sub_id']]))
1119
		fatal_lang_error('no_access', false);
1120
	$context['current_subscription'] = $context['subscriptions'][$context['sub_id']];
1121
1122
	// Searching?
1123
	if (isset($_POST['ssearch']))
1124
	{
1125
		return ViewSubscribedUsers();
1126
	}
1127
	// Saving?
1128
	elseif (isset($_REQUEST['save_sub']))
1129
	{
1130
		checkSession();
1131
1132
		// Work out the dates...
1133
		$starttime = mktime($_POST['hour'], $_POST['minute'], 0, $_POST['month'], $_POST['day'], $_POST['year']);
1134
		$endtime = mktime($_POST['hourend'], $_POST['minuteend'], 0, $_POST['monthend'], $_POST['dayend'], $_POST['yearend']);
1135
1136
		// Status.
1137
		$status = $_POST['status'];
1138
1139
		// New one?
1140
		if (empty($context['log_id']))
1141
		{
1142
			// Find the user...
1143
			$request = $smcFunc['db_query']('', '
1144
				SELECT id_member, id_group
1145
				FROM {db_prefix}members
1146
				WHERE real_name = {string:name}
1147
				LIMIT 1',
1148
				array(
1149
					'name' => $_POST['name'],
1150
				)
1151
			);
1152
			if ($smcFunc['db_num_rows']($request) == 0)
1153
				fatal_lang_error('error_member_not_found');
1154
1155
			list ($id_member, $id_group) = $smcFunc['db_fetch_row']($request);
1156
			$smcFunc['db_free_result']($request);
1157
1158
			// Ensure the member doesn't already have a subscription!
1159
			$request = $smcFunc['db_query']('', '
1160
				SELECT id_subscribe
1161
				FROM {db_prefix}log_subscribed
1162
				WHERE id_subscribe = {int:current_subscription}
1163
					AND id_member = {int:current_member}',
1164
				array(
1165
					'current_subscription' => $context['sub_id'],
1166
					'current_member' => $id_member,
1167
				)
1168
			);
1169
			if ($smcFunc['db_num_rows']($request) != 0)
1170
				fatal_lang_error('member_already_subscribed');
1171
			$smcFunc['db_free_result']($request);
1172
1173
			// Actually put the subscription in place.
1174
			if ($status == 1)
1175
				addSubscription($context['sub_id'], $id_member, 0, $starttime, $endtime);
1176
			else
1177
			{
1178
				$smcFunc['db_insert']('',
1179
					'{db_prefix}log_subscribed',
1180
					array(
1181
						'id_subscribe' => 'int', 'id_member' => 'int', 'old_id_group' => 'int', 'start_time' => 'int',
1182
						'end_time' => 'int', 'status' => 'int', 'pending_details' => 'string-65534'
1183
					),
1184
					array(
1185
						$context['sub_id'], $id_member, $id_group, $starttime,
1186
						$endtime, $status, $smcFunc['json_encode'](array())
1187
					),
1188
					array('id_sublog')
1189
				);
1190
1191
			}
1192
		}
1193
		// Updating.
1194
		else
1195
		{
1196
			$request = $smcFunc['db_query']('', '
1197
				SELECT id_member, status
1198
				FROM {db_prefix}log_subscribed
1199
				WHERE id_sublog = {int:current_log_item}',
1200
				array(
1201
					'current_log_item' => $context['log_id'],
1202
				)
1203
			);
1204
			if ($smcFunc['db_num_rows']($request) == 0)
1205
				fatal_lang_error('no_access', false);
1206
1207
			list ($id_member, $old_status) = $smcFunc['db_fetch_row']($request);
1208
			$smcFunc['db_free_result']($request);
1209
1210
			// Pick the right permission stuff depending on what the status is changing from/to.
1211
			if ($old_status == 1 && $status != 1)
1212
				removeSubscription($context['sub_id'], $id_member);
1213
			elseif ($status == 1 && $old_status != 1)
1214
			{
1215
				addSubscription($context['sub_id'], $id_member, 0, $starttime, $endtime);
1216
			}
1217
			else
1218
			{
1219
				$smcFunc['db_query']('', '
1220
					UPDATE {db_prefix}log_subscribed
1221
					SET start_time = {int:start_time}, end_time = {int:end_time}, status = {int:status}
1222
					WHERE id_sublog = {int:current_log_item}',
1223
					array(
1224
						'start_time' => $starttime,
1225
						'end_time' => $endtime,
1226
						'status' => $status,
1227
						'current_log_item' => $context['log_id'],
1228
					)
1229
				);
1230
			}
1231
		}
1232
1233
		// Done - redirect...
1234
		redirectexit('action=admin;area=paidsubscribe;sa=viewsub;sid=' . $context['sub_id']);
1235
	}
1236
	// Deleting?
1237
	elseif (isset($_REQUEST['delete']) || isset($_REQUEST['finished']))
1238
	{
1239
		checkSession();
1240
1241
		// Do the actual deletes!
1242
		if (!empty($_REQUEST['delsub']))
1243
		{
1244
			$toDelete = array();
1245
			foreach ($_REQUEST['delsub'] as $id => $dummy)
1246
				$toDelete[] = (int) $id;
1247
1248
			$request = $smcFunc['db_query']('', '
1249
				SELECT id_subscribe, id_member
1250
				FROM {db_prefix}log_subscribed
1251
				WHERE id_sublog IN ({array_int:subscription_list})',
1252
				array(
1253
					'subscription_list' => $toDelete,
1254
				)
1255
			);
1256
			while ($row = $smcFunc['db_fetch_assoc']($request))
1257
				removeSubscription($row['id_subscribe'], $row['id_member'], isset($_REQUEST['delete']));
1258
			$smcFunc['db_free_result']($request);
1259
		}
1260
		redirectexit('action=admin;area=paidsubscribe;sa=viewsub;sid=' . $context['sub_id']);
1261
	}
1262
1263
	// Default attributes.
1264
	if ($context['action_type'] == 'add')
1265
	{
1266
		$context['sub'] = array(
1267
			'id' => 0,
1268
			'start' => array(
1269
				'year' => (int) strftime('%Y', time()),
1270
				'month' => (int) strftime('%m', time()),
1271
				'day' => (int) strftime('%d', time()),
1272
				'hour' => (int) strftime('%H', time()),
1273
				'min' => (int) strftime('%M', time()) < 10 ? '0' . (int) strftime('%M', time()) : (int) strftime('%M', time()),
1274
				'last_day' => 0,
1275
			),
1276
			'end' => array(
1277
				'year' => (int) strftime('%Y', time()),
1278
				'month' => (int) strftime('%m', time()),
1279
				'day' => (int) strftime('%d', time()),
1280
				'hour' => (int) strftime('%H', time()),
1281
				'min' => (int) strftime('%M', time()) < 10 ? '0' . (int) strftime('%M', time()) : (int) strftime('%M', time()),
1282
				'last_day' => 0,
1283
			),
1284
			'status' => 1,
1285
		);
1286
		$context['sub']['start']['last_day'] = (int) strftime('%d', mktime(0, 0, 0, $context['sub']['start']['month'] == 12 ? 1 : $context['sub']['start']['month'] + 1, 0, $context['sub']['start']['month'] == 12 ? $context['sub']['start']['year'] + 1 : $context['sub']['start']['year']));
1287
		$context['sub']['end']['last_day'] = (int) strftime('%d', mktime(0, 0, 0, $context['sub']['end']['month'] == 12 ? 1 : $context['sub']['end']['month'] + 1, 0, $context['sub']['end']['month'] == 12 ? $context['sub']['end']['year'] + 1 : $context['sub']['end']['year']));
1288
1289
		if (isset($_GET['uid']))
1290
		{
1291
			$request = $smcFunc['db_query']('', '
1292
				SELECT real_name
1293
				FROM {db_prefix}members
1294
				WHERE id_member = {int:current_member}',
1295
				array(
1296
					'current_member' => (int) $_GET['uid'],
1297
				)
1298
			);
1299
			list ($context['sub']['username']) = $smcFunc['db_fetch_row']($request);
1300
			$smcFunc['db_free_result']($request);
1301
		}
1302
		else
1303
			$context['sub']['username'] = '';
1304
	}
1305
	// Otherwise load the existing info.
1306
	else
1307
	{
1308
		$request = $smcFunc['db_query']('', '
1309
			SELECT ls.id_sublog, ls.id_subscribe, ls.id_member, start_time, end_time, status, payments_pending, pending_details,
1310
				COALESCE(mem.real_name, {string:blank_string}) AS username
1311
			FROM {db_prefix}log_subscribed AS ls
1312
				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = ls.id_member)
1313
			WHERE ls.id_sublog = {int:current_subscription_item}
1314
			LIMIT 1',
1315
			array(
1316
				'current_subscription_item' => $context['log_id'],
1317
				'blank_string' => '',
1318
			)
1319
		);
1320
		if ($smcFunc['db_num_rows']($request) == 0)
1321
			fatal_lang_error('no_access', false);
1322
		$row = $smcFunc['db_fetch_assoc']($request);
1323
		$smcFunc['db_free_result']($request);
1324
1325
		// Any pending payments?
1326
		$context['pending_payments'] = array();
1327
		if (!empty($row['pending_details']))
1328
		{
1329
			$pending_details = $smcFunc['json_decode']($row['pending_details'], true);
1330
			foreach ($pending_details as $id => $pending)
1331
			{
1332
				// Only this type need be displayed.
1333
				if ($pending[3] == 'payback')
1334
				{
1335
					// Work out what the options were.
1336
					$costs = $smcFunc['json_decode']($context['current_subscription']['real_cost'], true);
1337
1338
					if ($context['current_subscription']['real_length'] == 'F')
1339
					{
1340
						foreach ($costs as $duration => $cost)
1341
						{
1342
							if ($cost != 0 && $cost == $pending[1] && $duration == $pending[2])
1343
								$context['pending_payments'][$id] = array(
1344
									'desc' => sprintf($modSettings['paid_currency_symbol'], $cost . '/' . $txt[$duration]),
1345
								);
1346
						}
1347
					}
1348
					elseif ($costs['fixed'] == $pending[1])
1349
					{
1350
						$context['pending_payments'][$id] = array(
1351
							'desc' => sprintf($modSettings['paid_currency_symbol'], $costs['fixed']),
1352
						);
1353
					}
1354
				}
1355
			}
1356
1357
			// Check if we are adding/removing any.
1358
			if (isset($_GET['pending']))
1359
			{
1360
				foreach ($pending_details as $id => $pending)
1361
				{
1362
					// Found the one to action?
1363
					if ($_GET['pending'] == $id && $pending[3] == 'payback' && isset($context['pending_payments'][$id]))
1364
					{
1365
						// Flexible?
1366
						if (isset($_GET['accept']))
1367
							addSubscription($context['current_subscription']['id'], $row['id_member'], $context['current_subscription']['real_length'] == 'F' ? strtoupper(substr($pending[2], 0, 1)) : 0);
1368
						unset($pending_details[$id]);
1369
1370
						$new_details = $smcFunc['json_encode']($pending_details);
1371
1372
						// Update the entry.
1373
						$smcFunc['db_query']('', '
1374
							UPDATE {db_prefix}log_subscribed
1375
							SET payments_pending = payments_pending - 1, pending_details = {string:pending_details}
1376
							WHERE id_sublog = {int:current_subscription_item}',
1377
							array(
1378
								'current_subscription_item' => $context['log_id'],
1379
								'pending_details' => $new_details,
1380
							)
1381
						);
1382
1383
						// Reload
1384
						redirectexit('action=admin;area=paidsubscribe;sa=modifyuser;lid=' . $context['log_id']);
1385
					}
1386
				}
1387
			}
1388
		}
1389
1390
		$context['sub_id'] = $row['id_subscribe'];
1391
		$context['sub'] = array(
1392
			'id' => 0,
1393
			'start' => array(
1394
				'year' => (int) strftime('%Y', $row['start_time']),
1395
				'month' => (int) strftime('%m', $row['start_time']),
1396
				'day' => (int) strftime('%d', $row['start_time']),
1397
				'hour' => (int) strftime('%H', $row['start_time']),
1398
				'min' => (int) strftime('%M', $row['start_time']) < 10 ? '0' . (int) strftime('%M', $row['start_time']) : (int) strftime('%M', $row['start_time']),
1399
				'last_day' => 0,
1400
			),
1401
			'end' => array(
1402
				'year' => (int) strftime('%Y', $row['end_time']),
1403
				'month' => (int) strftime('%m', $row['end_time']),
1404
				'day' => (int) strftime('%d', $row['end_time']),
1405
				'hour' => (int) strftime('%H', $row['end_time']),
1406
				'min' => (int) strftime('%M', $row['end_time']) < 10 ? '0' . (int) strftime('%M', $row['end_time']) : (int) strftime('%M', $row['end_time']),
1407
				'last_day' => 0,
1408
			),
1409
			'status' => $row['status'],
1410
			'username' => $row['username'],
1411
		);
1412
		$context['sub']['start']['last_day'] = (int) strftime('%d', mktime(0, 0, 0, $context['sub']['start']['month'] == 12 ? 1 : $context['sub']['start']['month'] + 1, 0, $context['sub']['start']['month'] == 12 ? $context['sub']['start']['year'] + 1 : $context['sub']['start']['year']));
1413
		$context['sub']['end']['last_day'] = (int) strftime('%d', mktime(0, 0, 0, $context['sub']['end']['month'] == 12 ? 1 : $context['sub']['end']['month'] + 1, 0, $context['sub']['end']['month'] == 12 ? $context['sub']['end']['year'] + 1 : $context['sub']['end']['year']));
1414
	}
1415
1416
	loadJavaScriptFile('suggest.js', array('defer' => false, 'minimize' => true), 'smf_suggest');
1417
}
1418
1419
/**
1420
 * Reapplies all subscription rules for each of the users.
1421
 *
1422
 * @param array $users An array of user IDs
1423
 */
1424
function reapplySubscriptions($users)
1425
{
1426
	global $smcFunc;
1427
1428
	// Make it an array.
1429
	if (!is_array($users))
0 ignored issues
show
introduced by
The condition is_array($users) is always true.
Loading history...
1430
		$users = array($users);
1431
1432
	// Get all the members current groups.
1433
	$groups = array();
1434
	$request = $smcFunc['db_query']('', '
1435
		SELECT id_member, id_group, additional_groups
1436
		FROM {db_prefix}members
1437
		WHERE id_member IN ({array_int:user_list})',
1438
		array(
1439
			'user_list' => $users,
1440
		)
1441
	);
1442
	while ($row = $smcFunc['db_fetch_assoc']($request))
1443
	{
1444
		$groups[$row['id_member']] = array(
1445
			'primary' => $row['id_group'],
1446
			'additional' => explode(',', $row['additional_groups']),
1447
		);
1448
	}
1449
	$smcFunc['db_free_result']($request);
1450
1451
	$request = $smcFunc['db_query']('', '
1452
		SELECT ls.id_member, ls.old_id_group, s.id_group, s.add_groups
1453
		FROM {db_prefix}log_subscribed AS ls
1454
			INNER JOIN {db_prefix}subscriptions AS s ON (s.id_subscribe = ls.id_subscribe)
1455
		WHERE ls.id_member IN ({array_int:user_list})
1456
			AND ls.end_time > {int:current_time}',
1457
		array(
1458
			'user_list' => $users,
1459
			'current_time' => time(),
1460
		)
1461
	);
1462
	while ($row = $smcFunc['db_fetch_assoc']($request))
1463
	{
1464
		// Specific primary group?
1465
		if ($row['id_group'] != 0)
1466
		{
1467
			// If this is changing - add the old one to the additional groups so it's not lost.
1468
			if ($row['id_group'] != $groups[$row['id_member']]['primary'])
1469
				$groups[$row['id_member']]['additional'][] = $groups[$row['id_member']]['primary'];
1470
			$groups[$row['id_member']]['primary'] = $row['id_group'];
1471
		}
1472
1473
		// Additional groups.
1474
		if (!empty($row['add_groups']))
1475
			$groups[$row['id_member']]['additional'] = array_merge($groups[$row['id_member']]['additional'], explode(',', $row['add_groups']));
1476
	}
1477
	$smcFunc['db_free_result']($request);
1478
1479
	// Update all the members.
1480
	foreach ($groups as $id => $group)
1481
	{
1482
		$group['additional'] = array_unique($group['additional']);
1483
		foreach ($group['additional'] as $key => $value)
1484
			if (empty($value))
1485
				unset($group['additional'][$key]);
1486
		$addgroups = implode(',', $group['additional']);
1487
1488
		$smcFunc['db_query']('', '
1489
			UPDATE {db_prefix}members
1490
			SET id_group = {int:primary_group}, additional_groups = {string:additional_groups}
1491
			WHERE id_member = {int:current_member}
1492
			LIMIT 1',
1493
			array(
1494
				'primary_group' => $group['primary'],
1495
				'current_member' => $id,
1496
				'additional_groups' => $addgroups,
1497
			)
1498
		);
1499
	}
1500
}
1501
1502
/**
1503
 * Add or extend a subscription of a user.
1504
 *
1505
 * @param int $id_subscribe The subscription ID
1506
 * @param int $id_member The ID of the member
1507
 * @param int|string $renewal 0 if we're forcing start/end time, otherwise a string indicating how long to renew the subscription for ('D', 'W', 'M' or 'Y')
1508
 * @param int $forceStartTime If set, forces the subscription to start at the specified time
1509
 * @param int $forceEndTime If set, forces the subscription to end at the specified time
1510
 */
1511
function addSubscription($id_subscribe, $id_member, $renewal = 0, $forceStartTime = 0, $forceEndTime = 0)
1512
{
1513
	global $context, $smcFunc;
1514
1515
	// Take the easy way out...
1516
	loadSubscriptions();
1517
1518
	// Exists, yes?
1519
	if (!isset($context['subscriptions'][$id_subscribe]))
1520
		return;
1521
1522
	$curSub = $context['subscriptions'][$id_subscribe];
1523
1524
	// Grab the duration.
1525
	$duration = $curSub['num_length'];
1526
1527
	// If this is a renewal change the duration to be correct.
1528
	if (!empty($renewal))
1529
	{
1530
		switch ($renewal)
1531
		{
1532
			case 'D':
1533
				$duration = 86400;
1534
				break;
1535
			case 'W':
1536
				$duration = 604800;
1537
				break;
1538
			case 'M':
1539
				$duration = 2629743;
1540
				break;
1541
			case 'Y':
1542
				$duration = 31556926;
1543
				break;
1544
			default:
1545
				break;
1546
		}
1547
	}
1548
1549
	// Firstly, see whether it exists, and is active. If so then this is meerly an extension.
1550
	$request = $smcFunc['db_query']('', '
1551
		SELECT id_sublog, end_time, start_time
1552
		FROM {db_prefix}log_subscribed
1553
		WHERE id_subscribe = {int:current_subscription}
1554
			AND id_member = {int:current_member}
1555
			AND status = {int:is_active}',
1556
		array(
1557
			'current_subscription' => $id_subscribe,
1558
			'current_member' => $id_member,
1559
			'is_active' => 1,
1560
		)
1561
	);
1562
1563
	if ($smcFunc['db_num_rows']($request) != 0)
1564
	{
1565
		list ($id_sublog, $endtime, $starttime) = $smcFunc['db_fetch_row']($request);
1566
1567
		// If this has already expired but is active, extension means the period from now.
1568
		if ($endtime < time())
1569
			$endtime = time();
1570
		if ($starttime == 0)
1571
			$starttime = time();
1572
1573
		// Work out the new expiry date.
1574
		$endtime += $duration;
1575
1576
		if ($forceEndTime != 0)
1577
			$endtime = $forceEndTime;
1578
1579
		// As everything else should be good, just update!
1580
		$smcFunc['db_query']('', '
1581
			UPDATE {db_prefix}log_subscribed
1582
			SET end_time = {int:end_time}, start_time = {int:start_time}, reminder_sent = {int:no_reminder_sent}
1583
			WHERE id_sublog = {int:current_subscription_item}',
1584
			array(
1585
				'end_time' => $endtime,
1586
				'start_time' => $starttime,
1587
				'current_subscription_item' => $id_sublog,
1588
				'no_reminder_sent' => 0,
1589
			)
1590
		);
1591
1592
		return;
1593
	}
1594
	$smcFunc['db_free_result']($request);
1595
1596
	// If we're here, that means we don't have an active subscription - that means we need to do some work!
1597
	$request = $smcFunc['db_query']('', '
1598
		SELECT m.id_group, m.additional_groups
1599
		FROM {db_prefix}members AS m
1600
		WHERE m.id_member = {int:current_member}',
1601
		array(
1602
			'current_member' => $id_member,
1603
		)
1604
	);
1605
1606
	// Just in case the member doesn't exist.
1607
	if ($smcFunc['db_num_rows']($request) == 0)
1608
		return;
1609
1610
	list ($old_id_group, $additional_groups) = $smcFunc['db_fetch_row']($request);
1611
	$smcFunc['db_free_result']($request);
1612
1613
	// Prepare additional groups.
1614
	$newAddGroups = explode(',', $curSub['add_groups']);
1615
	$curAddGroups = explode(',', $additional_groups);
1616
1617
	$newAddGroups = array_merge($newAddGroups, $curAddGroups);
1618
1619
	// Simple, simple, simple - hopefully... id_group first.
1620
	if ($curSub['prim_group'] != 0)
1621
	{
1622
		$id_group = $curSub['prim_group'];
1623
1624
		// Ensure their old privileges are maintained.
1625
		if ($old_id_group != 0)
1626
			$newAddGroups[] = $old_id_group;
1627
	}
1628
	else
1629
		$id_group = $old_id_group;
1630
1631
	// Yep, make sure it's unique, and no empties.
1632
	foreach ($newAddGroups as $k => $v)
1633
		if (empty($v))
1634
			unset($newAddGroups[$k]);
1635
	$newAddGroups = array_unique($newAddGroups);
1636
	$newAddGroups = implode(',', $newAddGroups);
1637
1638
	// Store the new settings.
1639
	$smcFunc['db_query']('', '
1640
		UPDATE {db_prefix}members
1641
		SET id_group = {int:primary_group}, additional_groups = {string:additional_groups}
1642
		WHERE id_member = {int:current_member}',
1643
		array(
1644
			'primary_group' => $id_group,
1645
			'current_member' => $id_member,
1646
			'additional_groups' => $newAddGroups,
1647
		)
1648
	);
1649
1650
	// Now log the subscription - maybe we have a dorment subscription we can restore?
1651
	$request = $smcFunc['db_query']('', '
1652
		SELECT id_sublog, end_time, start_time
1653
		FROM {db_prefix}log_subscribed
1654
		WHERE id_subscribe = {int:current_subscription}
1655
			AND id_member = {int:current_member}',
1656
		array(
1657
			'current_subscription' => $id_subscribe,
1658
			'current_member' => $id_member,
1659
		)
1660
	);
1661
1662
	/**
1663
	 * @todo Don't really need to do this twice...
1664
	 */
1665
	if ($smcFunc['db_num_rows']($request) != 0)
1666
	{
1667
		list ($id_sublog, $endtime, $starttime) = $smcFunc['db_fetch_row']($request);
1668
1669
		// If this has already expired but is active, extension means the period from now.
1670
		if ($endtime < time())
1671
			$endtime = time();
1672
		if ($starttime == 0)
1673
			$starttime = time();
1674
1675
		// Work out the new expiry date.
1676
		$endtime += $duration;
1677
1678
		if ($forceEndTime != 0)
1679
			$endtime = $forceEndTime;
1680
1681
		// As everything else should be good, just update!
1682
		$smcFunc['db_query']('', '
1683
			UPDATE {db_prefix}log_subscribed
1684
			SET start_time = {int:start_time}, end_time = {int:end_time}, old_id_group = {int:old_id_group}, status = {int:is_active}, reminder_sent = {int:no_reminder_sent}
1685
			WHERE id_sublog = {int:current_subscription_item}',
1686
			array(
1687
				'start_time' => $starttime,
1688
				'end_time' => $endtime,
1689
				'old_id_group' => $old_id_group,
1690
				'is_active' => 1,
1691
				'no_reminder_sent' => 0,
1692
				'current_subscription_item' => $id_sublog,
1693
			)
1694
		);
1695
1696
		return;
1697
	}
1698
	$smcFunc['db_free_result']($request);
1699
1700
	// Otherwise a very simple insert.
1701
	$endtime = time() + $duration;
1702
	if ($forceEndTime != 0)
1703
		$endtime = $forceEndTime;
1704
1705
	if ($forceStartTime == 0)
1706
		$starttime = time();
1707
	else
1708
		$starttime = $forceStartTime;
1709
1710
	$smcFunc['db_insert']('',
1711
		'{db_prefix}log_subscribed',
1712
		array(
1713
			'id_subscribe' => 'int', 'id_member' => 'int', 'old_id_group' => 'int', 'start_time' => 'int',
1714
			'end_time' => 'int', 'status' => 'int', 'pending_details' => 'string',
1715
		),
1716
		array(
1717
			$id_subscribe, $id_member, $old_id_group, $starttime,
1718
			$endtime, 1, '',
1719
		),
1720
		array('id_sublog')
1721
	);
1722
}
1723
1724
/**
1725
 * Removes a subscription from a user, as in removes the groups.
1726
 *
1727
 * @param int $id_subscribe The ID of the subscription
1728
 * @param int $id_member The ID of the member
1729
 * @param bool $delete Whether to delete the subscription or just disable it
1730
 */
1731
function removeSubscription($id_subscribe, $id_member, $delete = false)
1732
{
1733
	global $context, $smcFunc;
1734
1735
	loadSubscriptions();
1736
1737
	// Load the user core bits.
1738
	$request = $smcFunc['db_query']('', '
1739
		SELECT m.id_group, m.additional_groups
1740
		FROM {db_prefix}members AS m
1741
		WHERE m.id_member = {int:current_member}',
1742
		array(
1743
			'current_member' => $id_member,
1744
		)
1745
	);
1746
1747
	// Just in case of errors.
1748
	if ($smcFunc['db_num_rows']($request) == 0)
1749
	{
1750
		$smcFunc['db_query']('', '
1751
			DELETE FROM {db_prefix}log_subscribed
1752
			WHERE id_member = {int:current_member}',
1753
			array(
1754
				'current_member' => $id_member,
1755
			)
1756
		);
1757
		return;
1758
	}
1759
	list ($id_group, $additional_groups) = $smcFunc['db_fetch_row']($request);
1760
	$smcFunc['db_free_result']($request);
1761
1762
	// Get all of the subscriptions for this user that are active - it will be necessary!
1763
	$request = $smcFunc['db_query']('', '
1764
		SELECT id_subscribe, old_id_group
1765
		FROM {db_prefix}log_subscribed
1766
		WHERE id_member = {int:current_member}
1767
			AND status = {int:is_active}',
1768
		array(
1769
			'current_member' => $id_member,
1770
			'is_active' => 1,
1771
		)
1772
	);
1773
1774
	// These variables will be handy, honest ;)
1775
	$removals = array();
1776
	$allowed = array();
1777
	$old_id_group = 0;
1778
	$new_id_group = -1;
1779
	while ($row = $smcFunc['db_fetch_assoc']($request))
1780
	{
1781
		if (!isset($context['subscriptions'][$row['id_subscribe']]))
1782
			continue;
1783
1784
		// The one we're removing?
1785
		if ($row['id_subscribe'] == $id_subscribe)
1786
		{
1787
			$removals = explode(',', $context['subscriptions'][$row['id_subscribe']]['add_groups']);
1788
			if ($context['subscriptions'][$row['id_subscribe']]['prim_group'] != 0)
1789
				$removals[] = $context['subscriptions'][$row['id_subscribe']]['prim_group'];
1790
			$old_id_group = $row['old_id_group'];
1791
		}
1792
		// Otherwise things we allow.
1793
		else
1794
		{
1795
			$allowed = array_merge($allowed, explode(',', $context['subscriptions'][$row['id_subscribe']]['add_groups']));
1796
			if ($context['subscriptions'][$row['id_subscribe']]['prim_group'] != 0)
1797
			{
1798
				$allowed[] = $context['subscriptions'][$row['id_subscribe']]['prim_group'];
1799
				$new_id_group = $context['subscriptions'][$row['id_subscribe']]['prim_group'];
1800
			}
1801
		}
1802
	}
1803
	$smcFunc['db_free_result']($request);
1804
1805
	// Now, for everything we are removing check they definitely are not allowed it.
1806
	$existingGroups = explode(',', $additional_groups);
1807
	foreach ($existingGroups as $key => $group)
1808
		if (empty($group) || (in_array($group, $removals) && !in_array($group, $allowed)))
1809
			unset($existingGroups[$key]);
1810
1811
	// Finally, do something with the current primary group.
1812
	if (in_array($id_group, $removals))
1813
	{
1814
		// If this primary group is actually allowed keep it.
1815
		if (in_array($id_group, $allowed))
1816
			$existingGroups[] = $id_group;
1817
1818
		// Either way, change the id_group back.
1819
		if ($new_id_group < 1)
1820
		{
1821
			// If we revert to the old id-group we need to ensure it wasn't from a subscription.
1822
			foreach ($context['subscriptions'] as $id => $group)
1823
				// It was? Make them a regular member then!
1824
				if ($group['prim_group'] == $old_id_group)
1825
					$old_id_group = 0;
1826
1827
			$id_group = $old_id_group;
1828
		}
1829
		else
1830
			$id_group = $new_id_group;
1831
	}
1832
1833
	// Crazy stuff, we seem to have our groups fixed, just make them unique
1834
	$existingGroups = array_unique($existingGroups);
1835
	$existingGroups = implode(',', $existingGroups);
1836
1837
	// Update the member
1838
	$smcFunc['db_query']('', '
1839
		UPDATE {db_prefix}members
1840
		SET id_group = {int:primary_group}, additional_groups = {string:existing_groups}
1841
		WHERE id_member = {int:current_member}',
1842
		array(
1843
			'primary_group' => $id_group,
1844
			'current_member' => $id_member,
1845
			'existing_groups' => $existingGroups,
1846
		)
1847
	);
1848
1849
	// Disable the subscription.
1850
	if (!$delete)
1851
		$smcFunc['db_query']('', '
1852
			UPDATE {db_prefix}log_subscribed
1853
			SET status = {int:not_active}
1854
			WHERE id_member = {int:current_member}
1855
				AND id_subscribe = {int:current_subscription}',
1856
			array(
1857
				'not_active' => 0,
1858
				'current_member' => $id_member,
1859
				'current_subscription' => $id_subscribe,
1860
			)
1861
		);
1862
	// Otherwise delete it!
1863
	else
1864
		$smcFunc['db_query']('', '
1865
			DELETE FROM {db_prefix}log_subscribed
1866
			WHERE id_member = {int:current_member}
1867
				AND id_subscribe = {int:current_subscription}',
1868
			array(
1869
				'current_member' => $id_member,
1870
				'current_subscription' => $id_subscribe,
1871
			)
1872
		);
1873
}
1874
1875
/**
1876
 * This just kind of caches all the subscription data.
1877
 */
1878
function loadSubscriptions()
1879
{
1880
	global $context, $txt, $modSettings, $smcFunc;
1881
1882
	if (!empty($context['subscriptions']))
1883
		return;
1884
1885
	// Make sure this is loaded, just in case.
1886
	loadLanguage('ManagePaid');
1887
1888
	$request = $smcFunc['db_query']('', '
1889
		SELECT id_subscribe, name, description, cost, length, id_group, add_groups, active, repeatable
1890
		FROM {db_prefix}subscriptions',
1891
		array(
1892
		)
1893
	);
1894
	$context['subscriptions'] = array();
1895
	while ($row = $smcFunc['db_fetch_assoc']($request))
1896
	{
1897
		// Pick a cost.
1898
		$costs = $smcFunc['json_decode']($row['cost'], true);
1899
1900
		if ($row['length'] != 'F' && !empty($modSettings['paid_currency_symbol']) && !empty($costs['fixed']))
1901
			$cost = sprintf($modSettings['paid_currency_symbol'], $costs['fixed']);
1902
		else
1903
			$cost = '???';
1904
1905
		// Do the span.
1906
		preg_match('~(\d*)(\w)~', $row['length'], $match);
1907
		if (isset($match[2]))
1908
		{
1909
			$num_length = $match[1];
1910
			$length = $match[1] . ' ';
1911
			switch ($match[2])
1912
			{
1913
				case 'D':
1914
					$length .= $txt['paid_mod_span_days'];
1915
					$num_length *= 86400;
1916
					break;
1917
				case 'W':
1918
					$length .= $txt['paid_mod_span_weeks'];
1919
					$num_length *= 604800;
1920
					break;
1921
				case 'M':
1922
					$length .= $txt['paid_mod_span_months'];
1923
					$num_length *= 2629743;
1924
					break;
1925
				case 'Y':
1926
					$length .= $txt['paid_mod_span_years'];
1927
					$num_length *= 31556926;
1928
					break;
1929
			}
1930
		}
1931
		else
1932
			$length = '??';
1933
1934
		$context['subscriptions'][$row['id_subscribe']] = array(
1935
			'id' => $row['id_subscribe'],
1936
			'name' => $row['name'],
1937
			'desc' => $row['description'],
1938
			'cost' => $cost,
1939
			'real_cost' => $row['cost'],
1940
			'length' => $length,
1941
			'num_length' => $num_length,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $num_length does not seem to be defined for all execution paths leading up to this point.
Loading history...
1942
			'real_length' => $row['length'],
1943
			'pending' => 0,
1944
			'finished' => 0,
1945
			'total' => 0,
1946
			'active' => $row['active'],
1947
			'prim_group' => $row['id_group'],
1948
			'add_groups' => $row['add_groups'],
1949
			'flexible' => $row['length'] == 'F' ? true : false,
1950
			'repeatable' => $row['repeatable'],
1951
		);
1952
	}
1953
	$smcFunc['db_free_result']($request);
1954
1955
	// Do the counts.
1956
	$request = $smcFunc['db_query']('', '
1957
		SELECT COUNT(id_sublog) AS member_count, id_subscribe, status
1958
		FROM {db_prefix}log_subscribed
1959
		GROUP BY id_subscribe, status',
1960
		array(
1961
		)
1962
	);
1963
	while ($row = $smcFunc['db_fetch_assoc']($request))
1964
	{
1965
		$ind = $row['status'] == 0 ? 'finished' : 'total';
1966
1967
		if (isset($context['subscriptions'][$row['id_subscribe']]))
1968
			$context['subscriptions'][$row['id_subscribe']][$ind] = $row['member_count'];
1969
	}
1970
	$smcFunc['db_free_result']($request);
1971
1972
	// How many payments are we waiting on?
1973
	$request = $smcFunc['db_query']('', '
1974
		SELECT SUM(payments_pending) AS total_pending, id_subscribe
1975
		FROM {db_prefix}log_subscribed
1976
		GROUP BY id_subscribe',
1977
		array(
1978
		)
1979
	);
1980
	while ($row = $smcFunc['db_fetch_assoc']($request))
1981
	{
1982
		if (isset($context['subscriptions'][$row['id_subscribe']]))
1983
			$context['subscriptions'][$row['id_subscribe']]['pending'] = $row['total_pending'];
1984
	}
1985
	$smcFunc['db_free_result']($request);
1986
}
1987
1988
/**
1989
 * Load all the payment gateways.
1990
 * Checks the Sources directory for any files fitting the format of a payment gateway,
1991
 * loads each file to check it's valid, includes each file and returns the
1992
 * function name and whether it should work with this version of SMF.
1993
 *
1994
 * @return array An array of information about available payment gateways
1995
 */
1996
function loadPaymentGateways()
1997
{
1998
	global $sourcedir;
1999
2000
	$gateways = array();
2001
	if ($dh = opendir($sourcedir))
2002
	{
2003
		while (($file = readdir($dh)) !== false)
2004
		{
2005
			if (is_file($sourcedir . '/' . $file) && preg_match('~^Subscriptions-([A-Za-z\d]+)\.php$~', $file, $matches))
2006
			{
2007
				// Check this is definitely a valid gateway!
2008
				$fp = fopen($sourcedir . '/' . $file, 'rb');
2009
				$header = fread($fp, 4096);
0 ignored issues
show
Bug introduced by
It seems like $fp can also be of type false; however, parameter $handle of fread() does only seem to accept resource, 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

2009
				$header = fread(/** @scrutinizer ignore-type */ $fp, 4096);
Loading history...
2010
				fclose($fp);
0 ignored issues
show
Bug introduced by
It seems like $fp can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, 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

2010
				fclose(/** @scrutinizer ignore-type */ $fp);
Loading history...
2011
2012
				if (strpos($header, '// SMF Payment Gateway: ' . strtolower($matches[1])) !== false)
2013
				{
2014
					require_once($sourcedir . '/' . $file);
2015
2016
					$gateways[] = array(
2017
						'filename' => $file,
2018
						'code' => strtolower($matches[1]),
2019
						// Don't need anything snazzier than this yet.
2020
						'valid_version' => class_exists(strtolower($matches[1]) . '_payment') && class_exists(strtolower($matches[1]) . '_display'),
2021
						'payment_class' => strtolower($matches[1]) . '_payment',
2022
						'display_class' => strtolower($matches[1]) . '_display',
2023
					);
2024
				}
2025
			}
2026
		}
2027
	}
2028
	closedir($dh);
0 ignored issues
show
Bug introduced by
It seems like $dh can also be of type false; however, parameter $dir_handle of closedir() does only seem to accept resource, 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

2028
	closedir(/** @scrutinizer ignore-type */ $dh);
Loading history...
2029
2030
	return $gateways;
2031
}
2032
2033
?>