<?php
/*========================================================================*\
|| ###################################################################### ||
|| # vBulletin 6.2.3 - Licence Number L3138846
|| # ------------------------------------------------------------------ # ||
|| # Copyright 2000-2026 MH Sub I, LLC dba vBulletin. All Rights Reserved.  # ||
|| # This file may not be redistributed in whole or significant part.   # ||
|| # ----------------- VBULLETIN IS NOT FREE SOFTWARE ----------------- # ||
|| # http://www.vbulletin.com | http://www.vbulletin.com/license.html   # ||
|| ###################################################################### ||
\*========================================================================*/

// ######################## SET PHP ENVIRONMENT ###########################

// ##################### DEFINE IMPORTANT CONSTANTS #######################
define('CVS_REVISION', '$RCSfile$ - $Revision: 122391 $');

// #################### PRE-CACHE TEMPLATES AND DATA ######################
global $phrasegroups, $specialtemplates, $vbphrase, $vbulletin;
$phrasegroups = ['prefix', 'prefixadmin'];

// ########################## REQUIRE BACK-END ############################
require_once(dirname(__FILE__) . '/global.php');
require_once(DIR . '/includes/adminfunctions_prefix.php');

// ######################## CHECK ADMIN PERMISSIONS #######################
if (!can_administer('canadminforums'))
{
	print_cp_no_permission();
}

// ############################# LOG ACTION ###############################
$log_vars = [];
if (!empty($_REQUEST['prefixsetid']))
{
	$log_vars[] = 'prefixsetid = ' . htmlspecialchars_uni($_REQUEST['prefixsetid']);
}
if (!empty($_REQUEST['prefixid']))
{
	$log_vars[] = 'prefixid = ' . htmlspecialchars_uni($_REQUEST['prefixid']);
}
log_admin_action(implode(', ', $log_vars));

// ########################################################################
// ######################### START MAIN SCRIPT ############################
// ########################################################################

print_cp_header($vbphrase['thread_prefix_manager_gprefixadmin']);

if (empty($_REQUEST['do']))
{
	$_REQUEST['do'] = 'list';
}

// notes on phrases:
// prefixset_ID_title (prefixes), prefix_ID_title_plain (global), prefix_ID_title_rich (global)

// ########################################################################

if ($_REQUEST['do'] == 'duplicate')
{
	$assertor = vB::getDbAssertor();

	$prefixes = [];
	$result = $assertor->assertQuery('vBForum:getPrefixesBySet', []);
	foreach ($result AS $prefix)
	{
		$prefixsetphrase = 'prefixset_' . $prefix['prefixsetid'] . '_title';
		$prefixphrase = 'prefix_' . $prefix['prefixid'] . '_title_plain';

		// set up the grouped options in the format that the render function wants
		$prefixes[$vbphrase[$prefixsetphrase]][$prefix['prefixid']] = $vbphrase[$prefixphrase];
	}

	if (empty($prefixes))
	{
		print_cp_message($vbphrase['no_prefix_sets_defined_click_create']);
	}

	print_form_header2('admincp/prefix', 'doduplicate');
	print_table_start2();
	print_table_header($vbphrase['thread_prefixes_gprefixadmin'], 2);
	print_select_row($vbphrase['copy_permissions_from'], 'from', $prefixes, '', true);
	print_select_row($vbphrase['copy_permissions_to'], 'copyto[]', $prefixes, '', true, 10, true);
	print_yes_no_row($vbphrase['overwrite_customized_permissions_no_restrictions'], 'overwrite', 0);
	print_submit_row();
}

// ########################################################################

