Custom quick-mod tools (3.2.x)

Looking for an Extension? Have an Extension request? Post your request here for help. (Note: This forum is community supported; while there is an Extensions Development Team, said team does not dedicate itself to handling requests in this forum)
Suggested Hosts
Post Reply
JSR01
Registered User
Posts: 5
Joined: Tue Aug 14, 2018 1:27 pm

Custom quick-mod tools (3.2.x)

Post by JSR01 »

Hello everyone,

I'm looking for a method to define custom quick-mod tools for PHPBB3.2.3, please. I am working to migrate a community from (the late) ZetaBoards to a new PHPBB3 installation, and this is one of the oft-used features that i'm hoping to carry through to the new board. Ideally I'm looking to add a set of pre-defined quick-mod tools that require no user input other than the button-press to run, which perform multiple (existing) quick-mod actions all at once. It would be preferable (but certainly not essential) if these quick-mod tools could be set to only be available for use within certain forum sections.

As an example, I'd like to be able to set up a quick-mod tool that posts a predefined reply to the current topic, adds a prefix to the topic title, locks the topic, and moves the topic to a predefined forum. Instead of needing to perform each action individually and manually type the reply, rename the title, and select the move destination, the desired custom quick-mod tool could do the lot with a single click. Is such a feature possible?

While I'm a (very new) beginner to PHP, I very much enjoy learning & playing with it. In the event that this request is straightforward to set up, I'd appreciate any pointers on where to begin!
Last edited by JSR01 on Thu Sep 27, 2018 8:03 am, edited 1 time in total.
JSR01
Registered User
Posts: 5
Joined: Tue Aug 14, 2018 1:27 pm

Re: Custom quick-mod tools (3.2.x)

Post by JSR01 »

I hope it's acceptable to bump - apologies if not.
Can anyone help me find where the built-in quick-mod tools are defined?

Thanks!
User avatar
Restless Rancor
Registered User
Posts: 196
Joined: Tue Sep 18, 2018 1:51 pm

Re: Custom quick-mod tools (3.2.x)

Post by Restless Rancor »

Just registering my interest in such an extension, this could prove helpful especially for a support forum.
:geek:
These are not the droids you're looking for...
User avatar
Brf
Support Team Member
Support Team Member
Posts: 53411
Joined: Tue May 10, 2005 7:47 pm
Location: {postrow.POSTER_FROM}
Contact:

Re: Custom quick-mod tools (3.2.x)

Post by Brf »

JSR01 wrote: Thu Sep 27, 2018 8:03 am Can anyone help me find where the built-in quick-mod tools are defined?
Try searching viewtopic.php for "quick".
User avatar
Restless Rancor
Registered User
Posts: 196
Joined: Tue Sep 18, 2018 1:51 pm

Re: Custom quick-mod tools (3.2.x)

Post by Restless Rancor »

Brf wrote: Fri Sep 28, 2018 4:59 pm
JSR01 wrote: Thu Sep 27, 2018 8:03 am Can anyone help me find where the built-in quick-mod tools are defined?
Try searching viewtopic.php for "quick".
Hi Brf, I know there is a quick-mod tools drop-down for moderators, but if I understood correctly the OP would like to have a function that would do multiple tasks at once.
These are not the droids you're looking for...
User avatar
Brf
Support Team Member
Support Team Member
Posts: 53411
Joined: Tue May 10, 2005 7:47 pm
Location: {postrow.POSTER_FROM}
Contact:

Re: Custom quick-mod tools (3.2.x)

Post by Brf »

I was answering this:
JSR01 wrote: Thu Sep 27, 2018 8:03 am Can anyone help me find where the built-in quick-mod tools are defined?
User avatar
Restless Rancor
Registered User
Posts: 196
Joined: Tue Sep 18, 2018 1:51 pm

Re: Custom quick-mod tools (3.2.x)

Post by Restless Rancor »

Brf wrote: Fri Sep 28, 2018 5:09 pm I was answering this:
JSR01 wrote: Thu Sep 27, 2018 8:03 am Can anyone help me find where the built-in quick-mod tools are defined?
Oh of course, I'm sorry I glazed over the quote in your post!! :oops:
These are not the droids you're looking for...
JSR01
Registered User
Posts: 5
Joined: Tue Aug 14, 2018 1:27 pm

