Failed Conditions
Branch release-2.1 (4e22cf)
by Rick
06:39
created

ManageScheduledTasks.php ➔ EditTask()   F

Complexity

Conditions 17
Paths 1188

Size

Total Lines 102
Code Lines 52

Duplication

Lines 4
Ratio 3.92 %

Importance

Changes 0
Metric Value
cc 17
eloc 52
nc 1188
nop 0
dl 4
loc 102
rs 2
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 concerns itself with scheduled tasks management.
5
 *
6
 * Simple Machines Forum (SMF)
7
 *
8
 * @package SMF
9
 * @author Simple Machines http://www.simplemachines.org
10
 * @copyright 2017 Simple Machines and individual contributors
11
 * @license http://www.simplemachines.org/about/smf/license.php BSD
12
 *
13
 * @version 2.1 Beta 4
14
 */
15
16
if (!defined('SMF'))
17
	die('No direct access...');
18
19
/**
20
 * Scheduled tasks management dispatcher. This function checks permissions and delegates
21
 * to the appropriate function based on the sub-action.
22
 * Everything here requires admin_forum permission.
23
 *
24
 * @uses ManageScheduledTasks template file
25
 * @uses ManageScheduledTasks language file
26
 */
27
function ManageScheduledTasks()
28
{
29
	global $context, $txt;
30
31
	isAllowedTo('admin_forum');
32
33
	loadLanguage('ManageScheduledTasks');
34
	loadTemplate('ManageScheduledTasks');
35
36
	$subActions = array(
37
		'taskedit' => 'EditTask',
38
		'tasklog' => 'TaskLog',
39
		'tasks' => 'ScheduledTasks',
40
	);
41
42
	// We need to find what's the action.
43
	if (isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]))
44
		$context['sub_action'] = $_REQUEST['sa'];
45
	else
46
		$context['sub_action'] = 'tasks';
47
48
	// Now for the lovely tabs. That we all love.
49
	$context[$context['admin_menu_name']]['tab_data'] = array(
50
		'title' => $txt['scheduled_tasks_title'],
51
		'help' => '',
52
		'description' => $txt['maintain_info'],
53
		'tabs' => array(
54
			'tasks' => array(
55
				'description' => $txt['maintain_tasks_desc'],
56
			),
57
			'tasklog' => array(
58
				'description' => $txt['scheduled_log_desc'],
59
			),
60
		),
61
	);
62
63
	call_integration_hook('integrate_manage_scheduled_tasks', array(&$subActions));
64
65
	// Call it.
66
	call_helper($subActions[$context['sub_action']]);
67
}
68
69
/**
70
 * List all the scheduled task in place on the forum.
71
 *
72
 * @uses ManageScheduledTasks template, view_scheduled_tasks sub-template
73
 */
