Extensions
This commit is contained in:
613
ext/phpbbstudio/dice/controller/admin_controller.php
Normal file
613
ext/phpbbstudio/dice/controller/admin_controller.php
Normal file
@@ -0,0 +1,613 @@
|
||||
<?php
|
||||
/**
|
||||
* phpBB Studio's Dice extension for the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) 2019 phpBB Studio <https://www.phpbbstudio.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*/
|
||||
|
||||
namespace phpbbstudio\dice\controller;
|
||||
|
||||
/**
|
||||
* phpBB Studio's Dice Admin controller.
|
||||
*/
|
||||
class admin_controller implements admin_interface
|
||||
{
|
||||
/** @var \phpbb\config\config */
|
||||
protected $config;
|
||||
|
||||
/** @var \phpbb\db\driver\driver_interface */
|
||||
protected $db;
|
||||
|
||||
/** @var \phpbbstudio\dice\core\functions_common */
|
||||
protected $functions;
|
||||
|
||||
/** @var \phpbb\language\language */
|
||||
protected $lang;
|
||||
|
||||
/** @var \phpbb\log\log */
|
||||
protected $log;
|
||||
|
||||
/** @var \phpbb\request\request */
|
||||
protected $request;
|
||||
|
||||
/** @var \phpbb\template\template */
|
||||
protected $template;
|
||||
|
||||
/** @var \phpbb\user */
|
||||
protected $user;
|
||||
|
||||
/** @var \phpbb\user_loader */
|
||||
protected $user_loader;
|
||||
|
||||
/** @var string Forums table */
|
||||
protected $forums_table;
|
||||
|
||||
/** @var string Dice rolls table*/
|
||||
protected $rolls_table;
|
||||
|
||||
/** @var string Topics table */
|
||||
protected $topics_table;
|
||||
|
||||
/** @var string phpBB root path */
|
||||
protected $root_path;
|
||||
|
||||
/** @var string php File extension */
|
||||
protected $php_ext;
|
||||
|
||||
/** @var string Custom form action */
|
||||
protected $u_action;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param \phpbb\config\config $config Configuration object
|
||||
* @param \phpbb\db\driver\driver_interface $db Database object
|
||||
* @param \phpbbstudio\dice\core\functions_common $functions Common dice functions
|
||||
* @param \phpbb\language\language $lang Language object
|
||||
* @param \phpbb\log\log $log Log object
|
||||
* @param \phpbb\request\request $request Request object
|
||||
* @param \phpbb\template\template $template Template object
|
||||
* @param \phpbb\user $user User object
|
||||
* @param \phpbb\user_loader $user_loader User loader object
|
||||
* @param string $forums_table Forums table
|
||||
* @param string $rolls_table Dice rolls table
|
||||
* @param string $topics_table Topics table
|
||||
* @param string $root_path phpBB root path
|
||||
* @param string $php_ext phpEx
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
public function __construct(
|
||||
\phpbb\config\config $config,
|
||||
\phpbb\db\driver\driver_interface $db,
|
||||
\phpbbstudio\dice\core\functions_common $functions,
|
||||
\phpbb\language\language $lang,
|
||||
\phpbb\log\log $log,
|
||||
\phpbb\request\request $request,
|
||||
\phpbb\template\template $template,
|
||||
\phpbb\user $user,
|
||||
\phpbb\user_loader $user_loader,
|
||||
$forums_table,
|
||||
$rolls_table,
|
||||
$topics_table,
|
||||
$root_path,
|
||||
$php_ext
|
||||
)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->db = $db;
|
||||
$this->functions = $functions;
|
||||
$this->lang = $lang;
|
||||
$this->log = $log;
|
||||
$this->request = $request;
|
||||
$this->template = $template;
|
||||
$this->user = $user;
|
||||
$this->user_loader = $user_loader;
|
||||
$this->forums_table = $forums_table;
|
||||
$this->rolls_table = $rolls_table;
|
||||
$this->topics_table = $topics_table;
|
||||
|
||||
$this->root_path = $root_path;
|
||||
$this->php_ext = $php_ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function handle($action)
|
||||
{
|
||||
// Requests
|
||||
$submit = $this->request->is_set_post('submit');
|
||||
$value = $this->request->variable('value', '');
|
||||
|
||||
// Add a form key to the settings
|
||||
$form_key = 'dice_settings';
|
||||
add_form_key($form_key);
|
||||
|
||||
// Set up config settings
|
||||
$options = [
|
||||
'dice_sides_only',
|
||||
'dice_max_rolls',
|
||||
'dice_per_notation',
|
||||
'dice_qty_per_dice',
|
||||
'dice_qty_dice_per_notation',
|
||||
'dice_sides_per_dice',
|
||||
'dice_pc_dice_per_notation',
|
||||
'dice_fudge_dice_per_notation',
|
||||
'dice_penetration_dice_per_notation',
|
||||
'dice_compound_dice_per_notation',
|
||||
'dice_exploding_dice_per_notation',
|
||||
];
|
||||
|
||||
// Assign config settings
|
||||
$template_vars = [];
|
||||
foreach ($options as $option)
|
||||
{
|
||||
$template_vars[utf8_strtoupper($option)] = $this->config[$option];
|
||||
}
|
||||
|
||||
// Get the roll count from the database
|
||||
$rolls_total = $this->db->get_estimated_row_count($this->rolls_table);
|
||||
|
||||
// Get the orphaned roll count from the database
|
||||
$sql = 'SELECT COUNT(roll_id) as orphans FROM ' . $this->rolls_table . ' WHERE roll_id = 0 OR post_id = 0 OR topic_id = 0 OR forum_id = 0 OR user_id = 0';
|
||||
$result = $this->db->sql_query($sql);
|
||||
$rolls_orphan = $this->db->sql_fetchfield('orphans');
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
// Select the top topics with the most rolls
|
||||
$sql_array = [
|
||||
'SELECT' => 'COUNT(r.roll_id) as total,
|
||||
t.topic_id, t.topic_title,
|
||||
f.forum_id, f.forum_name',
|
||||
'FROM' => [$this->rolls_table => 'r'],
|
||||
'LEFT_JOIN' => [
|
||||
[
|
||||
'FROM' => [$this->topics_table => 't'],
|
||||
'ON' => 't.topic_id = r.topic_id',
|
||||
],
|
||||
[
|
||||
'FROM' => [$this->forums_table => 'f'],
|
||||
'ON' => 'f.forum_id = r.forum_id',
|
||||
],
|
||||
],
|
||||
'GROUP_BY' => 'r.topic_id, t.topic_title, f.forum_id, f.forum_name',
|
||||
'ORDER_BY' => 'total DESC',
|
||||
];
|
||||
|
||||
$sql = $this->db->sql_build_query('SELECT', $sql_array);
|
||||
$result = $this->db->sql_query_limit($sql, 8);
|
||||
|
||||
while ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
$this->template->assign_block_vars('topics', [
|
||||
'FORUM_NAME' => $row['forum_name'],
|
||||
'TOPIC_TITLE' => $row['topic_title'],
|
||||
'TOTAL' => (int) $row['total'],
|
||||
|
||||
'U_FORUM' => append_sid($this->root_path . 'viewforum.' . $this->php_ext, ['f' => (int) $row['forum_id']]),
|
||||
'U_TOPIC' => append_sid($this->root_path . 'viewtopic.' . $this->php_ext, ['f' => (int) $row['forum_id'], 't' => (int) $row['topic_id']]),
|
||||
]);
|
||||
}
|
||||
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
// Select the top users with the most rolls
|
||||
$users = [];
|
||||
|
||||
$sql = 'SELECT COUNT(roll_id) as total, user_id
|
||||
FROM ' . $this->rolls_table . '
|
||||
WHERE user_id > 0
|
||||
GROUP BY user_id
|
||||
ORDER BY total DESC';
|
||||
$result = $this->db->sql_query_limit($sql, 8);
|
||||
|
||||
while ($row = $this->db->sql_fetchrow($result))
|
||||
{
|
||||
$users[(int) $row['user_id']] = (int) $row['total'];
|
||||
}
|
||||
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
// Load the top users in the user_loader
|
||||
$this->user_loader->load_users(array_keys($users));
|
||||
|
||||
// Assign the users data to the template
|
||||
foreach ($users as $user_id => $total)
|
||||
{
|
||||
$this->template->assign_block_vars('users', [
|
||||
'AVATAR' => (string) $this->user_loader->get_avatar($user_id),
|
||||
'NAME' => (string) $this->user_loader->get_username($user_id, 'full'),
|
||||
'TOTAL' => (int) $total,
|
||||
]);
|
||||
}
|
||||
|
||||
// Dice sides
|
||||
$sides = $this->functions->get_dice_sides();
|
||||
|
||||
foreach ($sides as $side)
|
||||
{
|
||||
$this->template->assign_block_vars('sides', [
|
||||
'NUMBER' => $side,
|
||||
'U_DELETE' => $this->u_action . '&action=side_delete&value=' . $side,
|
||||
]);
|
||||
}
|
||||
|
||||
// Dice skins
|
||||
$skins = $this->functions->get_dice_skins();
|
||||
$skins_dir_valid = $this->functions->check_dice_skins_dir();
|
||||
|
||||
$skins_all_valid = true;
|
||||
|
||||
if ($skins_dir_valid)
|
||||
{
|
||||
$skins_available = $this->functions->available_dice_skins();
|
||||
|
||||
foreach($skins_available as $skin)
|
||||
{
|
||||
$valid = (bool) $this->functions->validate_dice_skin($skin, $sides);
|
||||
$installed = (bool) in_array($skin, $skins);
|
||||
|
||||
$skins_all_valid = ($installed && !$valid) ? false : $skins_all_valid;
|
||||
|
||||
$this->template->assign_block_vars('skins', [
|
||||
'NAME' => (string) $skin,
|
||||
'S_INSTALLED' => (bool) $installed,
|
||||
'S_VALID' => (bool) $valid,
|
||||
'U_ACTION' => $this->u_action . '&action=skin_' . ($installed ? 'uninstall' : 'install') . '&value=' . $skin,
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* Any skins installed but not found in the filesystem should be automatically removed.
|
||||
*
|
||||
* Skins that are in the installed list and not in the filesystem
|
||||
*/
|
||||
$skins_difference = array_diff($skins, $skins_available);
|
||||
|
||||
if (!empty($skins_difference))
|
||||
{
|
||||
$this->skins_update('skin_uninstall', $skins, $skins_difference);
|
||||
}
|
||||
}
|
||||
|
||||
// Garbage collection
|
||||
$errors = [];
|
||||
|
||||
// If the settings were submitted
|
||||
if ($submit)
|
||||
{
|
||||
if (!check_form_key($form_key))
|
||||
{
|
||||
$errors[] = $this->lang->lang('FORM_INVALID');
|
||||
}
|
||||
|
||||
// Request the options
|
||||
$option_sides_only = $this->request->variable('dice_sides_only', (bool) $this->config['dice_sides_only']);
|
||||
$option_skins_height = (int) $this->request->variable('dice_skins_img_height', (int) $this->config['dice_skins_img_height']);
|
||||
$option_skins_width = (int) $this->request->variable('dice_skins_img_width', (int) $this->config['dice_skins_img_width']);
|
||||
|
||||
$option_skins_dir = $this->request->variable('dice_skins_dir', (string) $this->config['dice_skins_dir'], true);
|
||||
|
||||
/**
|
||||
* Let's trim a bunch of characters from the beginning and end of a string
|
||||
*
|
||||
* https://www.php.net/manual/en/function.trim.php
|
||||
*
|
||||
* " " (ASCII 32 (0x20)), an ordinary space.
|
||||
* "\t" (ASCII 9 (0x09)), a tab.
|
||||
* "\n" (ASCII 10 (0x0A)), a new line (line feed).
|
||||
* "\r" (ASCII 13 (0x0D)), a carriage return.
|
||||
* "\0" (ASCII 0 (0x00)), the NUL-byte.
|
||||
* "\x0B" (ASCII 11 (0x0B)), a vertical tab.
|
||||
*
|
||||
* Added "/"
|
||||
*/
|
||||
$option_skins_dir = trim($option_skins_dir, "/ \t\n\r\0\x0B");
|
||||
|
||||
/**
|
||||
* Let's harden all of this a bit more
|
||||
*
|
||||
* Especially Dots, Backslashes plus a bunch of other chars aren't allowed.
|
||||
*/
|
||||
if (preg_match_all('/[\\\:*<>|"]|\.{2,}|^\./', $option_skins_dir, $matches))
|
||||
{
|
||||
$character_list = implode('<br>', $matches[0]);
|
||||
|
||||
$errors[] = $this->lang->lang('ACP_DICE_SKINS_PATH_ERROR', $character_list);
|
||||
}
|
||||
|
||||
// Check if directory exists
|
||||
if (!$this->functions->check_dice_dir($this->functions->make_dice_dir($option_skins_dir)))
|
||||
{
|
||||
$errors[] = $this->lang->lang('DIRECTORY_DOES_NOT_EXIST', $option_skins_dir);
|
||||
}
|
||||
|
||||
// Check if skin images are within the 16 - 80 pixels
|
||||
if ($option_skins_height < 16 || $option_skins_height > 80)
|
||||
{
|
||||
$errors[] = $this->lang->lang('ACP_DICE_SKINS_IMG_HEIGHT_ERROR');
|
||||
}
|
||||
|
||||
if ($option_skins_width < 16 || $option_skins_width > 80)
|
||||
{
|
||||
$errors[] = $this->lang->lang('ACP_DICE_SKINS_IMG_WIDTH_ERROR');
|
||||
}
|
||||
|
||||
// No errors? Lets start saving
|
||||
if (empty($errors))
|
||||
{
|
||||
if ($option_skins_dir != $this->config['dice_skins_dir'])
|
||||
{
|
||||
$this->config->set('dice_skins_dir', $option_skins_dir);
|
||||
}
|
||||
|
||||
if ($option_skins_height != $this->config['dice_skins_img_height'])
|
||||
{
|
||||
$this->config->set('dice_skins_img_height', $option_skins_height);
|
||||
}
|
||||
|
||||
if ($option_skins_width != $this->config['dice_skins_img_width'])
|
||||
{
|
||||
$this->config->set('dice_skins_img_width', $option_skins_width);
|
||||
}
|
||||
|
||||
if ($option_sides_only != $this->config['dice_sides_only'])
|
||||
{
|
||||
$this->config->set('dice_sides_only', $option_sides_only);
|
||||
}
|
||||
|
||||
$option_numbers = [
|
||||
'dice_max_rolls',
|
||||
'dice_per_notation',
|
||||
'dice_qty_per_dice',
|
||||
'dice_qty_dice_per_notation',
|
||||
'dice_sides_per_dice',
|
||||
'dice_pc_dice_per_notation',
|
||||
'dice_fudge_dice_per_notation',
|
||||
'dice_penetration_dice_per_notation',
|
||||
'dice_compound_dice_per_notation',
|
||||
'dice_exploding_dice_per_notation',
|
||||
];
|
||||
|
||||
foreach ($option_numbers as $n)
|
||||
{
|
||||
$setting = (int) $this->config[$n];
|
||||
$value = (int) $this->request->variable($n, $setting);
|
||||
|
||||
if ($value !== $setting)
|
||||
{
|
||||
$this->config->set($n, $value);
|
||||
}
|
||||
}
|
||||
|
||||
// Log it
|
||||
$this->log->add('admin', $this->user->data['user_id'], $this->user->data['user_ip'], 'LOG_ACP_DICE_SETTINGS');
|
||||
|
||||
// Success message
|
||||
trigger_error($this->lang->lang('CONFIG_UPDATED') . adm_back_link($this->u_action));
|
||||
}
|
||||
}
|
||||
|
||||
// Process any action
|
||||
if ($action)
|
||||
{
|
||||
switch ($action)
|
||||
{
|
||||
case 'example':
|
||||
$this->template->set_filenames(['example' => '@phpbbstudio_dice/dice_example.html']);
|
||||
$this->template->assign_var('S_IS_AJAX', $this->request->is_ajax());
|
||||
|
||||
if ($this->request->is_ajax())
|
||||
{
|
||||
$json_response = new \phpbb\json_response;
|
||||
$json_response->send([
|
||||
'MESSAGE_TITLE' => $this->lang->lang('INFORMATION'),
|
||||
'MESSAGE_TEXT' => $this->template->assign_display('example'),
|
||||
]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'locations':
|
||||
// Assign the link locations
|
||||
$this->assign_link_locations();
|
||||
|
||||
if ($this->request->is_set_post('submit_locations'))
|
||||
{
|
||||
// Request the link locations
|
||||
$links = $this->request_link_locations();
|
||||
|
||||
// Set the link locations
|
||||
$this->functions->set_dice_link_locations($links);
|
||||
|
||||
// Log it
|
||||
$this->log->add('admin', $this->user->data['user_id'], $this->user->data['user_ip'], 'LOG_ACP_DICE_LOCATIONS');
|
||||
|
||||
// Success message
|
||||
trigger_error($this->lang->lang('ACP_DICE_LOCATIONS_SUCCESS') . '<br>' . adm_back_link($this->u_action));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (confirm_box(true))
|
||||
{
|
||||
switch ($action)
|
||||
{
|
||||
case 'orphaned':
|
||||
$value = $this->delete_orphans();
|
||||
break;
|
||||
|
||||
case 'side_add':
|
||||
case 'side_delete':
|
||||
$this->sides_update($action, $sides, $value);
|
||||
break;
|
||||
|
||||
case 'skin_install':
|
||||
case 'skin_uninstall':
|
||||
$this->skins_update($action, $skins, $value);
|
||||
break;
|
||||
}
|
||||
|
||||
// Log it
|
||||
$this->log->add('admin', $this->user->data['user_id'], $this->user->data['user_ip'], 'LOG_ACP_DICE_' . utf8_strtoupper($action), false, [$value]);
|
||||
|
||||
// Show success message
|
||||
trigger_error($this->lang->lang('ACP_DICE_' . utf8_strtoupper($action) . '_SUCCESS', $value) . '<br>' . adm_back_link($this->u_action));
|
||||
}
|
||||
else
|
||||
{
|
||||
confirm_box(false, 'ACP_DICE_' . utf8_strtoupper($action), build_hidden_fields([
|
||||
'action' => $action,
|
||||
'value' => $value,
|
||||
]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->template->assign_vars(array_merge($template_vars, [
|
||||
'S_ERRORS' => !empty($errors),
|
||||
'ERROR_MSG' => implode('<br>', $errors),
|
||||
|
||||
'SKINS_DIR' => $this->config['dice_skins_dir'],
|
||||
'SKINS_DIR_ERROR' => !$skins_dir_valid,
|
||||
'SKINS_IMG_HEIGHT' => $this->config['dice_skins_img_height'],
|
||||
'SKINS_IMG_WIDTH' => $this->config['dice_skins_img_width'],
|
||||
'SKINS_INSTALLED' => count($skins),
|
||||
'SKINS_VALID' => $skins_all_valid,
|
||||
'ROLLS_TOTAL' => $rolls_total,
|
||||
'ROLLS_ORPHAN' => $rolls_orphan,
|
||||
|
||||
'U_ACTION' => $this->u_action . '#dice_settings',
|
||||
'U_BACK' => $this->u_action,
|
||||
'U_EXAMPLE' => $this->u_action . '&action=example',
|
||||
'U_LOCATIONS' => $this->u_action . '&action=locations',
|
||||
'U_ORPHANED' => $this->u_action . '&action=orphaned',
|
||||
'U_SIDE_ADD' => $this->u_action . '&action=side_add',
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function set_page_url($u_action)
|
||||
{
|
||||
$this->u_action = $u_action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all orphaned dice rolls.
|
||||
*
|
||||
* @return int Amount of dice rolls that were deleted
|
||||
* @access public
|
||||
*/
|
||||
protected function delete_orphans()
|
||||
{
|
||||
$sql = 'DELETE FROM ' . $this->rolls_table . ' WHERE roll_id = 0 OR post_id = 0 OR topic_id = 0 OR forum_id = 0 OR user_id = 0';
|
||||
$this->db->sql_query($sql);
|
||||
|
||||
return (int) $this->db->sql_affectedrows();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the installed dice sides setting.
|
||||
*
|
||||
* @param string $action The action to take (side_add|side_delete)
|
||||
* @param array $sides Array of currently installed dice sides
|
||||
* @param int $value The dice side to add or delete
|
||||
* @return void
|
||||
* @access protected
|
||||
*/
|
||||
protected function sides_update($action, array $sides, $value)
|
||||
{
|
||||
switch ($action)
|
||||
{
|
||||
case 'side_add':
|
||||
$sides[] = (int) $value;
|
||||
break;
|
||||
|
||||
case 'side_delete':
|
||||
if (($key = array_search($value, $sides)) !== false)
|
||||
{
|
||||
unset($sides[$key]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Clean the array (filter, unique, sort)
|
||||
$sides = $this->functions->clean_dice_array($sides);
|
||||
|
||||
// Store the new array in the database
|
||||
$this->functions->set_dice_sides($sides);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the installed dice skin setting.
|
||||
*
|
||||
* @param string $action The action to take (skin_install|skin_uninstall)
|
||||
* @param array $skins Array of currently installed dice skins
|
||||
* @param mixed $value The value/array to install (add) or uninstall (delete)
|
||||
* @return void
|
||||
* @access protected
|
||||
*/
|
||||
protected function skins_update($action,array $skins, $value)
|
||||
{
|
||||
// Force an array, if it is not already
|
||||
$value = is_array($value) ? (array) $value : (array) [$value];
|
||||
|
||||
switch ($action)
|
||||
{
|
||||
case 'skin_install':
|
||||
$skins = array_merge($skins, $value);
|
||||
break;
|
||||
|
||||
case 'skin_uninstall':
|
||||
$skins = array_diff($skins, $value);
|
||||
break;
|
||||
}
|
||||
|
||||
// Clean the array (filter, unique, sort)
|
||||
$skins = $this->functions->clean_dice_array($skins);
|
||||
|
||||
// Store the new array in the database
|
||||
$this->functions->set_dice_skins($skins);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign link locations.
|
||||
*
|
||||
* @return void
|
||||
* @access protected
|
||||
*/
|
||||
protected function assign_link_locations()
|
||||
{
|
||||
$template_vars = [];
|
||||
$locations = $this->functions->get_dice_link_locations();
|
||||
|
||||
foreach ($locations as $location)
|
||||
{
|
||||
$template_vars[$location['name']] = (bool) $location['status'];
|
||||
}
|
||||
|
||||
$this->template->assign_vars($template_vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request link locations
|
||||
*
|
||||
* @return array Array with link locations and their status
|
||||
* @access protected
|
||||
*/
|
||||
protected function request_link_locations()
|
||||
{
|
||||
$links = [];
|
||||
$locations = $this->functions->get_dice_link_locations();
|
||||
|
||||
foreach ($locations as $location)
|
||||
{
|
||||
$links[$location['name']] = $this->request->variable((string) $location['name'], false);
|
||||
}
|
||||
|
||||
return $links;
|
||||
}
|
||||
}
|
||||
33
ext/phpbbstudio/dice/controller/admin_interface.php
Normal file
33
ext/phpbbstudio/dice/controller/admin_interface.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* phpBB Studio's Dice extension for the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) 2019 phpBB Studio <https://www.phpbbstudio.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*/
|
||||
|
||||
namespace phpbbstudio\dice\controller;
|
||||
|
||||
/**
|
||||
* phpBB Studio's Dice Admin controller interface.
|
||||
*/
|
||||
interface admin_interface
|
||||
{
|
||||
/**
|
||||
* Display and handle any actions from the Dice ACP.
|
||||
*
|
||||
* @param string $action Any action to handle
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
public function handle($action);
|
||||
|
||||
/**
|
||||
* Make the custom form action available in the admin controller.
|
||||
*
|
||||
* @param string $u_action Custom form action
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
public function set_page_url($u_action);
|
||||
}
|
||||
458
ext/phpbbstudio/dice/controller/main_controller.php
Normal file
458
ext/phpbbstudio/dice/controller/main_controller.php
Normal file
@@ -0,0 +1,458 @@
|
||||
<?php
|
||||
/**
|
||||
* phpBB Studio's Dice extension for the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) 2019 phpBB Studio <https://www.phpbbstudio.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*/
|
||||
|
||||
namespace phpbbstudio\dice\controller;
|
||||
|
||||
/**
|
||||
* phpBB Studio's Dice Main controller.
|
||||
*/
|
||||
class main_controller implements main_interface
|
||||
{
|
||||
/** @var \phpbb\auth\auth */
|
||||
protected $auth;
|
||||
|
||||
/** @var \phpbb\config\config */
|
||||
protected $config;
|
||||
|
||||
/** @var \phpbbstudio\dice\core\functions_common */
|
||||
protected $functions;
|
||||
|
||||
/** @var \phpbb\controller\helper */
|
||||
protected $helper;
|
||||
|
||||
/** @var \phpbb\language\language */
|
||||
protected $lang;
|
||||
|
||||
/** @var \phpbbstudio\dice\operator\roll */
|
||||
protected $operator;
|
||||
|
||||
/** @var \phpbbstudio\dice\core\functions_regex */
|
||||
protected $regex;
|
||||
|
||||
/** @var \phpbb\request\request */
|
||||
protected $request;
|
||||
|
||||
/** @var \phpbb\template\template */
|
||||
protected $template;
|
||||
|
||||
/** @var \phpbb\user */
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param \phpbb\auth\auth $auth Authentication object
|
||||
* @param \phpbb\config\config $config Configuration object
|
||||
* @param \phpbbstudio\dice\core\functions_common $functions Common functions object
|
||||
* @param \phpbb\controller\helper $helper Controller helper object
|
||||
* @param \phpbb\language\language $lang Language object
|
||||
* @param \phpbbstudio\dice\operator\roll $operator Roll operator object
|
||||
* @param \phpbbstudio\dice\core\functions_regex $regex Regex functions
|
||||
* @param \phpbb\request\request $request Request object
|
||||
* @param \phpbb\template\template $template Template object
|
||||
* @param \phpbb\user $user User object
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
public function __construct(
|
||||
\phpbb\auth\auth $auth,
|
||||
\phpbb\config\config $config,
|
||||
\phpbbstudio\dice\core\functions_common $functions,
|
||||
\phpbb\controller\helper $helper,
|
||||
\phpbb\language\language $lang,
|
||||
\phpbbstudio\dice\operator\roll $operator,
|
||||
\phpbbstudio\dice\core\functions_regex $regex,
|
||||
\phpbb\request\request $request,
|
||||
\phpbb\template\template $template,
|
||||
\phpbb\user $user
|
||||
)
|
||||
{
|
||||
$this->auth = $auth;
|
||||
$this->config = $config;
|
||||
$this->functions = $functions;
|
||||
$this->helper = $helper;
|
||||
$this->lang = $lang;
|
||||
$this->operator = $operator;
|
||||
$this->regex = $regex;
|
||||
$this->request = $request;
|
||||
$this->template = $template;
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function add($forum_id, $topic_id, $post_id, $poster_id, $hash)
|
||||
{
|
||||
if (!$this->request->is_ajax())
|
||||
{
|
||||
throw new \phpbb\exception\http_exception(400, 'DICE_NOT_AJAX');
|
||||
}
|
||||
|
||||
// Set up JSON response
|
||||
$json_response = new \phpbb\json_response;
|
||||
|
||||
// Check the link hash for security
|
||||
if (!check_link_hash($hash, 'dice_add'))
|
||||
{
|
||||
$json_response->send([
|
||||
'MESSAGE_TITLE' => $this->lang->lang('ERROR'),
|
||||
'MESSAGE_TEXT' => $this->lang->lang('FORM_INVALID'),
|
||||
]);
|
||||
}
|
||||
|
||||
// Check if dice is enabled on this forum
|
||||
if (!$this->functions->forum_enabled($forum_id))
|
||||
{
|
||||
$json_response->send([
|
||||
'MESSAGE_TITLE' => $this->lang->lang('ERROR'),
|
||||
'MESSAGE_TEXT' => $this->lang->lang('DICE_ROLL_FORUM_DISABLED'),
|
||||
]);
|
||||
}
|
||||
|
||||
// Grab the author for this post, if we are not creating a new post
|
||||
$poster_id = $poster_id ? $poster_id : $this->user->data['user_id'];
|
||||
|
||||
if (!$this->functions->dice_auth_add($forum_id, (int) $poster_id))
|
||||
{
|
||||
$json_response->send([
|
||||
'MESSAGE_TITLE' => $this->lang->lang('ERROR'),
|
||||
'MESSAGE_TEXT' => $this->lang->lang('DICE_ROLL_ADD_UNAUTH'),
|
||||
]);
|
||||
}
|
||||
|
||||
// Set up limit
|
||||
$count = 0;
|
||||
|
||||
if ($this->functions->dice_limit($forum_id))
|
||||
{
|
||||
$entities = $this->operator->get_rolls_for_posting($forum_id, $topic_id, $post_id);
|
||||
$count = count($entities);
|
||||
|
||||
if ($this->functions->dice_limit_reached($count, $forum_id))
|
||||
{
|
||||
$json_response->send([
|
||||
'MESSAGE_TITLE' => $this->lang->lang('ERROR'),
|
||||
'MESSAGE_TEXT' => $this->lang->lang('DICE_ROLLS_TOO_MANY'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// Set up variables
|
||||
$user_id = (int) $this->user->data['user_id'];
|
||||
$notation = $this->request->variable('notation', '');
|
||||
$notation = htmlspecialchars_decode($notation, ENT_COMPAT);
|
||||
|
||||
/**
|
||||
* Get a roll entity from the operator.
|
||||
* @var \phpbbstudio\dice\entity\roll $entity
|
||||
*/
|
||||
$entity = $this->operator->get_entity();
|
||||
|
||||
// Map out entity functions and data
|
||||
$map_fields = [
|
||||
'set_forum' => $forum_id,
|
||||
'set_topic' => $topic_id,
|
||||
'set_post' => $post_id,
|
||||
'set_user' => $user_id,
|
||||
'set_time' => time(),
|
||||
'set_notation' => $notation,
|
||||
];
|
||||
|
||||
// Garbage collection
|
||||
$errors = [];
|
||||
|
||||
// Call all functions with the respective data
|
||||
foreach ($map_fields as $entity_function => $entity_data)
|
||||
{
|
||||
try
|
||||
{
|
||||
$entity->$entity_function($entity_data);
|
||||
}
|
||||
catch (\phpbbstudio\dice\exception\base $e)
|
||||
{
|
||||
$errors[] = $e->get_message($this->lang);
|
||||
}
|
||||
}
|
||||
|
||||
// Unset temporarily variables
|
||||
unset($map_fields);
|
||||
|
||||
// Try and roll the dice
|
||||
if (empty($errors))
|
||||
{
|
||||
try
|
||||
{
|
||||
$entity->roll();
|
||||
}
|
||||
catch (\phpbbstudio\dice\exception\base $e)
|
||||
{
|
||||
$errors[] = $e->get_message($this->lang);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($errors))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Insert the roll data to the database
|
||||
$entity->insert();
|
||||
|
||||
$count++;
|
||||
}
|
||||
catch (\phpbbstudio\dice\exception\out_of_bounds $e)
|
||||
{
|
||||
$errors[] = $e->get_message($this->lang);
|
||||
}
|
||||
}
|
||||
|
||||
// Send a json response
|
||||
$json_response->send([
|
||||
'ROLL_SUCCESS' => empty($errors),
|
||||
'ROLL_LIMIT' => (bool) $this->functions->dice_limit_reached($count, $forum_id),
|
||||
'ROLL_DATA' => $this->operator->get_roll_data_for_edit($entity),
|
||||
'MESSAGE_TITLE' => empty($errors) ? $this->lang->lang('SUCCESS') : $this->lang->lang('ERROR'),
|
||||
'MESSAGE_TEXT' => empty($errors) ? $this->lang->lang('DICE_ROLL_ADD_SUCCESS') : implode('<br>', $errors),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function edit($roll_id)
|
||||
{
|
||||
if (!$this->request->is_ajax())
|
||||
{
|
||||
throw new \phpbb\exception\http_exception(400, 'DICE_NOT_AJAX');
|
||||
}
|
||||
|
||||
// Set up a JSON response
|
||||
$json_response = new \phpbb\json_response;
|
||||
|
||||
/**
|
||||
* Get a roll entity from the operator.
|
||||
* @var \phpbbstudio\dice\entity\roll $entity
|
||||
*/
|
||||
$entity = $this->operator->get_entity();
|
||||
|
||||
try
|
||||
{
|
||||
$entity->load($roll_id);
|
||||
}
|
||||
catch (\phpbbstudio\dice\exception\out_of_bounds $e)
|
||||
{
|
||||
$json_response->send([
|
||||
'MESSAGE_TITLE' => $this->lang->lang('ERROR'),
|
||||
'MESSAGE_TEXT' => $e->get_message($this->lang),
|
||||
]);
|
||||
}
|
||||
|
||||
// Grab the author for this post, if we are not creating a new post
|
||||
$poster_id = $entity->get_post() ? $this->operator->get_author($entity->get_id()) : $this->user->data['user_id'];
|
||||
|
||||
if (!$this->functions->dice_auth_edit($entity->get_forum(), (int) $poster_id))
|
||||
{
|
||||
$json_response->send([
|
||||
'MESSAGE_TITLE' => $this->lang->lang('ERROR'),
|
||||
'MESSAGE_TEXT' => $this->lang->lang('DICE_ROLL_EDIT_UNAUTH'),
|
||||
]);
|
||||
}
|
||||
|
||||
if (confirm_box(true))
|
||||
{
|
||||
// Garbage collection
|
||||
$errors = [];
|
||||
|
||||
// Set up variables
|
||||
$user_id = (int) $this->user->data['user_id'];
|
||||
$notation = $this->request->variable('notation', '');
|
||||
$notation = htmlspecialchars_decode($notation, ENT_COMPAT);
|
||||
|
||||
try
|
||||
{
|
||||
$entity->set_notation($notation)->roll();
|
||||
}
|
||||
catch (\phpbbstudio\dice\exception\base $e)
|
||||
{
|
||||
$errors[] = $e->get_message($this->lang);
|
||||
}
|
||||
|
||||
if (empty($errors))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Update the roll data in the database
|
||||
$entity->set_edit_user($user_id)
|
||||
->set_edit_time(time())
|
||||
->increment_edit_count()
|
||||
->save();
|
||||
}
|
||||
catch (\phpbbstudio\dice\exception\out_of_bounds $e)
|
||||
{
|
||||
$errors[] = $e->get_message($this->lang);
|
||||
}
|
||||
}
|
||||
|
||||
// Send a json response
|
||||
$json_response->send([
|
||||
'ROLL_SUCCESS' => empty($errors),
|
||||
'ROLL_DATA' => $this->operator->get_roll_data_for_edit($entity),
|
||||
'MESSAGE_TITLE' => empty($errors) ? $this->lang->lang('SUCCESS') : $this->lang->lang('ERROR'),
|
||||
'MESSAGE_TEXT' => empty($errors) ? $this->lang->lang('DICE_ROLL_EDIT_SUCCESS') : implode('<br>', $errors),
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->template->assign_vars([
|
||||
'ROLL_DATA' => $this->operator->get_roll_data_for_edit($entity),
|
||||
]);
|
||||
|
||||
confirm_box(false, 'DICE_ROLL_EDIT', build_hidden_fields([
|
||||
'roll_id' => $roll_id,
|
||||
]), '@phpbbstudio_dice/dice_edit.html', $this->helper->get_current_url());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function delete($roll_id)
|
||||
{
|
||||
if (!$this->request->is_ajax())
|
||||
{
|
||||
throw new \phpbb\exception\http_exception(400, 'DICE_NOT_AJAX');
|
||||
}
|
||||
|
||||
// Set up a JSON response
|
||||
$json_response = new \phpbb\json_response;
|
||||
|
||||
/**
|
||||
* Get and load entity
|
||||
* @var \phpbbstudio\dice\entity\roll $entity
|
||||
*/
|
||||
$entity = $this->operator->get_entity()->load($roll_id);
|
||||
|
||||
// Grab the author for this post, if we are not creating a new post
|
||||
$poster_id = $entity->get_post() ? $this->operator->get_author($entity->get_id()) : $this->user->data['user_id'];
|
||||
|
||||
if (!$this->functions->dice_auth_delete($entity->get_forum(), (int) $poster_id))
|
||||
{
|
||||
$json_response->send([
|
||||
'MESSAGE_TITLE' => $this->lang->lang('ERROR'),
|
||||
'MESSAGE_TEXT' => $this->lang->lang('DICE_ROLL_DELETE_UNAUTH'),
|
||||
]);
|
||||
}
|
||||
|
||||
if (confirm_box(true))
|
||||
{
|
||||
// Delete the roll entity
|
||||
$success = $this->operator->delete($roll_id);
|
||||
|
||||
$count = 0;
|
||||
|
||||
if ($success)
|
||||
{
|
||||
$entities = $this->operator->get_rolls_for_posting($entity->get_forum(), $entity->get_topic(), $entity->get_post());
|
||||
$count = count($entities);
|
||||
}
|
||||
|
||||
$json_response->send([
|
||||
'ROLL_ID' => (int) $roll_id,
|
||||
'ROLL_SUCCESS' => (bool) $success,
|
||||
'ROLL_LIMIT' => (bool) $this->functions->dice_limit_reached($count, $entity->get_forum()),
|
||||
'MESSAGE_TITLE' => $success ? $this->lang->lang('SUCCESS') : $this->lang->lang('ERROR'),
|
||||
'MESSAGE_TEXT' => $success ? $this->lang->lang('DICE_ROLL_DELETE_SUCCESS') : $this->lang->lang('DICE_ROLL_NOT_EXIST', 1),
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/**
|
||||
* The 5th parameter (u_action) has to be set
|
||||
* for it to work correctly with AJAX and URL rewriting.
|
||||
*/
|
||||
confirm_box(false, 'DICE_ROLL_DELETE', build_hidden_fields([
|
||||
'roll_id' => (int) $roll_id,
|
||||
]), 'confirm_body.html', $this->helper->get_current_url());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function page()
|
||||
{
|
||||
if (!$this->auth->acl_get('u_dice_test'))
|
||||
{
|
||||
throw new \phpbb\exception\http_exception(403, 'NOT_AUTHORISED');
|
||||
}
|
||||
|
||||
$notation = $this->request->variable('notation', '', true);
|
||||
$notation = htmlspecialchars_decode($notation, ENT_COMPAT);
|
||||
$submit = $this->request->is_set_post('submit');
|
||||
|
||||
/** @var \phpbbstudio\dice\entity\roll $entity */
|
||||
$entity = $this->operator->get_entity();
|
||||
|
||||
if ($notation)
|
||||
{
|
||||
try
|
||||
{
|
||||
$entity->set_notation($notation)->roll();
|
||||
}
|
||||
catch (\phpbbstudio\dice\exception\unexpected_value $e)
|
||||
{
|
||||
$errors[] = $e->get_message($this->lang);
|
||||
}
|
||||
}
|
||||
|
||||
if ($submit && $this->request->is_ajax())
|
||||
{
|
||||
$json_response = new \phpbb\json_response;
|
||||
|
||||
$json_response->send([
|
||||
'MESSAGE_TITLE' => 'HI',
|
||||
'MESSAGE_TEXT' => $entity->get_output(),
|
||||
]);
|
||||
}
|
||||
|
||||
$skin = $this->request->variable('skin', $this->user->data['dice_u_skin'], true);
|
||||
$skins = $this->functions->get_dice_skins(true);
|
||||
$skin_data = $this->functions->get_dice_skin_data(true, $skin);
|
||||
$skin_options = $this->functions->build_dice_select($skins, $skin, true);
|
||||
|
||||
$this->template->assign_vars([
|
||||
'NOTATION' => $entity->get_notation(),
|
||||
'OUTPUT' => $entity->get_output(),
|
||||
'DISPLAY' => $entity->get_display($skin_data['name'], $skin_data['dir'], $skin_data['ext']),
|
||||
'TOTAL' => $entity->get_total(),
|
||||
|
||||
'DICE_IMG_HEIGHT' => (int) $this->config['dice_skins_img_height'],
|
||||
'DICE_IMG_WIDTH' => (int) $this->config['dice_skins_img_width'],
|
||||
|
||||
'DICE_ALLOWED_ONLY' => $this->config['dice_sides_only'],
|
||||
'DICE_ALLOWED_SIDES' => $this->functions->get_dice_sides(),
|
||||
|
||||
'LIMIT_DICE_ROLLS' => $this->config['dice_max_rolls'],
|
||||
'LIMIT_DICE_QTY' => $this->config['dice_qty_per_dice'],
|
||||
'LIMIT_DICE_SIDES' => $this->config['dice_sides_per_dice'],
|
||||
'LIMIT_DICE_FUDGE' => $this->config['dice_fudge_dice_per_notation'],
|
||||
'LIMIT_DICE_PC' => $this->config['dice_pc_dice_per_notation'],
|
||||
'LIMIT_DICE_EXPLODE' => $this->config['dice_exploding_dice_per_notation'],
|
||||
'LIMIT_DICE_PEN' => $this->config['dice_penetration_dice_per_notation'],
|
||||
'LIMIT_DICE_COMP' => $this->config['dice_compound_dice_per_notation'],
|
||||
|
||||
'SKIN_OPTIONS' => $skin_options,
|
||||
|
||||
'S_DICE_SUBMIT' => $submit,
|
||||
|
||||
'U_DICE_ACTION' => $this->helper->route('phpbbstudio_dice'),
|
||||
]);
|
||||
|
||||
return $this->helper->render('@phpbbstudio_dice/dice_page.html', $this->lang->lang('DICE_ROLL'));
|
||||
}
|
||||
}
|
||||
58
ext/phpbbstudio/dice/controller/main_interface.php
Normal file
58
ext/phpbbstudio/dice/controller/main_interface.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* phpBB Studio's Dice extension for the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) 2019 phpBB Studio <https://www.phpbbstudio.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*/
|
||||
|
||||
namespace phpbbstudio\dice\controller;
|
||||
|
||||
/**
|
||||
* phpBB Studio's Dice Main controller interface.
|
||||
*/
|
||||
interface main_interface
|
||||
{
|
||||
/**
|
||||
* Create a roll.
|
||||
*
|
||||
* @param int $forum_id The forum identifier
|
||||
* @param int $topic_id The topic identifier
|
||||
* @param int $post_id The post identifier
|
||||
* @param int $poster_id The poster identifier
|
||||
* @param string $hash The generated link hash
|
||||
* @return \phpbb\json_response
|
||||
* @throws \phpbb\exception\http_exception
|
||||
* @access public
|
||||
*/
|
||||
public function add($forum_id, $topic_id, $post_id, $poster_id, $hash);
|
||||
|
||||
/**
|
||||
* Edit a roll.
|
||||
*
|
||||
* @param int $roll_id The roll identifier
|
||||
* @return \phpbb\json_response
|
||||
* @throws \phpbb\exception\http_exception
|
||||
* @access public
|
||||
*/
|
||||
public function edit($roll_id);
|
||||
|
||||
/**
|
||||
* Delete a roll.
|
||||
*
|
||||
* @param int $roll_id The roll identifier
|
||||
* @return void \phpbb\json_response
|
||||
* @throws \phpbb\exception\http_exception
|
||||
* @access public
|
||||
*/
|
||||
public function delete($roll_id);
|
||||
|
||||
/**
|
||||
* Display a dice testing page.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* @throws \phpbb\exception\http_exception
|
||||
* @access public
|
||||
*/
|
||||
public function page();
|
||||
}
|
||||
Reference in New Issue
Block a user