! [Report to Helpdesk plugin] Preliminary facility to add reported PMs as helpdesk tickets. It's not thoroughly tested but it should cope with most things happily enough. [Feature 572]
gruffen

gruffen commited on 2011-08-05 03:03:14
Showing 5 changed files, with 325 additions and 2 deletions.

... ...
@@ -30,5 +30,10 @@ $txt['report_to_mod_func'] = 'Use this function to inform the moderators and adm
30 30
 
31 31
 $txt['report_normally'] = 'Do not direct reports to the helpdesk';
32 32
 $txt['report_posts_dept'] = 'Where should reported posts end up?';
33
+
33 34
 $txt['report_pms_dept'] = 'Where should reported private messages end up?';
35
+$txt['reported_pm'] = 'Reported private message';
36
+$txt['reported_pm_body_no_extra'] = 'The following message, "{subject}" by {author}, was reported by {reporter}' . "\n" . '---------------------------------------' . "\n" . '{body}' . "\n" . '---------------------------------------' . "\n\n" . 'The reason given was: ' . "\n" . '{comment}';
37
+$txt['reported_pm_body_extra'] = 'The following message, "{subject}" by {author}, was reported by {reporter}, and had also been sent to: {recipients}' . "\n" . '---------------------------------------' . "\n" . '{body}' . "\n" . '---------------------------------------' . "\n\n" . 'The reason given was: ' . "\n" . '{comment}';
38
+
34 39
 ?>
35 40
\ No newline at end of file
... ...
@@ -2,7 +2,7 @@
2 2
 <!DOCTYPE package-info SYSTEM "http://www.simplemachines.org/xml/package-info">
3 3
 <package-info xmlns="http://www.simplemachines.org/xml/package-info" xmlns:smf="http://www.simplemachines.org/">
4 4
 	<id>SimpleDeskTeam:reporthelpdesk</id>
5
-	<name>SimpleDesk: Report to Helpdesk</name>
5
+	<name>Report to Helpdesk</name>
6 6
 	<version>1.0</version>
7 7
 	<type>sdplugin</type>
8 8
 	<install for="2.0">
... ...
@@ -37,6 +37,9 @@ function shd_report_to_helpdesk_actions(&$actionArray)
37 37
 
38 38
 	if (!empty($modSettings['report_posts_dept']))
39 39
 		$actionArray['reporttm'] = array('sd_plugins_source/report_to_helpdesk/SDPluginReportToHelpdeskMain.php', 'shd_report_to_helpdesk');
40
+
41
+	if (!empty($modSettings['report_pms_dept']) && isset($_REQUEST['action'], $_REQUEST['sa']) && $_REQUEST['action'] == 'pm' && $_REQUEST['sa'] == 'report')
42
+		$actionArray['pm'] = array('sd_plugins_source/report_to_helpdesk/SDPluginReportToHelpdeskMain.php', 'shd_report_pm');
40 43
 }
41 44
 
42 45
 ?>
43 46
\ No newline at end of file
... ...
@@ -224,6 +224,14 @@ function shd_report_to_helpdesk2()
224 224
 	$context['ticket_id'] = $ticketOptions['id'];
225 225
 	$context['ticket_form']['ticket'] = $ticketOptions['id'];
226 226
 
227
+	shd_log_action(
228
+		'newticket',
229
+		array(
230
+			'ticket' => $context['ticket_id'],
231
+			'subject' => $ticketOptions['subject'],
232
+		)
233
+	);
234
+
227 235
 	// Handle notifications
228 236
 	require_once($sourcedir . '/sd_source/SimpleDesk-Notifications.php');
229 237
 	shd_notifications_notify_newticket($msgOptions, $ticketOptions, $posterOptions);
... ...
@@ -250,7 +258,7 @@ function shd_report_to_helpdesk_options($return_config)
250 258
 	$config_vars = array(
251 259
 		array('select', 'report_posts_dept', $dept_list),
252 260
 		'',
253
-		//array('select', 'report_pms_dept', $dept_list),
261
+		array('select', 'report_pms_dept', $dept_list),
254 262
 	);
