ModifyUserSubscription()   F
last analyzed

Complexity

Conditions 55
Paths > 20000

Size

Total Lines 330
Code Lines 170

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 55
eloc 170
nc 26160
nop 0
dl 0
loc 330
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 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 https://www.simplemachines.org
11
 * @copyright 2022 Simple Machines and individual contributors
12
 * @license https://www.simplemachines.org/about/smf/license.php BSD
13
 *
14
 * @version 2.1.0
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, $boardurl;
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'] = sprintf($txt['paid_note'], $boardurl);
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
		addInlineJavaScript('
207
		toggleOther();', true);
208
	}
209
	else
210
	{
211
		$config_vars = array(
212
			array('check', 'paid_enabled'),
213
		);
214
		$context['settings_title'] = $txt['paid_subscriptions'];
215
	}
216
217
	// Just searching?
218
	if ($return_config)
219
		return $config_vars;
220
221
	// Get the settings template fired up.
222
	require_once($sourcedir . '/ManageServer.php');
223
224
	// Some important context stuff
225
	$context['page_title'] = $txt['settings'];
226
	$context['sub_template'] = 'show_settings';
227
228
	// Get the final touches in place.
229
	$context['post_url'] = $scripturl . '?action=admin;area=paidsubscribe;save;sa=settings';
230
231
	// Saving the settings?
232
	if (isset($_GET['save']))
233
	{
234
		checkSession();
235
236
		$old = !empty($modSettings['paid_enabled']);
237
		$new = !empty($_POST['paid_enabled']);
238
		if ($old != $new)
239
		{
240
			// So we're changing this fundamental status. Great.
241
			$smcFunc['db_query']('', '
242
				UPDATE {db_prefix}scheduled_tasks
243
				SET disabled = {int:disabled}
244
				WHERE task = {string:task}',
245
				array(
246
					'disabled' => $new ? 0 : 1,
247
					'task' => 'paid_subscriptions',
248
				)
249
			);
250
251
			// This may well affect the next trigger, whether we're enabling or not.
252
			require_once($sourcedir . '/ScheduledTasks.php');
253
			CalculateNextTrigger('paid_subscriptions');
254
		}
255
256
		// Check the email addresses were actually email addresses.
257
		if (!empty($_POST['paid_email_to']))
258
		{
259
			$email_addresses = array();
260
			foreach (explode(',', $_POST['paid_email_to']) as $email)
261
			{
262
				$email = trim($email);
263
				if (!empty($email) && filter_var($email, FILTER_VALIDATE_EMAIL))
264
					$email_addresses[] = $email;
265
				$_POST['paid_email_to'] = implode(',', $email_addresses);
266
			}
267
		}
268
269
		// Can only handle this stuff if it's already enabled...
270
		if (!empty($modSettings['paid_enabled']))
271
		{
272
			// Sort out the currency stuff.
273
			if ($_POST['paid_currency'] != 'other')
274
			{
275
				$_POST['paid_currency_code'] = $_POST['paid_currency'];
276
				$_POST['paid_currency_symbol'] = $txt[$_POST['paid_currency'] . '_symbol'];
277
			}
278
			unset($config_vars['dummy_currency']);
279
		}
280
281
		saveDBSettings($config_vars);
282
		$_SESSION['adm-save'] = true;
283
284
		redirectexit('action=admin;area=paidsubscribe;sa=settings');
285
	}
286
287
	// Prepare the settings...
288
	prepareDBSettingContext($config_vars);
289
}
290
291
/**
292
 * View a list of all the current subscriptions
293
 * Requires the admin_forum permission.
294
 * Accessed from ?action=admin;area=paidsubscribe;sa=view.
295
 */
296
function ViewSubscriptions()
297
{
298
	global $context, $txt, $modSettings, $sourcedir, $scripturl;
299
300
	// Not made the settings yet?
301
	if (empty($modSettings['paid_currency_symbol']))
302
		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

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