74
function ScheduledTasks()
75
{
76
	global $context, $txt, $sourcedir, $smcFunc, $scripturl;
77
78
	// Mama, setup the template first - cause it's like the most important bit, like pickle in a sandwich.
79
	// ... ironically I don't like pickle. </grudge>
80
	$context['sub_template'] = 'view_scheduled_tasks';
81
	$context['page_title'] = $txt['maintain_tasks'];
82
83
	// Saving changes?
84
	if (isset($_REQUEST['save']) && isset($_POST['enable_task']))
85
	{
86
		checkSession();
87
88
		// We'll recalculate the dates at the end!
89
		require_once($sourcedir . '/ScheduledTasks.php');
90
91
		// Enable and disable as required.
92
		$enablers = array(0);
93
		foreach ($_POST['enable_task'] as $id => $enabled)
94
			if ($enabled)
95
				$enablers[] = (int) $id;
96
97
		// Do the update!
98
		$smcFunc['db_query']('', '
99
			UPDATE {db_prefix}scheduled_tasks
100
			SET disabled = CASE WHEN id_task IN ({array_int:id_task_enable}) THEN 0 ELSE 1 END',
101
			array(
102
				'id_task_enable' => $enablers,
103
			)
104
		);
105
106
		// Update the "allow_expire_redirect" setting...
107
		$get_info = $smcFunc['db_query']('', '
108
			SELECT disabled
109
			FROM {db_prefix}scheduled_tasks
110
			WHERE task = {string:remove_redirect}',
111
			array(
112
				'remove_redirect' => 'remove_topic_redirect'
113
			)
114
		);
115
116
		$temp = $smcFunc['db_fetch_assoc']($get_info);
117
		$task_disabled = !empty($temp['disabled']) ? 0 : 1;
118
		$smcFunc['db_free_result']($get_info);
119
120
		updateSettings(array('allow_expire_redirect' => $task_disabled));
121
122
		// Pop along...
123
		CalculateNextTrigger();
124
	}
125
126
	// Want to run any of the tasks?
127
	if (isset($_REQUEST['run']) && isset($_POST['run_task']))
128
	{
129
		$task_string = '';
130
131
		// Lets figure out which ones they want to run.
132
		$tasks = array();
133
		foreach ($_POST['run_task'] as $task => $dummy)
134
			$tasks[] = (int) $task;
135
136
		// Load up the tasks.
137
		$request = $smcFunc['db_query']('', '
138
			SELECT id_task, task, callable
139
			FROM {db_prefix}scheduled_tasks
140
			WHERE id_task IN ({array_int:tasks})
141
			LIMIT {int:limit}',
142
			array(
143
				'tasks' => $tasks,
144
				'limit' => count($tasks),
145
			)
146
		);
147
148
		// Lets get it on!
149
		require_once($sourcedir . '/ScheduledTasks.php');
150
		ignore_user_abort(true);
151
		while ($row = $smcFunc['db_fetch_assoc']($request))
152
		{
153
			// What kind of task are we handling?
154 View Code Duplication
			if (!empty($row['callable']))
155
				$task_string = $row['callable'];
156
157
			// Default SMF task or old mods?
158
			elseif (function_exists('scheduled_' . $row['task']))
159
				$task_string = 'scheduled_' . $row['task'];
160
161
			// One last resource, the task name.
162
			elseif (!empty($row['task']))
163
				$task_string = $row['task'];
164
165
			$start_time = microtime();
166
			// The functions got to exist for us to use it.
167
			if (empty($task_string))
168
				continue;
169
170
			// Try to stop a timeout, this would be bad...
171
			@set_time_limit(300);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
172
			if (function_exists('apache_reset_timeout'))
173
				@apache_reset_timeout();
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
174
175
			// Get the callable.
176
			$callable_task = call_helper($task_string, true);
177
178
			// Perform the task.
179
			if (!empty($callable_task))
180
				$completed = call_user_func($callable_task);
181
182
			else
183
				$completed = false;
184
185
			// Log that we did it ;)
186 View Code Duplication
			if ($completed)
187
			{
188
				$total_time = round(array_sum(explode(' ', microtime())) - array_sum(explode(' ', $start_time)), 3);
189
				$smcFunc['db_insert']('',
190
					'{db_prefix}log_scheduled_tasks',
191
					array('id_task' => 'int', 'time_run' => 'int', 'time_taken' => 'float'),
192
					array($row['id_task'], time(), $total_time),
193
					array('id_task')
194
				);
195
			}
196
		}
197
		$smcFunc['db_free_result']($request);
198
199
		// If we had any errors, push them to session so we can pick them up next time to tell the user.
200
		if (!empty($context['scheduled_errors']))
201
			$_SESSION['st_error'] = $context['scheduled_errors'];
202
203
		redirectexit('action=admin;area=scheduledtasks;done');
204
	}
205
206
	if (isset($_SESSION['st_error']))
207
	{
208
		$context['scheduled_errors'] = $_SESSION['st_error'];
209
		unset ($_SESSION['st_error']);
210
	}
211
212
	$listOptions = array(
213
		'id' => 'scheduled_tasks',
214
		'title' => $txt['maintain_tasks'],
215
		'base_href' => $scripturl . '?action=admin;area=scheduledtasks',
216
		'get_items' => array(
217
			'function' => 'list_getScheduledTasks',
218
		),
219
		'columns' => array(
220
			'name' => array(
221
				'header' => array(
222
					'value' => $txt['scheduled_tasks_name'],
223
					'style' => 'width: 40%;',
224
				),
225
				'data' => array(
226
					'sprintf' => array(
227
						'format' => '
228
							<a href="' . $scripturl . '?action=admin;area=scheduledtasks;sa=taskedit;tid=%1$d">%2$s</a><br><span class="smalltext">%3$s</span>',
229
						'params' => array(
230
							'id' => false,
231
							'name' => false,
232
							'desc' => false,
233
						),
234
					),
235
				),
236
			),
237
			'next_due' => array(
238
				'header' => array(
239
					'value' => $txt['scheduled_tasks_next_time'],
240
				),
241
				'data' => array(
242
					'db' => 'next_time',
243
					'class' => 'smalltext',
244
				),
245
			),
246
			'regularity' => array(
247
				'header' => array(
248
					'value' => $txt['scheduled_tasks_regularity'],
249
				),
250
				'data' => array(
251
					'db' => 'regularity',
252
					'class' => 'smalltext',
253
				),
254
			),
255
			'run_now' => array(
256
				'header' => array(
257
					'value' => $txt['scheduled_tasks_run_now'],
258
					'style' => 'width: 12%;',
259
					'class' => 'centercol',
260
				),
261
				'data' => array(
262
					'sprintf' => array(
263
						'format' =>
264
							'<input type="checkbox" name="run_task[%1$d]" id="run_task_%1$d" class="input_check">',
265
						'params' => array(
266
							'id' => false,
267
						),
268
					),
269
					'class' => 'centercol',
270
				),
271
			),
272
			'enabled' => array(
273
				'header' => array(
274
					'value' => $txt['scheduled_tasks_enabled'],
275
					'style' => 'width: 6%;',
276
					'class' => 'centercol',
277
				),
278
				'data' => array(
279
					'sprintf' => array(
280
						'format' =>
281
							'<input type="hidden" name="enable_task[%1$d]" id="task_%1$d" value="0"><input type="checkbox" name="enable_task[%1$d]" id="task_check_%1$d" %2$s class="input_check">',
282
						'params' => array(
283
							'id' => false,
284
							'checked_state' => false,
285
						),
286
					),
287
					'class' => 'centercol',
288
				),
289
			),
290
		),
291
		'form' => array(
292
			'href' => $scripturl . '?action=admin;area=scheduledtasks',
293
		),
294
		'additional_rows' => array(
295
			array(
296
				'position' => 'below_table_data',
297
				'value' => '
298
					<input type="submit" name="save" value="' . $txt['scheduled_tasks_save_changes'] . '" class="button_submit">
299
					<input type="submit" name="run" value="' . $txt['scheduled_tasks_run_now'] . '" class="button_submit">',
300
			),
301
			array(
302
				'position' => 'after_title',
303
				'value' => $txt['scheduled_tasks_time_offset'],
304
			),
305
		),
306
	);
307
308
	require_once($sourcedir . '/Subs-List.php');
309
	createList($listOptions);
310
311
	$context['sub_template'] = 'view_scheduled_tasks';
312
313
	$context['tasks_were_run'] = isset($_GET['done']);
314
}
315
316
/**
317
 * Callback function for createList() in ScheduledTasks().
318
 *
319
 * @param int $start The item to start with (not used here)
320
 * @param int $items_per_page The number of items to display per page (not used here)
321
 * @param string $sort A string indicating how to sort things (not used here)
322
 * @return array An array of information about available scheduled tasks
323
 */