Re: Custom quick-mod tools (3.2.x)

Post by JSR01 »

Just going to leave some notes here as I attempt to look into this further. If anyone has any helpful insight / suggestions, please feel free to jump in.

------

viewtopic.php :

Code: Select all

// Quick mod tools
$allow_change_type = ($auth->acl_get('m_', $forum_id) || ($user->data['is_registered'] && $user->data['user_id'] == $topic_data['topic_poster'])) ? true : false;

$s_quickmod_action = append_sid(
	"{$phpbb_root_path}mcp.$phpEx",
	array(
		'f'	=> $forum_id,
		't'	=> $topic_id,
		'start'		=> $start,
		'quickmod'	=> 1,
		'redirect'	=> urlencode(str_replace('&', '&', $viewtopic_url)),
	),
	true,
	$user->session_id
);

$quickmod_array = array(
//	'key'			=> array('LANG_KEY', $userHasPermissions),

	'lock'					=> array('LOCK_TOPIC', ($topic_data['topic_status'] == ITEM_UNLOCKED) && ($auth->acl_get('m_lock', $forum_id) || ($auth->acl_get('f_user_lock', $forum_id) && $user->data['is_registered'] && $user->data['user_id'] == $topic_data['topic_poster']))),
	'unlock'				=> array('UNLOCK_TOPIC', ($topic_data['topic_status'] != ITEM_UNLOCKED) && ($auth->acl_get('m_lock', $forum_id))),
	'delete_topic'		=> array('DELETE_TOPIC', ($auth->acl_get('m_delete', $forum_id) || (($topic_data['topic_visibility'] != ITEM_DELETED) && $auth->acl_get('m_softdelete', $forum_id)))),
	'restore_topic'		=> array('RESTORE_TOPIC', (($topic_data['topic_visibility'] == ITEM_DELETED) && $auth->acl_get('m_approve', $forum_id))),
	'move'					=> array('MOVE_TOPIC', $auth->acl_get('m_move', $forum_id) && $topic_data['topic_status'] != ITEM_MOVED),
	'split'					=> array('SPLIT_TOPIC', $auth->acl_get('m_split', $forum_id)),
	'merge'					=> array('MERGE_POSTS', $auth->acl_get('m_merge', $forum_id)),
	'merge_topic'		=> array('MERGE_TOPIC', $auth->acl_get('m_merge', $forum_id)),
	'fork'					=> array('FORK_TOPIC', $auth->acl_get('m_move', $forum_id)),
	'make_normal'		=> array('MAKE_NORMAL', ($allow_change_type && $auth->acl_gets('f_sticky', 'f_announce', 'f_announce_global', $forum_id) && $topic_data['topic_type'] != POST_NORMAL)),
	'make_sticky'		=> array('MAKE_STICKY', ($allow_change_type && $auth->acl_get('f_sticky', $forum_id) && $topic_data['topic_type'] != POST_STICKY)),
	'make_announce'	=> array('MAKE_ANNOUNCE', ($allow_change_type && $auth->acl_get('f_announce', $forum_id) && $topic_data['topic_type'] != POST_ANNOUNCE)),
	'make_global'		=> array('MAKE_GLOBAL', ($allow_change_type && $auth->acl_get('f_announce_global', $forum_id) && $topic_data['topic_type'] != POST_GLOBAL)),
	'topic_logs'			=> array('VIEW_TOPIC_LOGS', $auth->acl_get('m_', $forum_id)),
);

/**
* Event to modify data in the quickmod_array before it gets sent to the
* phpbb_add_quickmod_option function.
*
* @event core.viewtopic_add_quickmod_option_before
* @var	int				forum_id				Forum ID
* @var	int				post_id					Post ID
* @var	array			quickmod_array			Array with quick moderation options data
* @var	array			topic_data				Array with topic data
* @var	int				topic_id				Topic ID
* @var	array			topic_tracking_info		Array with topic tracking data
* @var	string			viewtopic_url			URL to the topic page
* @var	bool			allow_change_type		Topic change permissions check
* @since 3.1.9-RC1
*/
$vars = array(
	'forum_id',
	'post_id',
	'quickmod_array',
	'topic_data',
	'topic_id',
	'topic_tracking_info',
	'viewtopic_url',
	'allow_change_type',
);
extract($phpbb_dispatcher->trigger_event('core.viewtopic_add_quickmod_option_before', compact($vars)));

