Extensions
This commit is contained in:
609
ext/phpbbstudio/dice/core/functions_common.php
Normal file
609
ext/phpbbstudio/dice/core/functions_common.php
Normal file
@@ -0,0 +1,609 @@
|
||||
<?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\core;
|
||||
|
||||
/**
|
||||
* phpBB Studio's Dice Common functions.
|
||||
*/
|
||||
class functions_common
|
||||
{
|
||||
/** @var \phpbb\auth\auth */
|
||||
protected $auth;
|
||||
|
||||
/** @var \phpbb\config\config */
|
||||
protected $config;
|
||||
|
||||
/** @var \phpbb\config\db_text */
|
||||
protected $config_text;
|
||||
|
||||
/** @var \phpbb\db\driver\driver_interface */
|
||||
protected $db;
|
||||
|
||||
/** @var \phpbb\filesystem\filesystem */
|
||||
protected $filesystem;
|
||||
|
||||
/** @var \phpbbstudio\dice\core\functions_finder */
|
||||
protected $finder;
|
||||
|
||||
/** @var \phpbb\language\language */
|
||||
protected $lang;
|
||||
|
||||
/** @var \phpbb\path_helper */
|
||||
protected $path_helper;
|
||||
|
||||
/** @var \phpbb\user */
|
||||
protected $user;
|
||||
|
||||
/** @var string Forums table */
|
||||
protected $forums_table;
|
||||
|
||||
/** @var string phpBB root path */
|
||||
protected $root_path;
|
||||
|
||||
/** @var array Array of allowed image extensions */
|
||||
protected $image_extensions;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param \phpbb\auth\auth $auth Authentication object
|
||||
* @param \phpbb\config\config $config Configuration object
|
||||
* @param \phpbb\config\db_text $config_text Configuration database object
|
||||
* @param \phpbb\db\driver\driver_interface $db Database object
|
||||
* @param \phpbb\filesystem\filesystem $filesystem Filesystem object
|
||||
* @param \phpbbstudio\dice\core\functions_finder $finder Dice finder
|
||||
* @param \phpbb\language\language $lang Language object
|
||||
* @param \phpbb\path_helper $path_helper Path helper
|
||||
* @param \phpbb\user $user User object
|
||||
* @param string $forums_table Forums table
|
||||
* @param string $root_path phpBB root path
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
public function __construct(
|
||||
\phpbb\auth\auth $auth,
|
||||
\phpbb\config\config $config,
|
||||
\phpbb\config\db_text $config_text,
|
||||
\phpbb\db\driver\driver_interface $db,
|
||||
\phpbb\filesystem\filesystem $filesystem,
|
||||
functions_finder $finder,
|
||||
\phpbb\language\language $lang,
|
||||
\phpbb\path_helper $path_helper,
|
||||
\phpbb\user $user,
|
||||
$forums_table,
|
||||
$root_path
|
||||
)
|
||||
{
|
||||
$this->auth = $auth;
|
||||
$this->config = $config;
|
||||
$this->config_text = $config_text;
|
||||
$this->db = $db;
|
||||
$this->filesystem = $filesystem;
|
||||
$this->finder = $finder;
|
||||
$this->lang = $lang;
|
||||
$this->path_helper = $path_helper;
|
||||
$this->user = $user;
|
||||
$this->forums_table = $forums_table;
|
||||
$this->root_path = $root_path;
|
||||
|
||||
$this->image_extensions = ['gif', 'jpg', 'jpeg', 'png', 'bmp', 'svg'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there is a dice limit for this forum and user combination.
|
||||
*
|
||||
* @param int $forum_id The forum identifier
|
||||
* @return bool Whether or not there is a limit
|
||||
* @access public
|
||||
*/
|
||||
public function dice_limit($forum_id)
|
||||
{
|
||||
return ($this->config['dice_max_rolls'] && !$this->auth->acl_get('f_dice_no_limit', (int) $forum_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the dice limit has been reached for this forum, user and count combination.
|
||||
*
|
||||
* @param int $count The roll count
|
||||
* @param int $forum_id The forum identifier
|
||||
* @return bool Whether or not the limit has been reached
|
||||
* @access public
|
||||
*/
|
||||
public function dice_limit_reached($count, $forum_id)
|
||||
{
|
||||
return (($count >= $this->config['dice_max_rolls']) && $this->dice_limit($forum_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two user identifiers against each other. Used to determine if this user is the author of a post.
|
||||
*
|
||||
* @param int $user_id User identifier
|
||||
* @return bool Whether or not the identifiers are identical
|
||||
* @access public
|
||||
*/
|
||||
public function dice_author($user_id)
|
||||
{
|
||||
return ((int) $this->user->data['user_id'] === (int) $user_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this user can add a dice in this forum.
|
||||
*
|
||||
* @param int $forum_id Forum identifier
|
||||
* @param int $user_id User identifier of the poster
|
||||
* @return bool Whether or not this user can add a dice in this forum
|
||||
* @access public
|
||||
*/
|
||||
public function dice_auth_add($forum_id, $user_id)
|
||||
{
|
||||
return ($this->auth->acl_get('f_mod_dice_add', (int) $forum_id) || ($this->auth->acl_get('f_dice_roll', (int) $forum_id) && $this->dice_author($user_id)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this user can delete a dice in this forum.
|
||||
*
|
||||
* @param int $forum_id Forum identifier
|
||||
* @param int $user_id User identifier of the poster
|
||||
* @return bool Whether or not this user can delete a dice in this forum
|
||||
* @access public
|
||||
*/
|
||||
public function dice_auth_delete($forum_id, $user_id)
|
||||
{
|
||||
return ($this->auth->acl_get('f_mod_dice_delete', (int) $forum_id) || ($this->auth->acl_get('f_dice_delete', (int) $forum_id) && $this->dice_author($user_id)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this user can edit a dice in this forum.
|
||||
*
|
||||
* @param int $forum_id Forum identifier
|
||||
* @param int $user_id User identifier of the poster
|
||||
* @return bool Whether or not this user can edit a dice in this forum
|
||||
* @access public
|
||||
*/
|
||||
public function dice_auth_edit($forum_id, $user_id)
|
||||
{
|
||||
return ($this->auth->acl_get('f_mod_dice_edit', (int) $forum_id) || ($this->auth->acl_get('f_dice_edit', (int) $forum_id) && $this->dice_author($user_id)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a forum's dice settings.
|
||||
*
|
||||
* @param int $forum_id The forum identifier
|
||||
* @return mixed The forum's dice settings or false if no forum id was provided
|
||||
* @access public
|
||||
*/
|
||||
public function forum_data($forum_id)
|
||||
{
|
||||
if (empty($forum_id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$sql = 'SELECT dice_enabled, dice_skin_override, dice_f_skin FROM ' . $this->forums_table . ' WHERE forum_id = ' . (int) $forum_id;
|
||||
$result = $this->db->sql_query_limit($sql, 1);
|
||||
$row = $this->db->sql_fetchrow($result);
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the Dice extension is enabled for a specific forum.
|
||||
*
|
||||
* @param int $forum_id The forum identifier
|
||||
* @return bool Whether or not the extension is enabled for this forum
|
||||
* @access public
|
||||
*/
|
||||
public function forum_enabled($forum_id)
|
||||
{
|
||||
if (empty($forum_id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$sql = 'SELECT dice_enabled FROM ' . $this->forums_table . ' WHERE forum_id = ' . (int) $forum_id;
|
||||
$result = $this->db->sql_query_limit($sql, 1);
|
||||
$s_enabled = (bool) $this->db->sql_fetchfield('dice_enabled');
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return $s_enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the skin override is enabled for a specific forum.
|
||||
*
|
||||
* @param int $forum_id The forum identifier
|
||||
* @return bool Whether or not the skin override is enabled for this forum
|
||||
* @access public
|
||||
*/
|
||||
public function forum_skin_override($forum_id)
|
||||
{
|
||||
if (empty($forum_id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$sql = 'SELECT dice_skin_override FROM ' . $this->forums_table . ' WHERE forum_id = ' . (int) $forum_id;
|
||||
$result = $this->db->sql_query_limit($sql, 1);
|
||||
$s_override = (bool) $this->db->sql_fetchfield('dice_skin_override');
|
||||
$this->db->sql_freeresult($result);
|
||||
|
||||
return $s_override;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip emojis from a string
|
||||
*
|
||||
* @param string $string
|
||||
* @return string
|
||||
*/
|
||||
public function dice_strip_emojis($string)
|
||||
{
|
||||
return preg_replace('/[\x{10000}-\x{10FFFF}]/u', "", $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the installed dice skins from the database.
|
||||
*
|
||||
* @param bool $include_text Whether or not the "text" option should be included
|
||||
* @return array Array of installed dice skins
|
||||
* @access public
|
||||
*/
|
||||
public function get_dice_skins($include_text = false)
|
||||
{
|
||||
$skins = json_decode($this->config_text->get('dice_skins'), true);
|
||||
|
||||
if ($include_text)
|
||||
{
|
||||
array_unshift($skins, $this->lang->lang('DICE_TEXT'));
|
||||
}
|
||||
|
||||
return (array) $skins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the installed dice skins in the database.
|
||||
*
|
||||
* @param array $skins Array of installed dice skins
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
public function set_dice_skins(array $skins)
|
||||
{
|
||||
// Enforce data type
|
||||
$skins = (array) $skins;
|
||||
|
||||
$this->config_text->set('dice_skins', json_encode($skins));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the installed dice sides from the database.
|
||||
*
|
||||
* @return array Array of installed dice sides
|
||||
* @access public
|
||||
*/
|
||||
public function get_dice_sides()
|
||||
{
|
||||
return (array) json_decode($this->config_text->get('dice_sides'), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the installed dice sides in the database.
|
||||
*
|
||||
* @param array $sides Array of installed dice sides
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
public function set_dice_sides(array $sides)
|
||||
{
|
||||
// Enforce data type
|
||||
$sides = (array) $sides;
|
||||
|
||||
$this->config_text->set('dice_sides', json_encode($sides));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the correctly formatted dice skins directory.
|
||||
*
|
||||
* @return string Correctly formatted dice skins directory
|
||||
* @access public
|
||||
*/
|
||||
public function get_dice_skins_dir()
|
||||
{
|
||||
return $this->make_dice_dir($this->config['dice_skins_dir']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Correctly format a given directory, prefixed with phpBB's root path and a trailing slash.
|
||||
*
|
||||
* @param string $directory The directory to correctly format
|
||||
* @return string The correctly formatted directory
|
||||
* @access public
|
||||
*/
|
||||
public function make_dice_dir($directory)
|
||||
{
|
||||
return (string) $this->root_path . $directory . '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the dice skins directory exists and is readable.
|
||||
*
|
||||
* @return bool Whether or not the dice skins directory exists and is readable
|
||||
* @access public
|
||||
*/
|
||||
public function check_dice_skins_dir()
|
||||
{
|
||||
return $this->check_dice_dir($this->get_dice_skins_dir());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a directory or file exists.
|
||||
*
|
||||
* @param string $directory The directory to check for existance and readability
|
||||
* @return bool Whether or not the directory exists and is readable
|
||||
* @access public
|
||||
*/
|
||||
public function check_dice_dir($directory)
|
||||
{
|
||||
return ($this->filesystem->exists($directory) && $this->filesystem->is_readable($directory));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the web root path for a give source.
|
||||
*
|
||||
* @param string $src The source string to update.
|
||||
* @return string The updated source string.
|
||||
* @access public
|
||||
*/
|
||||
public function update_dice_img_path($src)
|
||||
{
|
||||
return $this->path_helper->update_web_root_path($src);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the available dice skins in the dice skins directory.
|
||||
*
|
||||
* @return array Array of available dice skins
|
||||
* @access public
|
||||
*/
|
||||
public function available_dice_skins()
|
||||
{
|
||||
return $this->finder->find_dice_skins($this->get_dice_skins_dir());
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate dice skins, check if all images for all installed sides are present.
|
||||
*
|
||||
* @param string $skin The dice skin to validate
|
||||
* @param array $sides Array of installed dice sides
|
||||
* @return bool Whether or not this dice skin has all images for all installed dice sides
|
||||
* @access public
|
||||
*/
|
||||
public function validate_dice_skin($skin, array $sides)
|
||||
{
|
||||
$valid = true;
|
||||
|
||||
$images = $this->finder->find_dice_images($this->get_dice_skins_dir(), $skin, $this->get_image_extensions());
|
||||
|
||||
foreach ($sides as $side)
|
||||
{
|
||||
for ($i = 1; $i <= $side; $i++)
|
||||
{
|
||||
$image_name = $this->get_dice_image_notation($side, $i);
|
||||
|
||||
$valid = !in_array($image_name, $images) ? false : $valid;
|
||||
}
|
||||
}
|
||||
|
||||
return (bool) $valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dice skin image notation.
|
||||
*
|
||||
* @param int $sides The dice sides
|
||||
* @param int $roll The dice roll outcome
|
||||
* @param string $ext The dice skin image extension
|
||||
* @return string The dice skin image notation
|
||||
* @access public
|
||||
*/
|
||||
public function get_dice_image_notation($sides, $roll, $ext = '')
|
||||
{
|
||||
return 'd' . (int) $sides . '_' . (int) $roll . ($ext ? '.' . $ext : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the allowed image extensions.
|
||||
*
|
||||
* @return array Array of allowed image extensions
|
||||
* @access public
|
||||
*/
|
||||
public function get_image_extensions()
|
||||
{
|
||||
return (array) $this->image_extensions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Excerpts the images extension within a folder previously checked.
|
||||
*
|
||||
* @param string $skin The skin's folder name
|
||||
* @return string The images extension
|
||||
* @access public
|
||||
*/
|
||||
public function find_image_extension($skin)
|
||||
{
|
||||
/**
|
||||
* Find all the files in the skin directory that start with
|
||||
* a "d", as dice image file names are: d0_0.ext
|
||||
*/
|
||||
$files = glob($this->get_dice_skins_dir() . $skin . '/d*.*');
|
||||
|
||||
if ($files)
|
||||
{
|
||||
$extension = false;
|
||||
$count = count($files);
|
||||
|
||||
// Loop over the files found
|
||||
for ($i = 0; $i < $count; $i++)
|
||||
{
|
||||
// Get the extension for this file
|
||||
$extension = pathinfo($files[$i], PATHINFO_EXTENSION);
|
||||
|
||||
// If the extension is an allowed image extension, break out the for loop.
|
||||
if (in_array($extension, $this->image_extensions))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $extension;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dice skin data for display.
|
||||
*
|
||||
* @param bool $override Whether or not the user's choice should be overridden
|
||||
* @param string $forum_skin The dice skin set in the Forum Settings
|
||||
* @return array Array with the dice skin data
|
||||
* @access public
|
||||
*/
|
||||
public function get_dice_skin_data($override, $forum_skin)
|
||||
{
|
||||
// Get all 'installed' dice skins
|
||||
$skins = $this->get_dice_skins(true);
|
||||
|
||||
// Get the user defined style, if not overridden by the forum settings
|
||||
$skin = ($this->auth->acl_get('u_dice_skin') || !$override) ? $this->user->data['dice_u_skin'] : $forum_skin;
|
||||
|
||||
// Make sure the user defined style is in the 'installed' dice skins
|
||||
$skin = in_array($skin, $skins) ? $skin : 'text';
|
||||
|
||||
// Get the image extension for this dice skin
|
||||
$ext = $skin !== 'text' ? $this->find_image_extension($skin) : '';
|
||||
|
||||
return (array) [
|
||||
'name' => $skin,
|
||||
'dir' => $this->get_dice_skins_dir(),
|
||||
'ext' => $ext,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean an array, used for the installed dice skins and dice sides.
|
||||
*
|
||||
* @param array $array The array to clean
|
||||
* @return array A cleaned array
|
||||
* @access public
|
||||
*/
|
||||
public function clean_dice_array(array $array)
|
||||
{
|
||||
// No empty values
|
||||
$array = array_filter($array);
|
||||
|
||||
// No duplicate values
|
||||
$array = array_unique($array);
|
||||
|
||||
// Sort ascending
|
||||
sort($array);
|
||||
|
||||
return (array) $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an options string for a HTML <select> field.
|
||||
*
|
||||
* @param array $array The array to build the options from
|
||||
* @param mixed $select The option that should be selected
|
||||
* @param bool $no_keys Whether or not to use the array keys as <option value="">
|
||||
* @return string An string of all options for a select field
|
||||
*/
|
||||
public function build_dice_select(array $array, $select, $no_keys)
|
||||
{
|
||||
$options = '';
|
||||
|
||||
foreach ($array as $key => $option)
|
||||
{
|
||||
$value = $no_keys ? $option : $key;
|
||||
$selected = $select == $value ? '" selected="selected' : '';
|
||||
|
||||
$options .= '<option value="' . $value . $selected .'">' . $option . '</option>';
|
||||
}
|
||||
|
||||
return (string) $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* The dice link locations and their BIT values
|
||||
*
|
||||
* @return array
|
||||
* @access protected
|
||||
*/
|
||||
protected function dice_link_locations()
|
||||
{
|
||||
return [
|
||||
1 => 'navbar_header_quick_links_before',
|
||||
2 => 'navbar_header_quick_links_after',
|
||||
4 => 'overall_header_navigation_prepend',
|
||||
8 => 'overall_header_navigation_append',
|
||||
16 => 'navbar_header_user_profile_append',
|
||||
32 => 'overall_footer_breadcrumb_append',
|
||||
64 => 'overall_footer_timezone_before',
|
||||
128 => 'overall_footer_timezone_after',
|
||||
256 => 'overall_footer_teamlink_before',
|
||||
512 => 'overall_footer_teamlink_after',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get dice link locations and their status.
|
||||
*
|
||||
* @return array Array with the link locations and their status
|
||||
* @access public
|
||||
*/
|
||||
public function get_dice_link_locations()
|
||||
{
|
||||
$links = [];
|
||||
$flags = $this->config['dice_link_locations'];
|
||||
$locations = $this->dice_link_locations();
|
||||
|
||||
foreach($locations as $flag => $location)
|
||||
{
|
||||
$links[] = [
|
||||
'name' => $location,
|
||||
'status' => ($flags & $flag) ? true : false,
|
||||
];
|
||||
}
|
||||
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set dice link locations and their status.
|
||||
*
|
||||
* @param array $links Array with the link locations and their status
|
||||
* @return void
|
||||
* @access public
|
||||
*/
|
||||
public function set_dice_link_locations(array $links)
|
||||
{
|
||||
$flags = 0;
|
||||
$locations = $this->dice_link_locations();
|
||||
$flipped = array_flip($locations);
|
||||
|
||||
foreach ($links as $link => $status)
|
||||
{
|
||||
$flags += ($status) ? $flipped[$link] : 0;
|
||||
}
|
||||
|
||||
$this->config->set('dice_link_locations', (int) $flags);
|
||||
}
|
||||
}
|
||||
73
ext/phpbbstudio/dice/core/functions_finder.php
Normal file
73
ext/phpbbstudio/dice/core/functions_finder.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?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\core;
|
||||
|
||||
use \Symfony\Component\Finder\Finder;
|
||||
|
||||
/**
|
||||
* phpBB Studio's Dice Finder functions.
|
||||
*/
|
||||
class functions_finder
|
||||
{
|
||||
/**
|
||||
* Find available dice skins in the given directory.
|
||||
*
|
||||
* @param string $directory The dice skins directory
|
||||
* @return array Array of available dice skins
|
||||
* @access public
|
||||
*/
|
||||
public function find_dice_skins($directory)
|
||||
{
|
||||
$skins = [];
|
||||
|
||||
$finder = new Finder;
|
||||
$finder->ignoreUnreadableDirs()
|
||||
->in($directory)
|
||||
->directories()
|
||||
->depth('== 0');
|
||||
|
||||
foreach($finder as $dir)
|
||||
{
|
||||
$skin = $dir->getBasename();
|
||||
|
||||
$skins[] = $skin;
|
||||
}
|
||||
|
||||
return (array) $skins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find available dice skin images for a given dice skin.
|
||||
*
|
||||
* @param string $directory The dice skins directory
|
||||
* @param string $skin The dice skin
|
||||
* @param array $exts Array of allowed image extensions
|
||||
* @return array Array of available dice skin images
|
||||
* @access public
|
||||
*/
|
||||
public function find_dice_images($directory, $skin, array $exts)
|
||||
{
|
||||
$images = [];
|
||||
|
||||
$finder = new Finder;
|
||||
$finder->in($directory . $skin)
|
||||
->files()
|
||||
->depth('== 0');
|
||||
|
||||
foreach ($finder as $image)
|
||||
{
|
||||
if (in_array($image->getExtension(), $exts))
|
||||
{
|
||||
$images[] = $image->getBasename('.' . $image->getExtension());
|
||||
}
|
||||
}
|
||||
|
||||
return (array) $images;
|
||||
}
|
||||
}
|
||||
136
ext/phpbbstudio/dice/core/functions_regex.php
Normal file
136
ext/phpbbstudio/dice/core/functions_regex.php
Normal file
@@ -0,0 +1,136 @@
|
||||
<?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\core;
|
||||
|
||||
/**
|
||||
* phpBB Studio's Dice Regex functions.
|
||||
*/
|
||||
class functions_regex
|
||||
{
|
||||
/**
|
||||
* Matches a basic arithmetic operator.
|
||||
*
|
||||
* @param string
|
||||
* @access protected
|
||||
*/
|
||||
protected $arithmetic_operator = '[+\\-*\\/]';
|
||||
|
||||
/**
|
||||
* Matches a basic comparison operator.
|
||||
*
|
||||
* @param string
|
||||
* @access protected
|
||||
*/
|
||||
protected $comparison_operators = '[<>!]?={1,3}|[<>]';
|
||||
|
||||
/**
|
||||
* Matches exploding/penetrating dice notation.
|
||||
*
|
||||
* @param string
|
||||
* @access protected
|
||||
*/
|
||||
protected $explode = '(!{1,2}p?)';
|
||||
|
||||
/**
|
||||
* Matches a number comparison (ie. <=4, =5, >3, !=1).
|
||||
*
|
||||
* @return string
|
||||
* @access protected
|
||||
*/
|
||||
protected function number_comparison()
|
||||
{
|
||||
return '(' . $this->comparison_operators . ')([0-9]+)';
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches the numbers for a 'fudge' die (ie. F, F.2).
|
||||
*
|
||||
* @return string
|
||||
* @access protected
|
||||
*/
|
||||
protected function fudge()
|
||||
{
|
||||
return 'F(?:\\.([12]))?';
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches a dice (ie. 2d6, d10, d%, dF, dF.2).
|
||||
*
|
||||
* @return string
|
||||
* @access protected
|
||||
*/
|
||||
protected function dice()
|
||||
{
|
||||
return '([1-9][0-9]*)?d([1-9][0-9]*|%|' . $this->fudge() . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches a dice, optional exploding/penetrating notation and roll comparison.
|
||||
*
|
||||
* @return string
|
||||
* @access protected
|
||||
*/
|
||||
protected function dice_full()
|
||||
{
|
||||
return $this->dice() . $this->explode . '?(?:' . $this->number_comparison() . ')?';
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches the addition to a dice (ie. +4, -10, *2, -L).
|
||||
*
|
||||
* @return string
|
||||
* @access protected
|
||||
*/
|
||||
protected function addition()
|
||||
{
|
||||
return '(' . $this->arithmetic_operator . ')([1-9]+0?(?![0-9]*d)|H|L)';
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches a standard dice notation. i.e;
|
||||
* 3d10-2
|
||||
* 4d20-L
|
||||
* 2d7/4
|
||||
* 3d8*2
|
||||
* 2d3+4-1
|
||||
* 2d10-H*1d6/2
|
||||
*
|
||||
* @return string
|
||||
* @access protected
|
||||
*/
|
||||
protected function notation()
|
||||
{
|
||||
return '('. $this->arithmetic_operator . ')?' . $this->dice_full() . '((?:' . $this->addition() . ')*)';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a regex from this class.
|
||||
*
|
||||
* @param string $name The regex name from this class
|
||||
* @param bool $match_whole If it should match the whole string
|
||||
* @return string A regular expression
|
||||
* @access public
|
||||
* @throws \phpbbstudio\dice\exception\unexpected_value
|
||||
*/
|
||||
public function get($name, $match_whole = false)
|
||||
{
|
||||
if (empty($name))
|
||||
{
|
||||
throw new \phpbbstudio\dice\exception\unexpected_value(['ROLL_REGEX_NAME', 'FIELD_MISSING']);
|
||||
}
|
||||
else if ((gettype($name) !== 'string') || !method_exists($this, $name))
|
||||
{
|
||||
throw new \phpbbstudio\dice\exception\unexpected_value(['ROLL_REGEX_NAME', 'ROLL_NAME_NOT_FOUND']);
|
||||
}
|
||||
|
||||
$pattern = $this->{$name}();
|
||||
|
||||
return '/' . ($match_whole ? '^' : '') . $pattern . ($match_whole ? '$' : '') . '/';
|
||||
}
|
||||
}
|
||||
228
ext/phpbbstudio/dice/core/functions_utils.php
Normal file
228
ext/phpbbstudio/dice/core/functions_utils.php
Normal file
@@ -0,0 +1,228 @@
|
||||
<?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\core;
|
||||
|
||||
/**
|
||||
* phpBB Studio's Dice Roll utility functions.
|
||||
*/
|
||||
class functions_utils
|
||||
{
|
||||
/**
|
||||
* Checks if the given value is a valid number.
|
||||
*
|
||||
* @param mixed $value The value to check
|
||||
* @return bool Whether it is a valid number or not
|
||||
* @access public
|
||||
*/
|
||||
public function is_numeric($value)
|
||||
{
|
||||
return (bool) (!is_array($value) && is_numeric($value) && is_finite(intval($value)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random number between the min and the max (inclusive).
|
||||
*
|
||||
* @param int $min The minimum number to be generated
|
||||
* @param int $max The maximum number to be generated
|
||||
* @return int The generated number
|
||||
* @access public
|
||||
*/
|
||||
public function generate_number($min, $max)
|
||||
{
|
||||
$min = $min ? intval($min) : 1;
|
||||
$max = $max ? intval($max) : $min;
|
||||
|
||||
if ($max <= $min)
|
||||
{
|
||||
return (int) $min;
|
||||
}
|
||||
|
||||
return (int) floor((mt_rand() / mt_getrandmax()) * ($max - $min + 1) + $min);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rolls a standard dice, callback method.
|
||||
*
|
||||
* @param int $sides The amount of sides for the dice
|
||||
* @return int The outcome of the roll
|
||||
* @access public
|
||||
*/
|
||||
public function default_dice($sides)
|
||||
{
|
||||
return (int) $this->generate_number(1, $sides);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rolls a fudge dice, callback method.
|
||||
*
|
||||
* @param mixed $non_blanks
|
||||
* @return int The outcome of the roll
|
||||
* @access public
|
||||
*/
|
||||
public function fudge_dice($non_blanks)
|
||||
{
|
||||
$non_blanks = (int) $non_blanks;
|
||||
$total = 0;
|
||||
|
||||
if ($non_blanks === 2)
|
||||
{
|
||||
// default fudge (2 of each non-blank) = 1d3 - 2
|
||||
$total = $this->generate_number(1, 3) - 2;
|
||||
}
|
||||
else if ($non_blanks === 1)
|
||||
{
|
||||
// only 1 of each non-blank
|
||||
// on 1d6 a roll of 1 = -1, 6 = +1, others = 0
|
||||
$num = $this->generate_number(1, 6);
|
||||
|
||||
if ($num === 1)
|
||||
{
|
||||
$total = -1;
|
||||
}
|
||||
else if ($num === 6)
|
||||
{
|
||||
$total = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return (int) $total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the value matches the given compare point
|
||||
* and returns the corresponding success / failure state value
|
||||
* success = 1, fail = 0
|
||||
*
|
||||
* @param int $value The value to compare against
|
||||
* @param array $compare_point Array holding a value and an operator
|
||||
* @return int Success/failure state value
|
||||
* @access public
|
||||
*/
|
||||
public function get_success_state_value($value, array $compare_point)
|
||||
{
|
||||
return $this->is_compare_point($compare_point, $value) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether value matches the given compare point.
|
||||
*
|
||||
* @param array $compare_point Array holding a value and an operator
|
||||
* @param int $value The value to compare against
|
||||
* @return bool Success/failure state
|
||||
* @access public
|
||||
*/
|
||||
public function is_compare_point(array $compare_point, $value)
|
||||
{
|
||||
return (bool) (!empty($compare_point) ? $this->compare_numbers($value, $compare_point['value'], $compare_point['operator']) : false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes two numbers and runs a mathematical equation on them, using the given operator.
|
||||
*
|
||||
* @param int $a The first number: initial number
|
||||
* @param int $b The second number: number to be added, subtracted, multiplied by, divided by
|
||||
* @param string $operator The valid arithmetic operator (+, -, /, *) to use
|
||||
* @return int The outcome of the equation
|
||||
* @access public
|
||||
*/
|
||||
public function equate_numbers($a, $b, $operator)
|
||||
{
|
||||
// Ensure values are numeric
|
||||
$a = $this->is_numeric($a) ? $a : 0;
|
||||
$b = $this->is_numeric($b) ? $b : 0;
|
||||
|
||||
switch ($operator)
|
||||
{
|
||||
case '*':
|
||||
// Multiple the value
|
||||
$a *= $b;
|
||||
break;
|
||||
|
||||
case '/':
|
||||
// Divide the value (handle division by zero)
|
||||
$a = !empty($b) ? $a / $b : 0;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
// subtract from value
|
||||
$a -= $b;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Add to the value
|
||||
$a += $b;
|
||||
break;
|
||||
}
|
||||
|
||||
return $a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if `a` is comparative to `b` with the given operator.
|
||||
*
|
||||
* @param int $a The first number
|
||||
* @param int $b The second number
|
||||
* @param string $operator The valid comparative operator (=, <, >, <=, >=, !=) to use
|
||||
* @return bool Outcome of the comparison
|
||||
* @access public
|
||||
*/
|
||||
public function compare_numbers($a, $b, $operator)
|
||||
{
|
||||
|
||||
switch ($operator)
|
||||
{
|
||||
case '=':
|
||||
case '==':
|
||||
$result = $a === $b;
|
||||
break;
|
||||
|
||||
case '<':
|
||||
$result = $a < $b;
|
||||
break;
|
||||
|
||||
case '>':
|
||||
$result = $a > $b;
|
||||
break;
|
||||
|
||||
case '<=':
|
||||
$result = $a <= $b;
|
||||
break;
|
||||
|
||||
case '>=':
|
||||
$result = $a >= $b;
|
||||
break;
|
||||
|
||||
case '!':
|
||||
case '!=':
|
||||
$result = $a !== $b;
|
||||
break;
|
||||
|
||||
default:
|
||||
$result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return (bool) $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an array of numbers and adds them together, returning the result.
|
||||
*
|
||||
* @param array $numbers Arrays of numbers to be added to each other
|
||||
* @return int The outcome of the additions
|
||||
* @access public
|
||||
*/
|
||||
public function sum_array($numbers)
|
||||
{
|
||||
return !is_array($numbers) ? 0 : array_reduce($numbers, function($prev, $current)
|
||||
{
|
||||
return $prev + ($this->is_numeric($current) ? intval($current) : 0);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user