324
function list_getScheduledTasks($start, $items_per_page, $sort)
0 ignored issues
show
Unused Code introduced by
The parameter $start is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $items_per_page is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $sort is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
325
{
326
	global $smcFunc, $txt;
327
328
	$request = $smcFunc['db_query']('', '
329
		SELECT id_task, next_time, time_offset, time_regularity, time_unit, disabled, task
330
		FROM {db_prefix}scheduled_tasks',
331
		array(
332
		)
333
	);
334
	$known_tasks = array();
335
	while ($row = $smcFunc['db_fetch_assoc']($request))
336
	{
337
		// Find the next for regularity - don't offset as it's always server time!
338
		$offset = sprintf($txt['scheduled_task_reg_starting'], date('H:i', $row['time_offset']));
339
		$repeating = sprintf($txt['scheduled_task_reg_repeating'], $row['time_regularity'], $txt['scheduled_task_reg_unit_' . $row['time_unit']]);
340
341
		$known_tasks[] = array(
342
			'id' => $row['id_task'],
343
			'function' => $row['task'],
344
			'name' => isset($txt['scheduled_task_' . $row['task']]) ? $txt['scheduled_task_' . $row['task']] : $row['task'],
345
			'desc' => isset($txt['scheduled_task_desc_' . $row['task']]) ? $txt['scheduled_task_desc_' . $row['task']] : '',
346
			'next_time' => $row['disabled'] ? $txt['scheduled_tasks_na'] : timeformat(($row['next_time'] == 0 ? time() : $row['next_time']), true, 'server'),
347
			'disabled' => $row['disabled'],
348
			'checked_state' => $row['disabled'] ? '' : 'checked',
349
			'regularity' => $offset . ', ' . $repeating,
350
		);
351
	}
352
	$smcFunc['db_free_result']($request);
353
354
	return $known_tasks;
355
}
356
357
/**
358
 * Function for editing a task.
359
 *
360
 * @uses ManageScheduledTasks template, edit_scheduled_tasks sub-template
361
 */