foreach ($quickmod_array as $option => $qm_ary)
{
	if (!empty($qm_ary[1]))
	{
		phpbb_add_quickmod_option($s_quickmod_action, $option, $qm_ary[0]);
	}
}
$quickmod_array seems to define the permissions for using the quick mod tools. E.g. since i'm interested in the 'move' tool:

Code: Select all

$quickmod_array = array(
	'move'					=> array('MOVE_TOPIC', $auth->acl_get('m_move', $forum_id) && $topic_data['topic_status'] != ITEM_MOVED),
	(...)
MOVE_TOPIC pulls the tool description from the language file \language\en\viewtopic.php (some, such as 'LOCK_TOPIC', are in \language\en\mcp.php):

Code: Select all

'MOVE_TOPIC'				=> 'Move topic',
$auth_get checks that the user has the permissions to perform the move ('m_move') in the active forum
Also checks that the topic hasn't already been moved

But the actual actions behind the quick mod tools are defined elsewhere.

-----

includes\functions_content.php :

Code: Select all

/**
 * Add an option to the quick-mod tools.
 *
 * @param string $url The recepting URL for the quickmod actions.
 * @param string $option The language key for the value of the option.
 * @param string $lang_string The language string to use.
 */
function phpbb_add_quickmod_option($url, $option, $lang_string)
{
	global $template, $user, $phpbb_path_helper;

	$lang_string = $user->lang($lang_string);
	$template->assign_block_vars('quickmod', array(
		'VALUE'		=> $option,
		'TITLE'		=> $lang_string,
		'LINK'		=> $phpbb_path_helper->append_url_params($url, array('action' => $option)),
	));
}
For now I assume this populates the list of quick mod tools.

-----

includes\acp\acp_users.php :

Code: Select all

// Handle quicktool actions
					switch ($action)
					{
						case 'banuser':
						case 'banemail':
						case 'banip':
						   (...)
						case 'reactivate':
						   (...)
						case 'active':
						   (...)
						case 'delsig':
						   (...)
						case 'delavatar':
						   (...)
						case 'delposts':
						   (...)
						case 'delattach':
						   (...)
						case 'deloutbox':
						   (...)
						case 'moveposts':

							if (!check_form_key($form_name))
							{
								trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
							}

							$user->add_lang('acp/forums');

							$new_forum_id = $request->variable('new_f', 0);

							if (!$new_forum_id)
							{
								$this->page_title = 'USER_ADMIN_MOVE_POSTS';

								$template->assign_vars(array(
									'S_SELECT_FORUM'		=> true,
									'U_ACTION'				=> $this->u_action . "&action=$action&u=$user_id",
									'U_BACK'				=> $this->u_action . "&u=$user_id",
									'S_FORUM_OPTIONS'		=> make_forum_select(false, false, false, true))
								);

								return;
							}

							// Is the new forum postable to?
							$sql = 'SELECT forum_name, forum_type
								FROM ' . FORUMS_TABLE . "
								WHERE forum_id = $new_forum_id";
							$result = $db->sql_query($sql);
							$forum_info = $db->sql_fetchrow($result);
							$db->sql_freeresult($result);

							if (!$forum_info)
							{
								trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
							}

							if ($forum_info['forum_type'] != FORUM_POST)
							{
								trigger_error($user->lang['MOVE_POSTS_NO_POSTABLE_FORUM'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING);
							}

							// Two stage?
							// Move topics comprising only posts from this user
							$topic_id_ary = $move_topic_ary = $move_post_ary = $new_topic_id_ary = array();
							$forum_id_ary = array($new_forum_id);

							$sql = 'SELECT topic_id, post_visibility, COUNT(post_id) AS total_posts
								FROM ' . POSTS_TABLE . "
								WHERE poster_id = $user_id
									AND forum_id <> $new_forum_id
								GROUP BY topic_id, post_visibility";
							$result = $db->sql_query($sql);

							while ($row = $db->sql_fetchrow($result))
							{
								$topic_id_ary[$row['topic_id']][$row['post_visibility']] = $row['total_posts'];
							}
							$db->sql_freeresult($result);

							if (count($topic_id_ary))
							{
								$sql = 'SELECT topic_id, forum_id, topic_title, topic_posts_approved, topic_posts_unapproved, topic_posts_softdeleted, topic_attachment
									FROM ' . TOPICS_TABLE . '
									WHERE ' . $db->sql_in_set('topic_id', array_keys($topic_id_ary));
								$result = $db->sql_query($sql);

								while ($row = $db->sql_fetchrow($result))
								{
									if ($topic_id_ary[$row['topic_id']][ITEM_APPROVED] == $row['topic_posts_approved']
										&& $topic_id_ary[$row['topic_id']][ITEM_UNAPPROVED] == $row['topic_posts_unapproved']
										&& $topic_id_ary[$row['topic_id']][ITEM_REAPPROVE] == $row['topic_posts_unapproved']
										&& $topic_id_ary[$row['topic_id']][ITEM_DELETED] == $row['topic_posts_softdeleted'])
									{
										$move_topic_ary[] = $row['topic_id'];
									}
									else
									{
										$move_post_ary[$row['topic_id']]['title'] = $row['topic_title'];
										$move_post_ary[$row['topic_id']]['attach'] = ($row['topic_attachment']) ? 1 : 0;
									}

									$forum_id_ary[] = $row['forum_id'];
								}
								$db->sql_freeresult($result);
							}

							// Entire topic comprises posts by this user, move these topics
							if (count($move_topic_ary))
							{
								move_topics($move_topic_ary, $new_forum_id, false);
							}

							if (count($move_post_ary))
							{
								// Create new topic
								// Update post_ids, report_ids, attachment_ids
								foreach ($move_post_ary as $topic_id => $post_ary)
								{
									// Create new topic
									$sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', array(
										'topic_poster'				=> $user_id,
										'topic_time'				=> time(),
										'forum_id' 					=> $new_forum_id,
										'icon_id'					=> 0,
										'topic_visibility'			=> ITEM_APPROVED,
										'topic_title' 				=> $post_ary['title'],
										'topic_first_poster_name'	=> $user_row['username'],
										'topic_type'				=> POST_NORMAL,
										'topic_time_limit'			=> 0,
										'topic_attachment'			=> $post_ary['attach'])
									);
									$db->sql_query($sql);

									$new_topic_id = $db->sql_nextid();

									// Move posts
									$sql = 'UPDATE ' . POSTS_TABLE . "
										SET forum_id = $new_forum_id, topic_id = $new_topic_id
										WHERE topic_id = $topic_id
											AND poster_id = $user_id";
									$db->sql_query($sql);

									if ($post_ary['attach'])
									{
										$sql = 'UPDATE ' . ATTACHMENTS_TABLE . "
											SET topic_id = $new_topic_id
											WHERE topic_id = $topic_id
												AND poster_id = $user_id";
										$db->sql_query($sql);
									}

									$new_topic_id_ary[] = $new_topic_id;
								}
							}

							$forum_id_ary = array_unique($forum_id_ary);
							$topic_id_ary = array_unique(array_merge(array_keys($topic_id_ary), $new_topic_id_ary));

							if (count($topic_id_ary))
							{
								sync('topic_reported', 'topic_id', $topic_id_ary);
								sync('topic', 'topic_id', $topic_id_ary);
							}

							if (count($forum_id_ary))
							{
								sync('forum', 'forum_id', $forum_id_ary, false, true);
							}

							$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_MOVE_POSTS', false, array($user_row['username'], $forum_info['forum_name']));
							$phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_MOVE_POSTS_USER', false, array(
								'reportee_id' => $user_id,
								$forum_info['forum_name']
							));

							trigger_error($user->lang['USER_POSTS_MOVED'] . adm_back_link($this->u_action . '&amp;u=' . $user_id));

						break;
						
						case 'leave_nr':
						   (...)
						   
						default:
							$u_action = $this->u_action;

							/**
							* Run custom quicktool code
							*
							* @event core.acp_users_overview_run_quicktool
							* @var	string	action		Quick tool that should be run
							* @var	array	user_row	Current user data
							* @var	string	u_action	The u_action link
							* @since 3.1.0-a1
							* @changed 3.2.2-RC1 Added u_action
							*/
							$vars = array('action', 'user_row', 'u_action');
							extract($phpbb_dispatcher->trigger_event('core.acp_users_overview_run_quicktool', compact($vars)));

							unset($u_action);
						break;
					}
    (...)
    
 if ($user_id == $user->data['user_id'])
				{
					$quick_tool_ary = array('delsig' => 'DEL_SIG', 'delavatar' => 'DEL_AVATAR', 'moveposts' => 'MOVE_POSTS', 'delposts' => 'DEL_POSTS', 'delattach' => 'DEL_ATTACH', 'deloutbox' => 'DEL_OUTBOX');
					if ($user_row['user_new'])
					{
						$quick_tool_ary['leave_nr'] = 'LEAVE_NR';
					}
				}
				else
				{
					$quick_tool_ary = array();

					if ($user_row['user_type'] != USER_FOUNDER)
					{
						$quick_tool_ary += array('banuser' => 'BAN_USER', 'banemail' => 'BAN_EMAIL', 'banip' => 'BAN_IP');
					}

					if ($user_row['user_type'] != USER_FOUNDER && $user_row['user_type'] != USER_IGNORE)
					{
						$quick_tool_ary += array('active' => (($user_row['user_type'] == USER_INACTIVE) ? 'ACTIVATE' : 'DEACTIVATE'));
					}

					$quick_tool_ary += array('delsig' => 'DEL_SIG', 'delavatar' => 'DEL_AVATAR', 'moveposts' => 'MOVE_POSTS', 'delposts' => 'DEL_POSTS', 'delattach' => 'DEL_ATTACH', 'deloutbox' => 'DEL_OUTBOX');

					if ($config['email_enable'] && ($user_row['user_type'] == USER_NORMAL || $user_row['user_type'] == USER_INACTIVE))
					{
						$quick_tool_ary['reactivate'] = 'FORCE';
					}

					if ($user_row['user_new'])
					{
						$quick_tool_ary['leave_nr'] = 'LEAVE_NR';
					}
				}