if ($_POST['do'] == 'doduplicate')
{
	$vbulletin->input->clean_array_gpc('p', [
		'from'      => vB_Cleaner::TYPE_STR,
		'copyto'    => vB_Cleaner::TYPE_ARRAY_STR,
		'overwrite' => vB_Cleaner::TYPE_BOOL
	]);

	// Get the from/to values.  The UI doesn't prevent selecting the source as a target but we don't want to
	// ignore that if they did.
	$from_prefixid = $vbulletin->GPC['from'];
	$copy_to = array_filter($vbulletin->GPC['copyto'], function ($x) use ($from_prefixid) {return $x != $from_prefixid;});
	$all_prefixids = array_merge($copy_to, [$from_prefixid]);

	if (!$copy_to)
	{
		print_stop_message('did_not_select_any_valid_prefixes_to_copy_to');
	}

	$assertor = vB::getDbAssertor();
	$result = $assertor->select('vBForum:prefixpermission', ['prefixid' => $all_prefixids], ['usergroupid', 'prefixid']);
	$prefix_restrictions = vB_Utility_Functions::iterableColumnGrouped($result, 'usergroupid', 'prefixid');

	$prefix_options = $assertor->getColumn('vBForum:prefix', 'options', ['prefixid' => $all_prefixids], false, 'prefixid');

	if (!isset($prefix_options[$from_prefixid]))
	{
		print_stop_message('you_did_not_select_any_prefixes');
	}

	$update_prefixids = [];
	foreach ($copy_to AS $prefixid)
	{
		if (empty($prefix_restrictions[$prefixid]) OR $vbulletin->GPC['overwrite'])
		{
			$update_prefixids[] = $prefixid;
		}
	}

	if ($update_prefixids)
	{
		$from_options = $prefix_options[$from_prefixid];
		$from_restrictions = $prefix_restrictions[$from_prefixid];

		$assertor->update('vBForum:prefix', ['options' => $from_options], ['prefixid' => $update_prefixids]);
		$assertor->delete('vBForum:prefixpermission', ['prefixid' => $update_prefixids]);

		$restriction_insert = [];
		foreach ($update_prefixids AS $prefixid)
		{
			foreach ($from_restrictions AS $usergroupid)
			{
				$restriction_insert[] = [$prefixid, $usergroupid];
			}
		}

		if ($restriction_insert)
		{
			$assertor->insertMultiple('vBForum:prefixpermission', ['prefixid', 'usergroupid'], $restriction_insert);
		}

		vB_Library::instance('prefix')->buildDatastore();
	}

	print_stop_message('duplicated_prefix_permissions', get_admincp_url('prefix', ['do' => 'list']));
}

// ########################################################################

$vbulletin->input->clean_array_gpc('p', [
	'dopermissionsmultiple' => vB_Cleaner::TYPE_STR
]);

if ($vbulletin->GPC['dopermissionsmultiple'])
{
	$vbulletin->input->clean_array_gpc('p', [
		'prefixids' => vB_Cleaner::TYPE_ARRAY_KEYS_STR
	]);

	if (empty($vbulletin->GPC['prefixids']))
	{
		print_stop_message('you_did_not_select_any_prefixes');
	}

	$_POST['do'] = $_REQUEST['do'] = 'permissions';
}

// ########################################################################