362
function EditTask()
363
{
364
	global $context, $txt, $sourcedir, $smcFunc;
365
366
	// Just set up some lovely context stuff.
367
	$context[$context['admin_menu_name']]['current_subsection'] = 'tasks';
368
	$context['sub_template'] = 'edit_scheduled_tasks';
369
	$context['page_title'] = $txt['scheduled_task_edit'];
370
	$context['server_time'] = timeformat(time(), false, 'server');
371
372
	// Cleaning...
373
	if (!isset($_GET['tid']))
374
		fatal_lang_error('no_access', false);
375
	$_GET['tid'] = (int) $_GET['tid'];
376
377
	// Saving?
378
	if (isset($_GET['save']))
379
	{
380
		checkSession();
381
		validateToken('admin-st');
382
383
		// We'll need this for calculating the next event.
384
		require_once($sourcedir . '/ScheduledTasks.php');
385
386
		// Do we have a valid offset?
387
		preg_match('~(\d{1,2}):(\d{1,2})~', $_POST['offset'], $matches);
388
389
		// If a half is empty then assume zero offset!
390 View Code Duplication
		if (!isset($matches[2]) || $matches[2] > 59)
391
			$matches[2] = 0;
392 View Code Duplication
		if (!isset($matches[1]) || $matches[1] > 23)
393
			$matches[1] = 0;
394
395
		// Now the offset is easy; easy peasy - except we need to offset by a few hours...
396
		$offset = $matches[1] * 3600 + $matches[2] * 60 - date('Z');
397
398
		// The other time bits are simple!
399
		$interval = max((int) $_POST['regularity'], 1);
400
		$unit = in_array(substr($_POST['unit'], 0, 1), array('m', 'h', 'd', 'w')) ? substr($_POST['unit'], 0, 1) : 'd';
401
402
		// Don't allow one minute intervals.
403
		if ($interval == 1 && $unit == 'm')
404
			$interval = 2;
405
406
		// Is it disabled?
407
		$disabled = !isset($_POST['enabled']) ? 1 : 0;
408
409
		// Do the update!
410
		$smcFunc['db_query']('', '
411
			UPDATE {db_prefix}scheduled_tasks
412
			SET disabled = {int:disabled}, time_offset = {int:time_offset}, time_unit = {string:time_unit},
413
				time_regularity = {int:time_regularity}
414
			WHERE id_task = {int:id_task}',
415
			array(
416
				'disabled' => $disabled,
417
				'time_offset' => $offset,
418
				'time_regularity' => $interval,
419
				'id_task' => $_GET['tid'],
420
				'time_unit' => $unit,
421
			)
422
		);
423
424
		// Check the next event.
425
		CalculateNextTrigger($_GET['tid'], true);
426
427
		// Return to the main list.
428
		redirectexit('action=admin;area=scheduledtasks');
429
	}
430
431
	// Load the task, understand? Que? Que?
432
	$request = $smcFunc['db_query']('', '
433
		SELECT id_task, next_time, time_offset, time_regularity, time_unit, disabled, task
434
		FROM {db_prefix}scheduled_tasks
435
		WHERE id_task = {int:id_task}',
436
		array(
437
			'id_task' => $_GET['tid'],
438
		)
439
	);
440
441
	// Should never, ever, happen!
442
	if ($smcFunc['db_num_rows']($request) == 0)
443
		fatal_lang_error('no_access', false);
444
445
	while ($row = $smcFunc['db_fetch_assoc']($request))
446
	{
447
		$context['task'] = array(
448
			'id' => $row['id_task'],
449
			'function' => $row['task'],
450
			'name' => isset($txt['scheduled_task_' . $row['task']]) ? $txt['scheduled_task_' . $row['task']] : $row['task'],
451
			'desc' => isset($txt['scheduled_task_desc_' . $row['task']]) ? $txt['scheduled_task_desc_' . $row['task']] : '',
452
			'next_time' => $row['disabled'] ? $txt['scheduled_tasks_na'] : timeformat($row['next_time'] == 0 ? time() : $row['next_time'], true, 'server'),
453
			'disabled' => $row['disabled'],
454
			'offset' => $row['time_offset'],
455
			'regularity' => $row['time_regularity'],
456
			'offset_formatted' => date('H:i', $row['time_offset']),
457
			'unit' => $row['time_unit'],
458
		);
459
	}
460
	$smcFunc['db_free_result']($request);
461
462
	createToken('admin-st');
463
}
464
465
/**
466
 * Show the log of all tasks that have taken place.
467
 *
468
 * @uses ManageScheduledTasks language file
469
 */