(...)


/**
				* Add additional quick tool options and overwrite user data
				*
				* @event core.acp_users_display_overview
				* @var	array	user_row			Array with user data
				* @var	array	quick_tool_ary		Ouick tool options
				* @since 3.1.0-a1
				*/
				$vars = array('user_row', 'quick_tool_ary');
				extract($phpbb_dispatcher->trigger_event('core.acp_users_display_overview', compact($vars)));

				$s_action_options = '<option class="sep" value="">' . $user->lang['SELECT_OPTION'] . '</option>';
				foreach ($quick_tool_ary as $value => $lang)
				{
					$s_action_options .= '<option value="' . $value . '">' . $user->lang['USER_ADMIN_' . $lang] . '</option>';
				}

(Omitted code with (...) ellipses just for clarity)
I think this is where the actual logic for each action is defined. But the list doesn't seem exhaustive; 'moveposts' is here, but nothing to lock, split, merge, sticky, etc.
Possibly some of those are included as part of the move logic. Looks like it includes cases to move whole topics, create new topics (i.e. split)

The last part I believe binds the tool logic above to the quick tool name defined earlier
User avatar
Brf
Support Team Member
Support Team Member
Posts: 53411
Joined: Tue May 10, 2005 7:47 pm
Location: {postrow.POSTER_FROM}
Contact:

Re: Custom quick-mod tools (3.2.x)

Post by Brf »

acp_users is handling actions in the Admin control panel, having to do with users.
The mcp quickmod code is in mcp.php and includes/mcp/mcp_main.php
JSR01
Registered User
Posts: 5
Joined: Tue Aug 14, 2018 1:27 pm

Re: Custom quick-mod tools (3.2.x)

Post by JSR01 »

Thanks Brf, much appreciated!
Post Reply

Return to “Extension Requests”