if ($_REQUEST['do'] == 'permissions')
{
	if (empty($vbulletin->GPC['prefixids']))
	{
		$vbulletin->input->clean_array_gpc('r', [
			'prefixid' => vB_Cleaner::TYPE_STR
		]);

		$prefixids = [$vbulletin->GPC['prefixid']];
	}
	else
	{
		$prefixids = $vbulletin->GPC['prefixids'];
	}

	$prefixes = $vbulletin->db->query_read("
		SELECT prefix.prefixid, prefix.options, prefixpermission.usergroupid AS restriction FROM " . TABLE_PREFIX . "prefix AS prefix
		LEFT JOIN " . TABLE_PREFIX . "prefixpermission AS prefixpermission ON (prefix.prefixid = prefixpermission.prefixid)
		WHERE prefix.prefixid IN ('" . implode("', '", array_map([$vbulletin->db, 'escape_string'], $prefixids)) . "')
	");

	$prefixdefaults = $prefixpermissions = [];

	while ($prefix = $vbulletin->db->fetch_array($prefixes))
	{
		if (empty($prefixpermissions["$prefix[prefixid]"]))
		{
			$prefixpermissions["$prefix[prefixid]"] = [intval($prefix['restriction'])];
		}
		else
		{
			$prefixpermissions["$prefix[prefixid]"][] = intval($prefix['restriction']);
		}

		$prefixdefaults[] = !$prefix['options'] & $vbulletin->bf_misc_prefixoptions['deny_by_default'];
	}
	$vbulletin->db->free_result($prefixes);

	$usergroupperms = [];
	foreach ($prefixpermissions AS $prefixid => $restrictions)
	{
		foreach ($restrictions AS $restriction)
		{
			if ($restriction)
			{
				if (empty($usergroupperms["$restriction"]))
				{
					$usergroupperms["$restriction"] = [$prefixid];
				}
				else
				{
					$usergroupperms["$restriction"][] = $prefixid;
				}
			}
		}
	}

	$conflicts = [];
	foreach ($usergroupperms AS $usergroup => $prefixes)
	{
		if (array_diff($prefixids, $prefixes))
		{
			$conflicts[] = $usergroup;
		}
	}

	if (!empty($conflicts))
	{
		$conflict_options = [
			$vbphrase['do_not_resolve_permission_conflict'],
			$vbphrase['grant_permission_for_selected_prefixes'],
			$vbphrase['deny_permission_for_selected_prefixes']
		];
	}

	$prefix_html = [];
	foreach ($prefixids AS $prefixid)
	{
		$prefix_html[] = '<a href="admincp/prefix.php?do=editprefix&amp;prefixid=' . htmlspecialchars_uni($prefixid) . '">' . htmlspecialchars_uni($vbphrase["prefix_{$prefixid}_title_plain"]) . '</a>';
	}

	print_form_header2('admincp/prefix', 'savepermissions');
	print_table_start2();
	print_table_header($vbphrase['edit_thread_prefix_permissions']);

	construct_hidden_code('prefixids', sign_client_string(serialize($prefixids)));
	construct_hidden_code('shownusergroups', sign_client_string(serialize(array_keys($vbulletin->usergroupcache))));

	print_description_row(construct_phrase($vbphrase['editing_permissions_for_x'], implode(', ', $prefix_html)));
	if (count(array_unique($prefixdefaults)) <= 1)
	{
		print_yes_no_row($vbphrase['allow_new_groups_to_use_selected_prefixes'], 'default', $prefixdefaults[0]);
	}
	else
	{
		$conflict_options_default = [
			'-1' => $vbphrase['leave_default_permissions_unchanged'],
			'1'  => $vbphrase['new_groups_may_use_selected_prefixes'],
			'0'  => $vbphrase['new_groups_may_not_use_selected_prefixes']
		];

		print_label_row(
			$vbphrase['allow_new_groups_to_use_selected_prefixes'],
			"<label for=\"sel_default\" class=\"smallfont\">" . $vbphrase['set_default_permissions'] . ": <select name=\"default\" id=\"sel_default\">" . construct_select_options($conflict_options_default, '-1') . "</select>"
		);
	}

	print_description_row('<label><input class="js-checkbox-master" type="checkbox"' . (empty($usergroupperms) ? ' checked="checked"' : '') . " />$vbphrase[check_uncheck_all]</label>", false, 2, 'thead');

	foreach ($vbulletin->usergroupcache AS $usergroupid => $usergroup)
	{
		if (in_array($usergroupid, $conflicts))
		{
			print_label_row(
				"<label><input type=\"checkbox\" disabled=\"disabled\"/>$usergroup[title]</label>",
				"<label for=\"sel_ug$usergroupid\" class=\"smallfont\">" . $vbphrase['resolve_permission_conflict'] . ": <select name=\"conflict[$usergroupid]\" id=\"sel_ug$usergroupid\">" . construct_select_options($conflict_options, 0) . "</select>"

			);
		}
		else
		{
			print_description_row("<label><input type=\"checkbox\" name=\"usergroup[$usergroupid]\" class=\"js-checkbox-child\"" . (empty($usergroupperms["$usergroupid"]) ? ' checked="checked"' : '') . " />$usergroup[title]</label>");

		}
	}

	print_submit_row();
}

// ########################################################################

if ($_POST['do'] == 'savepermissions')
{
	$vbulletin->input->clean_array_gpc('p', [
		'prefixids' => vB_Cleaner::TYPE_NOCLEAN,
		'shownusergroups' => vB_Cleaner::TYPE_NOCLEAN,
		'conflict' => vB_Cleaner::TYPE_ARRAY_INT,
		'usergroup' => vB_Cleaner::TYPE_ARRAY_KEYS_INT,
	]);

	$prefixids_raw = vb_unserialize_array(verify_client_string($vbulletin->GPC['prefixids']));
	$prefixids = [];
	foreach ($prefixids_raw AS $prefixid)
	{
		$prefixids[] = $vbulletin->cleaner->clean($prefixid, vB_Cleaner::TYPE_STR);
	}

	$shownusergroups_raw = vb_unserialize_array(verify_client_string($vbulletin->GPC['shownusergroups']));
	$shownusergroups = [];
	foreach ($shownusergroups_raw AS $shownusergroup)
	{
		$shownusergroups[] = $vbulletin->cleaner->clean($shownusergroup, vB_Cleaner::TYPE_UINT);
	}

	if (empty($prefixids))
	{
		print_stop_message('you_did_not_select_any_prefixes');
	}

	$assertor = vB::getDbAssertor();
	$result = $assertor->select('vBForum:prefixpermission', ['prefixid' => $prefixids], ['usergroupid', 'prefixid']);
	$prefixpermissions = vB_Utility_Functions::iterableColumnGrouped($result, 'usergroupid', 'prefixid');

	$usergroupperms = [];
	foreach ($prefixpermissions AS $prefixid => $restrictions)
	{
		foreach ($restrictions AS $restriction)
		{
			$restriction = intval($restriction);
			if ($restriction)
			{
				if (empty($usergroupperms["$restriction"]))
				{
					$usergroupperms["$restriction"] = [$prefixid];
				}
				else
				{
					$usergroupperms["$restriction"][] = $prefixid;
				}
			}
		}
	}

	$conflicts = [];
	$override_no = [];
	foreach ($usergroupperms AS $usergroup => $prefixes)
	{
		if (in_array($usergroup, array_keys($vbulletin->GPC['conflict'])))
		{
			if ($vbulletin->GPC['conflict']["$usergroup"] === 0)
			{
				$conflicts[] = $usergroup;
			}
			else if ($vbulletin->GPC['conflict']["$usergroup"] === 2)
			{
				$override_no[] = $usergroup;
			}
		}
		else if (array_diff($prefixids, $prefixes)) // Marks as conflict when saving in race condition
		{
			if ($vbulletin->GPC['conflict']["$usergroup"] === 0)
			{
				$conflicts[] = $usergroup;
			}
		}
	}

	$vbulletin->db->query_write("
		DELETE FROM " . TABLE_PREFIX . "prefixpermission
		WHERE prefixid IN ('" . implode("', '", array_map([$vbulletin->db, 'escape_string'], $prefixids)) . "')
		" . (!empty($conflicts) ? "AND usergroupid NOT IN (" . implode(', ', $conflicts) . ")" : '')
	);

	$todeny = [];
	foreach ($shownusergroups AS $shownusergroup)
	{
		if (array_key_exists($shownusergroup, $vbulletin->usergroupcache))
		{
			if (!in_array($shownusergroup, $conflicts))
			{
				if (!in_array($shownusergroup, $vbulletin->GPC['usergroup']) AND !in_array($shownusergroup, array_keys($vbulletin->GPC['conflict'])))
				{
					$todeny[] = $shownusergroup;
				}
			}
		}
	}

	$todeny = array_merge($todeny, $override_no);

	$sql_values = [];
	foreach ($prefixids AS $prefixid)
	{
		foreach ($todeny AS $deny)
		{
			$sql_values[] = [$prefixid, $deny];
		}
	}

	if ($sql_values)
	{
		$assertor->insertMultiple('vBForum:prefixpermission', ['prefixid', 'usergroupid'], $sql_values);
	}

	$vbulletin->input->clean_array_gpc('p', [
		'default' => vB_Cleaner::TYPE_INT
	]);

	if ($vbulletin->GPC['default'] != -1)
	{
		$vbulletin->db->query_write("
			UPDATE " . TABLE_PREFIX . "prefix SET options = options " . (empty($vbulletin->GPC['default']) ? '| ' : '& ~') . $vbulletin->bf_misc_prefixoptions['deny_by_default'] . "
			WHERE prefixid IN ('" . implode("', '", array_map([$vbulletin->db, 'escape_string'], $prefixids)) . "')
		");
	}
	vB_Library::instance('prefix')->buildDatastore();

	print_stop_message('saved_prefix_permissions', get_admincp_url('prefix', ['do' => 'list']));
}

// ########################################################################

if ($_POST['do'] == 'killprefix')
{
	$vbulletin->input->clean_array_gpc('p', [
		'prefixid' => vB_Cleaner::TYPE_NOHTML,
	]);

	vB_Library::instance('prefix')->deletePrefix($vbulletin->GPC['prefixid']);
	print_stop_message('prefix_deleted', get_admincp_url('prefix', ['do' => 'list']));
}

// ########################################################################

if ($_REQUEST['do'] == 'deleteprefix')
{
	$vbulletin->input->clean_array_gpc('r', [
		'prefixid' => vB_Cleaner::TYPE_NOHTML,
	]);

	$assertor = vB::getDbAssertor();
	$prefix = $assertor->getRow('vBForum:prefix', ['prefixid' => $vbulletin->GPC['prefixid']], false, ['prefixid']);

	if (!$prefix)
	{
		print_stop_message(['could_not_find', '<b>prefix</b>', 'prefixid', $vbulletin->GPC['prefixid']]);
	}

	$title = $vbphrase['prefix_' . $prefix['prefixid'] . '_title_plain'];
	$description = construct_phrase(
		$vbphrase['are_you_sure_want_to_delete_prefix_x'],
		$title,
		'prefixid',
		$prefix['prefixid'],
	);

	$header = construct_phrase($vbphrase['confirm_deletion_x'], htmlspecialchars_uni($title));
	$hidden = ['prefixid' => $prefix['prefixid']];
	print_confirmation($vbphrase, 'prefix', 'killprefix', $description, $hidden, $header);
}

// ########################################################################

if ($_POST['do'] == 'insertprefix')
{
	$vbulletin->input->clean_array_gpc('p', [
		'prefixid' => vB_Cleaner::TYPE_NOHTML,
		'origprefixid' => vB_Cleaner::TYPE_NOHTML,
		'prefixsetid' => vB_Cleaner::TYPE_NOHTML,
		'title_plain' => vB_Cleaner::TYPE_STR,
		'title_rich' => vB_Cleaner::TYPE_STR,
		'displayorder' => vB_Cleaner::TYPE_UINT
	]);

	$prefixdm = new vB_DataManager_Prefix(vB_DataManager_Constants::ERRTYPE_CP);

	if ($vbulletin->GPC['origprefixid'])
	{
		$prefix = $assertor->getRow('vBForum:prefix', ['prefixid' => $vbulletin->GPC['origprefixid']]);
		if (!$prefix)
		{
			print_stop_message('invalid_action_specified');
		}

		$prefixdm->set_existing($prefix);
	}
	else
	{
		$prefixdm->set('prefixid', $vbulletin->GPC['prefixid']);
	}

	$prefixdm->set('prefixsetid', $vbulletin->GPC['prefixsetid']);
	$prefixdm->set('displayorder', $vbulletin->GPC['displayorder']);
	$prefixdm->set_info('title_plain', $vbulletin->GPC['title_plain']);
	$prefixdm->set_info('title_rich', $vbulletin->GPC['title_rich']);
	$prefixdm->set('options', $vbulletin->bf_misc_prefixoptions['deny_by_default']);

	$prefixdm->save();

	print_stop_message('prefix_saved', get_admincp_url('prefix', ['do' => 'list']));
}

// ########################################################################

if ($_REQUEST['do'] == 'addprefix' OR $_REQUEST['do'] == 'editprefix')
{
	$vbulletin->input->clean_array_gpc('r', [
		'prefixid' => vB_Cleaner::TYPE_NOHTML,
		'prefixsetid' => vB_Cleaner::TYPE_NOHTML
	]);

	// fetch existing prefix if we want to edit
	if ($vbulletin->GPC['prefixid'])
	{
		$prefix = $assertor->getRow('vBForum:prefix', ['prefixid' => $vbulletin->GPC['prefixid']]);
	}

	print_form_header2('admincp/prefix', 'insertprefix');
	print_table_start2();

	// if not editing a set, setup the default for a new set
	if (empty($prefix))
	{
		$prefix = [
			'prefixid' => '',
			'prefixsetid' => $vbulletin->GPC['prefixsetid'],
			'title_plain' => '',
			'title_rich' => '',
			'displayorder' => 10
		];

		print_table_header($vbphrase['adding_prefix']);
		print_input_row($vbphrase['prefix_id_alphanumeric_note'], 'prefixid', '', true, 35, 25);

		$plaintranslink = '';
		$richtranslink = '';
	}
	else
	{
		$plaintitlephrase = 'prefix_' . $prefix['prefixid'] . '_title_plain';
		$richtitlephrase = 'prefix_' . $prefix['prefixid'] . '_title_rich';

		$phraseApi = vB_Api::instanceInternal('phrase');
		$basephrase = $phraseApi->getBasePhrases([$plaintitlephrase, $richtitlephrase]);

		$prefix['title_plain'] = $basephrase['phrases'][$plaintitlephrase];
		$prefix['title_rich'] = $basephrase['phrases'][$richtitlephrase];

		print_table_header($vbphrase['editing_prefix']);
		print_label_row($vbphrase['prefix_id_alphanumeric_note'], $prefix['prefixid'], '', 'top', 'prefixid');
		construct_hidden_code('origprefixid', $prefix['prefixid']);

		$plaintranslink = '<dfn>' . construct_translation_link($vbphrase['translations'], 'global', $plaintitlephrase) . '</dfn>';
		$richtranslink = '<dfn>' . construct_translation_link($vbphrase['translations'], 'global', $richtitlephrase) . '</dfn>';
	}

	$result = $assertor->select('vBForum:prefixset', [], 'displayorder', ['prefixsetid']);
	$prefixsets = [];
	foreach ($result AS $row)
	{
		$prefixsets[$row['prefixsetid']] = $vbphrase['prefixset_' . $row['prefixsetid'] . '_title'];
	}

	print_select_row($vbphrase['prefix_set'], 'prefixsetid', $prefixsets, $prefix['prefixsetid'], true);
	print_input_row($vbphrase['title_plain_text'] . $plaintranslink, 'title_plain', $prefix['title_plain']);
	print_input_row($vbphrase['title_rich_text'] . $richtranslink, 'title_rich', $prefix['title_rich']);
	print_input_row($vbphrase['display_order'], 'displayorder', $prefix['displayorder']);
	print_submit_row();
}

// ########################################################################

if ($_POST['do'] == 'killset')
{
	$vbulletin->input->clean_array_gpc('p', [
		'prefixsetid' => vB_Cleaner::TYPE_NOHTML,
	]);

	vB_Library::instance('prefix')->deletePrefixSet($vbulletin->GPC['prefixsetid']);
	print_stop_message('prefix_set_deleted', get_admincp_url('prefix', ['do' => 'list']));
}

// ########################################################################

if ($_REQUEST['do'] == 'deleteset')
{
	$vbulletin->input->clean_array_gpc('r', [
		'prefixsetid' => vB_Cleaner::TYPE_NOHTML,
	]);

	$assertor = vB::getDbAssertor();
	$prefixset = $assertor->getRow('vBForum:prefixset', ['prefixsetid' => $vbulletin->GPC['prefixsetid']], false, ['prefixsetid']);
	if (!$prefixset)
	{
		print_stop_message(['could_not_find', '<b>prefixset</b>', 'prefixsetid', $vbulletin->GPC['prefixsetid']]);
	}

	$title = $vbphrase['prefixset_' . $prefixset['prefixsetid'] . '_title'];
	$description = construct_phrase(
		$vbphrase['are_you_sure_want_to_delete_prefixset_x'],
		$title,
		'prefixsetid',
		$prefixset['prefixsetid'],
	);

	$header = construct_phrase($vbphrase['confirm_deletion_x'], htmlspecialchars_uni($title));
	$hidden = ['prefixsetid' => $prefixset['prefixsetid']];
	print_confirmation($vbphrase, 'prefix', 'killset', $description, $hidden, $header);
}

// ########################################################################

if ($_POST['do'] == 'insertset')
{
	$vbulletin->input->clean_array_gpc('p', [
		'prefixsetid' => vB_Cleaner::TYPE_NOHTML,
		'origprefixsetid' => vB_Cleaner::TYPE_NOHTML,
		'title' => vB_Cleaner::TYPE_STR,
		'displayorder' => vB_Cleaner::TYPE_UINT,
		'nodeids' => vB_Cleaner::TYPE_ARRAY_INT
	]);

	$assertor = vB::getDbAssertor();
	$prefixsetdm = new vB_DataManager_PrefixSet(vB_DataManager_Constants::ERRTYPE_CP);

	if ($vbulletin->GPC['origprefixsetid'])
	{
		$prefixset = $assertor->getRow('vBForum:prefixset', ['prefixsetid' => $vbulletin->GPC['origprefixsetid']]);
		if (!$prefixset)
		{
			print_stop_message('invalid_action_specified_gcpglobal');
		}

		$prefixsetdm->set_existing($prefixset);
	}
	else
	{
		$prefixsetdm->set('prefixsetid', $vbulletin->GPC['prefixsetid']);
	}

	$prefixsetdm->set('displayorder', $vbulletin->GPC['displayorder']);
	$prefixsetdm->set_info('title', $vbulletin->GPC['title']);

	$prefixsetdm->save();
	$vbulletin->GPC['prefixsetid'] = $prefixsetdm->fetch_field('prefixsetid');

	// setup this prefix set for selected forums
	// We check origprefixsetid but then fetch based on prefixsetid.  That looks odd but not going to touch it.
	$old_channels = [];
	if ($vbulletin->GPC['origprefixsetid'])
	{
		// find where the prefix used to be used
		$channel_list_sql = $vbulletin->db->query_read("
			SELECT nodeid
			FROM " . TABLE_PREFIX . "channelprefixset
			WHERE prefixsetid = '" . $vbulletin->db->escape_string($vbulletin->GPC['prefixsetid']) . "'
		");
		while ($channel = $vbulletin->db->fetch_array($channel_list_sql))
		{
			$old_channels[] = $channel['nodeid'];
		}
	}

	$new_channels = array_diff($vbulletin->GPC['nodeids'], [-1, 0]);

	$vbulletin->db->query_write("
		DELETE FROM " . TABLE_PREFIX . "channelprefixset
		WHERE prefixsetid = '" . $vbulletin->db->escape_string($vbulletin->GPC['prefixsetid']) . "'
	");

	$add_channels_query = [];
	$escaped_id = $vbulletin->db->escape_string($vbulletin->GPC['prefixsetid']);

	foreach ($new_channels AS $channelid)
	{
		$add_channels_query[] = "($channelid, '$escaped_id')";
	}

	if ($add_channels_query)
	{
		$vbulletin->db->query_write("
			INSERT IGNORE INTO " . TABLE_PREFIX . "channelprefixset
				(nodeid, prefixsetid)
			VALUES
				" . implode(',', $add_channels_query)
		);
	}

	// find the forums that were removed and remove these prefixes from threads
	$removed_channels = array_diff($old_channels, $new_channels);
	if ($removed_channels)
	{
		$prefixes = [];
		$prefix_sql = $vbulletin->db->query_read("
			SELECT prefixid
			FROM " . TABLE_PREFIX . "prefix
			WHERE prefixsetid = '" . $vbulletin->db->escape_string($vbulletin->GPC['prefixsetid']) . "'
		");
		while ($prefix = $vbulletin->db->fetch_array($prefix_sql))
		{
			$prefixes[] = $prefix['prefixid'];
		}

		remove_prefixes_forum($prefixes, $removed_channels);
	}

	vB_Library::instance('prefix')->buildDatastore();
	print_stop_message('prefix_set_saved', get_admincp_url('prefix', ['do' => 'list']));
}

// ########################################################################

if ($_REQUEST['do'] == 'addset' OR $_REQUEST['do'] == 'editset')
{
	$vbulletin->input->clean_array_gpc('r', [
		'prefixsetid' => vB_Cleaner::TYPE_NOHTML
	]);

	$assertor = vB::getDbAssertor();

	// fetch existing prefix set if we want to edit
	if ($vbulletin->GPC['prefixsetid'])
	{
		$prefixset = $assertor->getRow('vBForum:prefixset', ['prefixsetid' => $vbulletin->GPC['prefixsetid']]);
	}

	print_form_header2('admincp/prefix', 'insertset');
	print_table_start2();

	if (!empty($prefixset))
	{
		$titlephrase = 'prefixset_' . $prefixset['prefixsetid'] . '_title';

		$phraseApi = vB_Api::instanceInternal('phrase');
		$basephrase = $phraseApi->getBasePhrases([$titlephrase]);
		$prefixset['title'] = reset($basephrase['phrases']);

		print_table_header($vbphrase['editing_prefix_set']);
		print_label_row($vbphrase['prefix_set_id_alphanumeric_note'], $prefixset['prefixsetid'], '', 'top', 'prefixsetid');
		construct_hidden_code('origprefixsetid', $prefixset['prefixsetid']);
		$translink = '<dfn>' . construct_translation_link($vbphrase['translations'], 'prefix', $titlephrase) . '</dfn>';
		$enabled_channels = $assertor->getColumn('vBForum:channelprefixset', 'nodeid', ['prefixsetid' => $prefixset['prefixsetid']]);
	}
	else
	{
		$prefixset = [
			'prefixsetid' => '',
			'title' => '',
			'displayorder' => 10
		];

		print_table_header($vbphrase['adding_prefix_set']);
		print_input_row($vbphrase['prefix_set_id_alphanumeric_note'], 'prefixsetid', '', true, 35, 25);
		$translink = '';
		$enabled_channels = [];
	}

	print_input_row($vbphrase['title'] . $translink, 'title', $prefixset['title']);
	print_input_row($vbphrase['display_order'], 'displayorder', $prefixset['displayorder']);

	if (!$enabled_channels)
	{
		// default to selecting "none"
		$enabled_channels = [-1];
	}

	print_channel_chooser($vbphrase['use_prefix_set_in_these_channels'], 'nodeids[]', $enabled_channels, $vbphrase['none'], false, true);
	print_submit_row();
}

// ########################################################################

if ($_POST['do'] == 'displayorder')
{
	$vbulletin->input->clean_array_gpc('p', [
		'prefixset_order' => vB_Cleaner::TYPE_ARRAY_UINT,
		'prefix_order' => vB_Cleaner::TYPE_ARRAY_UINT
	]);

	$assertor = vB::getDbAssertor();

	foreach ($vbulletin->GPC['prefixset_order'] AS $prefixsetid => $displayorder)
	{
		$assertor->update('vBForum:prefixset', ['displayorder' => $displayorder], ['prefixsetid' => $prefixsetid]);
	}

	foreach ($vbulletin->GPC['prefix_order'] AS $prefixid => $displayorder)
	{
		$assertor->update('vBForum:prefix', ['displayorder' => $displayorder], ['prefixid' => $prefixid]);
	}

	vB_Library::instance('prefix')->buildDatastore();
	print_stop_message('saved_display_order_successfully', get_admincp_url('prefix', ['do' => 'list']));
}

// ########################################################################

if ($_REQUEST['do'] == 'list')
{
	$assertor = vB::getDbAssertor();

	$prefixsets = [];
	$result = $assertor->select('vBForum:prefixset', [], 'displayorder');
	foreach ($result AS $prefixset)
	{
		$prefixsets[$prefixset['prefixsetid']] = $prefixset;
		$prefixsets[$prefixset['prefixsetid']]['prefixes'] = [];
	}

	$result = $assertor->select('vBForum:prefix', [], 'displayorder');
	foreach ($result AS $prefix)
	{
		if (isset($prefixsets[$prefix['prefixsetid']]))
		{
			$prefixsets[$prefix['prefixsetid']]['prefixes'][$prefix['prefixid']] = $prefix;
		}
	}

	$colspan = 3;
	print_form_header2('admincp/prefix', 'displayorder');
	print_table_start();
	print_table_header($vbphrase['thread_prefixes_gprefixadmin'], $colspan);

	if (!$prefixsets)
	{
		print_description_row($vbphrase['no_prefix_sets_defined_click_create'], false, 3, '', 'center');
	}
	else
	{
		// display existing sets
		foreach ($prefixsets AS $prefixset)
		{
			$setid = $prefixset['prefixsetid'];
			$setname = htmlspecialchars_uni($vbphrase['prefixset_' . $setid . '_title']);

			$cells = [];
			$cells[] = construct_checkbox_control($setname, '', false, 0, ['data-child' => 'js-checkbox-child-' . $setid, 'class' => 'js-checkbox-master']);
			$cells[] = construct_displayorder_control('prefixset_order[' . $setid . ']', $prefixset['displayorder'], $vbphrase['display_order']);
			$cells[] = '<div class="normal">' .
				construct_link_code2($vbphrase['add_prefix'], get_admincp_url('prefix', ['do' => 'addprefix', 'prefixsetid' => $setid])) .
				construct_link_code2($vbphrase['edit'], get_admincp_url('prefix', ['do' => 'editset', 'prefixsetid' => $setid])) .
				construct_link_code2($vbphrase['delete'], get_admincp_url('prefix', ['do' => 'deleteset', 'prefixsetid' => $setid])) .
				'</div>';

			print_cells_row2($cells, 'thead');

			if (!$prefixset['prefixes'])
			{
				print_description_row(construct_phrase($vbphrase['no_prefixes_defined_click_create'], $prefixset['prefixsetid']), false, $colspan, '', 'center');
			}
			else
			{
				foreach ($prefixset['prefixes'] AS $prefix)
				{
					$prefixid = $prefix['prefixid'];
					$prefixname = htmlspecialchars_uni($vbphrase['prefix_' . $prefixid . '_title_plain']);

					$cells = [];
					$cells[] = construct_checkbox_control($prefixname, 'prefixids[' . $prefixid . ']', false, 0, ['class' => 'js-checkbox-child-' . $setid]);
					$cells[] = construct_displayorder_control('prefix_order[' . $prefixid . ']', $prefix['displayorder'], $vbphrase['display_order']);

					$cells[] = '<div class="smallfont">' .
						construct_link_code2($vbphrase['edit'], get_admincp_url('prefix', ['do' => 'editprefix', 'prefixid' => $prefixid])) .
						construct_link_code2($vbphrase['delete'], get_admincp_url('prefix', ['do' => 'deleteprefix', 'prefixid' => $prefixid])) .
						construct_link_code2($vbphrase['edit_permissions'], get_admincp_url('prefix', ['do' => 'permissions', 'prefixid' => $prefixid])) .
						'</div>';

					print_cells_row2($cells);
				}
			}
		}
	}

	$buttons = [
		construct_submit_button($vbphrase['edit_selected_prefix_permissions'], [], ['name' => 'dopermissionsmultiple']),
		construct_submit_button($vbphrase['save_display_order']),
		construct_link_button($vbphrase['add_prefix_set'] , get_admincp_url('prefix', ['do' => 'addset'])),
	];

	print_table_button_footer($buttons, $colspan);
}

print_cp_footer();

/*=========================================================================*\
|| #######################################################################
|| # Downloaded: 13:27, Sun Aug 30th 2026
|| # CVS: $RCSfile$ - $Revision: 122391 $
|| #######################################################################
\*=========================================================================*/