255 263
 	$context['settings_title'] = $txt['shdp_report_to_helpdesk'];
256 264
 	$context['settings_icon'] = 'warning.png';
... ...
@@ -283,4 +291,310 @@ function shd_report_to_helpdesk_hdadminopts()
283 291
 	);
284 292
 }
285 293
 
294
+function shd_report_pm()
295
+{
296
+	// This is one ugly function. We have to reproduce a decent chunk of PersonalMessage.php to make this work, because you can't hook into the PM system otherwise.
297
+	global $txt, $scripturl, $sourcedir, $context, $user_info, $user_settings, $language, $smcFunc, $modSettings;
298
+
299
+	// No guests!
300
+	is_not_guest();
301
+
302
+	// You're not supposed to be here at all, if you can't even read PMs.
303
+	isAllowedTo('pm_read');
304
+
305
+	// Things we need, to make us strong.
306
+	require_once($sourcedir . '/Subs-Post.php');
307
+	require_once($sourcedir . '/PersonalMessage.php');
308
+	shd_load_language('SDPluginReportToHelpdesk', $language);
309
+	require_once($sourcedir . '/sd_source/Subs-SimpleDeskPost.php');
310
+
311
+	loadLanguage('PersonalMessage');
312
+
313
+	if (WIRELESS && WIRELESS_PROTOCOL == 'wap')
314
+		fatal_lang_error('wireless_error_notyet', false);
315
+	elseif (WIRELESS)
316
+		$context['sub_template'] = WIRELESS_PROTOCOL . '_pm';
317
+	else
318
+		loadTemplate('PersonalMessage');
319
+
320
+	// Load up the members maximum message capacity.
321
+	if ($user_info['is_admin'])
322
+		$context['message_limit'] = 0;
323
+	elseif (($context['message_limit'] = cache_get_data('msgLimit:' . $user_info['id'], 360)) === null)
324
+	{
325
+		// !!! Why do we do this?  It seems like if they have any limit we should use it.
326
+		$request = $smcFunc['db_query']('', '
327
+			SELECT MAX(max_messages) AS top_limit, MIN(max_messages) AS bottom_limit
328
+			FROM {db_prefix}membergroups
329
+			WHERE id_group IN ({array_int:users_groups})',
330
+			array(
331
+				'users_groups' => $user_info['groups'],
332
+			)
333
+		);
334
+		list ($maxMessage, $minMessage) = $smcFunc['db_fetch_row']($request);
335
+		$smcFunc['db_free_result']($request);
336
+
337
+		$context['message_limit'] = $minMessage == 0 ? 0 : $maxMessage;
338
+
339
+		// Save us doing it again!
340
+		cache_put_data('msgLimit:' . $user_info['id'], $context['message_limit'], 360);
341
+	}
342
+
343
+	// Prepare the context for the capacity bar.
344
+	if (!empty($context['message_limit']))
345
+	{
346
+		$bar = ($user_info['messages'] * 100) / $context['message_limit'];
347
+
348
+		$context['limit_bar'] = array(
349
+			'messages' => $user_info['messages'],
350
+			'allowed' => $context['message_limit'],
351
+			'percent' => $bar,
352
+			'bar' => min(100, (int) $bar),
353
+			'text' => sprintf($txt['pm_currently_using'], $user_info['messages'], round($bar, 1)),
354
+		);
355
+	}
356
+
357
+	// a previous message was sent successfully? show a small indication.
358
+	if (isset($_GET['done']) && ($_GET['done'] == 'sent'))
359
+		$context['pm_sent'] = true;
360
+
361
+	// Now we have the labels, and assuming we have unsorted mail, apply our rules!
362
+	if ($user_settings['new_pm'])
363
+	{
364
+		$context['labels'] = $user_settings['message_labels'] == '' ? array() : explode(',', $user_settings['message_labels']);
365
+		foreach ($context['labels'] as $id_label => $label_name)
366
+			$context['labels'][(int) $id_label] = array(
367
+				'id' => $id_label,
368
+				'name' => trim($label_name),
369
+				'messages' => 0,
370
+				'unread_messages' => 0,
371
+			);
372
+		$context['labels'][-1] = array(
373
+			'id' => -1,
374
+			'name' => $txt['pm_msg_label_inbox'],
375
+			'messages' => 0,
376
+			'unread_messages' => 0,
377
+		);
378
+
379
+		ApplyRules();
380
+		updateMemberData($user_info['id'], array('new_pm' => 0));
381
+		$smcFunc['db_query']('', '
382
+			UPDATE {db_prefix}pm_recipients
383
+			SET is_new = {int:not_new}
384
+			WHERE id_member = {int:current_member}',
385
+			array(
386
+				'current_member' => $user_info['id'],
387
+				'not_new' => 0,
388
+			)
389
+		);
390
+	}
391
+
392
+	// Load the label data.
393
+	if ($user_settings['new_pm'] || ($context['labels'] = cache_get_data('labelCounts:' . $user_info['id'], 720)) === null)
394
+	{
395
+		$context['labels'] = $user_settings['message_labels'] == '' ? array() : explode(',', $user_settings['message_labels']);
396
+		foreach ($context['labels'] as $id_label => $label_name)
397
+			$context['labels'][(int) $id_label] = array(
398
+				'id' => $id_label,
399
+				'name' => trim($label_name),
400
+				'messages' => 0,
401
+				'unread_messages' => 0,
402
+			);
403
+		$context['labels'][-1] = array(
404
+			'id' => -1,
405
+			'name' => $txt['pm_msg_label_inbox'],
406
+			'messages' => 0,
407
+			'unread_messages' => 0,
408
+		);
409
+
410
+		// Looks like we need to reseek!
411
+		$result = $smcFunc['db_query']('', '
412
+			SELECT labels, is_read, COUNT(*) AS num
413
+			FROM {db_prefix}pm_recipients
414
+			WHERE id_member = {int:current_member}
415
+				AND deleted = {int:not_deleted}
416
+			GROUP BY labels, is_read',
417
+			array(
418
+				'current_member' => $user_info['id'],
419
+				'not_deleted' => 0,
420
+			)
421
+		);
422
+		while ($row = $smcFunc['db_fetch_assoc']($result))
423
+		{
424
+			$this_labels = explode(',', $row['labels']);
425
+			foreach ($this_labels as $this_label)
426
+			{
427
+				$context['labels'][(int) $this_label]['messages'] += $row['num'];
428
+				if (!($row['is_read'] & 1))
429
+					$context['labels'][(int) $this_label]['unread_messages'] += $row['num'];
430
+			}
431
+		}
432
+		$smcFunc['db_free_result']($result);
433
+
434
+		// Store it please!
435
+		cache_put_data('labelCounts:' . $user_info['id'], $context['labels'], 720);
436
+	}
437
+
438
+	// This determines if we have more labels than just the standard inbox.
439
+	$context['currently_using_labels'] = count($context['labels']) > 1 ? 1 : 0;
440
+
441
+	// Some stuff for the labels...
442
+	$context['current_label_id'] = isset($_REQUEST['l']) && isset($context['labels'][(int) $_REQUEST['l']]) ? (int) $_REQUEST['l'] : -1;
443
+	$context['current_label'] = &$context['labels'][(int) $context['current_label_id']]['name'];
444
+	$context['folder'] = !isset($_REQUEST['f']) || $_REQUEST['f'] != 'sent' ? 'inbox' : 'sent';
445
+
446
+	// This is convenient.  Do you know how annoying it is to do this every time?!
447
+	$context['current_label_redirect'] = 'action=pm;f=' . $context['folder'] . (isset($_GET['start']) ? ';start=' . $_GET['start'] : '') . (isset($_REQUEST['l']) ? ';l=' . $_REQUEST['l'] : '');
448
+	$context['can_issue_warning'] = in_array('w', $context['admin_features']) && allowedTo('issue_warning') && $modSettings['warning_settings'][0] == 1;
449
+
450
+	// Build the linktree for all the actions...
451
+	$context['linktree'][] = array(
452
+		'url' => $scripturl . '?action=pm',
453
+		'name' => $txt['personal_messages']
454
+	);
455
+
456
+	// Preferences...
457
+	$context['display_mode'] = WIRELESS ? 0 : $user_settings['pm_prefs'] & 3;
458
+
459
+	// NOW FINALLY, we do something actually pertinent to reporting, that isn't just scaffolding from PersonalMessage.php.
460
+	messageIndexBar('report');
461
+
462
+	// Check that this feature is even enabled!
463
+	if (empty($modSettings['enableReportPM']) || empty($_REQUEST['pmsg']))
464
+		fatal_lang_error('no_access', false);
465
+
466
+	$pmsg = (int) $_REQUEST['pmsg'];
467
+
468
+	if (!isAccessiblePM($pmsg, 'inbox'))
469
+		fatal_lang_error('no_access', false);
470
+
471
+	$context['pm_id'] = $pmsg;
472
+	$context['page_title'] = $txt['pm_report_title'];
473
+
474
+	// If we're here, just send the user to the template, with a few useful context bits.
475
+	if (!isset($_POST['report']))
476
+	{
477
+		$context['sub_template'] = 'report_message';
478
+
479
+		$context['admins'] = array();
480
+		$context['admin_count'] = 1; // To stop the form displaying a list of admins. It's going to the helpdesk instead, remember?
481
+	}
482
+	// Otherwise, let's get down to the sending stuff.
483
+	else
484
+	{
485
+		// Check the session before proceeding any further!
486
+		checkSession('post');
487
+
488
+		// First, pull out the message contents, and verify it actually went to them!
489
+		$request = $smcFunc['db_query']('', '
490
+			SELECT pm.subject, pm.body, pm.msgtime, pm.id_member_from, IFNULL(m.real_name, pm.from_name) AS sender_name
491
+			FROM {db_prefix}personal_messages AS pm
492
+				INNER JOIN {db_prefix}pm_recipients AS pmr ON (pmr.id_pm = pm.id_pm)
493
+				LEFT JOIN {db_prefix}members AS m ON (m.id_member = pm.id_member_from)
494
+			WHERE pm.id_pm = {int:id_pm}
495
+				AND pmr.id_member = {int:current_member}
496
+				AND pmr.deleted = {int:not_deleted}
497
+			LIMIT 1',
498
+			array(
499
+				'current_member' => $user_info['id'],
500
+				'id_pm' => $context['pm_id'],
501
+				'not_deleted' => 0,
502
+			)
503
+		);
504
+		// Can only be a hacker here!
505
+		if ($smcFunc['db_num_rows']($request) == 0)
506
+			fatal_lang_error('no_access', false);
507
+		list ($subject, $body, $time, $memberFromID, $memberFromName) = $smcFunc['db_fetch_row']($request);
508
+		$smcFunc['db_free_result']($request);
509
+
510
+		// Remove the line breaks...
511
+		$body = preg_replace('~<br ?/?' . '>~i', "\n", $body);
512
+
513
+		// Get any other recipients of the email.
514
+		$request = $smcFunc['db_query']('', '
515
+			SELECT mem_to.id_member AS id_member_to, mem_to.real_name AS to_name, pmr.bcc
516
+			FROM {db_prefix}pm_recipients AS pmr
517
+				LEFT JOIN {db_prefix}members AS mem_to ON (mem_to.id_member = pmr.id_member)
518
+			WHERE pmr.id_pm = {int:id_pm}
519
+				AND pmr.id_member != {int:current_member}',
520
+			array(
521
+				'current_member' => $user_info['id'],
522
+				'id_pm' => $context['pm_id'],
523
+			)
524
+		);
525
+		$recipients = array();
526
+		$hidden_recipients = 0;
527
+		while ($row = $smcFunc['db_fetch_assoc']($request))
528
+		{
529
+			// If it's hidden still don't reveal their names - privacy after all ;)
530
+			if ($row['bcc'])
531
+				$hidden_recipients++;
532
+			else
533
+				$recipients[] = un_htmlspecialchars($row['to_name']);
534
+		}
535
+		$smcFunc['db_free_result']($request);
536
+
537
+		if ($hidden_recipients)
538
+			$recipients[] = sprintf($txt['pm_report_pm_hidden'], $hidden_recipients);
539
+
540
+		$memberFromName = un_htmlspecialchars($memberFromName);
541
+
542
+		$replacements = array(
543
+			'{reporter}' => un_htmlspecialchars($user_info['name']),
544
+			'{author}' => un_htmlspecialchars($memberFromName),
545
+			'{comment}' => $_POST['reason'],
546
+			'{body}' => un_htmlspecialchars($body),
547
+		);
548
+		if (!empty($recipients))
549
+			$replacements['{recipients}'] = implode(', ', $recipients);
550
+
551
+		$report_body = str_replace(array_keys($replacements), array_values($replacements), !empty($recipients) ? $txt['reported_pm_body_extra'] : $txt['reported_pm_body_no_extra']);
552
+
553
+		preparsecode($report_body);
554
+
555
+		$msgOptions = array(
556
+			'id' => 0,
557
+			'body' => $report_body,
558
+			'smileys_enabled' => false,
559
+		);
560
+		$ticketOptions = array(
561
+			'id' => 0,
562
+			'mark_as_read' => true,
563
+			'subject' => $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($txt['reported_pm'] . ': ' . $subject)),
564
+			'private' => false,
565
+			'status' => TICKET_STATUS_NEW,
566
+			'urgency' => TICKET_URGENCY_LOW,
567
+			'assigned' => 0,
568
+			'dept' => $modSettings['report_pms_dept'],
569
+		);
570
+		$posterOptions = array(
571
+			'id' => $user_info['id'],
572
+			'name' => $user_info['name'],
573
+			'email' => $user_info['email'],
574
+			'ip' => $user_info['ip'],
575
+		);
576
+
577
+		shd_create_ticket_post($msgOptions, $ticketOptions, $posterOptions);
578
+		shd_clear_active_tickets();
579
+
580
+		// Update our nice ticket store with the ticket id
581
+		$context['ticket_id'] = $ticketOptions['id'];
582
+		$context['ticket_form']['ticket'] = $ticketOptions['id'];
583
+
584
+		shd_log_action(
585
+			'newticket',
586
+			array(
587
+				'ticket' => $context['ticket_id'],
588
+				'subject' => $ticketOptions['subject'],
589
+			)
590
+		);
591
+
592
+		// Handle notifications
593
+		require_once($sourcedir . '/sd_source/SimpleDesk-Notifications.php');
594
+		shd_notifications_notify_newticket($msgOptions, $ticketOptions, $posterOptions);
595
+
596
+		// Leave them with a template.
597
+		$context['sub_template'] = 'report_message_complete';
598
+	}
599
+}
286 600
 ?>
287 601
\ No newline at end of file
... ...
@@ -57,6 +57,7 @@ function shdplugin_report_to_helpdesk()
57 57
 			'compatibility' => array(
58 58
 				'SimpleDesk 2.0 Anatidae', // should tie up with the SHD_VERSION constants
59 59
 			),
60
+			'acp_url' => 'action=admin;area=helpdesk_options;sa=report_to_helpdesk',
60 61
 		),
61 62
 		'includes' => array(
62 63
 			'source' => array(
63 64