470
function TaskLog()
471
{
472
	global $scripturl, $context, $txt, $smcFunc, $sourcedir;
473
474
	// Lets load the language just incase we are outside the Scheduled area.
475
	loadLanguage('ManageScheduledTasks');
476
477
	// Empty the log?
478
	if (!empty($_POST['removeAll']))
479
	{
480
		checkSession();
481
		validateToken('admin-tl');
482
483
		$smcFunc['db_query']('truncate_table', '
484
			TRUNCATE {db_prefix}log_scheduled_tasks',
485
			array(
486
			)
487
		);
488
	}
489
490
	// Setup the list.
491
	$listOptions = array(
492
		'id' => 'task_log',
493
		'items_per_page' => 30,
494
		'title' => $txt['scheduled_log'],
495
		'no_items_label' => $txt['scheduled_log_empty'],
496
		'base_href' => $context['admin_area'] == 'scheduledtasks' ? $scripturl . '?action=admin;area=scheduledtasks;sa=tasklog' : $scripturl . '?action=admin;area=logs;sa=tasklog',
497
		'default_sort_col' => 'date',
498
		'get_items' => array(
499
			'function' => 'list_getTaskLogEntries',
500
		),
501
		'get_count' => array(
502
			'function' => 'list_getNumTaskLogEntries',
503
		),
504
		'columns' => array(
505
			'name' => array(
506
				'header' => array(
507
					'value' => $txt['scheduled_tasks_name'],
508
				),
509
				'data' => array(
510
					'db' => 'name'
511
				),
512
			),
513
			'date' => array(
514
				'header' => array(
515
					'value' => $txt['scheduled_log_time_run'],
516
				),
517
				'data' => array(
518
					'function' => function($rowData)
519
					{
520
						return timeformat($rowData['time_run'], true);
521
					},
522
				),
523
				'sort' => array(
524
					'default' => 'lst.id_log DESC',
525
					'reverse' => 'lst.id_log',
526
				),
527
			),
528
			'time_taken' => array(
529
				'header' => array(
530
					'value' => $txt['scheduled_log_time_taken'],
531
				),
532
				'data' => array(
533
					'sprintf' => array(
534
						'format' => $txt['scheduled_log_time_taken_seconds'],
535
						'params' => array(
536
							'time_taken' => false,
537
						),
538
					),
539
				),
540
				'sort' => array(
541
					'default' => 'lst.time_taken',
542
					'reverse' => 'lst.time_taken DESC',
543
				),
544
			),
545
		),
546
		'form' => array(
547
			'href' => $context['admin_area'] == 'scheduledtasks' ? $scripturl . '?action=admin;area=scheduledtasks;sa=tasklog' : $scripturl . '?action=admin;area=logs;sa=tasklog',
548
			'token' => 'admin-tl',
549
		),
550
		'additional_rows' => array(
551
			array(
552
				'position' => 'below_table_data',
553
				'value' => '
554
					<input type="submit" name="removeAll" value="' . $txt['scheduled_log_empty_log'] . '" data-confirm="' . $txt['scheduled_log_empty_log_confirm'] . '" class="button_submit you_sure">',
555
			),
556
			array(
557
				'position' => 'after_title',
558
				'value' => $txt['scheduled_tasks_time_offset'],
559
			),
560
		),
561
	);
562
563
	createToken('admin-tl');
564
565
	require_once($sourcedir . '/Subs-List.php');
566
	createList($listOptions);
567
568
	$context['sub_template'] = 'show_list';
569
	$context['default_list'] = 'task_log';
570
571
	// Make it all look tify.
572
	$context[$context['admin_menu_name']]['current_subsection'] = 'tasklog';
573
	$context['page_title'] = $txt['scheduled_log'];
574
}
575
576
/**
577
 * Callback function for createList() in TaskLog().
578
 *
579
 * @param int $start The item to start with (for pagination purposes)
580
 * @param int $items_per_page How many items to display per page
581
 * @param string $sort A string indicating how to sort the results
582
 * @return array An array of info about task log entries
583
 */
