mirror of
https://github.com/slawkens/myaac.git
synced 2025-10-15 10:14:55 +02:00
Refactoring classes into src/ folder, so they will be auto-loaded by composer
This commit is contained in:
56
system/src/Cache/APC.php
Normal file
56
system/src/Cache/APC.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* Cache APC class
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @author Mark Samman (Talaturen) <marksamman@gmail.com>
|
||||
* @copyright 2019 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
namespace MyAAC\Cache;
|
||||
|
||||
class APC
|
||||
{
|
||||
private $prefix;
|
||||
private $enabled;
|
||||
|
||||
public function __construct($prefix = '')
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
$this->enabled = function_exists('apc_fetch');
|
||||
}
|
||||
|
||||
public function set($key, $var, $ttl = 0)
|
||||
{
|
||||
$key = $this->prefix . $key;
|
||||
apc_delete($key);
|
||||
apc_store($key, $var, $ttl);
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
{
|
||||
$tmp = '';
|
||||
if ($this->fetch($this->prefix . $key, $tmp)) {
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function fetch($key, &$var)
|
||||
{
|
||||
return ($var = apc_fetch($this->prefix . $key)) !== false;
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
apc_delete($this->prefix . $key);
|
||||
}
|
||||
|
||||
public function enabled()
|
||||
{
|
||||
return $this->enabled;
|
||||
}
|
||||
}
|
56
system/src/Cache/APCu.php
Normal file
56
system/src/Cache/APCu.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* Cache APC class
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @author Mark Samman (Talaturen) <marksamman@gmail.com>
|
||||
* @copyright 2019 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
namespace MyAAC\Cache;
|
||||
|
||||
class APCu
|
||||
{
|
||||
private $prefix;
|
||||
private $enabled;
|
||||
|
||||
public function __construct($prefix = '')
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
$this->enabled = function_exists('apcu_fetch');
|
||||
}
|
||||
|
||||
public function set($key, $var, $ttl = 0)
|
||||
{
|
||||
$key = $this->prefix . $key;
|
||||
apcu_delete($key);
|
||||
apcu_store($key, $var, $ttl);
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
{
|
||||
$tmp = '';
|
||||
if ($this->fetch($this->prefix . $key, $tmp)) {
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function fetch($key, &$var)
|
||||
{
|
||||
return ($var = apcu_fetch($this->prefix . $key)) !== false;
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
apcu_delete($this->prefix . $key);
|
||||
}
|
||||
|
||||
public function enabled()
|
||||
{
|
||||
return $this->enabled;
|
||||
}
|
||||
}
|
128
system/src/Cache/Cache.php
Normal file
128
system/src/Cache/Cache.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
/**
|
||||
* Cache class
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @author Mark Samman (Talaturen) <marksamman@gmail.com>
|
||||
* @copyright 2019 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
namespace MyAAC\Cache;
|
||||
|
||||
/**
|
||||
* Class Cache
|
||||
*
|
||||
* @method set($key, $var, $ttl = 0)
|
||||
* @method get($key)
|
||||
* @method fetch($key, &$var)
|
||||
* @method delete($key)
|
||||
*/
|
||||
class Cache
|
||||
{
|
||||
static private $instance;
|
||||
|
||||
/**
|
||||
* @return Cache
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
if (!self::$instance) {
|
||||
return self::generateInstance(config('cache_engine'), config('cache_prefix'));
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $engine
|
||||
* @param string $prefix
|
||||
* @return Cache
|
||||
*/
|
||||
public static function generateInstance($engine = '', $prefix = '')
|
||||
{
|
||||
if (config('env') === 'dev') {
|
||||
self::$instance = new self();
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
switch (strtolower($engine)) {
|
||||
case 'apc':
|
||||
self::$instance = new APC($prefix);
|
||||
break;
|
||||
|
||||
case 'apcu':
|
||||
self::$instance = new APCu($prefix);
|
||||
break;
|
||||
|
||||
case 'eaccelerator':
|
||||
self::$instance = new eAccelerator($prefix);
|
||||
break;
|
||||
|
||||
case 'xcache':
|
||||
self::$instance = new XCache($prefix);
|
||||
break;
|
||||
|
||||
case 'file':
|
||||
self::$instance = new File($prefix, CACHE);
|
||||
break;
|
||||
|
||||
case 'php':
|
||||
self::$instance = new PHP($prefix, CACHE);
|
||||
break;
|
||||
|
||||
case 'auto':
|
||||
self::$instance = self::generateInstance(self::detect(), $prefix);
|
||||
break;
|
||||
|
||||
default:
|
||||
self::$instance = new self();
|
||||
break;
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function detect()
|
||||
{
|
||||
if (function_exists('apc_fetch'))
|
||||
return 'apc';
|
||||
else if (function_exists('apcu_fetch'))
|
||||
return 'apcu';
|
||||
else if (function_exists('eaccelerator_get'))
|
||||
return 'eaccelerator';
|
||||
else if (function_exists('xcache_get') && ini_get('xcache.var_size'))
|
||||
return 'xcache';
|
||||
|
||||
return 'file';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function enabled()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function remember($key, $ttl, $callback)
|
||||
{
|
||||
$cache = self::getInstance();
|
||||
if (!$cache->enabled()) {
|
||||
return $callback();
|
||||
}
|
||||
|
||||
$value = null;
|
||||
if ($cache->fetch($key, $value)) {
|
||||
return unserialize($value);
|
||||
}
|
||||
|
||||
$value = $callback();
|
||||
$cache->set($key, serialize($value), $ttl);
|
||||
return $value;
|
||||
}
|
||||
}
|
56
system/src/Cache/EAccelerator.php
Normal file
56
system/src/Cache/EAccelerator.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* Cache eAccelerator class
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @author Mark Samman (Talaturen) <marksamman@gmail.com>
|
||||
* @copyright 2019 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
namespace MyAAC\Cache;
|
||||
|
||||
class EAccelerator
|
||||
{
|
||||
private $prefix;
|
||||
private $enabled;
|
||||
|
||||
public function __construct($prefix = '')
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
$this->enabled = function_exists('eaccelerator_get');
|
||||
}
|
||||
|
||||
public function set($key, $var, $ttl = 0)
|
||||
{
|
||||
$key = $this->prefix . $key;
|
||||
eaccelerator_rm($key);
|
||||
eaccelerator_put($key, $var, $ttl);
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
{
|
||||
$tmp = '';
|
||||
if ($this->fetch($this->prefix . $key, $tmp)) {
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function fetch($key, &$var)
|
||||
{
|
||||
return ($var = eaccelerator_get($this->prefix . $key)) !== null;
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
eaccelerator_rm($this->prefix . $key);
|
||||
}
|
||||
|
||||
public function enabled()
|
||||
{
|
||||
return $this->enabled;
|
||||
}
|
||||
}
|
76
system/src/Cache/File.php
Normal file
76
system/src/Cache/File.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* File cache class
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @copyright 2019 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
namespace MyAAC\Cache;
|
||||
|
||||
class File
|
||||
{
|
||||
private $prefix;
|
||||
private $dir;
|
||||
private $enabled;
|
||||
|
||||
public function __construct($prefix = '', $dir = '')
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
$this->dir = $dir;
|
||||
$this->enabled = (file_exists($this->dir) && is_dir($this->dir) && is_writable($this->dir));
|
||||
}
|
||||
|
||||
public function set($key, $var, $ttl = 0)
|
||||
{
|
||||
$file = $this->_name($key);
|
||||
file_put_contents($file, $var);
|
||||
|
||||
if ($ttl === 0) {
|
||||
$ttl = 365 * 24 * 60 * 60; // 365 days
|
||||
}
|
||||
|
||||
touch($file, time() + $ttl);
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
{
|
||||
$tmp = '';
|
||||
if ($this->fetch($key, $tmp)) {
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function fetch($key, &$var)
|
||||
{
|
||||
$file = $this->_name($key);
|
||||
if (!file_exists($file) || filemtime($file) < time()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$var = file_get_contents($file);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
$file = $this->_name($key);
|
||||
if (file_exists($file)) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
|
||||
public function enabled()
|
||||
{
|
||||
return $this->enabled;
|
||||
}
|
||||
|
||||
private function _name($key)
|
||||
{
|
||||
return sprintf('%s%s%s', $this->dir, $this->prefix, sha1($key));
|
||||
}
|
||||
}
|
83
system/src/Cache/PHP.php
Normal file
83
system/src/Cache/PHP.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/**
|
||||
* PHP cache class
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @copyright 2019 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
namespace MyAAC\Cache;
|
||||
|
||||
class PHP
|
||||
{
|
||||
private $prefix;
|
||||
private $dir;
|
||||
private $enabled;
|
||||
|
||||
public function __construct($prefix = '', $dir = '')
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
$this->dir = $dir;
|
||||
$this->enabled = (file_exists($this->dir) && is_dir($this->dir) && is_writable($this->dir));
|
||||
}
|
||||
|
||||
public function set($key, $var, $ttl = 0)
|
||||
{
|
||||
$var = var_export($var, true);
|
||||
|
||||
// Write to temp file first to ensure atomicity
|
||||
$tmp = $this->dir . "tmp_$key." . uniqid('', true) . '.tmp';
|
||||
file_put_contents($tmp, '<?php $var = ' . $var . ';', LOCK_EX);
|
||||
|
||||
$file = $this->_name($key);
|
||||
rename($tmp, $file);
|
||||
|
||||
if ($ttl === 0) {
|
||||
$ttl = 365 * 24 * 60 * 60; // 365 days
|
||||
}
|
||||
|
||||
touch($file, time() + $ttl);
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
{
|
||||
$tmp = '';
|
||||
if ($this->fetch($key, $tmp)) {
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function fetch($key, &$var)
|
||||
{
|
||||
$file = $this->_name($key);
|
||||
if (!file_exists($file) || filemtime($file) < time()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@include $file;
|
||||
$var = isset($var) ? $var : null;
|
||||
return true;
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
$file = $this->_name($key);
|
||||
if (file_exists($file)) {
|
||||
unlink($file);
|
||||
}
|
||||
}
|
||||
|
||||
public function enabled()
|
||||
{
|
||||
return $this->enabled;
|
||||
}
|
||||
|
||||
private function _name($key)
|
||||
{
|
||||
return sprintf('%s%s%s', $this->dir, $this->prefix, sha1($key) . '.php');
|
||||
}
|
||||
}
|
62
system/src/Cache/XCache.php
Normal file
62
system/src/Cache/XCache.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* XCache class
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @author Mark Samman (Talaturen) <marksamman@gmail.com>
|
||||
* @copyright 2019 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
namespace MyAAC\Cache;
|
||||
|
||||
class XCache
|
||||
{
|
||||
private $prefix;
|
||||
private $enabled;
|
||||
|
||||
public function __construct($prefix = '')
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
$this->enabled = function_exists('xcache_get') && ini_get('xcache.var_size');
|
||||
}
|
||||
|
||||
public function set($key, $var, $ttl = 0)
|
||||
{
|
||||
$key = $this->prefix . $key;
|
||||
xcache_unset($key);
|
||||
xcache_set($key, $var, $ttl);
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
{
|
||||
$tmp = '';
|
||||
if ($this->fetch($this->prefix . $key, $tmp)) {
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function fetch($key, &$var)
|
||||
{
|
||||
$key = $this->prefix . $key;
|
||||
if (!xcache_isset($key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$var = xcache_get($key);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
xcache_unset($this->prefix . $key);
|
||||
}
|
||||
|
||||
public function enabled()
|
||||
{
|
||||
return $this->enabled;
|
||||
}
|
||||
}
|
150
system/src/Changelog.php
Normal file
150
system/src/Changelog.php
Normal file
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
use MyAAC\Cache\Cache;
|
||||
use MyAAC\Models\Changelog as ModelsChangelog;
|
||||
|
||||
class Changelog
|
||||
{
|
||||
static public function verify($body,$date, &$errors)
|
||||
{
|
||||
if(!isset($date) || !isset($body[0])) {
|
||||
$errors[] = 'Please fill all inputs.';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(strlen($body) > CL_LIMIT) {
|
||||
$errors[] = 'Changelog content cannot be longer than ' . CL_LIMIT . ' characters.';
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static public function add($body, $type, $where, $player_id, $cdate, &$errors)
|
||||
{
|
||||
if(!self::verify($body,$cdate, $errors))
|
||||
return false;
|
||||
|
||||
$row = new ModelsChangelog;
|
||||
$row->body = $body;
|
||||
$row->type = $type;
|
||||
$row->date = $cdate;
|
||||
$row->where = $where;
|
||||
$row->player_id = $player_id ?? 0;
|
||||
if ($row->save()) {
|
||||
self::clearCache();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static public function get($id) {
|
||||
return ModelsChangelog::find($id);
|
||||
}
|
||||
|
||||
static public function update($id, $body, $type, $where, $player_id, $date, &$errors)
|
||||
{
|
||||
if(!self::verify($body,$date, $errors))
|
||||
return false;
|
||||
|
||||
if (ModelsChangelog::where('id', '=', $id)->update([
|
||||
'body' => $body,
|
||||
'type' => $type,
|
||||
'where' => $where,
|
||||
'player_id' => $player_id ?? 0,
|
||||
'date' => $date
|
||||
])) {
|
||||
self::clearCache();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static public function delete($id, &$errors)
|
||||
{
|
||||
if(isset($id))
|
||||
{
|
||||
$row = ModelsChangelog::find($id);
|
||||
if ($row) {
|
||||
if (!$row->delete()) {
|
||||
$errors[] = 'Fail during delete Changelog.';
|
||||
}
|
||||
} else {
|
||||
$errors[] = 'Changelog with id ' . $id . ' does not exist.';
|
||||
}
|
||||
} else {
|
||||
$errors[] = 'Changelog id not set.';
|
||||
}
|
||||
|
||||
if(count($errors)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
self::clearCache();
|
||||
return true;
|
||||
}
|
||||
|
||||
static public function toggleHidden($id, &$errors, &$status)
|
||||
{
|
||||
if(isset($id))
|
||||
{
|
||||
$row = ModelsChangelog::find($id);
|
||||
if ($row) {
|
||||
$row->hidden = $row->hidden == 1 ? 0 : 1;
|
||||
if (!$row->save()) {
|
||||
$errors[] = 'Fail during toggle hidden Changelog.';
|
||||
}
|
||||
$status = $row->hidden;
|
||||
} else {
|
||||
$errors[] = 'Changelog with id ' . $id . ' does not exists.';
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
$errors[] = 'Changelog id not set.';
|
||||
|
||||
if(count($errors)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
self::clearCache();
|
||||
return true;
|
||||
}
|
||||
|
||||
static public function getCached($type)
|
||||
{
|
||||
global $template_name;
|
||||
|
||||
$cache = Cache::getInstance();
|
||||
if ($cache->enabled())
|
||||
{
|
||||
$tmp = '';
|
||||
if ($cache->fetch('changelog_' . $template_name, $tmp) && isset($tmp[0])) {
|
||||
return $tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static public function clearCache()
|
||||
{
|
||||
global $template_name;
|
||||
$cache = Cache::getInstance();
|
||||
if (!$cache->enabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tmp = '';
|
||||
foreach (get_templates() as $template) {
|
||||
if ($cache->fetch('changelog_' . $template_name, $tmp)) {
|
||||
$cache->delete('changelog_' . $template_name);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
290
system/src/CreateCharacter.php
Normal file
290
system/src/CreateCharacter.php
Normal file
@@ -0,0 +1,290 @@
|
||||
<?php
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
use MyAAC\Models\Player;
|
||||
|
||||
/**
|
||||
* CreateCharacter
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Gesior <jerzyskalski@wp.pl>
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @copyright 2019 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
class CreateCharacter
|
||||
{
|
||||
/**
|
||||
* @param $name
|
||||
* @param $errors
|
||||
* @return bool
|
||||
*/
|
||||
public function checkName($name, &$errors)
|
||||
{
|
||||
$minLength = setting('core.create_character_name_min_length');
|
||||
$maxLength = setting('core.create_character_name_max_length');
|
||||
|
||||
if(empty($name)) {
|
||||
$errors['name'] = 'Please enter a name for your character!';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(strlen($name) > $maxLength) {
|
||||
$errors['name'] = 'Name is too long. Max. length <b>' . $maxLength . '</b> letters.';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(strlen($name) < $minLength) {
|
||||
$errors['name'] = 'Name is too short. Min. length <b>' . $minLength . '</b> letters.';
|
||||
return false;
|
||||
}
|
||||
|
||||
$name_length = strlen($name);
|
||||
if(strspn($name, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM- '") != $name_length) {
|
||||
$errors['name'] = 'This name contains invalid letters, words or format. Please use only a-Z, - , \' and space.';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!preg_match("/[A-z ']/", $name)) {
|
||||
$errors['name'] = 'Your name contains illegal characters.';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!admin() && !\Validator::newCharacterName($name)) {
|
||||
$errors['name'] = \Validator::getLastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(Player::where('name', '=', $name)->exists()) {
|
||||
$errors['name'] = 'Character with this name already exist.';
|
||||
return false;
|
||||
}
|
||||
|
||||
return empty($errors);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param int $sex
|
||||
* @param int $vocation
|
||||
* @param int $town
|
||||
* @param array $errors
|
||||
* @return bool
|
||||
*/
|
||||
public function check($name, $sex, &$vocation, &$town, &$errors)
|
||||
{
|
||||
$this->checkName($name, $errors);
|
||||
|
||||
if(empty($sex) && $sex != "0") {
|
||||
$errors['sex'] = 'Please select the sex for your character!';
|
||||
}
|
||||
|
||||
if(count(config('character_samples')) > 1)
|
||||
{
|
||||
if(!isset($vocation))
|
||||
$errors['vocation'] = 'Please select a vocation for your character.';
|
||||
}
|
||||
else {
|
||||
$vocation = config('character_samples')[0];
|
||||
}
|
||||
|
||||
if(count(config('character_towns')) > 1) {
|
||||
if(!isset($town)) {
|
||||
$errors['town'] = 'Please select a town for your character.';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$town = config('character_towns')[0];
|
||||
}
|
||||
|
||||
if(empty($errors)) {
|
||||
if(!isset(config('genders')[$sex]))
|
||||
$errors['sex'] = 'Sex is invalid.';
|
||||
if(!in_array($town, config('character_towns'), false))
|
||||
$errors['town'] = 'Please select valid town.';
|
||||
if(count(config('character_samples')) > 1)
|
||||
{
|
||||
$newchar_vocation_check = false;
|
||||
foreach((array)config('character_samples') as $char_vocation_key => $sample_char)
|
||||
if($vocation === $char_vocation_key)
|
||||
$newchar_vocation_check = true;
|
||||
if(!$newchar_vocation_check)
|
||||
$errors['vocation'] = 'Unknown vocation. Please fill in form again.';
|
||||
}
|
||||
else
|
||||
$vocation = 0;
|
||||
}
|
||||
|
||||
return empty($errors);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param int $sex
|
||||
* @param int $vocation
|
||||
* @param int $town
|
||||
* @param \OTS_Account $account
|
||||
* @param array $errors
|
||||
* @return bool
|
||||
* @throws \E_OTS_NotLoaded
|
||||
* @throws \Twig_Error_Loader
|
||||
* @throws \Twig_Error_Runtime
|
||||
* @throws \Twig_Error_Syntax
|
||||
*/
|
||||
public function doCreate($name, $sex, $vocation, $town, $account, &$errors)
|
||||
{
|
||||
if(!$this->check($name, $sex, $vocation, $town, $errors)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(empty($errors))
|
||||
{
|
||||
$number_of_players_on_account = $account->getPlayersList(true)->count();
|
||||
if($number_of_players_on_account >= setting('core.characters_per_account'))
|
||||
$errors[] = 'You have too many characters on your account <b>('.$number_of_players_on_account . '/' . setting('core.characters_per_account') . ')</b>!';
|
||||
}
|
||||
|
||||
if(empty($errors))
|
||||
{
|
||||
$char_to_copy_name = config('character_samples')[$vocation];
|
||||
$char_to_copy = new \OTS_Player();
|
||||
$char_to_copy->find($char_to_copy_name);
|
||||
if(!$char_to_copy->isLoaded())
|
||||
$errors[] = 'Wrong characters configuration. Try again or contact with admin. ADMIN: Go to Admin Panel -> Settings -> Create Character and set valid characters to copy names. Character to copy: <b>'.$char_to_copy_name.'</b> doesn\'t exist.';
|
||||
}
|
||||
|
||||
if(!empty($errors)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
global $db;
|
||||
|
||||
if($sex == "0")
|
||||
$char_to_copy->setLookType(136);
|
||||
|
||||
$player = new \OTS_Player();
|
||||
$player->setName($name);
|
||||
$player->setAccount($account);
|
||||
$player->setGroupId(1);
|
||||
$player->setSex($sex);
|
||||
$player->setVocation($char_to_copy->getVocation());
|
||||
if($db->hasColumn('players', 'promotion'))
|
||||
$player->setPromotion($char_to_copy->getPromotion());
|
||||
|
||||
if($db->hasColumn('players', 'direction'))
|
||||
$player->setDirection($char_to_copy->getDirection());
|
||||
|
||||
$player->setConditions($char_to_copy->getConditions());
|
||||
$rank = $char_to_copy->getRank();
|
||||
if($rank->isLoaded()) {
|
||||
$player->setRank($char_to_copy->getRank());
|
||||
}
|
||||
|
||||
if($db->hasColumn('players', 'lookaddons'))
|
||||
$player->setLookAddons($char_to_copy->getLookAddons());
|
||||
|
||||
$player->setTownId($town);
|
||||
$player->setExperience($char_to_copy->getExperience());
|
||||
$player->setLevel($char_to_copy->getLevel());
|
||||
$player->setMagLevel($char_to_copy->getMagLevel());
|
||||
$player->setHealth($char_to_copy->getHealth());
|
||||
$player->setHealthMax($char_to_copy->getHealthMax());
|
||||
$player->setMana($char_to_copy->getMana());
|
||||
$player->setManaMax($char_to_copy->getManaMax());
|
||||
$player->setManaSpent($char_to_copy->getManaSpent());
|
||||
$player->setSoul($char_to_copy->getSoul());
|
||||
|
||||
for($skill = \POT::SKILL_FIRST; $skill <= \POT::SKILL_LAST; $skill++) {
|
||||
$value = 10;
|
||||
if (setting('core.use_character_sample_skills')) {
|
||||
$value = $char_to_copy->getSkill($skill);
|
||||
}
|
||||
|
||||
$player->setSkill($skill, $value);
|
||||
}
|
||||
|
||||
$player->setLookBody($char_to_copy->getLookBody());
|
||||
$player->setLookFeet($char_to_copy->getLookFeet());
|
||||
$player->setLookHead($char_to_copy->getLookHead());
|
||||
$player->setLookLegs($char_to_copy->getLookLegs());
|
||||
$player->setLookType($char_to_copy->getLookType());
|
||||
$player->setCap($char_to_copy->getCap());
|
||||
$player->setBalance(0);
|
||||
$player->setPosX(0);
|
||||
$player->setPosY(0);
|
||||
$player->setPosZ(0);
|
||||
|
||||
if($db->hasColumn('players', 'stamina')) {
|
||||
$player->setStamina($char_to_copy->getStamina());
|
||||
}
|
||||
|
||||
if($db->hasColumn('players', 'loss_experience')) {
|
||||
$player->setLossExperience($char_to_copy->getLossExperience());
|
||||
$player->setLossMana($char_to_copy->getLossMana());
|
||||
$player->setLossSkills($char_to_copy->getLossSkills());
|
||||
}
|
||||
if($db->hasColumn('players', 'loss_items')) {
|
||||
$player->setLossItems($char_to_copy->getLossItems());
|
||||
$player->setLossContainers($char_to_copy->getLossContainers());
|
||||
}
|
||||
|
||||
$player->save();
|
||||
$player->setCustomField('created', time());
|
||||
|
||||
$player = new \OTS_Player();
|
||||
$player->find($name);
|
||||
|
||||
if(!$player->isLoaded()) {
|
||||
error("Error. Can't create character. Probably problem with database. Please try again later or contact with admin.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if($db->hasTable('player_skills')) {
|
||||
for($skill = \POT::SKILL_FIRST; $skill <= \POT::SKILL_LAST; $skill++) {
|
||||
$value = 10;
|
||||
if (setting('core.use_character_sample_skills')) {
|
||||
$value = $char_to_copy->getSkill($skill);
|
||||
}
|
||||
$skillExists = $db->query('SELECT `skillid` FROM `player_skills` WHERE `player_id` = ' . $player->getId() . ' AND `skillid` = ' . $skill);
|
||||
if($skillExists->rowCount() <= 0) {
|
||||
$db->query('INSERT INTO `player_skills` (`player_id`, `skillid`, `value`, `count`) VALUES ('.$player->getId().', '.$skill.', ' . $value . ', 0)');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($db->hasTable('player_items') && $db->hasColumn('player_items', 'pid') && $db->hasColumn('player_items', 'sid') && $db->hasColumn('player_items', 'itemtype')) {
|
||||
$loaded_items_to_copy = $db->query("SELECT * FROM player_items WHERE player_id = ".$char_to_copy->getId()."");
|
||||
foreach($loaded_items_to_copy as $save_item) {
|
||||
$blob = $db->quote($save_item['attributes']);
|
||||
$db->query("INSERT INTO `player_items` (`player_id` ,`pid` ,`sid` ,`itemtype`, `count`, `attributes`) VALUES ('".$player->getId()."', '".$save_item['pid']."', '".$save_item['sid']."', '".$save_item['itemtype']."', '".$save_item['count']."', $blob);");
|
||||
}
|
||||
}
|
||||
|
||||
global $hooks;
|
||||
if (!$hooks->trigger(HOOK_ACCOUNT_CREATE_CHARACTER_AFTER,
|
||||
[
|
||||
'account' => $account,
|
||||
'player' => $player,
|
||||
'name' => $name,
|
||||
'sex' => $sex,
|
||||
'vocation' => $vocation,
|
||||
'town' => $town,
|
||||
]
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
global $twig;
|
||||
$twig->display('success.html.twig', array(
|
||||
'title' => 'Character Created',
|
||||
'description' => 'The character <b>' . $name . '</b> has been created.<br/>
|
||||
Please select the outfit when you log in for the first time.<br/><br/>
|
||||
<b>See you on ' . configLua('serverName') . '!</b>'
|
||||
));
|
||||
|
||||
$account->logAction('Created character <b>' . $name . '</b>.');
|
||||
return true;
|
||||
}
|
||||
}
|
183
system/src/Creatures.php
Normal file
183
system/src/Creatures.php
Normal file
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
/**
|
||||
* Creatures class
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Gesior <jerzyskalski@wp.pl>
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @copyright 2019 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
use MyAAC\Models\Monster;
|
||||
|
||||
class Creatures {
|
||||
/**
|
||||
* @var \OTS_MonstersList
|
||||
*/
|
||||
private static $monstersList;
|
||||
private static $lastError = '';
|
||||
|
||||
public static function loadFromXML($show = false) {
|
||||
try {
|
||||
Monster::query()->delete();
|
||||
} catch(\Exception $error) {}
|
||||
|
||||
if($show) {
|
||||
echo '<h2>Reload monsters.</h2>';
|
||||
echo "<h2>All records deleted from table '" . TABLE_PREFIX . "monsters' in database.</h2>";
|
||||
}
|
||||
|
||||
try {
|
||||
self::$monstersList = new \OTS_MonstersList(config('data_path') . 'monster/');
|
||||
}
|
||||
catch(\Exception $e) {
|
||||
self::$lastError = $e->getMessage();
|
||||
return false;
|
||||
}
|
||||
|
||||
$items = array();
|
||||
Items::load();
|
||||
foreach((array)Items::$items as $id => $item) {
|
||||
$items[$item['name']] = $id;
|
||||
}
|
||||
|
||||
//$names_added must be an array
|
||||
$names_added[] = '';
|
||||
//add monsters
|
||||
foreach(self::$monstersList as $lol) {
|
||||
$monster = self::$monstersList->current();
|
||||
if(!$monster->loaded()) {
|
||||
if($show) {
|
||||
warning('Error while adding monster: ' . self::$monstersList->currentFile());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
//load monster mana needed to summon/convince
|
||||
$mana = $monster->getManaCost();
|
||||
|
||||
//load monster name
|
||||
$name = $monster->getName();
|
||||
//load monster health
|
||||
$health = $monster->getHealth();
|
||||
//load monster speed and calculate "speed level"
|
||||
$speed_ini = $monster->getSpeed();
|
||||
if($speed_ini <= 220) {
|
||||
$speed_lvl = 1;
|
||||
} else {
|
||||
$speed_lvl = ($speed_ini - 220) / 2;
|
||||
}
|
||||
//check "is monster use haste spell"
|
||||
$defenses = $monster->getDefenses();
|
||||
$use_haste = 0;
|
||||
foreach($defenses as $defense) {
|
||||
if($defense == 'speed') {
|
||||
$use_haste = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//load race
|
||||
$race = $monster->getRace();
|
||||
$armor = $monster->getArmor();
|
||||
$defensev = $monster->getDefense();
|
||||
|
||||
//load look
|
||||
$look = $monster->getLook();
|
||||
|
||||
//load monster flags
|
||||
$flags = $monster->getFlags();
|
||||
if(!isset($flags['summonable']))
|
||||
$flags['summonable'] = '0';
|
||||
if(!isset($flags['convinceable']))
|
||||
$flags['convinceable'] = '0';
|
||||
|
||||
if(!isset($flags['pushable']))
|
||||
$flags['pushable'] = '0';
|
||||
if(!isset($flags['canpushitems']))
|
||||
$flags['canpushitems'] = '0';
|
||||
if(!isset($flags['canpushcreatures']))
|
||||
$flags['canpushcreatures'] = '0';
|
||||
if(!isset($flags['runonhealth']))
|
||||
$flags['runonhealth'] = '0';
|
||||
if(!isset($flags['canwalkonenergy']))
|
||||
$flags['canwalkonenergy'] = '0';
|
||||
if(!isset($flags['canwalkonpoison']))
|
||||
$flags['canwalkonpoison'] = '0';
|
||||
if(!isset($flags['canwalkonfire']))
|
||||
$flags['canwalkonfire'] = '0';
|
||||
if(!isset($flags['hostile']))
|
||||
$flags['hostile'] = '0';
|
||||
if(!isset($flags['attackable']))
|
||||
$flags['attackable'] = '0';
|
||||
if(!isset($flags['rewardboss']))
|
||||
$flags['rewardboss'] = '0';
|
||||
|
||||
$summons = $monster->getSummons();
|
||||
$loot = $monster->getLoot();
|
||||
foreach($loot as &$item) {
|
||||
if(!\Validator::number($item['id'])) {
|
||||
if(isset($items[$item['id']])) {
|
||||
$item['id'] = $items[$item['id']];
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!in_array($name, $names_added)) {
|
||||
try {
|
||||
Monster::create(array(
|
||||
'name' => $name,
|
||||
'mana' => empty($mana) ? 0 : $mana,
|
||||
'exp' => $monster->getExperience(),
|
||||
'health' => $health,
|
||||
'speed_lvl' => $speed_lvl,
|
||||
'use_haste' => $use_haste,
|
||||
'voices' => json_encode($monster->getVoices()),
|
||||
'immunities' => json_encode($monster->getImmunities()),
|
||||
'elements' => json_encode($monster->getElements()),
|
||||
'summonable' => $flags['summonable'] > 0 ? 1 : 0,
|
||||
'convinceable' => $flags['convinceable'] > 0 ? 1 : 0,
|
||||
'pushable' => $flags['pushable'] > 0 ? 1 : 0,
|
||||
'canpushitems' => $flags['canpushitems'] > 0 ? 1 : 0,
|
||||
'canpushcreatures' => $flags['canpushcreatures'] > 0 ? 1 : 0,
|
||||
'runonhealth' => $flags['runonhealth'] > 0 ? 1 : 0,
|
||||
'canwalkonenergy' => $flags['canwalkonenergy'] > 0 ? 1 : 0,
|
||||
'canwalkonpoison' => $flags['canwalkonpoison'] > 0 ? 1 : 0,
|
||||
'canwalkonfire' => $flags['canwalkonfire'] > 0 ? 1 : 0,
|
||||
'hostile' => $flags['hostile'] > 0 ? 1 : 0,
|
||||
'attackable' => $flags['attackable'] > 0 ? 1 : 0,
|
||||
'rewardboss' => $flags['rewardboss'] > 0 ? 1 : 0,
|
||||
'defense' => $defensev,
|
||||
'armor' => $armor,
|
||||
'race' => $race,
|
||||
'loot' => json_encode($loot),
|
||||
'look' => json_encode($look),
|
||||
'summons' => json_encode($summons)
|
||||
));
|
||||
|
||||
if($show) {
|
||||
success('Added: ' . $name . '<br/>');
|
||||
}
|
||||
}
|
||||
catch(\Exception $error) {
|
||||
if($show) {
|
||||
warning('Error while adding monster (' . $name . '): ' . $error->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
$names_added[] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function getMonstersList() {
|
||||
return self::$monstersList;
|
||||
}
|
||||
|
||||
public static function getLastError() {
|
||||
return self::$lastError;
|
||||
}
|
||||
}
|
44
system/src/Data.php
Normal file
44
system/src/Data.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* Data class
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @copyright 2019 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
class Data
|
||||
{
|
||||
private $table = '';
|
||||
|
||||
public function __construct($table) {
|
||||
$this->table = $table;
|
||||
}
|
||||
|
||||
public function get($where)
|
||||
{
|
||||
global $db;
|
||||
return $db->select($this->table, $where);
|
||||
}
|
||||
|
||||
public function add($data)
|
||||
{
|
||||
global $db;
|
||||
return $db->insert($this->table, $data);
|
||||
}
|
||||
|
||||
public function delete($data, $where)
|
||||
{
|
||||
global $db;
|
||||
return $db->delete($this->table, $data, $where);
|
||||
}
|
||||
|
||||
public function update($data, $where)
|
||||
{
|
||||
global $db;
|
||||
return $db->update($this->table, $data, $where);
|
||||
}
|
||||
}
|
107
system/src/DataLoader.php
Normal file
107
system/src/DataLoader.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
/**
|
||||
* Project: MyAAC
|
||||
* Automatic Account Creator for Open Tibia Servers
|
||||
*
|
||||
* This is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @copyright 2020 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
class DataLoader
|
||||
{
|
||||
private static $locale;
|
||||
private static $startTime;
|
||||
|
||||
/**
|
||||
* Load data from server
|
||||
*/
|
||||
public static function load()
|
||||
{
|
||||
self::$startTime = microtime(true);
|
||||
|
||||
if(Items::loadFromXML()) {
|
||||
success(self::$locale['step_database_loaded_items'] . self::getLoadedTime());
|
||||
}
|
||||
else {
|
||||
error(Items::getError());
|
||||
}
|
||||
|
||||
self::$startTime = microtime(true);
|
||||
|
||||
if(Creatures::loadFromXML()) {
|
||||
success(self::$locale['step_database_loaded_monsters'] . self::getLoadedTime());
|
||||
|
||||
if(Creatures::getMonstersList()->hasErrors()) {
|
||||
self::$locale['step_database_error_monsters'] = str_replace('$LOG$', 'system/logs/error.log', self::$locale['step_database_error_monsters']);
|
||||
warning(self::$locale['step_database_error_monsters']);
|
||||
}
|
||||
}
|
||||
else {
|
||||
error(Creatures::getLastError());
|
||||
}
|
||||
|
||||
self::$startTime = microtime(true);
|
||||
|
||||
if(NPCs::loadFromXML()) {
|
||||
success(self::$locale['step_database_loaded_npcs'] . self::getLoadedTime());
|
||||
}
|
||||
else {
|
||||
error(self::$locale['step_database_error_npcs']);
|
||||
}
|
||||
|
||||
self::$startTime = microtime(true);
|
||||
|
||||
if(Spells::loadFromXML()) {
|
||||
success(self::$locale['step_database_loaded_spells'] . self::getLoadedTime());
|
||||
}
|
||||
else {
|
||||
error(Spells::getLastError());
|
||||
}
|
||||
|
||||
self::$startTime = microtime(true);
|
||||
|
||||
if (Towns::save()) {
|
||||
success(self::$locale['step_database_loaded_towns'] . self::getLoadedTime());
|
||||
}
|
||||
else {
|
||||
warning(self::$locale['step_database_error_towns']);
|
||||
}
|
||||
|
||||
self::$startTime = microtime(true);
|
||||
|
||||
if(Weapons::loadFromXML()) {
|
||||
success(self::$locale['step_database_loaded_weapons'] . self::getLoadedTime());
|
||||
}
|
||||
else {
|
||||
error(Weapons::getError());
|
||||
}
|
||||
}
|
||||
|
||||
public static function setLocale($locale) {
|
||||
self::$locale = $locale;
|
||||
}
|
||||
|
||||
private static function getLoadedTime()
|
||||
{
|
||||
$endTime = round(microtime(true) - self::$startTime, 3);
|
||||
return ' (' . str_replace('$TIME$', $endTime, self::$locale['loaded_in_ms']) . ')';
|
||||
}
|
||||
}
|
7
system/src/Exceptions/SensitiveException.php
Normal file
7
system/src/Exceptions/SensitiveException.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace MyAAC\Exceptions;
|
||||
|
||||
class SensitiveException extends \Exception
|
||||
{
|
||||
}
|
325
system/src/Forum.php
Normal file
325
system/src/Forum.php
Normal file
@@ -0,0 +1,325 @@
|
||||
<?php
|
||||
/**
|
||||
* Forum class
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Gesior <jerzyskalski@wp.pl>
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @copyright 2019 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
$settingForumTablePrefix = setting('core.forum_table_prefix');
|
||||
if(null !== $settingForumTablePrefix && !empty(trim($settingForumTablePrefix))) {
|
||||
if(!in_array($settingForumTablePrefix, array('myaac_', 'z_'))) {
|
||||
throw new \RuntimeException('Invalid value for forum_table_prefix in config.php. Can be only: "myaac_" or "z_".');
|
||||
}
|
||||
|
||||
define('FORUM_TABLE_PREFIX', $settingForumTablePrefix);
|
||||
}
|
||||
else {
|
||||
if($db->hasTable('z_forum')) {
|
||||
define('FORUM_TABLE_PREFIX', 'z_');
|
||||
}
|
||||
else {
|
||||
define('FORUM_TABLE_PREFIX', 'myaac_');
|
||||
}
|
||||
}
|
||||
|
||||
class Forum
|
||||
{
|
||||
/**
|
||||
* @param \OTS_Account $account
|
||||
* @return bool
|
||||
* @throws \E_OTS_NotLoaded
|
||||
*/
|
||||
public static function canPost($account)
|
||||
{
|
||||
global $db, $config;
|
||||
|
||||
if(!$account->isLoaded() || $account->isBanned())
|
||||
return false;
|
||||
|
||||
if(self::isModerator())
|
||||
return true;
|
||||
|
||||
return
|
||||
$db->query(
|
||||
'SELECT `id` FROM `players` WHERE `account_id` = ' . $db->quote($account->getId()) .
|
||||
' AND `level` >= ' . $db->quote(setting('core.forum_level_required')) .
|
||||
' LIMIT 1')->rowCount() > 0;
|
||||
}
|
||||
|
||||
public static function isModerator() {
|
||||
return hasFlag(FLAG_CONTENT_FORUM) || superAdmin();
|
||||
}
|
||||
|
||||
public static function add_thread($title, $body, $section_id, $player_id, $account_id, &$errors)
|
||||
{
|
||||
global $db;
|
||||
$thread_id = 0;
|
||||
if($db->insert(FORUM_TABLE_PREFIX . 'forum', array(
|
||||
'first_post' => 0,
|
||||
'last_post' => time(),
|
||||
'section' => $section_id,
|
||||
'replies' => 0,
|
||||
'views' => 0,
|
||||
'author_aid' => isset($account_id) ? $account_id : 0,
|
||||
'author_guid' => isset($player_id) ? $player_id : 0,
|
||||
'post_text' => $body, 'post_topic' => $title,
|
||||
'post_smile' => 0, 'post_html' => 1,
|
||||
'post_date' => time(),
|
||||
'last_edit_aid' => 0, 'edit_date' => 0,
|
||||
'post_ip' => $_SERVER['REMOTE_ADDR']
|
||||
))) {
|
||||
$thread_id = $db->lastInsertId();
|
||||
$db->query("UPDATE `" . FORUM_TABLE_PREFIX . "forum` SET `first_post`=".(int) $thread_id." WHERE `id` = ".(int) $thread_id);
|
||||
}
|
||||
|
||||
return $thread_id;
|
||||
}
|
||||
|
||||
public static function add_post($thread_id, $section, $author_aid, $author_guid, $post_text, $post_topic, $smile, $html)
|
||||
{
|
||||
global $db;
|
||||
$db->insert(FORUM_TABLE_PREFIX . 'forum', array(
|
||||
'first_post' => $thread_id,
|
||||
'section' => $section,
|
||||
'author_aid' => $author_aid,
|
||||
'author_guid' => $author_guid,
|
||||
'post_text' => $post_text,
|
||||
'post_topic' => $post_topic,
|
||||
'post_smile' => $smile,
|
||||
'post_html' => $html,
|
||||
'post_date' => time(),
|
||||
'post_ip' => $_SERVER['REMOTE_ADDR']
|
||||
));
|
||||
}
|
||||
public static function add_board($name, $description, $access, $guild, &$errors)
|
||||
{
|
||||
global $db;
|
||||
if(isset($name[0]) && isset($description[0]))
|
||||
{
|
||||
$query = $db->select(TABLE_PREFIX . 'forum_boards', array('name' => $name));
|
||||
|
||||
if($query === false)
|
||||
{
|
||||
$query =
|
||||
$db->query(
|
||||
'SELECT ' . $db->fieldName('ordering') .
|
||||
' FROM ' . $db->tableName(TABLE_PREFIX . 'forum_boards') .
|
||||
' ORDER BY ' . $db->fieldName('ordering') . ' DESC LIMIT 1'
|
||||
);
|
||||
|
||||
$ordering = 0;
|
||||
if($query->rowCount() > 0) {
|
||||
$query = $query->fetch();
|
||||
$ordering = $query['ordering'] + 1;
|
||||
}
|
||||
$db->insert(TABLE_PREFIX . 'forum_boards', array('name' => $name, 'description' => $description, 'access' => $access, 'guild' => $guild, 'ordering' => $ordering));
|
||||
}
|
||||
else
|
||||
$errors[] = 'Forum board with this name already exists.';
|
||||
}
|
||||
else
|
||||
$errors[] = 'Please fill all inputs.';
|
||||
|
||||
return !count($errors);
|
||||
}
|
||||
|
||||
public static function get_board($id) {
|
||||
global $db;
|
||||
return $db->select(TABLE_PREFIX . 'forum_boards', array('id' => $id));
|
||||
}
|
||||
|
||||
public static function update_board($id, $name, $access, $guild, $description) {
|
||||
global $db;
|
||||
$db->update(TABLE_PREFIX . 'forum_boards', array('name' => $name, 'description' => $description, 'access' => $access, 'guild' => $guild), array('id' => $id));
|
||||
}
|
||||
|
||||
public static function delete_board($id, &$errors)
|
||||
{
|
||||
global $db;
|
||||
if(isset($id))
|
||||
{
|
||||
if(self::get_board($id) !== false)
|
||||
$db->delete(TABLE_PREFIX . 'forum_boards', array('id' => $id));
|
||||
else
|
||||
$errors[] = 'Forum board with id ' . $id . ' does not exists.';
|
||||
}
|
||||
else
|
||||
$errors[] = 'id not set';
|
||||
|
||||
return !count($errors);
|
||||
}
|
||||
|
||||
public static function toggleHidden_board($id, &$errors)
|
||||
{
|
||||
global $db;
|
||||
if(isset($id))
|
||||
{
|
||||
$query = self::get_board($id);
|
||||
if($query !== false)
|
||||
$db->update(TABLE_PREFIX . 'forum_boards', array('hidden' => ($query['hidden'] == 1 ? 0 : 1)), array('id' => $id));
|
||||
else
|
||||
$errors[] = 'Forum board with id ' . $id . ' does not exists.';
|
||||
}
|
||||
else
|
||||
$errors[] = 'id not set';
|
||||
|
||||
return !count($errors);
|
||||
}
|
||||
|
||||
public static function move_board($id, $i, &$errors)
|
||||
{
|
||||
global $db;
|
||||
$query = self::get_board($id);
|
||||
if($query !== false)
|
||||
{
|
||||
$ordering = $query['ordering'] + $i;
|
||||
$old_record = $db->select(TABLE_PREFIX . 'forum_boards', array('ordering' => $ordering));
|
||||
if($old_record !== false)
|
||||
$db->update(TABLE_PREFIX . 'forum_boards', array('ordering' => $query['ordering']), array('ordering' => $ordering));
|
||||
|
||||
$db->update(TABLE_PREFIX . 'forum_boards', array('ordering' => $ordering), array('id' => $id));
|
||||
}
|
||||
else
|
||||
$errors[] = 'Forum board with id ' . $id . ' does not exists.';
|
||||
|
||||
return !count($errors);
|
||||
}
|
||||
|
||||
public static function parseSmiles($text)
|
||||
{
|
||||
$smileys = array(
|
||||
';D' => 1,
|
||||
':D' => 1,
|
||||
':cool:' => 2,
|
||||
';cool;' => 2,
|
||||
':ekk:' => 3,
|
||||
';ekk;' => 3,
|
||||
';o' => 4,
|
||||
';O' => 4,
|
||||
':o' => 4,
|
||||
':O' => 4,
|
||||
':(' => 5,
|
||||
';(' => 5,
|
||||
':mad:' => 6,
|
||||
';mad;' => 6,
|
||||
';rolleyes;' => 7,
|
||||
':rolleyes:' => 7,
|
||||
':)' => 8,
|
||||
';d' => 9,
|
||||
':d' => 9,
|
||||
';)' => 10
|
||||
);
|
||||
|
||||
foreach($smileys as $search => $replace)
|
||||
$text = str_replace($search, '<img src="images/forum/smile/'.$replace.'.gif" alt="'. $search .'" title="' . $search . '" />', $text);
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
public static function parseBBCode($text, $smiles)
|
||||
{
|
||||
$rows = 0;
|
||||
while(stripos($text, '[code]') !== false && stripos($text, '[/code]') !== false )
|
||||
{
|
||||
$code = substr($text, stripos($text, '[code]')+6, stripos($text, '[/code]') - stripos($text, '[code]') - 6);
|
||||
if(!is_int($rows / 2)) { $bgcolor = 'ABED25'; } else { $bgcolor = '23ED25'; } $rows++;
|
||||
$text = str_ireplace('[code]'.$code.'[/code]', '<i>Code:</i><br /><table cellpadding="0" style="background-color: #'.$bgcolor.'; width: 480px; border-style: dotted; border-color: #CCCCCC; border-width: 2px"><tr><td>'.$code.'</td></tr></table>', $text);
|
||||
}
|
||||
$rows = 0;
|
||||
while(stripos($text, '[quote]') !== false && stripos($text, '[/quote]') !== false )
|
||||
{
|
||||
$quote = substr($text, stripos($text, '[quote]')+7, stripos($text, '[/quote]') - stripos($text, '[quote]') - 7);
|
||||
if(!is_int($rows / 2)) { $bgcolor = 'AAAAAA'; } else { $bgcolor = 'CCCCCC'; } $rows++;
|
||||
$text = str_ireplace('[quote]'.$quote.'[/quote]', '<table cellpadding="0" style="background-color: #'.$bgcolor.'; width: 480px; border-style: dotted; border-color: #007900; border-width: 2px"><tr><td>'.$quote.'</td></tr></table>', $text);
|
||||
}
|
||||
$rows = 0;
|
||||
while(stripos($text, '[url]') !== false && stripos($text, '[/url]') !== false )
|
||||
{
|
||||
$url = substr($text, stripos($text, '[url]')+5, stripos($text, '[/url]') - stripos($text, '[url]') - 5);
|
||||
$text = str_ireplace('[url]'.$url.'[/url]', '<a href="'.$url.'" target="_blank">'.$url.'</a>', $text);
|
||||
}
|
||||
|
||||
$xhtml = false;
|
||||
$tags = array(
|
||||
'#\[b\](.*?)\[/b\]#si' => ($xhtml ? '<strong>\\1</strong>' : '<b>\\1</b>'),
|
||||
'#\[i\](.*?)\[/i\]#si' => ($xhtml ? '<em>\\1</em>' : '<i>\\1</i>'),
|
||||
'#\[u\](.*?)\[/u\]#si' => ($xhtml ? '<span style="text-decoration: underline;">\\1</span>' : '<u>\\1</u>'),
|
||||
'#\[s\](.*?)\[/s\]#si' => ($xhtml ? '<strike>\\1</strike>' : '<s>\\1</s>'),
|
||||
|
||||
'#\[guild\](.*?)\[/guild\]#si' => urldecode(generateLink(getGuildLink('$1', false), '$1', true)),
|
||||
'#\[house\](.*?)\[/house\]#si' => urldecode(generateLink(getHouseLink('$1', false), '$1', true)),
|
||||
'#\[player\](.*?)\[/player\]#si' => urldecode(generateLink(getPlayerLink('$1', false), '$1', true)),
|
||||
// TODO: [poll] tag
|
||||
|
||||
'#\[color=(.*?)\](.*?)\[/color\]#si' => ($xhtml ? '<span style="color: \\1;">\\2</span>' : '<span style="color: \\1">\\2</span>'),
|
||||
'#\[img\](.*?)\[/img\]#si' => ($xhtml ? '<img class="forum-image" style="max-width:550px; max-height; 550px;" src="\\1" border="0" alt="" />' : '<img class="forum-image" style="max-width:550px; max-height; 550px;" src="\\1" border="0" alt="">'),
|
||||
'#\[url=(.*?)\](.*?)\[/url\]#si' => '<a href="\\1" title="\\2">\\2</a>',
|
||||
// '#\[email\](.*?)\[/email\]#si' => '<a href="mailto:\\1" title="Email \\1">\\1</a>',
|
||||
'#\[code\](.*?)\[/code\]#si' => '<code>\\1</code>',
|
||||
// '#\[align=(.*?)\](.*?)\[/align\]#si' => ($xhtml ? '<div style="text-align: \\1;">\\2</div>' : '<div align="\\1">\\2</div>'),
|
||||
// '#\[br\]#si' => ($xhtml ? '<br style="clear: both;" />' : '<br>'),
|
||||
);
|
||||
|
||||
foreach($tags as $search => $replace)
|
||||
$text = preg_replace($search, $replace, $text);
|
||||
|
||||
return ($smiles ? Forum::parseSmiles($text) : $text);
|
||||
}
|
||||
|
||||
public static function showPost($topic, $text, $smiles = true, $html = false)
|
||||
{
|
||||
if($html) {
|
||||
return '<b>' . $topic . '</b><hr />' . $text;
|
||||
}
|
||||
|
||||
$post = '';
|
||||
if(!empty($topic))
|
||||
$post .= '<b>'.($smiles ? self::parseSmiles($topic) : $topic).'</b><hr />';
|
||||
|
||||
$post .= self::parseBBCode(nl2br($text), $smiles);
|
||||
return $post;
|
||||
}
|
||||
|
||||
public static function hasAccess($board_id) {
|
||||
global $sections, $logged, $account_logged, $logged_access;
|
||||
if(!isset($sections[$board_id]))
|
||||
return false;
|
||||
|
||||
$hasAccess = true;
|
||||
$section = $sections[$board_id];
|
||||
if($section['guild'] > 0) {
|
||||
if($logged) {
|
||||
$guild = new \OTS_Guild();
|
||||
$guild->load($section['guild']);
|
||||
$status = false;
|
||||
if($guild->isLoaded()) {
|
||||
$account_players = $account_logged->getPlayers();
|
||||
foreach ($account_players as $player) {
|
||||
if($guild->hasMember($player)) {
|
||||
$status = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$status) $hasAccess = false;
|
||||
}
|
||||
else {
|
||||
$hasAccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
if($section['access'] > 0) {
|
||||
if($logged_access < $section['access']) {
|
||||
$hasAccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $hasAccess;
|
||||
}
|
||||
}
|
42
system/src/Hook.php
Normal file
42
system/src/Hook.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
class Hook
|
||||
{
|
||||
private $_name, $_type, $_file;
|
||||
|
||||
public function __construct($name, $type, $file) {
|
||||
$this->_name = $name;
|
||||
$this->_type = $type;
|
||||
$this->_file = $file;
|
||||
}
|
||||
|
||||
public function execute($params)
|
||||
{
|
||||
global $db, $config, $template_path, $ots, $content, $twig;
|
||||
|
||||
if(is_callable($this->_file))
|
||||
{
|
||||
$params['db'] = $db;
|
||||
$params['config'] = $config;
|
||||
$params['template_path'] = $template_path;
|
||||
$params['ots'] = $ots;
|
||||
$params['content'] = $content;
|
||||
$params['twig'] = $twig;
|
||||
|
||||
$tmp = $this->_file;
|
||||
$ret = $tmp($params);
|
||||
}
|
||||
else {
|
||||
extract($params);
|
||||
|
||||
$ret = include BASE . $this->_file;
|
||||
}
|
||||
|
||||
return !isset($ret) || $ret == 1 || $ret;
|
||||
}
|
||||
|
||||
public function name() {return $this->_name;}
|
||||
public function type() {return $this->_type;}
|
||||
}
|
44
system/src/Hooks.php
Normal file
44
system/src/Hooks.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
class Hooks
|
||||
{
|
||||
private static $_hooks = array();
|
||||
|
||||
public function register($hook, $type = '', $file = null) {
|
||||
if(!($hook instanceof Hook))
|
||||
$hook = new Hook($hook, $type, $file);
|
||||
|
||||
self::$_hooks[$hook->type()][] = $hook;
|
||||
}
|
||||
|
||||
public function trigger($type, $params = array())
|
||||
{
|
||||
$ret = true;
|
||||
if(isset(self::$_hooks[$type]))
|
||||
{
|
||||
foreach(self::$_hooks[$type] as $name => $hook) {
|
||||
/** @var $hook Hook */
|
||||
if (!$hook->execute($params)) {
|
||||
$ret = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function exist($type) {
|
||||
return isset(self::$_hooks[$type]);
|
||||
}
|
||||
|
||||
public function load()
|
||||
{
|
||||
foreach(Plugins::getHooks() as $hook) {
|
||||
$this->register($hook['name'], $hook['type'], $hook['file']);
|
||||
}
|
||||
|
||||
Plugins::clearWarnings();
|
||||
}
|
||||
}
|
140
system/src/Items.php
Normal file
140
system/src/Items.php
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
/**
|
||||
* Items class
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Gesior <jerzyskalski@wp.pl>
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @copyright 2019 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
use MyAAC\Cache\PHP as CachePHP;
|
||||
use MyAAC\Models\Spell;
|
||||
|
||||
class Items
|
||||
{
|
||||
private static $error = '';
|
||||
public static $items;
|
||||
|
||||
public static function loadFromXML($show = false)
|
||||
{
|
||||
$file_path = config('data_path') . 'items/items.xml';
|
||||
if (!file_exists($file_path)) {
|
||||
self::$error = 'Cannot load file ' . $file_path;
|
||||
return false;
|
||||
}
|
||||
|
||||
$xml = new \DOMDocument;
|
||||
$xml->load($file_path);
|
||||
|
||||
$items = array();
|
||||
foreach ($xml->getElementsByTagName('item') as $item) {
|
||||
if ($item->getAttribute('fromid')) {
|
||||
for ($id = $item->getAttribute('fromid'); $id <= $item->getAttribute('toid'); $id++) {
|
||||
$tmp = self::parseNode($id, $item, $show);
|
||||
$items[$tmp['id']] = $tmp['content'];
|
||||
}
|
||||
} else {
|
||||
$tmp = self::parseNode($item->getAttribute('id'), $item, $show);
|
||||
$items[$tmp['id']] = $tmp['content'];
|
||||
}
|
||||
}
|
||||
|
||||
$cache_php = new CachePHP(config('cache_prefix'), CACHE . 'persistent/');
|
||||
$cache_php->set('items', $items, 5 * 365 * 24 * 60 * 60);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function parseNode($id, $node, $show = false) {
|
||||
$name = $node->getAttribute('name');
|
||||
$article = $node->getAttribute('article');
|
||||
$plural = $node->getAttribute('plural');
|
||||
|
||||
$attributes = array();
|
||||
foreach($node->getElementsByTagName('attribute') as $attr) {
|
||||
$attributes[strtolower($attr->getAttribute('key'))] = $attr->getAttribute('value');
|
||||
}
|
||||
|
||||
return array('id' => $id, 'content' => array('article' => $article, 'name' => $name, 'plural' => $plural, 'attributes' => $attributes));
|
||||
}
|
||||
|
||||
public static function getError() {
|
||||
return self::$error;
|
||||
}
|
||||
|
||||
public static function load() {
|
||||
if(self::$items) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cache_php = new CachePHP(config('cache_prefix'), CACHE . 'persistent/');
|
||||
self::$items = $cache_php->get('items');
|
||||
}
|
||||
|
||||
public static function get($id) {
|
||||
self::load();
|
||||
return isset(self::$items[$id]) ? self::$items[$id] : [];
|
||||
}
|
||||
|
||||
public static function getDescription($id, $count = 1) {
|
||||
$item = self::get($id);
|
||||
|
||||
$attr = $item['attributes'];
|
||||
$s = '';
|
||||
if(!empty($item['name'])) {
|
||||
if($count > 1) {
|
||||
if($attr['showcount']) {
|
||||
$s .= $count . ' ';
|
||||
}
|
||||
|
||||
if(!empty($item['plural'])) {
|
||||
$s .= $item['plural'];
|
||||
}
|
||||
else if((int)$attr['showcount'] == 0) {
|
||||
$s .= $item['name'];
|
||||
}
|
||||
else {
|
||||
$s .= $item['name'] . 's';
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!empty($item['aticle'])) {
|
||||
$s .= $item['article'] . ' ';
|
||||
}
|
||||
|
||||
$s .= $item['name'];
|
||||
}
|
||||
}
|
||||
else
|
||||
$s .= 'an item of type ' . $item['id'];
|
||||
|
||||
if(isset($attr['type']) && strtolower($attr['type']) == 'rune') {
|
||||
$item = Spell::where('item_id', $id)->first();
|
||||
if($item) {
|
||||
if($item->level > 0 && $item->maglevel > 0) {
|
||||
$s .= '. ' . ($count > 1 ? "They" : "It") . ' can only be used by ';
|
||||
}
|
||||
|
||||
$configVocations = config('vocations');
|
||||
if(!empty(trim($item->vocations))) {
|
||||
$vocations = json_decode($item->vocations);
|
||||
if(count($vocations) > 0) {
|
||||
foreach($vocations as $voc => $show) {
|
||||
$vocations[$configVocations[$voc]] = $show;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$s .= 'players';
|
||||
}
|
||||
|
||||
$s .= ' with';
|
||||
|
||||
}
|
||||
}
|
||||
return $s;
|
||||
}
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace MyAAC\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class AccountVipList extends Model {
|
||||
|
60
system/src/NPCs.php
Normal file
60
system/src/NPCs.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* NPC class
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Gesior <jerzyskalski@wp.pl>
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @author Lee
|
||||
* @copyright 2021 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
use MyAAC\Cache\PHP as CachePHP;
|
||||
|
||||
class NPCs
|
||||
{
|
||||
public static $npcs;
|
||||
|
||||
public static function loadFromXML($show = false)
|
||||
{
|
||||
$npc_path = config('data_path') . 'npc/';
|
||||
if (!file_exists($npc_path))
|
||||
return false;
|
||||
|
||||
$npcs = [];
|
||||
$xml = new \DOMDocument();
|
||||
foreach (preg_grep('~\.(xml)$~i', scandir($npc_path)) as $npc) {
|
||||
$xml->load($npc_path . $npc);
|
||||
if ($xml) {
|
||||
$element = $xml->getElementsByTagName('npc')->item(0);
|
||||
if (isset($element)) {
|
||||
$name = $element->getAttribute('name');
|
||||
if (!empty($name) && !in_array($name, $npcs)) {
|
||||
$npcs[] = strtolower($name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($npcs) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$cache_php = new CachePHP(config('cache_prefix'), CACHE . 'persistent/');
|
||||
$cache_php->set('npcs', $npcs, 5 * 365 * 24 * 60 * 60);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function load()
|
||||
{
|
||||
if (self::$npcs) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cache_php = new CachePHP(config('cache_prefix'), CACHE . 'persistent/');
|
||||
self::$npcs = $cache_php->get('npcs');
|
||||
}
|
||||
}
|
169
system/src/News.php
Normal file
169
system/src/News.php
Normal file
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
use MyAAC\Cache\Cache;
|
||||
use MyAAC\Models\News as ModelsNews;
|
||||
|
||||
class News
|
||||
{
|
||||
static public function verify($title, $body, $article_text, $article_image, &$errors)
|
||||
{
|
||||
if(!isset($title[0]) || !isset($body[0])) {
|
||||
$errors[] = 'Please fill all inputs.';
|
||||
return false;
|
||||
}
|
||||
if(strlen($title) > NEWS_TITLE_LIMIT) {
|
||||
$errors[] = 'News title cannot be longer than ' . NEWS_TITLE_LIMIT . ' characters.';
|
||||
return false;
|
||||
}
|
||||
if(strlen($body) > NEWS_BODY_LIMIT) {
|
||||
$errors[] = 'News content cannot be longer than ' . NEWS_BODY_LIMIT . ' characters.';
|
||||
return false;
|
||||
}
|
||||
if(strlen($article_text) > ARTICLE_TEXT_LIMIT) {
|
||||
$errors[] = 'Article text cannot be longer than ' . ARTICLE_TEXT_LIMIT . ' characters.';
|
||||
return false;
|
||||
}
|
||||
if(strlen($article_image) > ARTICLE_IMAGE_LIMIT) {
|
||||
$errors[] = 'Article image cannot be longer than ' . ARTICLE_IMAGE_LIMIT . ' characters.';
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static public function add($title, $body, $type, $category, $player_id, $comments, $article_text, $article_image, &$errors)
|
||||
{
|
||||
if(!self::verify($title, $body, $article_text, $article_image, $errors))
|
||||
return false;
|
||||
|
||||
ModelsNews::create([
|
||||
'title' => $title,
|
||||
'body' => $body,
|
||||
'type' => $type,
|
||||
'date' => time(),
|
||||
'category' => $category,
|
||||
'player_id' => isset($player_id) ? $player_id : 0,
|
||||
'comments' => $comments,
|
||||
'article_text' => ($type == 3 ? $article_text : ''),
|
||||
'article_image' => ($type == 3 ? $article_image : '')
|
||||
]);
|
||||
self::clearCache();
|
||||
return true;
|
||||
}
|
||||
|
||||
static public function get($id) {
|
||||
return ModelsNews::find($id)->toArray();
|
||||
}
|
||||
|
||||
static public function update($id, $title, $body, $type, $category, $player_id, $comments, $article_text, $article_image, &$errors)
|
||||
{
|
||||
if(!self::verify($title, $body, $article_text, $article_image, $errors))
|
||||
return false;
|
||||
|
||||
ModelsNews::where('id', $id)->update([
|
||||
'title' => $title,
|
||||
'body' => $body,
|
||||
'type' => $type,
|
||||
'category' => $category,
|
||||
'last_modified_by' => isset($player_id) ? $player_id : 0,
|
||||
'last_modified_date' => time(),
|
||||
'comments' => $comments,
|
||||
'article_text' => $article_text,
|
||||
'article_image' => $article_image
|
||||
]);
|
||||
self::clearCache();
|
||||
return true;
|
||||
}
|
||||
|
||||
static public function delete($id, &$errors)
|
||||
{
|
||||
if(isset($id)) {
|
||||
$row = ModelsNews::find($id);
|
||||
if($row) {
|
||||
if (!$row->delete()) {
|
||||
$errors[] = 'Fail during delete News.';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$errors[] = 'News with id ' . $id . ' does not exists.';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$errors[] = 'News id not set.';
|
||||
}
|
||||
|
||||
if(count($errors)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
self::clearCache();
|
||||
return true;
|
||||
}
|
||||
|
||||
static public function toggleHidden($id, &$errors, &$status)
|
||||
{
|
||||
if(isset($id))
|
||||
{
|
||||
$row = ModelsNews::find($id);
|
||||
if($row)
|
||||
{
|
||||
$row->hidden = $row->hidden == 1 ? 0 : 1;
|
||||
if (!$row->save()) {
|
||||
$errors[] = 'Fail during toggle hidden News.';
|
||||
}
|
||||
$status = $row->hidden;
|
||||
}
|
||||
else
|
||||
$errors[] = 'News with id ' . $id . ' does not exists.';
|
||||
}
|
||||
else
|
||||
$errors[] = 'News id not set.';
|
||||
|
||||
if(count($errors)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
self::clearCache();
|
||||
return true;
|
||||
}
|
||||
|
||||
static public function getCached($type)
|
||||
{
|
||||
global $template_name;
|
||||
|
||||
$cache = Cache::getInstance();
|
||||
if ($cache->enabled())
|
||||
{
|
||||
$tmp = '';
|
||||
if ($cache->fetch('news_' . $template_name . '_' . $type, $tmp) && isset($tmp[0])) {
|
||||
return $tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static public function clearCache()
|
||||
{
|
||||
$cache = Cache::getInstance();
|
||||
if (!$cache->enabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tmp = '';
|
||||
foreach (get_templates() as $template) {
|
||||
if ($cache->fetch('news_' . $template . '_' . NEWS, $tmp)) {
|
||||
$cache->delete('news_' . $template . '_' . NEWS);
|
||||
}
|
||||
|
||||
if ($cache->fetch('news_' . $template . '_' . TICKER, $tmp)) {
|
||||
$cache->delete('news_' . $template . '_' . TICKER);
|
||||
}
|
||||
|
||||
if ($cache->fetch('news_' . $template . '_' . ARTICLE, $tmp)) {
|
||||
$cache->delete('news_' . $template . '_' . ARTICLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
731
system/src/Plugins.php
Normal file
731
system/src/Plugins.php
Normal file
@@ -0,0 +1,731 @@
|
||||
<?php
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
use Composer\Semver\Semver;
|
||||
use MyAAC\Cache\Cache;
|
||||
use MyAAC\Models\Menu;
|
||||
|
||||
class Plugins {
|
||||
private static $warnings = [];
|
||||
private static $error = null;
|
||||
private static $plugin_json = [];
|
||||
|
||||
public static function getRoutes()
|
||||
{
|
||||
$cache = Cache::getInstance();
|
||||
if ($cache->enabled()) {
|
||||
$tmp = '';
|
||||
if ($cache->fetch('plugins_routes', $tmp)) {
|
||||
return unserialize($tmp);
|
||||
}
|
||||
}
|
||||
|
||||
$routes = [];
|
||||
|
||||
$pluginPages = glob(PLUGINS . '*/pages/*.php');
|
||||
foreach ($pluginPages as $file) {
|
||||
$file = str_replace(PLUGINS, 'plugins/', $file);
|
||||
$name = pathinfo($file, PATHINFO_FILENAME);
|
||||
|
||||
$routes[] = [['get', 'post'], $name, $file, 1000];
|
||||
}
|
||||
|
||||
foreach(self::getAllPluginsJson() as $plugin) {
|
||||
$warningPreTitle = 'Plugin: ' . $plugin['name'] . ' - ';
|
||||
|
||||
if (isset($plugin['routes'])) {
|
||||
foreach ($plugin['routes'] as $_name => $info) {
|
||||
// default method: get
|
||||
$method = $info['method'] ?? ['GET'];
|
||||
if ($method !== '*') {
|
||||
$methods = is_string($method) ? explode(',', $info['method']) : $method;
|
||||
foreach ($methods as $method) {
|
||||
$method = strtolower($method);
|
||||
if (!in_array($method, ['get', 'post', 'put', 'patch', 'delete', 'head'])) {
|
||||
self::$warnings[] = $warningPreTitle . 'Not allowed method ' . $method . '... Disabling this route...';
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$methods = '*'; // all available methods
|
||||
}
|
||||
|
||||
if (!isset($info['priority'])) {
|
||||
$info['priority'] = 100; // default priority
|
||||
}
|
||||
|
||||
if (isset($info['redirect_from'])) {
|
||||
removeIfFirstSlash($info['redirect_from']);
|
||||
|
||||
$info['pattern'] = $info['redirect_from'];
|
||||
if (!isset($info['redirect_to'])) {
|
||||
self::$warnings[] = $warningPreTitle . 'redirect set without "redirect_to".';
|
||||
}
|
||||
else {
|
||||
removeIfFirstSlash($info['redirect_to']);
|
||||
$info['file'] = '__redirect__/' . $info['redirect_to'];
|
||||
}
|
||||
}
|
||||
|
||||
// replace first occurrence of / in pattern if found (will be auto-added later)
|
||||
removeIfFirstSlash($info['pattern']);
|
||||
|
||||
foreach ($routes as $id => &$route) {
|
||||
if($route[1] == $info['pattern']) {
|
||||
if($info['priority'] < $route[3]) {
|
||||
self::$warnings[] = $warningPreTitle . "Duplicated route with lower priority: {$info['pattern']}. Disabling this route...";
|
||||
continue 2;
|
||||
}
|
||||
else {
|
||||
self::$warnings[] = $warningPreTitle . "Duplicated route with lower priority: {$route[1]} ({$route[3]}). Disabling this route...";
|
||||
unset($routes[$id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$routes[] = [$methods, $info['pattern'], $info['file'], $info['priority']];
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
usort($routes, function ($a, $b)
|
||||
{
|
||||
// key 3 is priority
|
||||
if ($a[3] == $b[3]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ($a[3] > $b[3]) ? -1 : 1;
|
||||
});
|
||||
*/
|
||||
// cleanup before passing back
|
||||
// priority is not needed anymore
|
||||
foreach ($routes as &$route) {
|
||||
unset($route[3]);
|
||||
}
|
||||
|
||||
if ($cache->enabled()) {
|
||||
$cache->set('plugins_routes', serialize($routes), 600);
|
||||
}
|
||||
|
||||
return $routes;
|
||||
}
|
||||
|
||||
public static function getThemes()
|
||||
{
|
||||
$cache = Cache::getInstance();
|
||||
if ($cache->enabled()) {
|
||||
$tmp = '';
|
||||
if ($cache->fetch('plugins_themes', $tmp)) {
|
||||
return unserialize($tmp);
|
||||
}
|
||||
}
|
||||
|
||||
$themes = [];
|
||||
$pluginThemes = glob(PLUGINS . '*/themes/*', GLOB_ONLYDIR);
|
||||
foreach ($pluginThemes as $path) {
|
||||
$path = str_replace(PLUGINS, 'plugins/', $path);
|
||||
$name = pathinfo($path, PATHINFO_FILENAME);
|
||||
|
||||
$themes[$name] = $path;
|
||||
}
|
||||
|
||||
if ($cache->enabled()) {
|
||||
$cache->set('plugins_themes', serialize($themes), 600);
|
||||
}
|
||||
|
||||
return $themes;
|
||||
}
|
||||
|
||||
public static function getHooks()
|
||||
{
|
||||
$cache = Cache::getInstance();
|
||||
if ($cache->enabled()) {
|
||||
$tmp = '';
|
||||
if ($cache->fetch('plugins_hooks', $tmp)) {
|
||||
return unserialize($tmp);
|
||||
}
|
||||
}
|
||||
|
||||
$hooks = [];
|
||||
foreach(self::getAllPluginsJson() as $plugin) {
|
||||
if (isset($plugin['hooks'])) {
|
||||
foreach ($plugin['hooks'] as $_name => $info) {
|
||||
if (str_contains($info['type'], 'HOOK_')) {
|
||||
$info['type'] = str_replace('HOOK_', '', $info['type']);
|
||||
}
|
||||
|
||||
if (defined('HOOK_'. $info['type'])) {
|
||||
$hook = constant('HOOK_'. $info['type']);
|
||||
$hooks[] = ['name' => $_name, 'type' => $hook, 'file' => $info['file']];
|
||||
} else {
|
||||
self::$warnings[] = 'Plugin: ' . $plugin['name'] . '. Unknown event type: ' . $info['type'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($cache->enabled()) {
|
||||
$cache->set('plugins_hooks', serialize($hooks), 600);
|
||||
}
|
||||
|
||||
return $hooks;
|
||||
}
|
||||
|
||||
public static function getAllPluginsSettings()
|
||||
{
|
||||
$cache = Cache::getInstance();
|
||||
if ($cache->enabled()) {
|
||||
$tmp = '';
|
||||
if ($cache->fetch('plugins_settings', $tmp)) {
|
||||
return unserialize($tmp);
|
||||
}
|
||||
}
|
||||
|
||||
$settings = [];
|
||||
foreach (self::getAllPluginsJson() as $plugin) {
|
||||
if (isset($plugin['settings'])) {
|
||||
$settingsFile = require BASE . $plugin['settings'];
|
||||
if (!isset($settingsFile['key'])) {
|
||||
warning("Settings file for plugin - {$plugin['name']} does not contain 'key' field");
|
||||
continue;
|
||||
}
|
||||
|
||||
$settings[$settingsFile['key']] = ['pluginFilename' => $plugin['filename'], 'settingsFilename' => $plugin['settings']];
|
||||
}
|
||||
}
|
||||
|
||||
if ($cache->enabled()) {
|
||||
$cache->set('plugins_settings', serialize($settings), 600); // cache for 10 minutes
|
||||
}
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
public static function getAllPluginsJson($disabled = false)
|
||||
{
|
||||
$cache = Cache::getInstance();
|
||||
if ($cache->enabled()) {
|
||||
$tmp = '';
|
||||
if ($cache->fetch('plugins', $tmp)) {
|
||||
return unserialize($tmp);
|
||||
}
|
||||
}
|
||||
|
||||
$plugins = [];
|
||||
foreach (get_plugins($disabled) as $filename) {
|
||||
$plugin = self::getPluginJson($filename);
|
||||
|
||||
if (!$plugin) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$plugin['filename'] = $filename;
|
||||
$plugins[] = $plugin;
|
||||
}
|
||||
|
||||
if ($cache->enabled()) {
|
||||
$cache->set('plugins', serialize($plugins), 600); // cache for 10 minutes
|
||||
}
|
||||
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
public static function getPluginSettings($filename)
|
||||
{
|
||||
$plugin_json = self::getPluginJson($filename);
|
||||
if (!$plugin_json) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isset($plugin_json['settings']) || !file_exists(BASE . $plugin_json['settings'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $plugin_json['settings'];
|
||||
}
|
||||
|
||||
public static function getPluginJson($filename = null)
|
||||
{
|
||||
if(!isset($filename)) {
|
||||
return self::$plugin_json;
|
||||
}
|
||||
|
||||
$pathToPlugin = PLUGINS . $filename . '.json';
|
||||
if (!file_exists($pathToPlugin)) {
|
||||
self::$warnings[] = "Cannot load $filename.json. File doesn't exist.";
|
||||
return false;
|
||||
}
|
||||
|
||||
$string = file_get_contents($pathToPlugin);
|
||||
$plugin_json = json_decode($string, true);
|
||||
if ($plugin_json == null) {
|
||||
self::$warnings[] = "Cannot load $filename.json. File might be not a valid json code.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($plugin_json['enabled']) && !getBoolean($plugin_json['enabled'])) {
|
||||
self::$warnings[] = 'Skipping ' . $filename . '... The plugin is disabled.';
|
||||
return false;
|
||||
}
|
||||
|
||||
return $plugin_json;
|
||||
}
|
||||
|
||||
public static function install($file): bool
|
||||
{
|
||||
global $db;
|
||||
|
||||
if(!\class_exists('\ZipArchive')) {
|
||||
throw new \RuntimeException('Please install PHP zip extension. Plugins upload disabled until then.');
|
||||
}
|
||||
|
||||
$zip = new \ZipArchive();
|
||||
if($zip->open($file) !== true) {
|
||||
self::$error = 'There was a problem with opening zip archive.';
|
||||
return false;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $zip->numFiles; $i++) {
|
||||
$tmp = $zip->getNameIndex($i);
|
||||
if(pathinfo($tmp, PATHINFO_DIRNAME) == 'plugins' && pathinfo($tmp, PATHINFO_EXTENSION) == 'json')
|
||||
$json_file = $tmp;
|
||||
}
|
||||
|
||||
if(!isset($json_file)) {
|
||||
self::$error = 'Cannot find plugin info .json file. Installation is discontinued.';
|
||||
return false;
|
||||
}
|
||||
|
||||
$plugin_temp_dir = CACHE . 'plugins/' . str_replace('.zip', '', basename($file)) . '/';
|
||||
if(!$zip->extractTo($plugin_temp_dir)) { // place in cache dir
|
||||
self::$error = 'There was a problem with extracting zip archive to cache directory.';
|
||||
$zip->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
self::$error = 'There was a problem with extracting zip archive.';
|
||||
$file_name = $plugin_temp_dir . $json_file;
|
||||
if(!file_exists($file_name)) {
|
||||
self::$error = "Cannot load " . $file_name . ". File doesn't exist.";
|
||||
$zip->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
$pluginFilename = str_replace('.json', '', basename($json_file));
|
||||
if (self::existDisabled($pluginFilename)) {
|
||||
success('The plugin already existed, but was disabled. It has been enabled again and will be now reinstalled.');
|
||||
self::enable($pluginFilename);
|
||||
}
|
||||
|
||||
$string = file_get_contents($file_name);
|
||||
$plugin_json = json_decode($string, true);
|
||||
self::$plugin_json = $plugin_json;
|
||||
if ($plugin_json == null) {
|
||||
self::$warnings[] = 'Cannot load ' . $file_name . '. File might be not a valid json code.';
|
||||
}
|
||||
else {
|
||||
$continue = true;
|
||||
|
||||
if(!isset($plugin_json['name']) || empty(trim($plugin_json['name']))) {
|
||||
self::$warnings[] = 'Plugin "name" tag is not set.';
|
||||
}
|
||||
if(!isset($plugin_json['description']) || empty(trim($plugin_json['description']))) {
|
||||
self::$warnings[] = 'Plugin "description" tag is not set.';
|
||||
}
|
||||
if(!isset($plugin_json['version']) || empty(trim($plugin_json['version']))) {
|
||||
self::$warnings[] = 'Plugin "version" tag is not set.';
|
||||
}
|
||||
if(!isset($plugin_json['author']) || empty(trim($plugin_json['author']))) {
|
||||
self::$warnings[] = 'Plugin "author" tag is not set.';
|
||||
}
|
||||
if(!isset($plugin_json['contact']) || empty(trim($plugin_json['contact']))) {
|
||||
self::$warnings[] = 'Plugin "contact" tag is not set.';
|
||||
}
|
||||
|
||||
if(isset($plugin_json['require'])) {
|
||||
$require = $plugin_json['require'];
|
||||
|
||||
$myaac_satified = true;
|
||||
if(isset($require['myaac_'])) {
|
||||
$require_myaac = $require['myaac_'];
|
||||
if(!Semver::satisfies(MYAAC_VERSION, $require_myaac)) {
|
||||
$myaac_satified = false;
|
||||
}
|
||||
}
|
||||
else if(isset($require['myaac'])) {
|
||||
$require_myaac = $require['myaac'];
|
||||
if(version_compare(MYAAC_VERSION, $require_myaac, '<')) {
|
||||
$myaac_satified = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$myaac_satified) {
|
||||
self::$error = "Your AAC version doesn't meet the requirement of this plugin. Required version is: " . $require_myaac . ", and you're using version " . MYAAC_VERSION . ".";
|
||||
return false;
|
||||
}
|
||||
|
||||
$php_satisfied = true;
|
||||
if(isset($require['php_'])) {
|
||||
$require_php = $require['php_'];
|
||||
if(!Semver::satisfies(phpversion(), $require_php)) {
|
||||
$php_satisfied = false;
|
||||
}
|
||||
}
|
||||
else if(isset($require['php'])) {
|
||||
$require_php = $require['php'];
|
||||
if(version_compare(phpversion(), $require_php, '<')) {
|
||||
$php_satisfied = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$php_satisfied) {
|
||||
self::$error = "Your PHP version doesn't meet the requirement of this plugin. Required version is: " . $require_php . ", and you're using version " . phpversion() . ".";
|
||||
$continue = false;
|
||||
}
|
||||
|
||||
$database_satisfied = true;
|
||||
if(isset($require['database_'])) {
|
||||
$require_database = $require['database_'];
|
||||
if(!Semver::satisfies(DATABASE_VERSION, $require_database)) {
|
||||
$database_satisfied = false;
|
||||
}
|
||||
}
|
||||
else if(isset($require['database'])) {
|
||||
$require_database = $require['database'];
|
||||
if(version_compare(DATABASE_VERSION, $require_database, '<')) {
|
||||
$database_satisfied = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$database_satisfied) {
|
||||
self::$error = "Your database version doesn't meet the requirement of this plugin. Required version is: " . $require_database . ", and you're using version " . DATABASE_VERSION . ".";
|
||||
$continue = false;
|
||||
}
|
||||
|
||||
if($continue) {
|
||||
foreach($require as $req => $version) {
|
||||
$req = strtolower(trim($req));
|
||||
$version = trim($version);
|
||||
|
||||
if(in_array($req, array('myaac', 'myaac_', 'php', 'php_', 'database', 'database_'))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(in_array($req, array('php-ext', 'php-extension'))) { // require php extension
|
||||
$tmpDisplayError = false;
|
||||
$explode = explode(',', $version);
|
||||
|
||||
foreach ($explode as $item) {
|
||||
if(!extension_loaded($item)) {
|
||||
$errors[] = "This plugin requires php extension: " . $item . " to be installed.";
|
||||
$tmpDisplayError = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($tmpDisplayError) {
|
||||
self::$error = implode('<br/>', $errors);
|
||||
$continue = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if($req == 'table') {
|
||||
$tmpDisplayError = false;
|
||||
$explode = explode(',', $version);
|
||||
foreach ($explode as $item) {
|
||||
if(!$db->hasTable($item)) {
|
||||
$errors[] = "This plugin requires table: " . $item . " to exist in the database.";
|
||||
$tmpDisplayError = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($tmpDisplayError) {
|
||||
self::$error = implode('<br/>', $errors);
|
||||
$continue = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if($req == 'column') {
|
||||
$tmpDisplayError = false;
|
||||
$explode = explode(',', $version);
|
||||
foreach ($explode as $item) {
|
||||
$tmp = explode('.', $item);
|
||||
|
||||
if(count($tmp) == 2) {
|
||||
if(!$db->hasColumn($tmp[0], $tmp[1])) {
|
||||
$errors[] = "This plugin requires database column: " . $tmp[0] . "." . $tmp[1] . " to exist in database.";
|
||||
$tmpDisplayError = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
self::$warnings[] = "Invalid plugin require column: " . $item;
|
||||
}
|
||||
}
|
||||
|
||||
if ($tmpDisplayError) {
|
||||
self::$error = implode('<br/>', $errors);
|
||||
$continue = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(strpos($req, 'ext-') !== false) {
|
||||
$tmp = explode('-', $req);
|
||||
if(count($tmp) == 2) {
|
||||
if(!extension_loaded($tmp[1]) || !Semver::satisfies(phpversion($tmp[1]), $version)) {
|
||||
self::$error = "This plugin requires php extension: " . $tmp[1] . ", version " . $version . " to be installed.";
|
||||
$continue = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(!self::is_installed($req, $version)) {
|
||||
self::$error = "This plugin requires another plugin to run correctly. The another plugin is: " . $req . ", with version " . $version . ".";
|
||||
$continue = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($continue) {
|
||||
if(!$zip->extractTo(BASE)) { // "Real" Install
|
||||
self::$error = 'There was a problem with extracting zip archive to base directory.';
|
||||
$zip->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($plugin_json['install'])) {
|
||||
if (file_exists(BASE . $plugin_json['install'])) {
|
||||
$db->revalidateCache();
|
||||
require BASE . $plugin_json['install'];
|
||||
$db->revalidateCache();
|
||||
}
|
||||
else
|
||||
self::$warnings[] = 'Cannot load install script. Your plugin might be not working correctly.';
|
||||
}
|
||||
|
||||
clearCache();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function isEnabled($pluginFileName): bool
|
||||
{
|
||||
$filenameJson = $pluginFileName . '.json';
|
||||
return !is_file(PLUGINS . 'disabled.' . $filenameJson) && is_file(PLUGINS . $filenameJson);
|
||||
}
|
||||
|
||||
public static function existDisabled($pluginFileName): bool
|
||||
{
|
||||
$filenameJson = $pluginFileName . '.json';
|
||||
return is_file(PLUGINS . 'disabled.' . $filenameJson);
|
||||
}
|
||||
|
||||
public static function enable($pluginFileName): bool {
|
||||
return self::enableDisable($pluginFileName, true);
|
||||
}
|
||||
|
||||
public static function disable($pluginFileName): bool {
|
||||
return self::enableDisable($pluginFileName, false);
|
||||
}
|
||||
|
||||
private static function enableDisable($pluginFileName, $enable): bool
|
||||
{
|
||||
$filenameJson = $pluginFileName . '.json';
|
||||
$fileExist = is_file(PLUGINS . ($enable ? 'disabled.' : '') . $filenameJson);
|
||||
if (!$fileExist) {
|
||||
self::$error = 'Cannot ' . ($enable ? 'enable' : 'disable') . ' plugin: ' . $pluginFileName . '. File does not exist.';
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = rename(PLUGINS . ($enable ? 'disabled.' : '') . $filenameJson, PLUGINS . ($enable ? '' : 'disabled.') . $filenameJson);
|
||||
if (!$result) {
|
||||
self::$error = 'Cannot ' . ($enable ? 'enable' : 'disable') . ' plugin: ' . $pluginFileName . '. Permission problem.';
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is to execute the "install" part of the plugin
|
||||
*
|
||||
* @param $plugin_name
|
||||
* @return bool
|
||||
*/
|
||||
public static function executeInstall($plugin_name): bool
|
||||
{
|
||||
$filename = BASE . 'plugins/' . $plugin_name . '.json';
|
||||
if(!file_exists($filename)) {
|
||||
self::$error = 'Plugin ' . $plugin_name . ' does not exist.';
|
||||
return false;
|
||||
}
|
||||
|
||||
$string = file_get_contents($filename);
|
||||
$plugin_json = json_decode($string, true);
|
||||
if(!$plugin_json) {
|
||||
self::$error = 'Cannot load plugin info ' . $plugin_name . '.json';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!isset($plugin_json['install'])) {
|
||||
self::$error = "Plugin doesn't have install options defined. Skipping...";
|
||||
return false;
|
||||
}
|
||||
|
||||
global $db;
|
||||
if (file_exists(BASE . $plugin_json['install'])) {
|
||||
$db->revalidateCache();
|
||||
require BASE . $plugin_json['install'];
|
||||
$db->revalidateCache();
|
||||
}
|
||||
else {
|
||||
self::$warnings[] = 'Cannot load install script. Your plugin might be not working correctly.';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function uninstall($plugin_name): bool
|
||||
{
|
||||
$filename = BASE . 'plugins/' . $plugin_name . '.json';
|
||||
if(!file_exists($filename)) {
|
||||
self::$error = 'Plugin ' . $plugin_name . ' does not exist.';
|
||||
return false;
|
||||
}
|
||||
$string = file_get_contents($filename);
|
||||
$plugin_info = json_decode($string, true);
|
||||
if(!$plugin_info) {
|
||||
self::$error = 'Cannot load plugin info ' . $plugin_name . '.json';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!isset($plugin_info['uninstall'])) {
|
||||
self::$error = "Plugin doesn't have uninstall options defined. Skipping...";
|
||||
return false;
|
||||
}
|
||||
|
||||
$success = true;
|
||||
foreach($plugin_info['uninstall'] as $file) {
|
||||
if(strpos($file, '/') === 0) {
|
||||
$success = false;
|
||||
self::$error = "You cannot use absolute paths (starting with slash - '/'): " . $file;
|
||||
break;
|
||||
}
|
||||
|
||||
$file = str_replace('\\', '/', BASE . $file);
|
||||
$realpath = str_replace('\\', '/', realpath(dirname($file)));
|
||||
if(!is_sub_dir($file, BASE) || $realpath != dirname($file)) {
|
||||
$success = false;
|
||||
self::$error = "You don't have rights to delete: " . $file;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if($success) {
|
||||
foreach($plugin_info['uninstall'] as $file) {
|
||||
if(!deleteDirectory(BASE . $file)) {
|
||||
self::$warnings[] = 'Cannot delete: ' . $file;
|
||||
}
|
||||
}
|
||||
|
||||
$cache = Cache::getInstance();
|
||||
if($cache->enabled()) {
|
||||
$cache->delete('templates');
|
||||
$cache->delete('hooks');
|
||||
$cache->delete('template_menus');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function is_installed($plugin_name, $version): bool
|
||||
{
|
||||
$filename = BASE . 'plugins/' . $plugin_name . '.json';
|
||||
if(!file_exists($filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$string = file_get_contents($filename);
|
||||
$plugin_info = json_decode($string, true);
|
||||
if(!$plugin_info) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!isset($plugin_info['version'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Semver::satisfies($plugin_info['version'], $version);
|
||||
}
|
||||
|
||||
public static function getWarnings() {
|
||||
return self::$warnings;
|
||||
}
|
||||
|
||||
public static function clearWarnings() {
|
||||
self::$warnings = [];
|
||||
}
|
||||
|
||||
public static function getError() {
|
||||
return self::$error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install menus
|
||||
* Helper function for plugins
|
||||
*
|
||||
* @param string $templateName
|
||||
* @param array $categories
|
||||
*/
|
||||
public static function installMenus($templateName, $categories)
|
||||
{
|
||||
// check if menus already exist
|
||||
$menuInstalled = Menu::where('template', $templateName)->select('id')->first();
|
||||
if ($menuInstalled) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($categories as $category => $menus) {
|
||||
$i = 0;
|
||||
foreach ($menus as $name => $link) {
|
||||
$color = '';
|
||||
$blank = 0;
|
||||
|
||||
if (is_array($link)) {
|
||||
if (isset($link['name'])) {
|
||||
$name = $link['name'];
|
||||
}
|
||||
if (isset($link['color'])) {
|
||||
$color = $link['color'];
|
||||
}
|
||||
if (isset($link['blank'])) {
|
||||
$blank = $link['blank'] ? 1 : 0;
|
||||
}
|
||||
|
||||
$link = $link['link'];
|
||||
}
|
||||
|
||||
$insert_array = [
|
||||
'template' => $templateName,
|
||||
'name' => $name,
|
||||
'link' => $link,
|
||||
'category' => $category,
|
||||
'ordering' => $i++,
|
||||
'blank' => $blank,
|
||||
'color' => $color,
|
||||
];
|
||||
|
||||
Menu::create($insert_array);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
607
system/src/Settings.php
Normal file
607
system/src/Settings.php
Normal file
@@ -0,0 +1,607 @@
|
||||
<?php
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
use MyAAC\Cache\Cache;
|
||||
use MyAAC\Models\Settings as ModelsSettings;
|
||||
|
||||
class Settings implements \ArrayAccess
|
||||
{
|
||||
static private $instance;
|
||||
private $settingsFile = [];
|
||||
private $settingsDatabase = [];
|
||||
private $cache = [];
|
||||
private $valuesAsked = [];
|
||||
private $errors = [];
|
||||
|
||||
/**
|
||||
* @return Settings
|
||||
*/
|
||||
public static function getInstance(): Settings
|
||||
{
|
||||
if (!self::$instance) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function load()
|
||||
{
|
||||
$cache = Cache::getInstance();
|
||||
if ($cache->enabled()) {
|
||||
$tmp = '';
|
||||
if ($cache->fetch('settings', $tmp)) {
|
||||
$this->settingsDatabase = unserialize($tmp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$settings = ModelsSettings::all();
|
||||
foreach ($settings as $setting)
|
||||
{
|
||||
$this->settingsDatabase[$setting->name][$setting->key] = $setting->value;
|
||||
}
|
||||
|
||||
if ($cache->enabled()) {
|
||||
$cache->set('settings', serialize($this->settingsDatabase), 600);
|
||||
}
|
||||
}
|
||||
|
||||
public function save($pluginName, $values)
|
||||
{
|
||||
$this->loadPlugin($pluginName);
|
||||
|
||||
if (!isset($this->settingsFile[$pluginName])) {
|
||||
throw new \RuntimeException("Error on save settings: plugin $pluginName does not exist");
|
||||
}
|
||||
|
||||
$settings = $this->settingsFile[$pluginName];
|
||||
|
||||
global $hooks;
|
||||
if (!$hooks->trigger(HOOK_ADMIN_SETTINGS_BEFORE_SAVE, [
|
||||
'name' => $pluginName,
|
||||
'values' => $values,
|
||||
'settings' => $settings,
|
||||
])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($settings['callbacks']['beforeSave'])) {
|
||||
if (!$settings['callbacks']['beforeSave']($settings, $values)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$this->errors = [];
|
||||
ModelsSettings::where('name', $pluginName)->delete();
|
||||
foreach ($values as $key => $value) {
|
||||
$errorMessage = '';
|
||||
if (isset($settings['settings'][$key]['callbacks']['beforeSave']) && !$settings['settings'][$key]['callbacks']['beforeSave']($key, $value, $errorMessage)) {
|
||||
$this->errors[] = $errorMessage;
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
ModelsSettings::create([
|
||||
'name' => $pluginName,
|
||||
'key' => $key,
|
||||
'value' => $value
|
||||
]);
|
||||
} catch (\PDOException $error) {
|
||||
$this->errors[] = 'Error while saving setting (' . $pluginName . ' - ' . $key . '): ' . $error->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
$cache = Cache::getInstance();
|
||||
if ($cache->enabled()) {
|
||||
$cache->delete('settings');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function updateInDatabase($pluginName, $key, $value)
|
||||
{
|
||||
if (ModelsSettings::where(['name' => $pluginName, 'key' => $key])->exists()) {
|
||||
ModelsSettings::where(['name' => $pluginName, 'key' => $key])->update(['value' => $value]);
|
||||
}
|
||||
else {
|
||||
// insert new
|
||||
ModelsSettings::create(['name' => $pluginName, 'key' => $key, 'value' => $value]);
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteFromDatabase($pluginName, $key = null)
|
||||
{
|
||||
if (!isset($key)) {
|
||||
ModelsSettings::where('name', $pluginName)->delete();
|
||||
}
|
||||
else {
|
||||
ModelsSettings::where('name', $pluginName)->where('key', $key)->delete();
|
||||
}
|
||||
}
|
||||
|
||||
public static function display($plugin, $settings): array
|
||||
{
|
||||
$settingsDb = ModelsSettings::where('name', $plugin)->pluck('value', 'key')->toArray();
|
||||
$config = [];
|
||||
require BASE . 'config.local.php';
|
||||
|
||||
foreach ($config as $key => $value) {
|
||||
if (is_bool($value)) {
|
||||
$settingsDb[$key] = $value ? 'true' : 'false';
|
||||
}
|
||||
elseif (is_array($value)) {
|
||||
$settingsDb[$key] = $value;
|
||||
}
|
||||
else {
|
||||
$settingsDb[$key] = (string)$value;
|
||||
}
|
||||
}
|
||||
|
||||
$javascript = '';
|
||||
ob_start();
|
||||
?>
|
||||
<ul class="nav nav-tabs" id="myTab">
|
||||
<?php
|
||||
$i = 0;
|
||||
foreach($settings as $setting) {
|
||||
if (isset($setting['script'])) {
|
||||
$javascript .= $setting['script'] . PHP_EOL;
|
||||
}
|
||||
|
||||
if ($setting['type'] === 'category') {
|
||||
?>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link<?= ($i === 0 ? ' active' : ''); ?>" id="home-tab-<?= $i++; ?>" data-toggle="tab" href="#tab-<?= str_replace(' ', '', $setting['title']); ?>" type="button"><?= $setting['title']; ?></a>
|
||||
</li>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
<div class="tab-content" id="tab-content">
|
||||
<?php
|
||||
|
||||
$checkbox = function ($key, $type, $value) {
|
||||
echo '<label><input type="radio" id="' . $key . '_' . ($type ? 'yes' : 'no') . '" name="settings[' . $key . ']" value="' . ($type ? 'true' : 'false') . '" ' . ($value === $type ? 'checked' : '') . '/>' . ($type ? 'Yes' : 'No') . '</label> ';
|
||||
};
|
||||
|
||||
$i = 0;
|
||||
$j = 0;
|
||||
foreach($settings as $key => $setting) {
|
||||
if ($setting['type'] === 'category') {
|
||||
if ($j++ !== 0) { // close previous category
|
||||
echo '</tbody></table></div>';
|
||||
}
|
||||
?>
|
||||
<div class="tab-pane fade show<?= ($j === 1 ? ' active' : ''); ?>" id="tab-<?= str_replace(' ', '', $setting['title']); ?>">
|
||||
<?php
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($setting['type'] === 'section') {
|
||||
if ($i++ !== 0) { // close previous section
|
||||
echo '</tbody></table>';
|
||||
}
|
||||
?>
|
||||
<h3 id="row_<?= $key ?>" style="text-align: center"><strong><?= $setting['title']; ?></strong></h3>
|
||||
<table class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 13%">Name</th>
|
||||
<th style="width: 30%">Value</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($setting['hidden']) || !$setting['hidden']) {
|
||||
?>
|
||||
<tr id="row_<?= $key ?>">
|
||||
<td><label for="<?= $key ?>" class="control-label"><?= $setting['name'] ?></label></td>
|
||||
<td>
|
||||
<?php
|
||||
}
|
||||
if (isset($setting['hidden']) && $setting['hidden']) {
|
||||
$value = '';
|
||||
if ($setting['type'] === 'boolean') {
|
||||
$value = ($setting['default'] ? 'true' : 'false');
|
||||
}
|
||||
else if (in_array($setting['type'], ['text', 'number', 'email', 'password', 'textarea'])) {
|
||||
$value = $setting['default'];
|
||||
}
|
||||
else if ($setting['type'] === 'options') {
|
||||
$value = $setting['options'][$setting['default']];
|
||||
}
|
||||
|
||||
echo '<input type="hidden" name="settings[' . $key . ']" value="' . $value . '" id="' . $key . '"';
|
||||
}
|
||||
else if ($setting['type'] === 'boolean') {
|
||||
if(isset($settingsDb[$key])) {
|
||||
if($settingsDb[$key] === 'true') {
|
||||
$value = true;
|
||||
}
|
||||
else {
|
||||
$value = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$value = ($setting['default'] ?? false);
|
||||
}
|
||||
|
||||
$checkbox($key, true, $value);
|
||||
$checkbox($key, false, $value);
|
||||
}
|
||||
|
||||
else if (in_array($setting['type'], ['text', 'number', 'email', 'password'])) {
|
||||
if ($setting['type'] === 'number') {
|
||||
$min = (isset($setting['min']) ? ' min="' . $setting['min'] . '"' : '');
|
||||
$max = (isset($setting['max']) ? ' max="' . $setting['max'] . '"' : '');
|
||||
$step = (isset($setting['step']) ? ' step="' . $setting['step'] . '"' : '');
|
||||
}
|
||||
else {
|
||||
$min = $max = $step = '';
|
||||
}
|
||||
|
||||
echo '<input class="form-control" type="' . $setting['type'] . '" name="settings[' . $key . ']" value="' . ($settingsDb[$key] ?? ($setting['default'] ?? '')) . '" id="' . $key . '"' . $min . $max . $step . '/>';
|
||||
}
|
||||
|
||||
else if($setting['type'] === 'textarea') {
|
||||
if (is_array($settingsDb[$key])) {
|
||||
$settingsDb[$key] = implode(',', $settingsDb[$key]);
|
||||
}
|
||||
|
||||
$value = ($settingsDb[$key] ?? ($setting['default'] ?? ''));
|
||||
$valueWithSpaces = array_map('trim', preg_split('/\r\n|\r|\n/', trim($value)));
|
||||
$rows = count($valueWithSpaces);
|
||||
if ($rows < 2) {
|
||||
$rows = 2; // always min 2 rows for textarea
|
||||
}
|
||||
echo '<textarea class="form-control" rows="' . $rows . '" name="settings[' . $key . ']" id="' . $key . '">' . $value . '</textarea>';
|
||||
}
|
||||
|
||||
else if ($setting['type'] === 'options') {
|
||||
if ($setting['options'] === '$templates') {
|
||||
$templates = [];
|
||||
foreach (get_templates() as $value) {
|
||||
$templates[$value] = $value;
|
||||
}
|
||||
|
||||
$setting['options'] = $templates;
|
||||
}
|
||||
|
||||
else if($setting['options'] === '$clients') {
|
||||
$clients = [];
|
||||
foreach((array)config('clients') as $client) {
|
||||
|
||||
$client_version = (string)($client / 100);
|
||||
if(strpos($client_version, '.') === false)
|
||||
$client_version .= '.0';
|
||||
|
||||
$clients[$client] = $client_version;
|
||||
}
|
||||
|
||||
$setting['options'] = $clients;
|
||||
}
|
||||
else if ($setting['options'] == '$timezones') {
|
||||
$timezones = [];
|
||||
foreach (\DateTimeZone::listIdentifiers() as $value) {
|
||||
$timezones[$value] = $value;
|
||||
}
|
||||
|
||||
$setting['options'] = $timezones;
|
||||
}
|
||||
|
||||
else {
|
||||
if (is_string($setting['options'])) {
|
||||
$setting['options'] = explode(',', $setting['options']);
|
||||
foreach ($setting['options'] as &$option) {
|
||||
$option = trim($option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo '<select class="form-control" name="settings[' . $key . ']" id="' . $key . '">';
|
||||
foreach ($setting['options'] as $value => $option) {
|
||||
$compareTo = ($settingsDb[$key] ?? ($setting['default'] ?? ''));
|
||||
if($value === 'true') {
|
||||
$selected = $compareTo === true;
|
||||
}
|
||||
else if($value === 'false') {
|
||||
$selected = $compareTo === false;
|
||||
}
|
||||
else {
|
||||
$selected = $compareTo == $value;
|
||||
}
|
||||
|
||||
echo '<option value="' . $value . '" ' . ($selected ? 'selected' : '') . '>' . $option . '</option>';
|
||||
}
|
||||
echo '</select>';
|
||||
}
|
||||
|
||||
if (!isset($setting['hidden']) || !$setting['hidden']) {
|
||||
?>
|
||||
</td>
|
||||
<td>
|
||||
<div class="well setting-default"><?php
|
||||
echo (isset($setting['desc']) ? makeLinksClickable($setting['desc']) : '');
|
||||
echo '<br/>';
|
||||
echo '<strong>Default:</strong> ';
|
||||
|
||||
if ($setting['type'] === 'boolean') {
|
||||
echo ($setting['default'] ? 'Yes' : 'No');
|
||||
}
|
||||
else if (in_array($setting['type'], ['text', 'number', 'email', 'password', 'textarea'])) {
|
||||
echo $setting['default'];
|
||||
}
|
||||
else if ($setting['type'] === 'options') {
|
||||
if (is_int($setting['default']) || !empty($setting['default'])) {
|
||||
echo $setting['options'][$setting['default']];
|
||||
}
|
||||
}
|
||||
?></div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<button name="save" type="submit" class="btn btn-primary">Save</button>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
return ['content' => ob_get_clean(), 'script' => $javascript];
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
if (is_null($offset)) {
|
||||
throw new \RuntimeException("Settings: You cannot set empty offset with value: $value!");
|
||||
}
|
||||
|
||||
$this->loadPlugin($offset);
|
||||
|
||||
$pluginKeyName = $this->valuesAsked['pluginKeyName'];
|
||||
$key = $this->valuesAsked['key'];
|
||||
|
||||
// remove whole plugin settings
|
||||
if (!isset($value)) {
|
||||
$this->offsetUnset($offset);
|
||||
$this->deleteFromDatabase($pluginKeyName, $key);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->settingsDatabase[$pluginKeyName][$key] = $value;
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetExists($offset): bool
|
||||
{
|
||||
$this->loadPlugin($offset);
|
||||
|
||||
$pluginKeyName = $this->valuesAsked['pluginKeyName'];
|
||||
$key = $this->valuesAsked['key'];
|
||||
|
||||
// remove specified plugin settings (all)
|
||||
if(is_null($key)) {
|
||||
return isset($this->settingsDatabase[$offset]);
|
||||
}
|
||||
|
||||
return isset($this->settingsDatabase[$pluginKeyName][$key]);
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
$this->loadPlugin($offset);
|
||||
|
||||
$pluginKeyName = $this->valuesAsked['pluginKeyName'];
|
||||
$key = $this->valuesAsked['key'];
|
||||
|
||||
if (isset($this->cache[$offset])) {
|
||||
unset($this->cache[$offset]);
|
||||
}
|
||||
|
||||
// remove specified plugin settings (all)
|
||||
if(!isset($key)) {
|
||||
unset($this->settingsFile[$pluginKeyName]);
|
||||
unset($this->settingsDatabase[$pluginKeyName]);
|
||||
$this->deleteFromDatabase($pluginKeyName);
|
||||
return;
|
||||
}
|
||||
|
||||
unset($this->settingsFile[$pluginKeyName]['settings'][$key]);
|
||||
unset($this->settingsDatabase[$pluginKeyName][$key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get settings
|
||||
* Usage: $setting['plugin_name.key']
|
||||
* Example: $settings['shop_system.paypal_email']
|
||||
*
|
||||
* @param mixed $offset
|
||||
* @return array|mixed
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
// try cache hit
|
||||
if(isset($this->cache[$offset])) {
|
||||
return $this->cache[$offset];
|
||||
}
|
||||
|
||||
$this->loadPlugin($offset);
|
||||
|
||||
$pluginKeyName = $this->valuesAsked['pluginKeyName'];
|
||||
$key = $this->valuesAsked['key'];
|
||||
|
||||
// return specified plugin settings (all)
|
||||
if(!isset($key)) {
|
||||
if (!isset($this->settingsFile[$pluginKeyName]['settings'])) {
|
||||
throw new \RuntimeException('Unknown plugin settings: ' . $pluginKeyName);
|
||||
}
|
||||
return $this->settingsFile[$pluginKeyName]['settings'];
|
||||
}
|
||||
|
||||
$ret = [];
|
||||
if(isset($this->settingsFile[$pluginKeyName]['settings'][$key])) {
|
||||
$ret = $this->settingsFile[$pluginKeyName]['settings'][$key];
|
||||
}
|
||||
|
||||
if(isset($this->settingsDatabase[$pluginKeyName][$key])) {
|
||||
$value = $this->settingsDatabase[$pluginKeyName][$key];
|
||||
|
||||
$ret['value'] = $value;
|
||||
}
|
||||
else {
|
||||
$ret['value'] = $this->settingsFile[$pluginKeyName]['settings'][$key]['default'];
|
||||
}
|
||||
|
||||
if(isset($ret['type'])) {
|
||||
switch($ret['type']) {
|
||||
case 'boolean':
|
||||
$ret['value'] = getBoolean($ret['value']);
|
||||
break;
|
||||
|
||||
case 'number':
|
||||
if (!isset($ret['step']) || (int)$ret['step'] == 1) {
|
||||
$ret['value'] = (int)$ret['value'];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($ret['callbacks']['get'])) {
|
||||
$ret['value'] = $ret['callbacks']['get']($ret['value']);
|
||||
}
|
||||
|
||||
$this->cache[$offset] = $ret;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
private function updateValuesAsked($offset)
|
||||
{
|
||||
$pluginKeyName = $offset;
|
||||
if (strpos($offset, '.')) {
|
||||
$explode = explode('.', $offset, 2);
|
||||
|
||||
$pluginKeyName = $explode[0];
|
||||
$key = $explode[1];
|
||||
|
||||
$this->valuesAsked = ['pluginKeyName' => $pluginKeyName, 'key' => $key];
|
||||
}
|
||||
else {
|
||||
$this->valuesAsked = ['pluginKeyName' => $pluginKeyName, 'key' => null];
|
||||
}
|
||||
}
|
||||
|
||||
private function loadPlugin($offset)
|
||||
{
|
||||
$this->updateValuesAsked($offset);
|
||||
|
||||
$pluginKeyName = $this->valuesAsked['pluginKeyName'];
|
||||
$key = $this->valuesAsked['key'];
|
||||
|
||||
if (!isset($this->settingsFile[$pluginKeyName])) {
|
||||
if ($pluginKeyName === 'core') {
|
||||
$settingsFilePath = SYSTEM . 'settings.php';
|
||||
} else {
|
||||
//$pluginSettings = Plugins::getPluginSettings($pluginKeyName);
|
||||
$settings = Plugins::getAllPluginsSettings();
|
||||
if (!isset($settings[$pluginKeyName])) {
|
||||
warning("Setting $pluginKeyName does not exist or does not have settings defined.");
|
||||
return;
|
||||
}
|
||||
|
||||
$settingsFilePath = BASE . $settings[$pluginKeyName]['settingsFilename'];
|
||||
}
|
||||
|
||||
if (!file_exists($settingsFilePath)) {
|
||||
throw new \RuntimeException('Failed to load settings file for plugin: ' . $pluginKeyName);
|
||||
}
|
||||
|
||||
$this->settingsFile[$pluginKeyName] = require $settingsFilePath;
|
||||
}
|
||||
}
|
||||
|
||||
public static function saveConfig($config, $filename, &$content = '')
|
||||
{
|
||||
$content = "<?php" . PHP_EOL;
|
||||
|
||||
unset($config['installed']);
|
||||
|
||||
$content .= "\$config['installed'] = true;" . PHP_EOL;
|
||||
|
||||
foreach ($config as $key => $value) {
|
||||
$content .= "\$config['$key'] = ";
|
||||
$content .= var_export($value, true);
|
||||
$content .= ';' . PHP_EOL;
|
||||
}
|
||||
|
||||
$success = file_put_contents($filename, $content);
|
||||
|
||||
// we saved new config.php, need to revalidate cache (only if opcache is enabled)
|
||||
if (function_exists('opcache_invalidate')) {
|
||||
opcache_invalidate($filename);
|
||||
}
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
public static function testDatabaseConnection($config): bool
|
||||
{
|
||||
$user = null;
|
||||
$password = null;
|
||||
$dns = [];
|
||||
|
||||
if( isset($config['database_name']) ) {
|
||||
$dns[] = 'dbname=' . $config['database_name'];
|
||||
}
|
||||
|
||||
if( isset($config['database_user']) ) {
|
||||
$user = $config['database_user'];
|
||||
}
|
||||
|
||||
if( isset($config['database_password']) ) {
|
||||
$password = $config['database_password'];
|
||||
}
|
||||
|
||||
if( isset($config['database_host']) ) {
|
||||
$dns[] = 'host=' . $config['database_host'];
|
||||
}
|
||||
|
||||
if( isset($config['database_port']) ) {
|
||||
$dns[] = 'port=' . $config['database_port'];
|
||||
}
|
||||
|
||||
try {
|
||||
$connectionTest = new \PDO('mysql:' . implode(';', $dns), $user, $password);
|
||||
$connectionTest->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
||||
}
|
||||
catch(\PDOException $error) {
|
||||
error('MySQL connection failed. Settings has been reverted.');
|
||||
error($error->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getErrors() {
|
||||
return $this->errors;
|
||||
}
|
||||
}
|
186
system/src/Spells.php
Normal file
186
system/src/Spells.php
Normal file
@@ -0,0 +1,186 @@
|
||||
<?php
|
||||
/**
|
||||
* Spells class
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Gesior <jerzyskalski@wp.pl>
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @copyright 2019 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
use MyAAC\Models\Spell;
|
||||
|
||||
class Spells {
|
||||
private static $spellsList = null;
|
||||
private static $lastError = '';
|
||||
|
||||
// 1 - attack, 2 - healing, 3 - summon, 4 - supply, 5 - support
|
||||
public static function loadGroup($tGroup) {
|
||||
switch ($tGroup) {
|
||||
case "attack":
|
||||
return 1;
|
||||
case "healing":
|
||||
return 2;
|
||||
case "summon":
|
||||
return 3;
|
||||
case "supply":
|
||||
return 4;
|
||||
case "support":
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
public static function loadFromXML($show = false) {
|
||||
global $config;
|
||||
|
||||
try {
|
||||
Spell::query()->delete();
|
||||
} catch(\Exception $error) {}
|
||||
|
||||
if($show) {
|
||||
echo '<h2>Reload spells.</h2>';
|
||||
echo '<h2>All records deleted from table <b>' . TABLE_PREFIX . 'spells</b> in database.</h2>';
|
||||
}
|
||||
|
||||
try {
|
||||
self::$spellsList = new \OTS_SpellsList($config['data_path'].'spells/spells.xml');
|
||||
}
|
||||
catch(\Exception $e) {
|
||||
self::$lastError = $e->getMessage();
|
||||
return false;
|
||||
}
|
||||
|
||||
//add conjure spells
|
||||
$conjurelist = self::$spellsList->getConjuresList();
|
||||
if($show) {
|
||||
echo "<h3>Conjure:</h3>";
|
||||
}
|
||||
|
||||
foreach($conjurelist as $spellname) {
|
||||
$spell = self::$spellsList->getConjure($spellname);
|
||||
$name = $spell->getName();
|
||||
|
||||
$words = $spell->getWords();
|
||||
if(strpos($words, '#') !== false)
|
||||
continue;
|
||||
|
||||
try {
|
||||
Spell::create(array(
|
||||
'name' => $name,
|
||||
'words' => $words,
|
||||
'type' => 2,
|
||||
'mana' => $spell->getMana(),
|
||||
'level' => $spell->getLevel(),
|
||||
'maglevel' => $spell->getMagicLevel(),
|
||||
'soul' => $spell->getSoul(),
|
||||
'premium' => $spell->isPremium() ? 1 : 0,
|
||||
'vocations' => json_encode($spell->getVocations()),
|
||||
'conjure_count' => $spell->getConjureCount(),
|
||||
'conjure_id' => $spell->getConjureId(),
|
||||
'reagent' => $spell->getReagentId(),
|
||||
'hidden' => $spell->isEnabled() ? 0 : 1
|
||||
));
|
||||
|
||||
if($show) {
|
||||
success('Added: ' . $name . '<br/>');
|
||||
}
|
||||
}
|
||||
catch(\PDOException $error) {
|
||||
if($show) {
|
||||
warning('Error while adding spell (' . $name . '): ' . $error->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add instant spells
|
||||
$instantlist = self::$spellsList->getInstantsList();
|
||||
if($show) {
|
||||
echo "<h3>Instant:</h3>";
|
||||
}
|
||||
|
||||
foreach($instantlist as $spellname) {
|
||||
$spell = self::$spellsList->getInstant($spellname);
|
||||
$name = $spell->getName();
|
||||
|
||||
$words = $spell->getWords();
|
||||
if(strpos($words, '#') !== false)
|
||||
continue;
|
||||
|
||||
try {
|
||||
Spell::create(array(
|
||||
'name' => $name,
|
||||
'words' => $words,
|
||||
'type' => 1,
|
||||
'mana' => $spell->getMana(),
|
||||
'level' => $spell->getLevel(),
|
||||
'maglevel' => $spell->getMagicLevel(),
|
||||
'soul' => $spell->getSoul(),
|
||||
'premium' => $spell->isPremium() ? 1 : 0,
|
||||
'vocations' => json_encode($spell->getVocations()),
|
||||
'conjure_count' => 0,
|
||||
'hidden' => $spell->isEnabled() ? 0 : 1
|
||||
));
|
||||
|
||||
if($show) {
|
||||
success('Added: ' . $name . '<br/>');
|
||||
}
|
||||
}
|
||||
catch(\PDOException $error) {
|
||||
if($show) {
|
||||
warning('Error while adding spell (' . $name . '): ' . $error->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add runes
|
||||
$runeslist = self::$spellsList->getRunesList();
|
||||
if($show) {
|
||||
echo "<h3>Runes:</h3>";
|
||||
}
|
||||
|
||||
foreach($runeslist as $spellname) {
|
||||
$spell = self::$spellsList->getRune($spellname);
|
||||
|
||||
$name = $spell->getName() . ' Rune';
|
||||
|
||||
try {
|
||||
Spell::create(array(
|
||||
'name' => $name,
|
||||
'words' => $spell->getWords(),
|
||||
'type' => 3,
|
||||
'mana' => $spell->getMana(),
|
||||
'level' => $spell->getLevel(),
|
||||
'maglevel' => $spell->getMagicLevel(),
|
||||
'soul' => $spell->getSoul(),
|
||||
'premium' => $spell->isPremium() ? 1 : 0,
|
||||
'vocations' => json_encode($spell->getVocations()),
|
||||
'conjure_count' => 0,
|
||||
'item_id' => $spell->getID(),
|
||||
'hidden' => $spell->isEnabled() ? 0 : 1
|
||||
));
|
||||
|
||||
if($show) {
|
||||
success('Added: ' . $name . '<br/>');
|
||||
}
|
||||
}
|
||||
catch(\PDOException $error) {
|
||||
if($show) {
|
||||
warning('Error while adding spell (' . $name . '): ' . $error->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function getSpellsList() {
|
||||
return self::$spellsList;
|
||||
}
|
||||
|
||||
public static function getLastError() {
|
||||
return self::$lastError;
|
||||
}
|
||||
}
|
56
system/src/Timer.php
Normal file
56
system/src/Timer.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* Timer class
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @copyright 2019 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
class Timer
|
||||
{
|
||||
private $start = 0;
|
||||
private $stop = 0;
|
||||
private $elapsed = 0;
|
||||
|
||||
function __construct($start = true) {
|
||||
if($start) $this->start();
|
||||
}
|
||||
|
||||
function start() {
|
||||
$this->start = $this->_gettime();
|
||||
}
|
||||
|
||||
function stop()
|
||||
{
|
||||
$this->stop = $this->_gettime();
|
||||
$this->elapsed = $this->_compute();
|
||||
}
|
||||
|
||||
function elapsed()
|
||||
{
|
||||
if(!$this->elapsed)
|
||||
$this->stop();
|
||||
|
||||
return $this->elapsed;
|
||||
}
|
||||
|
||||
function reset()
|
||||
{
|
||||
$this->start = 0;
|
||||
$this->stop = 0;
|
||||
$this->elapsed = 0;
|
||||
}
|
||||
|
||||
private function _gettime() {
|
||||
return microtime(true);
|
||||
}
|
||||
|
||||
private function _compute() {
|
||||
return $this->stop - $this->start;
|
||||
}
|
||||
}
|
||||
?>
|
129
system/src/Towns.php
Normal file
129
system/src/Towns.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
/**
|
||||
* Project: MyAAC
|
||||
* Automatic Account Creator for Open Tibia Servers
|
||||
*
|
||||
* This is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @copyright 2020 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
use MyAAC\Models\Town;
|
||||
|
||||
class Towns
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private static $filename = CACHE . 'persistent/' . 'towns.php';
|
||||
|
||||
/**
|
||||
* Determine towns
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function determine()
|
||||
{
|
||||
global $db;
|
||||
|
||||
if($db->hasTable('towns')) {
|
||||
return self::getFromDatabase();
|
||||
}
|
||||
|
||||
return self::getFromOTBM();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load cached towns file
|
||||
*/
|
||||
public static function load()
|
||||
{
|
||||
$towns = config('towns');
|
||||
if (file_exists(self::$filename)) {
|
||||
$towns = require self::$filename;
|
||||
}
|
||||
|
||||
config(['towns', $towns]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save into cache file
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function save()
|
||||
{
|
||||
$towns = self::determine();
|
||||
if (count($towns) > 0) {
|
||||
file_put_contents(self::$filename, '<?php return ' . var_export($towns, true) . ';', LOCK_EX);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load from OTBM map file
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getFromOTBM()
|
||||
{
|
||||
$mapName = configLua('mapName');
|
||||
if (!isset($mapName)) {
|
||||
$mapName = configLua('map');
|
||||
$mapFile = config('server_path') . $mapName;
|
||||
}
|
||||
|
||||
if (strpos($mapName, '.otbm') === false) {
|
||||
$mapName .= '.otbm';
|
||||
}
|
||||
|
||||
if (!isset($mapFile)) {
|
||||
$mapFile = config('data_path') . 'world/' . $mapName;
|
||||
}
|
||||
|
||||
if (strpos($mapFile, '.gz') !== false) {
|
||||
$mapFile = str_replace('.gz', '', $mapFile);
|
||||
}
|
||||
|
||||
$towns = [];
|
||||
if (file_exists($mapFile)) {
|
||||
ini_set('memory_limit', '-1');
|
||||
|
||||
$townsReader = new TownsReader($mapFile);
|
||||
$townsReader->load();
|
||||
|
||||
$towns = $townsReader->get();
|
||||
}
|
||||
|
||||
return $towns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load from database
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getFromDatabase()
|
||||
{
|
||||
return Town::pluck('name', 'id')->toArray();
|
||||
}
|
||||
}
|
84
system/src/TownsReader.php
Normal file
84
system/src/TownsReader.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/*
|
||||
This file is part of OTSCMS (http://www.otscms.com/) project.
|
||||
|
||||
Copyright (C) 2005 - 2007 Wrzasq (wrzasq@gmail.com)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
/*
|
||||
This code bases on original OTServ code for .otbm files - file iomapotbm.cpp rev.2141
|
||||
*/
|
||||
class TownsReader
|
||||
{
|
||||
// node bytes
|
||||
const ESCAPE_CHAR = 0xFD;
|
||||
const NODE_START = 0xFE;
|
||||
|
||||
// map node types
|
||||
const OTBM_TOWN = 13;
|
||||
|
||||
// file handler
|
||||
protected $file;
|
||||
|
||||
// towns
|
||||
private $towns = [];
|
||||
|
||||
// loads map .otbm file
|
||||
public function __construct($file)
|
||||
{
|
||||
// opens file for reading
|
||||
$this->file = fopen($file, 'rb');
|
||||
}
|
||||
|
||||
public function load()
|
||||
{
|
||||
// checks if file is opened correctly
|
||||
if ($this->file) {
|
||||
// skips version
|
||||
fseek($this->file, 4);
|
||||
|
||||
// reads nodes chain
|
||||
while (!feof($this->file)) {
|
||||
// reads byte
|
||||
switch (ord(fgetc($this->file))) {
|
||||
// maybe a town node
|
||||
case self::NODE_START:
|
||||
// reads node type
|
||||
if (ord(fgetc($this->file)) == self::OTBM_TOWN) {
|
||||
$id = unpack('L', fread($this->file, 4));
|
||||
$length = unpack('S', fread($this->file, 2));
|
||||
|
||||
// reads town name
|
||||
$this->towns[$id[1]] = fread($this->file, $length[1]);
|
||||
}
|
||||
break;
|
||||
|
||||
// escape next character - it might be NODE_START character which is in fact not
|
||||
case self::ESCAPE_CHAR:
|
||||
fgetc($this->file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function get() {
|
||||
return $this->towns;
|
||||
}
|
||||
}
|
123
system/src/UsageStatistics.php
Normal file
123
system/src/UsageStatistics.php
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
/**
|
||||
* Usage Statistics
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @copyright 2019 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
use MyAAC\Cache\Cache;
|
||||
|
||||
class UsageStatistics {
|
||||
private static $report_url = 'https://my-aac.org/report_usage.php';
|
||||
|
||||
public static function report() {
|
||||
$data = json_encode(self::getStats());
|
||||
|
||||
$options = array(
|
||||
'http' => array(
|
||||
'header' => 'Content-type: application/json' . "\r\n"
|
||||
. 'Content-Length: ' . strlen($data) . "\r\n",
|
||||
'content' => $data
|
||||
)
|
||||
);
|
||||
|
||||
$context = stream_context_create($options);
|
||||
$result = file_get_contents(self::$report_url, false, $context);
|
||||
|
||||
return $result !== false;
|
||||
}
|
||||
|
||||
public static function getStats() {
|
||||
global $config, $db;
|
||||
|
||||
$ret = array();
|
||||
|
||||
$ret['unique_id'] = hash('sha1', $config['server_path']);
|
||||
$ret['server_os'] = php_uname('s') . ' ' . php_uname('r');
|
||||
|
||||
$ret['myaac_version'] = MYAAC_VERSION;
|
||||
$ret['myaac_db_version'] = DATABASE_VERSION;
|
||||
|
||||
if($db->hasTable('server_config')) {
|
||||
$query = $db->query('SELECT `value` FROM `server_config` WHERE `config` = ' . $db->quote('database_version'));
|
||||
if($query->rowCount() == 1) {
|
||||
$query = $query->fetch();
|
||||
$ret['otserv_db_version'] = $query['value'];
|
||||
}
|
||||
}
|
||||
|
||||
$ret['client_version'] = $config['client'];
|
||||
|
||||
$ret['php_version'] = phpversion();
|
||||
|
||||
$query = $db->query('SELECT VERSION() as `version`;');
|
||||
if($query->rowCount() == 1) {
|
||||
$query = $query->fetch();
|
||||
$ret['mysql_version'] = $query['version'];
|
||||
}
|
||||
|
||||
$query = $db->query('SELECT SUM(ROUND(((DATA_LENGTH + INDEX_LENGTH) / 1024 ), 0)) AS "size"
|
||||
FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE TABLE_SCHEMA = "' . $config['database_name'] . '";');
|
||||
|
||||
if($query->rowCount() == 1) {
|
||||
$query = $query->fetch();
|
||||
$ret['database_size'] = $query['size'];
|
||||
}
|
||||
|
||||
$ret['views_counter'] = getDatabaseConfig('views_counter');
|
||||
|
||||
$query = $db->query('SELECT COUNT(`id`) as `size` FROM `accounts`;');
|
||||
if($query->rowCount() == 1) {
|
||||
$query = $query->fetch();
|
||||
$ret['accounts_size'] = $query['size'];
|
||||
}
|
||||
|
||||
$query = $db->query('SELECT COUNT(`id`) as `size` FROM `players`;');
|
||||
if($query->rowCount() == 1) {
|
||||
$query = $query->fetch();
|
||||
$ret['players_size'] = $query['size'];
|
||||
}
|
||||
|
||||
$query = $db->query('SELECT COUNT(`id`) as `size` FROM `' . TABLE_PREFIX . 'monsters`;');
|
||||
if($query->rowCount() == 1) {
|
||||
$query = $query->fetch();
|
||||
$ret['monsters_size'] = $query['size'];
|
||||
}
|
||||
|
||||
$query = $db->query('SELECT COUNT(`id`) as `size` FROM `' . TABLE_PREFIX . 'spells`;');
|
||||
if($query->rowCount() == 1) {
|
||||
$query = $query->fetch();
|
||||
$ret['spells_size'] = $query['size'];
|
||||
}
|
||||
|
||||
$ret['locales'] = get_locales();
|
||||
$ret['plugins'] = array();
|
||||
foreach(get_plugins() as $plugin) {
|
||||
$string = file_get_contents(BASE . 'plugins/' . $plugin . '.json');
|
||||
$plugin_info = json_decode($string, true);
|
||||
if($plugin_info != false) {
|
||||
if(isset($plugin_info['version'])) {
|
||||
$ret['plugins'][$plugin] = $plugin_info['version'];
|
||||
}
|
||||
}
|
||||
}
|
||||
$ret['templates'] = get_templates();
|
||||
|
||||
$ret['date_timezone'] = setting('core.date_timezone');
|
||||
$ret['backward_support'] = setting('core.backward_support');
|
||||
|
||||
$cache_engine = strtolower($config['cache_engine']);
|
||||
if($cache_engine == 'auto') {
|
||||
$cache_engine = Cache::detect();
|
||||
}
|
||||
|
||||
$ret['cache_engine'] = $cache_engine;
|
||||
return $ret;
|
||||
}
|
||||
}
|
442
system/src/Validator.php
Normal file
442
system/src/Validator.php
Normal file
@@ -0,0 +1,442 @@
|
||||
<?php
|
||||
/**
|
||||
* Validator class
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @copyright 2019 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
use MyAAC\Models\Monster;
|
||||
use MyAAC\Models\Spell;
|
||||
|
||||
class Validator
|
||||
{
|
||||
private static $lastError = '';
|
||||
public static function number($number) {
|
||||
if(!preg_match("/^([0-9]+)$/", $number)) {
|
||||
self::$lastError = 'Invalid number format.';
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate account id
|
||||
* Id lenght must be 6-10 chars
|
||||
*
|
||||
* @param string $id Account id to check
|
||||
* @return bool Is account name valid?
|
||||
*/
|
||||
public static function accountId($id)
|
||||
{
|
||||
if(!isset($id[0]))
|
||||
{
|
||||
self::$lastError = 'Please enter your account number!';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!Validator::number($id)) {
|
||||
self::$lastError = 'Invalid account number format. Please use only numbers 0-9.';
|
||||
return false;
|
||||
}
|
||||
|
||||
$length = strlen($id);
|
||||
if($length < 6)
|
||||
{
|
||||
self::$lastError = 'Account is too short (min. 6 chars).';
|
||||
return false;
|
||||
}
|
||||
|
||||
if($length > 10)
|
||||
{
|
||||
self::$lastError = 'Account is too long (max. 10 chars).';
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate account name
|
||||
* Name lenght must be 3-32 chars
|
||||
*
|
||||
* @param string $name Account name to check
|
||||
* @return bool Is account name valid?
|
||||
*/
|
||||
public static function accountName($name)
|
||||
{
|
||||
if(!isset($name[0]))
|
||||
{
|
||||
self::$lastError = 'Please enter your account name!';
|
||||
return false;
|
||||
}
|
||||
|
||||
$length = strlen($name);
|
||||
if($length < 3)
|
||||
{
|
||||
self::$lastError = 'Account name is too short (min. 3 chars).';
|
||||
return false;
|
||||
}
|
||||
|
||||
if($length > 32)
|
||||
{
|
||||
self::$lastError = 'Account name is too long (max. 32 chars).';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(preg_match('/ {2,}/', $name))
|
||||
{
|
||||
self::$lastError = 'Invalid account name format. Use only A-Z and numbers 0-9 and no double spaces.';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!preg_match("/^[A-Z0-9]+$/i", $name))
|
||||
{
|
||||
self::$lastError = 'Invalid account name format. Use only A-Z and numbers 0-9.';
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Advanced mail validator
|
||||
*
|
||||
* @param string $email
|
||||
* @return bool Is email valid?
|
||||
*/
|
||||
public static function email($email) {
|
||||
if(empty($email)) {
|
||||
self::$lastError = 'Please enter your new email address.';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(strlen($email) > 255) {
|
||||
self::$lastError = 'E-mail is too long (max. 255 chars).';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(setting('core.account_mail_block_plus_sign')) {
|
||||
$explode = explode('@', $email);
|
||||
if(isset($explode[0]) && (strpos($explode[0],'+') !== false)) {
|
||||
self::$lastError = 'Please do not use plus (+) sign in your e-mail.';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!preg_match('/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9_](?:[A-z0-9_\-](?!\.)){0,61}[a-zA-Z0-9_]?\.)+[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!$)){0,61}[a-zA-Z0-9_]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/', $email)) {
|
||||
self::$lastError = 'Invalid e-mail format.';
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate account password
|
||||
* Name lenght must be 3-32 chars
|
||||
*
|
||||
* @param string $name Account name to check
|
||||
* @return bool Is account name valid?
|
||||
*/
|
||||
public static function password($password)
|
||||
{
|
||||
if (!isset($password[0])) {
|
||||
self::$lastError = 'Please enter the password.';
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strlen($password) < 8 || strlen($password) > 29) {
|
||||
self::$lastError = 'The password must have at least 8 and maximum 29 letters!';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!preg_match('/[a-zA-Z]/', $password)) {
|
||||
self::$lastError = 'The password must contain at least one letter A-Z or a-z!';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!preg_match('/[0-9]/', $password)) {
|
||||
self::$lastError = 'The password must contain at least one number!';
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate character name.
|
||||
* Name lenght must be 3-25 chars
|
||||
*
|
||||
* @param string $name Name to check
|
||||
* @return bool Is name valid?
|
||||
*/
|
||||
public static function characterName($name)
|
||||
{
|
||||
if(!isset($name[0]))
|
||||
{
|
||||
self::$lastError = 'Please enter character name.';
|
||||
return false;
|
||||
}
|
||||
|
||||
// installer doesn't know config.php yet
|
||||
// that's why we need to ignore the nulls
|
||||
if(defined('MYAAC_INSTALL')) {
|
||||
$minLength = 4;
|
||||
$maxLength = 21;
|
||||
}
|
||||
else {
|
||||
$minLength = setting('core.create_character_name_min_length');
|
||||
$maxLength = setting('core.create_character_name_max_length');
|
||||
}
|
||||
|
||||
$length = strlen($name);
|
||||
if($length < $minLength)
|
||||
{
|
||||
self::$lastError = "Character name is too short. Min. length <b>$minLength</b> characters.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if($length > $maxLength)
|
||||
{
|
||||
self::$lastError = "Character name is too long. Max. length <b>$maxLength</b> characters.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(strspn($name, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM- [ ] '") != $length)
|
||||
{
|
||||
self::$lastError = "Invalid name format. Use only A-Z, spaces and '.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(preg_match('/ {2,}/', $name))
|
||||
{
|
||||
self::$lastError = 'Invalid character name format. Use only A-Z and no double spaces.';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!preg_match("/[A-z ']/", $name))
|
||||
{
|
||||
self::$lastError = "Invalid name format. Use only A-Z, spaces and '.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate new character name.
|
||||
* Name lenght must be 3-25 chars
|
||||
*
|
||||
* @param string $name Name to check
|
||||
* @return bool Is name valid?
|
||||
*/
|
||||
public static function newCharacterName($name)
|
||||
{
|
||||
global $db, $config;
|
||||
|
||||
$name_lower = strtolower($name);
|
||||
|
||||
$first_words_blocked = array_merge(["'", '-'], setting('core.create_character_name_blocked_prefix'));
|
||||
foreach($first_words_blocked as $word) {
|
||||
if($word == substr($name_lower, 0, strlen($word))) {
|
||||
self::$lastError = 'Your name contains blocked words.';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(substr($name_lower, -1) == "'" || substr($name_lower, -1) == "-") {
|
||||
self::$lastError = 'Your name contains illegal characters.';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(substr($name_lower, 1, 1) == ' ') {
|
||||
self::$lastError = 'Your name contains illegal space.';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(substr($name_lower, -2, 1) == " ") {
|
||||
self::$lastError = 'Your name contains illegal space.';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(preg_match('/ {2,}/', $name)) {
|
||||
self::$lastError = 'Invalid character name format. Use only A-Z and numbers 0-9 and no double spaces.';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(strtolower($config['lua']['serverName']) == $name_lower) {
|
||||
self::$lastError = 'Your name cannot be same as server name.';
|
||||
return false;
|
||||
}
|
||||
|
||||
$names_blocked = setting('core.create_character_name_blocked_names');
|
||||
foreach($names_blocked as $word) {
|
||||
if($word == $name_lower) {
|
||||
self::$lastError = 'Your name contains blocked words.';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$words_blocked = array_merge(['--', "''","' ", " '", '- ', ' -', "-'", "'-"], setting('core.create_character_name_blocked_words'));
|
||||
foreach($words_blocked as $word) {
|
||||
if(!(strpos($name_lower, $word) === false)) {
|
||||
self::$lastError = 'Your name contains illegal words.';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$name_length = strlen($name_lower);
|
||||
for($i = 0; $i < $name_length; $i++)
|
||||
{
|
||||
if(isset($name_lower[$i]) && isset($name_lower[$i + 1]) && $name_lower[$i] == $name_lower[$i + 1] && isset($name_lower[$i + 2]) && $name_lower[$i] == $name_lower[$i + 2]) {
|
||||
self::$lastError = 'Your name is invalid.';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// check if was namelocked previously
|
||||
if($db->hasTable('player_namelocks') && $db->hasColumn('player_namelocks', 'name')) {
|
||||
$namelock = $db->query('SELECT `player_id` FROM `player_namelocks` WHERE `name` = ' . $db->quote($name));
|
||||
if($namelock->rowCount() > 0) {
|
||||
self::$lastError = 'Character with this name has been namelocked.';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$monstersCheck = setting('core.create_character_name_monsters_check');
|
||||
if ($monstersCheck) {
|
||||
if (Monster::where('name', 'like', $name_lower)->exists()) {
|
||||
self::$lastError = 'Your name cannot contains monster name.';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$spellsCheck = setting('core.create_character_name_spells_check');
|
||||
if ($spellsCheck) {
|
||||
if (Spell::where('name', 'like', $name_lower)->exists()) {
|
||||
self::$lastError = 'Your name cannot contains spell name.';
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Spell::where('words', $name_lower)->exists()) {
|
||||
self::$lastError = 'Your name cannot contains spell name.';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$npcCheck = setting('core.create_character_name_npc_check');
|
||||
if ($npcCheck) {
|
||||
NPCs::load();
|
||||
if(NPCs::$npcs) {
|
||||
foreach (NPCs::$npcs as $npc) {
|
||||
if(strpos($name_lower, $npc) !== false) {
|
||||
self::$lastError = 'Your name cannot contains NPC name.';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate guild name
|
||||
* Name lenght must be 3-32 chars
|
||||
*
|
||||
* @param string $name Name to check
|
||||
* @return bool Is name valid?
|
||||
*/
|
||||
public static function guildName($name)
|
||||
{
|
||||
if(empty($name)) {
|
||||
self::$lastError = 'Please enter guild name.';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(strspn($name, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789- ") != strlen($name)) {
|
||||
self::$lastError = 'Invalid guild name format.';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!preg_match("/[A-z ]{3,32}/", $name)) {
|
||||
self::$lastError = 'Invalid guild name format.';
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate guild nick
|
||||
* Nick lenght must be 3-40 chars
|
||||
*
|
||||
* @param string $name Name to check
|
||||
* @return bool Is name valid?
|
||||
*/
|
||||
public static function guildNick($name)
|
||||
{
|
||||
if(empty($name)) {
|
||||
self::$lastError = 'Please enter guild nick.';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(strspn($name, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789- ") != strlen($name)) {
|
||||
self::$lastError = 'Invalid guild nick format.';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!preg_match("/[A-z ]{3,40}/", $name)) {
|
||||
self::$lastError = 'Invalid guild nick format.';
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate rank name
|
||||
* Rank lenght must be 1-32 chars
|
||||
*
|
||||
* @param string $name Name to check
|
||||
* @return bool Is name valid?
|
||||
*/
|
||||
public static function rankName($name)
|
||||
{
|
||||
if(empty($name)) {
|
||||
self::$lastError = 'Please enter rank name.';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(strspn($name, "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789-[ ] ") != strlen($name)) {
|
||||
self::$lastError = 'Invalid rank name. Please use only a-Z, 0-9 and spaces.';
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!preg_match("/[A-z ]{1,32}/", $name)) {
|
||||
self::$lastError = 'Invalid rank name. Please use only a-Z, 0-9 and spaces.';
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Simple string validator, checks if string contains valid characters
|
||||
*
|
||||
* @param string $str String to validate
|
||||
* @param boolean $numbers Numbers should be allowed?
|
||||
*/
|
||||
public static function str($str, $numbers = false) {
|
||||
return preg_match('/^[a-z0-9\ ]*$/i', $str);
|
||||
}
|
||||
|
||||
public static function getLastError() {
|
||||
return self::$lastError;
|
||||
}
|
||||
}
|
126
system/src/Visitors.php
Normal file
126
system/src/Visitors.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
/**
|
||||
* Visitors class
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @copyright 2019 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
use MyAAC\Cache\Cache;
|
||||
use MyAAC\Models\Visitor;
|
||||
|
||||
class Visitors
|
||||
{
|
||||
private $sessionTime; // time session will live
|
||||
private $data; // cached data
|
||||
private $cacheEnabled;
|
||||
private $cache;
|
||||
|
||||
public function __construct($sessionTime = 10)
|
||||
{
|
||||
$this->cache = Cache::getInstance();
|
||||
|
||||
$this->cacheEnabled = $this->cache->enabled();
|
||||
if($this->cacheEnabled)
|
||||
{
|
||||
$tmp = '';
|
||||
if($this->cache->fetch('visitors', $tmp))
|
||||
$this->data = unserialize($tmp);
|
||||
else
|
||||
$this->data = array();
|
||||
}
|
||||
|
||||
$this->sessionTime = $sessionTime;
|
||||
$this->cleanVisitors();
|
||||
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
$userAgentShortened = substr($_SERVER['HTTP_USER_AGENT'] ?? 'unknown', 0, 255);
|
||||
|
||||
if($this->visitorExists($ip))
|
||||
$this->updateVisitor($ip, $_SERVER['REQUEST_URI'], $userAgentShortened);
|
||||
else
|
||||
$this->addVisitor($ip, $_SERVER['REQUEST_URI'], $userAgentShortened);
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if($this->cacheEnabled)
|
||||
$this->cache->set('visitors', serialize($this->data), 120);
|
||||
}
|
||||
|
||||
public function visitorExists($ip)
|
||||
{
|
||||
if($this->cacheEnabled) {
|
||||
return isset($this->data[$ip]);
|
||||
}
|
||||
|
||||
return Visitor::where('ip', $ip)->exists();
|
||||
}
|
||||
|
||||
private function cleanVisitors()
|
||||
{
|
||||
if($this->cacheEnabled)
|
||||
{
|
||||
$timeNow = time();
|
||||
foreach($this->data as $ip => $details)
|
||||
{
|
||||
if($timeNow - (int)$details['lastvisit'] > $this->sessionTime * 60)
|
||||
unset($this->data[$ip]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Visitor::where('lastvisit', '<', (time() - $this->sessionTime * 60))->delete();
|
||||
}
|
||||
|
||||
private function updateVisitor($ip, $page, $userAgent)
|
||||
{
|
||||
if($this->cacheEnabled) {
|
||||
$this->data[$ip] = array('page' => $page, 'lastvisit' => time(), 'user_agent' => $userAgent);
|
||||
return;
|
||||
}
|
||||
|
||||
Visitor::where('ip', $ip)->update(['lastvisit' => time(), 'page' => $page, 'user_agent' => $userAgent]);
|
||||
}
|
||||
|
||||
private function addVisitor($ip, $page, $userAgent)
|
||||
{
|
||||
if($this->cacheEnabled) {
|
||||
$this->data[$ip] = array('page' => $page, 'lastvisit' => time(), 'user_agent' => $userAgent);
|
||||
return;
|
||||
}
|
||||
|
||||
Visitor::create(['ip' => $ip, 'lastvisit' => time(), 'page' => $page, 'user_agent' => $userAgent]);
|
||||
}
|
||||
|
||||
public function getVisitors()
|
||||
{
|
||||
if($this->cacheEnabled) {
|
||||
foreach($this->data as $ip => &$details)
|
||||
$details['ip'] = $ip;
|
||||
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
return Visitor::orderByDesc('lastvisit')->get()->toArray();
|
||||
}
|
||||
|
||||
public function getAmountVisitors()
|
||||
{
|
||||
if($this->cacheEnabled) {
|
||||
return count($this->data);
|
||||
}
|
||||
|
||||
return Visitor::count();
|
||||
}
|
||||
|
||||
public function show() {
|
||||
echo $this->getAmountVisitors();
|
||||
}
|
||||
}
|
||||
?>
|
87
system/src/Weapons.php
Normal file
87
system/src/Weapons.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
/**
|
||||
* Weapons class
|
||||
*
|
||||
* @package MyAAC
|
||||
* @author Gesior <jerzyskalski@wp.pl>
|
||||
* @author Slawkens <slawkens@gmail.com>
|
||||
* @copyright 2019 MyAAC
|
||||
* @link https://my-aac.org
|
||||
*/
|
||||
|
||||
namespace MyAAC;
|
||||
|
||||
use MyAAC\Models\Weapon;
|
||||
|
||||
defined('MYAAC') or die('Direct access not allowed!');
|
||||
|
||||
class Weapons {
|
||||
private static $error = '';
|
||||
|
||||
public static function loadFromXML($show = false)
|
||||
{
|
||||
global $config;
|
||||
|
||||
try {
|
||||
Weapon::query()->delete();
|
||||
} catch (\PDOException $error) {
|
||||
}
|
||||
|
||||
$file_path = $config['data_path'] . 'weapons/weapons.xml';
|
||||
if (!file_exists($file_path)) {
|
||||
self::$error = 'Cannot load file ' . $file_path;
|
||||
return false;
|
||||
}
|
||||
|
||||
$xml = new \DOMDocument;
|
||||
$xml->load($file_path);
|
||||
|
||||
foreach ($xml->getElementsByTagName('wand') as $weapon) {
|
||||
self::parseNode($weapon, $show);
|
||||
}
|
||||
foreach ($xml->getElementsByTagName('melee') as $weapon) {
|
||||
self::parseNode($weapon, $show);
|
||||
}
|
||||
foreach ($xml->getElementsByTagName('distance') as $weapon) {
|
||||
self::parseNode($weapon, $show);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function parseNode($node, $show = false) {
|
||||
global $config;
|
||||
|
||||
$id = (int)$node->getAttribute('id');
|
||||
$vocations_ids = array_flip($config['vocations']);
|
||||
$level = (int)$node->getAttribute('level');
|
||||
$maglevel = (int)$node->getAttribute('maglevel');
|
||||
|
||||
$vocations = array();
|
||||
foreach($node->getElementsByTagName('vocation') as $vocation) {
|
||||
$show = $vocation->getAttribute('showInDescription');
|
||||
if(!empty($vocation->getAttribute('id')))
|
||||
$voc_id = $vocation->getAttribute('id');
|
||||
else {
|
||||
$voc_id = $vocations_ids[$vocation->getAttribute('name')];
|
||||
}
|
||||
|
||||
$vocations[$voc_id] = strlen($show) == 0 || $show != '0';
|
||||
}
|
||||
|
||||
if(Weapon::find($id)) {
|
||||
if($show) {
|
||||
warning('Duplicated weapon with id: ' . $id);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Weapon::create([
|
||||
'id' => $id, 'level' => $level, 'maglevel' => $maglevel, 'vocations' => json_encode($vocations)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getError() {
|
||||
return self::$error;
|
||||
}
|
||||
}
|
103
system/src/global.php
Normal file
103
system/src/global.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
$i = 0;
|
||||
|
||||
define('HOOK_STARTUP', ++$i);
|
||||
define('HOOK_BEFORE_PAGE', ++$i);
|
||||
define('HOOK_AFTER_PAGE', ++$i);
|
||||
define('HOOK_FINISH', ++$i);
|
||||
define('HOOK_TIBIACOM_ARTICLE', ++$i);
|
||||
define('HOOK_TIBIACOM_BORDER_3', ++$i);
|
||||
define('HOOK_CHARACTERS_BEFORE_INFORMATIONS', ++$i);
|
||||
define('HOOK_CHARACTERS_AFTER_INFORMATIONS', ++$i);
|
||||
define('HOOK_CHARACTERS_BEFORE_SKILLS', ++$i);
|
||||
define('HOOK_CHARACTERS_AFTER_SKILLS', ++$i);
|
||||
define('HOOK_CHARACTERS_AFTER_QUESTS', ++$i);
|
||||
define('HOOK_CHARACTERS_AFTER_EQUIPMENT', ++$i);
|
||||
define('HOOK_CHARACTERS_BEFORE_DEATHS', ++$i);
|
||||
define('HOOK_CHARACTERS_BEFORE_SIGNATURE', ++$i);
|
||||
define('HOOK_CHARACTERS_AFTER_SIGNATURE', ++$i);
|
||||
define('HOOK_CHARACTERS_AFTER_ACCOUNT', ++$i);
|
||||
define('HOOK_CHARACTERS_AFTER_CHARACTERS', ++$i);
|
||||
define('HOOK_LOGIN', ++$i);
|
||||
define('HOOK_LOGIN_ATTEMPT', ++$i);
|
||||
define('HOOK_LOGOUT', ++$i);
|
||||
define('HOOK_ACCOUNT_CHANGE_PASSWORD_POST', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_BEFORE_FORM', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_BEFORE_BOXES', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_BETWEEN_BOXES_1', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_BETWEEN_BOXES_2', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_AFTER_BOXES', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_BEFORE_ACCOUNT', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_AFTER_ACCOUNT', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_AFTER_EMAIL', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_AFTER_COUNTRY', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_AFTER_PASSWORD', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_AFTER_PASSWORDS', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_BEFORE_CHARACTER_NAME', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_AFTER_CHARACTER_NAME', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_AFTER_SEX', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_AFTER_VOCATION', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_AFTER_TOWNS', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_BEFORE_SUBMIT_BUTTON', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_AFTER_FORM', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_POST', ++$i);
|
||||
define('HOOK_ACCOUNT_LOGIN_BEFORE_PAGE', ++$i);
|
||||
define('HOOK_ACCOUNT_LOGIN_BEFORE_ACCOUNT', ++$i);
|
||||
define('HOOK_ACCOUNT_LOGIN_AFTER_ACCOUNT', ++$i);
|
||||
define('HOOK_ACCOUNT_LOGIN_BEFORE_PASSWORD', ++$i);
|
||||
define('HOOK_ACCOUNT_LOGIN_AFTER_PASSWORD', ++$i);
|
||||
define('HOOK_ACCOUNT_LOGIN_AFTER_REMEMBER_ME', ++$i);
|
||||
define('HOOK_ACCOUNT_LOGIN_AFTER_PAGE', ++$i);
|
||||
define('HOOK_ACCOUNT_LOGIN_POST', ++$i);
|
||||
define('HOOK_ACCOUNT_CREATE_CHARACTER_AFTER', ++$i);
|
||||
define('HOOK_ADMIN_HEAD_END', ++$i);
|
||||
define('HOOK_ADMIN_HEAD_START', ++$i);
|
||||
define('HOOK_ADMIN_BODY_START', ++$i);
|
||||
define('HOOK_ADMIN_BODY_END', ++$i);
|
||||
define('HOOK_ADMIN_BEFORE_PAGE', ++$i);
|
||||
define('HOOK_ADMIN_MENU', ++$i);
|
||||
define('HOOK_ADMIN_LOGIN_AFTER_ACCOUNT', ++$i);
|
||||
define('HOOK_ADMIN_LOGIN_AFTER_PASSWORD', ++$i);
|
||||
define('HOOK_ADMIN_LOGIN_AFTER_SIGN_IN', ++$i);
|
||||
define('HOOK_ADMIN_ACCOUNTS_SAVE_POST', ++$i);
|
||||
define('HOOK_ADMIN_SETTINGS_BEFORE_SAVE', ++$i);
|
||||
define('HOOK_CRONJOB', ++$i);
|
||||
define('HOOK_EMAIL_CONFIRMED', ++$i);
|
||||
define('HOOK_GUILDS_BEFORE_GUILD_HEADER', ++$i);
|
||||
define('HOOK_GUILDS_AFTER_GUILD_HEADER', ++$i);
|
||||
define('HOOK_GUILDS_AFTER_GUILD_INFORMATION', ++$i);
|
||||
define('HOOK_GUILDS_AFTER_GUILD_MEMBERS', ++$i);
|
||||
define('HOOK_GUILDS_AFTER_INVITED_CHARACTERS', ++$i);
|
||||
define('HOOK_TWIG', ++$i);
|
||||
|
||||
const HOOK_FIRST = HOOK_STARTUP;
|
||||
define('HOOK_LAST', $i);
|
||||
|
||||
function is_sub_dir($path = NULL, $parent_folder = BASE): bool|string
|
||||
{
|
||||
//Get directory path minus last folder
|
||||
$dir = dirname($path);
|
||||
$folder = substr($path, strlen($dir));
|
||||
|
||||
//Check the base dir is valid
|
||||
$dir = realpath($dir);
|
||||
|
||||
//Only allow valid filename characters
|
||||
$folder = preg_replace('/[^a-z0-9\.\-_]/i', '', $folder);
|
||||
|
||||
//If this is a bad path or a bad end folder name
|
||||
if( !$dir OR !$folder OR $folder === '.') {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Rebuild path
|
||||
$path = $dir. '/' . $folder;
|
||||
|
||||
//If this path is higher than the parent folder
|
||||
if( strcasecmp($path, $parent_folder) > 0 ) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
Reference in New Issue
Block a user