584
function list_getTaskLogEntries($start, $items_per_page, $sort)
585
{
586
	global $smcFunc, $txt;
587
588
	$request = $smcFunc['db_query']('', '
589
		SELECT lst.id_log, lst.id_task, lst.time_run, lst.time_taken, st.task
590
		FROM {db_prefix}log_scheduled_tasks AS lst
591
			INNER JOIN {db_prefix}scheduled_tasks AS st ON (st.id_task = lst.id_task)
592
		ORDER BY {raw:sort}
593
		LIMIT {int:start}, {int:items}',
594
		array(
595
			'sort' => $sort,
596
			'start' => $start,
597
			'items' => $items_per_page,
598
		)
599
	);
600
	$log_entries = array();
601
	while ($row = $smcFunc['db_fetch_assoc']($request))
602
		$log_entries[] = array(
603
			'id' => $row['id_log'],
604
			'name' => isset($txt['scheduled_task_' . $row['task']]) ? $txt['scheduled_task_' . $row['task']] : $row['task'],
605
			'time_run' => $row['time_run'],
606
			'time_taken' => $row['time_taken'],
607
		);
608
	$smcFunc['db_free_result']($request);
609
610
	return $log_entries;
611
}
612
613
/**
614
 * Callback function for createList() in TaskLog().
615
 * @return int The number of log entries
616
 */
617
function list_getNumTaskLogEntries()
618
{
619
	global $smcFunc;
620
621
	$request = $smcFunc['db_query']('', '
622
		SELECT COUNT(*)
623
		FROM {db_prefix}log_scheduled_tasks',
624
		array(
625
		)
626
	);
627
	list ($num_entries) = $smcFunc['db_fetch_row']($request);
628
	$smcFunc['db_free_result']($request);
629
630
	return $num_entries;
631
}
632
633
?>