From 273ca6d17f7c020cd240c21a69c0bb2aef597287 Mon Sep 17 00:00:00 2001 From: Jakiboy Date: Tue, 25 Jun 2024 15:14:43 +0100 Subject: [PATCH] Update --- composer.json | 2 +- src/README.md | 24 +-- src/VanillePluginOption.php | 95 ++++++++---- src/exc/CacheException.php | 23 --- src/inc/Cache.php | 4 +- src/inc/Crawler.php | 4 +- src/inc/Date.php | 2 +- src/inc/Encryption.php | 42 +++--- src/inc/File.php | 2 +- src/inc/Format.php | 232 ++++++++++++++++++++++++++++ src/inc/Hook.php | 154 +------------------ src/inc/Post.php | 32 +--- src/inc/Query.php | 15 -- src/inc/Request.php | 78 ++++------ src/inc/Server.php | 83 +++++++---- src/inc/Session.php | 7 +- src/inc/Stringify.php | 57 +++++-- src/inc/System.php | 4 +- src/inc/Table.php | 50 ++++++- src/inc/Tokenizer.php | 2 +- src/inc/TypeCheck.php | 54 +++---- src/inc/User.php | 33 +--- src/inc/Xml.php | 2 +- src/int/RequestInterface.php | 37 +++-- src/int/UpdaterInterface.php | 37 ++--- src/lib/API.php | 173 +++++++++++++-------- src/lib/Ajax.php | 20 ++- src/lib/Asset.php | 6 +- src/lib/Backup.php | 18 +-- src/lib/Cache.php | 282 ++++++++--------------------------- src/lib/Hook.php | 3 +- src/lib/Loader.php | 7 +- src/lib/Migrate.php | 14 -- src/lib/Mobile.php | 3 + src/lib/Model.php | 55 +++++-- src/lib/Orm.php | 6 +- src/lib/OrmQuery.php | 3 +- src/lib/Queue.php | 3 +- src/lib/Requirement.php | 2 +- src/lib/Rewrite.php | 12 +- src/lib/Shortcode.php | 44 +++++- src/lib/Updater.php | 101 ++++--------- src/tr/TraitCacheable.php | 4 +- src/tr/TraitFormattable.php | 46 ++++-- src/tr/TraitHookable.php | 4 +- src/tr/TraitIO.php | 2 +- src/tr/TraitRequestable.php | 31 ++-- src/tr/TraitSecurable.php | 21 +-- src/tr/TraitTranslatable.php | 4 +- 49 files changed, 976 insertions(+), 963 deletions(-) delete mode 100644 src/exc/CacheException.php create mode 100644 src/inc/Format.php diff --git a/composer.json b/composer.json index 55c86a8c..210fabcc 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name":"jakiboy/vanilleplugin", - "version":"1.0.6", + "version":"1.0.7", "type":"library", "description":"WordPress Plugin Framework", "keywords":[ diff --git a/src/README.md b/src/README.md index aae13124..b862d333 100644 --- a/src/README.md +++ b/src/README.md @@ -9,14 +9,6 @@ The "traits" folder (tr) contains VanillePlugin "librairies" traits. These classes **SHOULD NOT** include: - Exceptions (exc) -- Core (VanillePluginValidator) - -The "third-parties" folder (third) contains VanillePlugin third-party wrapper classes. - -These classes **SHOULD NOT** include: -- Exceptions (exc) -- Interfaces (int) -- librairies (lib) - Core (VanillePluginConfig, VanillePluginOption, VanillePluginValidator) The "interfaces" folder (int) contains VanillePlugin "librairies" interfaces. @@ -27,20 +19,13 @@ These classes **CAN ONLY** be used by: The "includes" folder (inc) contains VanillePlugin wrapper classes, Used to improve or change behavior of built-in PHP & WordPress functions. -These classes **SHOULD NOT** include: -- Exceptions (exc) -- Interfaces (int) -- librairies (lib) -- Third-parties (third) -- Traits (tr) -- Core (VanillePluginConfig, VanillePluginOption, VanillePluginValidator) +These classes **SHOULD NOT** include any of VanillePlugin parts The "exceptions" folder (exc) contains VanillePlugin core exceptions. -These classes **SHOULD NOT** include: -- Interfaces (int) +These classes **SHOULD NOT** include any of VanillePlugin parts +and **CAN ONLY** be used by: - librairies (lib) -- Third-parties (third) - Traits (tr) - Core (VanillePluginConfig, VanillePluginOption, VanillePluginValidator) @@ -51,7 +36,6 @@ The VanillePluginConfig **SHOULD NOT** include: - Includes (inc) - Interfaces (int) - librairies (lib) -- Third-parties (third) - Core (VanillePluginOption) The VanillePluginOption **SHOULD NOT** include: @@ -59,11 +43,9 @@ The VanillePluginOption **SHOULD NOT** include: - Includes (inc) - Interfaces (int) - librairies (lib) -- Third-parties (third) - Core (VanillePluginValidator) The VanillePluginValidator **SHOULD NOT** include: - Interfaces (int) - librairies (lib) -- Third-parties (third) - Core (VanillePluginConfig, VanillePluginOption) \ No newline at end of file diff --git a/src/VanillePluginOption.php b/src/VanillePluginOption.php index 8fe977db..5377e62c 100644 --- a/src/VanillePluginOption.php +++ b/src/VanillePluginOption.php @@ -66,10 +66,10 @@ protected function removePluginAction(string $hook, $callback, int $priority = 1 * @access protected * @inheritdoc */ - protected function doPluginAction(string $hook, $args = null) + protected function doPluginAction(string $hook, ...$args) { $hook = $this->applyNamespace($hook); - $this->doAction($hook, $args); + $this->doAction($hook, ...$args); } /** @@ -114,10 +114,10 @@ protected function removePluginFilter(string $hook, $callback, int $priority = 1 * @access protected * @inheritdoc */ - protected function applyPluginFilter(string $hook, $value, $args = null) + protected function applyPluginFilter(string $hook, $value, ...$args) { $hook = $this->applyNamespace($hook); - return $this->applyFilter($hook, $value, $args); + return $this->applyFilter($hook, $value, ...$args); } /** @@ -596,7 +596,7 @@ protected function createToken($action = null) : string { if ( $this->isType('string', $action) ) { if ( empty($action) ) { - $action = 'check'; + $action = 'verify'; } $action = $this->applyNamespace($action); } @@ -604,16 +604,16 @@ protected function createToken($action = null) : string } /** - * Check token. + * Verify token. * * @access protected * @inheritdoc */ - protected function checkToken($action = null, bool $strict = false) + protected function verifyToken($action = null, bool $strict = false) { if ( $this->isType('string', $action) ) { if ( empty($action) ) { - $action = 'check'; + $action = 'verify'; } $action = $this->applyNamespace($action); } @@ -635,16 +635,16 @@ protected function checkToken($action = null, bool $strict = false) } /** - * Check AJAX token. + * Verify AJAX token. * * @access protected * @inheritdoc */ - protected function checkAjaxToken($action = null, bool $strict = false) + protected function verifyAjaxToken($action = null, bool $strict = false) { if ( $this->isType('string', $action) ) { if ( empty($action) ) { - $action = 'check'; + $action = 'verify'; } $action = $this->applyNamespace($action); } @@ -666,12 +666,12 @@ protected function checkAjaxToken($action = null, bool $strict = false) } /** - * Check role permission. + * Verify role permission. * * @access protected * @inheritdoc */ - protected function checkPermission($id = null) + protected function verifyPermission($id = null) { if ( !$this->isAdministrator($id) ) { $code = ($this->hasDebug()) ? 401 : 200; @@ -748,16 +748,20 @@ protected function purgePluginTransients() : bool * [Filter: {plugin}-cache-key]. * [Filter: {plugin}-cache-lang]. * [Filter: {plugin}-cache-group]. + * [Filter: {plugin}-get-cache]. + * [Filter: {plugin}-cache-status]. * * @access protected * @inheritdoc */ - protected function getPluginCache($key, ?string $group = null) + protected function getPluginCache($key, ?bool &$status = null, ?string $group = null) { - $key = $this->applyNamespace($key); + $key = $this->lowercase( + $this->applyNamespace($key) + ); $key = $this->applyPluginFilter('cache-key', $key); - if ( $this->isMultilingual() ) { + if ( $this->hasMultilingual() ) { $key = "{$key}-{$this->getLang()}"; $key = $this->applyPluginFilter('cache-lang', $key); } @@ -767,7 +771,12 @@ protected function getPluginCache($key, ?string $group = null) $group = $this->applyPluginFilter('cache-group', $group); } - return $this->getCache($key, $group); + if ( $this->hasPluginFilter('get-cache') ) { + $status = $this->applyPluginFilter('cache-status', $status, $key); + return $this->applyPluginFilter('get-cache', $key, $group); + } + + return $this->getCache($key, $status, $group); } /** @@ -775,16 +784,19 @@ protected function getPluginCache($key, ?string $group = null) * [Filter: {plugin}-cache-key]. * [Filter: {plugin}-cache-lang]. * [Filter: {plugin}-cache-group]. + * [Filter: {plugin}-set-cache]. * * @access protected * @inheritdoc */ protected function setPluginCache($key, $value, ?int $ttl = null, ?string $group = null) : bool { - $key = $this->applyNamespace($key); + $key = $this->lowercase( + $this->applyNamespace($key) + ); $key = $this->applyPluginFilter('cache-key', $key); - if ( $this->isMultilingual() ) { + if ( $this->hasMultilingual() ) { $key = "{$key}-{$this->getLang()}"; $key = $this->applyPluginFilter('cache-lang', $key); } @@ -799,6 +811,10 @@ protected function setPluginCache($key, $value, ?int $ttl = null, ?string $group $ttl = $this->applyPluginFilter('cache-ttl', $ttl); } + if ( $this->hasPluginFilter('set-cache') ) { + return $this->applyPluginFilter('set-cache', $key, $value, $ttl, $group); + } + return $this->setCache($key, $value, $ttl, $group); } @@ -807,16 +823,19 @@ protected function setPluginCache($key, $value, ?int $ttl = null, ?string $group * [Filter: {plugin}-cache-key]. * [Filter: {plugin}-cache-lang]. * [Filter: {plugin}-cache-group]. + * [Filter: {plugin}-add-cache]. * * @access protected * @inheritdoc */ protected function addPluginCache($key, $value, ?int $ttl = null, ?string $group = null) : bool { - $key = $this->applyNamespace($key); + $key = $this->lowercase( + $this->applyNamespace($key) + ); $key = $this->applyPluginFilter('cache-key', $key); - if ( $this->isMultilingual() ) { + if ( $this->hasMultilingual() ) { $key = "{$key}-{$this->getLang()}"; $key = $this->applyPluginFilter('cache-lang', $key); } @@ -831,6 +850,10 @@ protected function addPluginCache($key, $value, ?int $ttl = null, ?string $group $ttl = $this->applyPluginFilter('cache-ttl', $ttl); } + if ( $this->hasPluginFilter('add-cache') ) { + return $this->applyPluginFilter('add-cache', $key, $value, $ttl, $group); + } + return $this->addCache($key, $value, $ttl, $group); } @@ -839,16 +862,19 @@ protected function addPluginCache($key, $value, ?int $ttl = null, ?string $group * [Filter: {plugin}-cache-key]. * [Filter: {plugin}-cache-lang]. * [Filter: {plugin}-cache-group]. + * [Filter: {plugin}-update-cache]. * * @access protected * @inheritdoc */ protected function updatePluginCache($key, $value, ?int $ttl = null, ?string $group = null) : bool { - $key = $this->applyNamespace($key); + $key = $this->lowercase( + $this->applyNamespace($key) + ); $key = $this->applyPluginFilter('cache-key', $key); - if ( $this->isMultilingual() ) { + if ( $this->hasMultilingual() ) { $key = "{$key}-{$this->getLang()}"; $key = $this->applyPluginFilter('cache-lang', $key); } @@ -863,7 +889,11 @@ protected function updatePluginCache($key, $value, ?int $ttl = null, ?string $gr $ttl = $this->applyPluginFilter('cache-ttl', $ttl); } - return $this->updateCache($key, $value, $ttl); + if ( $this->hasPluginFilter('update-cache') ) { + return $this->applyPluginFilter('update-cache', $key, $value, $ttl, $group); + } + + return $this->updateCache($key, $value, $ttl, $group); } /** @@ -871,16 +901,19 @@ protected function updatePluginCache($key, $value, ?int $ttl = null, ?string $gr * [Filter: {plugin}-cache-key]. * [Filter: {plugin}-cache-lang]. * [Filter: {plugin}-cache-group]. + * [Filter: {plugin}-delete-cache]. * * @access protected * @inheritdoc */ protected function deletePluginCache($key, ?string $group = null) : bool { - $key = $this->applyNamespace($key); + $key = $this->lowercase( + $this->applyNamespace($key) + ); $key = $this->applyPluginFilter('cache-key', $key); - if ( $this->isMultilingual() ) { + if ( $this->hasMultilingual() ) { $key = "{$key}-{$this->getLang()}"; $key = $this->applyPluginFilter('cache-lang', $key); } @@ -890,17 +923,25 @@ protected function deletePluginCache($key, ?string $group = null) : bool $group = $this->applyPluginFilter('cache-group', $group); } + if ( $this->hasPluginFilter('delete-cache') ) { + return $this->applyPluginFilter('delete-cache', $key, $group); + } + return $this->deleteCache($key, $group); } /** * Purge plugin cache. + * [Filter: {plugin}-purge-cache]. * * @access protected * @inheritdoc */ protected function purgePluginCache() : bool { + if ( $this->hasPluginFilter('purge-cache') ) { + return $this->applyPluginFilter('purge-cache', false); + } return $this->purgeCache(); } @@ -1078,7 +1119,7 @@ protected function setResponse($msg, $content = [], string $status = 'success', if ( $this->isType('array', $msg) && count($msg) == 2 ) { $temp = $msg[0]; $args = (array)$msg[1]; - $msg = $this->transVar($temp, $args); + $msg = $this->transVar($temp, $args); } else { $msg = $this->translate($msg); diff --git a/src/exc/CacheException.php b/src/exc/CacheException.php deleted file mode 100644 index eedc9b46..00000000 --- a/src/exc/CacheException.php +++ /dev/null @@ -1,23 +0,0 @@ - - * @link : https://jakiboy.github.io/VanillePlugin/ - * @license : MIT - * - * This file if a part of VanillePlugin Framework. - */ - -declare(strict_types=1); - -namespace VanillePlugin\exc; - -class CacheException extends VanillePluginException -{ - public static function undefinedCacheKey() - { - return 'Undefined cache key'; - } -} diff --git a/src/inc/Cache.php b/src/inc/Cache.php index b1c2a1e4..ec9a7c51 100644 --- a/src/inc/Cache.php +++ b/src/inc/Cache.php @@ -29,9 +29,9 @@ final class Cache * @param bool $found * @return mixed */ - public static function get($key, string $group = '', bool $force = false, ?bool &$found = null) + public static function get($key, string $group = '', bool $force = false, ?bool &$status = null) { - return wp_cache_get($key, $group, $force, $found); + return wp_cache_get($key, $group, $force, $status); } /** diff --git a/src/inc/Crawler.php b/src/inc/Crawler.php index ae4f2fce..07ce0439 100644 --- a/src/inc/Crawler.php +++ b/src/inc/Crawler.php @@ -25,7 +25,7 @@ final class Crawler * @var string METHOD * @var string PATTERN */ - private const METHOD = 'GET'; + private const METHOD = 'GET'; private const PATTERN = '*'; /** @@ -45,7 +45,7 @@ final class Crawler public function __construct(string $pattern = self::PATTERN, string $method = self::METHOD) { $this->pattern = $pattern; - $this->method = $method; + $this->method = $method; } /** diff --git a/src/inc/Date.php b/src/inc/Date.php index a34f99e5..39cd623f 100644 --- a/src/inc/Date.php +++ b/src/inc/Date.php @@ -206,7 +206,7 @@ public static function newTime($h = 0, $m = 0, $s = 0, $mt = 0, $d = 0, $y = 0) /** * Get date expiring interval using duration string, * Returns -1 if invalid date or duration. - * + * * @access public * @param string $duration * @param mixed $date diff --git a/src/inc/Encryption.php b/src/inc/Encryption.php index c53d5142..be8d9179 100644 --- a/src/inc/Encryption.php +++ b/src/inc/Encryption.php @@ -16,27 +16,31 @@ /** * Built-in encryption class, - * @uses JWT is recommended for external use. + * JWT is recommended for external use. */ class Encryption { + /** + * @access public + * @var string PREFIX Default encryption prefix + */ + public const PREFIX = '[vanillecrypt]'; + /** * @access private * @var string SECRET Default secret key (Passphrase) * @var string VECTOR Default initialzation vector * @var int LENGTH Default encryption vector length - * @var string PREFIX Default encryption prefix * @var string ALGO Default hash algorithm * @var int OPTIONS Default openssl options * @var string CIPHER Default openssl cipher algorithm */ - private const SECRET = 'v8t1pQ92PN'; - private const VECTOR = 'ZRfvSPsFQ'; - private const LENGTH = 16; - private const PREFIX = '[vanillecrypt]'; - private const ALGO = 'sha256'; + private const SECRET = 'v8t1pQ92PN'; + private const VECTOR = 'ZRfvSPsFQ'; + private const LENGTH = 16; + private const ALGO = 'sha256'; private const OPTIONS = 0; - private const CIPHER = 'AES-256-CBC'; + private const CIPHER = 'AES-256-CBC'; /** * @access private @@ -62,7 +66,7 @@ class Encryption /** * Init encryption (Encrypt / Decrypt). - * + * * @param mixed $data * @param string $key * @param string $vector @@ -102,7 +106,7 @@ public function setOptions(int $options = self::OPTIONS) : self /** * Set OpenSSL cipher algorithm. - * + * * @access public * @param string $options * @param object @@ -115,7 +119,7 @@ public function setCipher(string $cipher = self::CIPHER) : self /** * Set encryption prefix. - * + * * @access public * @param string $prefix * @param object @@ -130,7 +134,7 @@ public function setPrefix(string $prefix = self::PREFIX) : self /** * Initialize hash. - * + * * @access public * @param string $algo * @return object @@ -144,7 +148,7 @@ public function initialize(string $algo = self::ALGO) : self /** * Encrypt data. - * + * * @access public * @param int $loop, Base64 loop (Max 5) * @param string @@ -176,7 +180,7 @@ public function encrypt(int $loop = 1) : string /** * Decrypt data. - * + * * @access public * @param int $loop, Base64 loop (Max 5) * @param mixed @@ -207,9 +211,9 @@ public function decrypt(int $loop = 1) /** * Get decrypted data as string. - * + * * @access public - * @param object + * @return object */ public function asString() : self { @@ -219,9 +223,9 @@ public function asString() : self /** * Bypass encrypted string. - * + * * @access public - * @param object + * @return object */ public function bypass() : self { @@ -231,7 +235,7 @@ public function bypass() : self /** * Check whether data is crypted using prefix. - * + * * @access public * @param bool */ diff --git a/src/inc/File.php b/src/inc/File.php index 8cc45344..bda54b11 100644 --- a/src/inc/File.php +++ b/src/inc/File.php @@ -459,7 +459,7 @@ public static function clearDir(string $path) : bool } else { $dir = "{$path}/{$file}"; - foreach( @scandir($dir) as $file ) { + foreach ( @scandir($dir) as $file ) { if ( '.' === $file || '..' === $file ) { continue; } diff --git a/src/inc/Format.php b/src/inc/Format.php new file mode 100644 index 00000000..a62eabf4 --- /dev/null +++ b/src/inc/Format.php @@ -0,0 +1,232 @@ + + * @link : https://jakiboy.github.io/VanillePlugin/ + * @license : MIT + * + * This file if a part of VanillePlugin Framework. + */ + +declare(strict_types=1); + +namespace VanillePlugin\inc; + +final class Format +{ + /** + * Format hook. + * + * @access public + * @param string $hook + * @return string + */ + public static function hook(string $hook) : string + { + $name = Stringify::lowercase($hook); + + if ( Stringify::contains($name, 'wp-ajax-') ) { + $hook = Stringify::replace('wp-ajax-nopriv-', 'wp_ajax_nopriv_', $hook); + $hook = Stringify::replace('wp-ajax-', 'wp_ajax_', $hook); + return $hook; + } + + switch ( $name ) { + case 'loaded': + $hook = 'wp_loaded'; + break; + case 'head': + $hook = 'wp_head'; + break; + case 'body': + $hook = 'wp_body_open'; + break; + case 'content': + $hook = 'the_content'; + break; + case 'footer': + $hook = 'wp_footer'; + break; + case 'enqueue-scripts': + $hook = 'wp_enqueue_scripts'; + break; + case 'body-class': + $hook = 'body_class'; + break; + case 'user-register': + $hook = 'user_register'; + break; + case 'user-auth': + $hook = 'wp_authenticate_user'; + break; + case 'login-enqueue-scripts': + $hook = 'login_enqueue_scripts'; + break; + case 'login-body-class': + $hook = 'login_body_class'; + break; + case 'login-header-url': + $hook = 'login_headerurl'; + break; + case 'login-header-text': + $hook = 'login_headertext'; + break; + case 'login-form': + $hook = 'login_form'; + break; + case 'login-form-defaults': + $hook = 'login_form_defaults'; + break; + case 'amp-css': + $hook = 'amp_post_template_css'; + break; + case 'amp-head': + $hook = 'amp_post_template_head'; + break; + case 'amp-footer': + $hook = 'amp_post_template_footer'; + break; + case 'plugins-loaded': + $hook = 'plugins_loaded'; + break; + case 'plugin-row': + $hook = 'plugin_row_meta'; + break; + case 'admin-init': + $hook = 'admin_init'; + break; + case 'admin-menu': + $hook = 'admin_menu'; + break; + case 'admin-bar-menu': + $hook = 'admin_bar_menu'; + break; + case 'show-admin-bar': + $hook = 'show_admin_bar'; + break; + case 'admin-enqueue-scripts': + $hook = 'admin_enqueue_scripts'; + break; + case 'admin-body-class': + $hook = 'admin_body_class'; + break; + case 'admin-footer-text': + $hook = 'admin_footer_text'; + break; + case 'admin-notices': + $hook = 'admin_notices'; + break; + case 'mail': + $hook = 'wp_mail'; + break; + case 'mail-from': + $hook = 'wp_mail_from'; + break; + case 'mail-name': + $hook = 'wp_mail_from_name'; + break; + case 'update-footer': + $hook = 'update_footer'; + break; + case 'save-post': + $hook = 'save_post'; + break; + case 'insert-post-data': + $hook = 'wp_insert_post_data'; + break; + case 'post-status': + $hook = 'transition_post_status'; + break; + case 'media-button': + $hook = 'media_buttons'; + break; + case 'template-redirect': + $hook = 'template_redirect'; + break; + case 'dashboard-setup': + $hook = 'wp_dashboard_setup'; + break; + case 'rest-api': + $hook = 'rest_api_init'; + break; + case 'http-request-args': + $hook = 'http_request_args'; + break; + case 'cron-schedules': + $hook = 'cron_schedules'; + break; + case 'upgrader-process-complete': + $hook = 'upgrader_process_complete'; + break; + case 'auto-update-plugin': + $hook = 'auto_update_plugin'; + break; + case 'plugins-api': + $hook = 'plugins_api'; + break; + case 'pre-transient-update-plugins': + $hook = 'pre_set_site_transient_update_plugins'; + break; + case 'pre-transient-update-themes': + $hook = 'pre_set_site_transient_update_themes'; + break; + case 'rewrite-rules': + $hook = 'mod_rewrite_rules'; + break; + } + return $hook; + } + + /** + * Get post formatted data. + * + * @access public + * @param mixed $post + * @return mixed + */ + public static function post($post) + { + if ( $post ) { + return [ + 'id' => $post->ID, + 'slug' => $post->post_name, + 'title' => $post->post_title, + 'content' => $post->post_content, + 'link' => $post->guid, + 'type' => Stringify::lowercase($post->post_type), + 'status' => $post->post_status, + 'author' => $post->post_author, + 'date' => $post->post_date, + 'edited' => $post->post_modified + ]; + } + return $post; + } + + /** + * Get user formatted data. + * + * @access public + * @param mixed $user + * @return mixed + */ + public static function user($user) + { + if ( TypeCheck::isObject($user) ) { + $name = $user->data->display_name; + if ( empty($name) ) { + $name = $user->data->user_nicename; + } + return [ + 'id' => $user->data->ID, + 'login' => $user->data->user_login, + 'name' => $name, + 'email' => $user->data->user_email, + 'hash' => $user->data->user_pass + ]; + } + return $user; + } +} diff --git a/src/inc/Hook.php b/src/inc/Hook.php index 80ec12b3..217010ed 100644 --- a/src/inc/Hook.php +++ b/src/inc/Hook.php @@ -87,7 +87,7 @@ public static function action(string $file, $callback) */ public static function addAction(string $hook, $callback, int $priority = 10, int $args = 1) { - add_action(self::format($hook), $callback, $priority, $args); + add_action(Format::hook($hook), $callback, $priority, $args); } /** @@ -101,7 +101,7 @@ public static function addAction(string $hook, $callback, int $priority = 10, in */ public static function removeAction(string $hook, $callback, int $priority = 10) : bool { - return remove_action(self::format($hook), $callback, $priority); + return remove_action(Format::hook($hook), $callback, $priority); } /** @@ -112,9 +112,9 @@ public static function removeAction(string $hook, $callback, int $priority = 10) * @param mixed $args * @return void */ - public static function doAction(string $hook, $args = null) + public static function doAction(string $hook, ...$args) { - do_action($hook, $args); + do_action($hook, ...$args); } /** @@ -142,7 +142,7 @@ public static function hasAction(string $hook, $callback = false) */ public static function addFilter(string $hook, $callback, int $priority = 10, int $args = 1) { - add_filter(self::format($hook), $callback, $priority, $args); + add_filter(Format::hook($hook), $callback, $priority, $args); } /** @@ -168,9 +168,9 @@ public static function removeFilter(string $hook, $callback, int $priority = 10) * @param mixed $args * @return mixed */ - public static function applyFilter(string $hook, $value, $args = null) + public static function applyFilter(string $hook, $value, ...$args) { - return apply_filters($hook, $value, $args); + return apply_filters($hook, $value, ...$args); } /** @@ -334,144 +334,4 @@ public static function removeScripts(array $exclude) } } } - - /** - * Format hook. - * - * @access private - * @param string $hook - * @return string - */ - private static function format(string $hook) : string - { - switch ( Stringify::lowercase($hook) ) { - case 'loaded': - $hook = 'wp_loaded'; - break; - case 'head': - $hook = 'wp_head'; - break; - case 'body': - $hook = 'wp_body_open'; - break; - case 'content': - $hook = 'the_content'; - break; - case 'footer': - $hook = 'wp_footer'; - break; - case 'enqueue-scripts': - $hook = 'wp_enqueue_scripts'; - break; - case 'body-class': - $hook = 'body_class'; - break; - case 'user-register': - $hook = 'user_register'; - break; - case 'user-auth': - $hook = 'wp_authenticate_user'; - break; - case 'login-enqueue-scripts': - $hook = 'login_enqueue_scripts'; - break; - case 'login-body-class': - $hook = 'login_body_class'; - break; - case 'login-header-url': - $hook = 'login_headerurl'; - break; - case 'login-header-text': - $hook = 'login_headertext'; - break; - case 'login-form': - $hook = 'login_form'; - break; - case 'login-form-defaults': - $hook = 'login_form_defaults'; - break; - case 'amp-css': - $hook = 'amp_post_template_css'; - break; - case 'amp-head': - $hook = 'amp_post_template_head'; - break; - case 'amp-footer': - $hook = 'amp_post_template_footer'; - break; - case 'plugins-loaded': - $hook = 'plugins_loaded'; - break; - case 'plugin-row': - $hook = 'plugin_row_meta'; - break; - case 'admin-init': - $hook = 'admin_init'; - break; - case 'admin-menu': - $hook = 'admin_menu'; - break; - case 'admin-bar-menu': - $hook = 'admin_bar_menu'; - break; - case 'show-admin-bar': - $hook = 'show_admin_bar'; - break; - case 'admin-enqueue-scripts': - $hook = 'admin_enqueue_scripts'; - break; - case 'admin-body-class': - $hook = 'admin_body_class'; - break; - case 'admin-footer-text': - $hook = 'admin_footer_text'; - break; - case 'admin-notices': - $hook = 'admin_notices'; - break; - case 'mail': - $hook = 'wp_mail'; - break; - case 'mail-from': - $hook = 'wp_mail_from'; - break; - case 'mail-name': - $hook = 'wp_mail_from_name'; - break; - case 'update-footer': - $hook = 'update_footer'; - break; - case 'upgrader-process-complete': - $hook = 'upgrader_process_complete'; - break; - case 'save-post': - $hook = 'save_post'; - break; - case 'insert-post-data': - $hook = 'wp_insert_post_data'; - break; - case 'media-button': - $hook = 'media_buttons'; - break; - case 'auto-update-plugin': - $hook = 'auto_update_plugin'; - break; - case 'template-redirect': - $hook = 'template_redirect'; - break; - case 'dashboard-setup': - $hook = 'wp_dashboard_setup'; - break; - case 'rest-api': - $hook = 'rest_api_init'; - break; - case 'post-status': - $hook = 'transition_post_status'; - break; - case 'cron-schedules': - $hook = 'cron_schedules'; - break; - } - return $hook; - } } diff --git a/src/inc/Post.php b/src/inc/Post.php index 00b0ea9d..5379a192 100644 --- a/src/inc/Post.php +++ b/src/inc/Post.php @@ -55,7 +55,7 @@ public static function current(bool $format = true) { global $post; if ( $format ) { - return self::format($post); + return Format::post($post); } return $post; } @@ -73,7 +73,7 @@ public static function getById($id = null, bool $format = true) if ( !$id ) $id = self::getId(); $post = get_post($id); if ( $format ) { - return self::format($post); + return Format::post($post); } return $post; } @@ -284,35 +284,9 @@ public static function all(array $args = [], bool $format = true) : array $posts = get_posts($args); if ( $format ) { $posts = Arrayify::map(function($post) { - return self::format($post); + return Format::post($post); }, $posts); } return $posts; } - - /** - * Get post formatted data. - * - * @access private - * @param mixed $post - * @return mixed - */ - private static function format($post) - { - if ( $post ) { - return [ - 'id' => $post->ID, - 'slug' => $post->post_name, - 'title' => $post->post_title, - 'content' => $post->post_content, - 'link' => $post->guid, - 'type' => $post->post_type, - 'status' => $post->post_status, - 'author' => $post->post_author, - 'date' => $post->post_date, - 'edited' => $post->post_modified - ]; - } - return $post; - } } diff --git a/src/inc/Query.php b/src/inc/Query.php index de604971..40e5b741 100644 --- a/src/inc/Query.php +++ b/src/inc/Query.php @@ -80,19 +80,4 @@ public static function getTitle() { return get_the_title(); } - - /** - * Get query formatted args. - * - * @access private - * @param mixed $args - * @return mixed - */ - private static function format($args) - { - if ( $args ) { - return []; - } - return $args; - } } diff --git a/src/inc/Request.php b/src/inc/Request.php index 182710c0..03b0e501 100644 --- a/src/inc/Request.php +++ b/src/inc/Request.php @@ -21,6 +21,7 @@ class Request implements RequestInterface /** * @access private * @var string $baseUrl, Request base URL + * @var string $endpoint, Request endpoint * @var string $method, Request method * @var array $headers, Request headers * @var array $cookies, Request cookies @@ -29,6 +30,7 @@ class Request implements RequestInterface * @var mixed $response, Raw response */ protected $baseUrl; + protected $endpoint; protected $method = 'GET'; protected $headers = []; protected $cookies = []; @@ -41,13 +43,12 @@ class Request implements RequestInterface */ public function __construct(string $method = 'GET', array $args = [], ?string $baseUrl = null) { - $this->method = $method; - $this->args = $args; + $this->method = $method; + $this->args = $args; $this->baseUrl = $baseUrl; } /** - * @access public * @inheritdoc */ public function setMethod(string $method) : self @@ -57,7 +58,6 @@ public function setMethod(string $method) : self } /** - * @access public * @inheritdoc */ public function setBaseUrl(string $url) : self @@ -67,7 +67,6 @@ public function setBaseUrl(string $url) : self } /** - * @access public * @inheritdoc */ public function setArgs(array $args = []) : self @@ -77,7 +76,6 @@ public function setArgs(array $args = []) : self } /** - * @access public * @inheritdoc */ public function addArg(string $arg, $value = null) @@ -86,7 +84,6 @@ public function addArg(string $arg, $value = null) } /** - * @access public * @inheritdoc */ public function setHeaders(array $headers = []) : self @@ -96,7 +93,6 @@ public function setHeaders(array $headers = []) : self } /** - * @access public * @inheritdoc */ public function addHeader(string $header, $value = null) @@ -105,7 +101,6 @@ public function addHeader(string $header, $value = null) } /** - * @access public * @inheritdoc */ public function setCookies(array $cookies = []) : self @@ -115,7 +110,6 @@ public function setCookies(array $cookies = []) : self } /** - * @access public * @inheritdoc */ public function addCookie(string $cookie, $value = null) @@ -124,7 +118,6 @@ public function addCookie(string $cookie, $value = null) } /** - * @access public * @inheritdoc */ public function setBody(array $body = []) : self @@ -134,7 +127,6 @@ public function setBody(array $body = []) : self } /** - * @access public * @inheritdoc */ public function addBody(string $body, $value = null) @@ -143,28 +135,27 @@ public function addBody(string $body, $value = null) } /** - * @access public * @inheritdoc */ public function send(?string $url = null) : self { - $args = Arrayify::merge([ + $this->args = Arrayify::merge([ 'method' => $this->method, 'headers' => $this->headers, 'body' => $this->body, 'cookies' => $this->cookies ], $this->args); + $this->endpoint = "{$this->baseUrl}{$url}"; $this->response = wp_remote_request( - "{$this->baseUrl}{$url}", - $args + $this->endpoint, + $this->args ); return $this; } /** - * @access public * @inheritdoc */ public function get(string $url, array $args = []) : self @@ -174,7 +165,6 @@ public function get(string $url, array $args = []) : self } /** - * @access public * @inheritdoc */ public function post(string $url, array $args = []) : self @@ -184,7 +174,6 @@ public function post(string $url, array $args = []) : self } /** - * @access public * @inheritdoc */ public function head(string $url, array $args = []) : self @@ -194,52 +183,36 @@ public function head(string $url, array $args = []) : self } /** - * @access public * @inheritdoc */ public function put(string $url, array $args = []) : self { - if ( isset($args['method']) ) { - unset($args['method']); - $args['method'] = 'PUT'; - } - + $args['method'] = 'PUT'; $this->response = wp_remote_request($url, $args); return $this; } /** - * @access public * @inheritdoc */ public function patch(string $url, array $args = []) : self { - if ( isset($args['method']) ) { - unset($args['method']); - $args['method'] = 'PATCH'; - } - + $args['method'] = 'PATCH'; $this->response = wp_remote_request($url, $args); return $this; } /** - * @access public * @inheritdoc */ public function delete(string $url, array $args = []) : self { - if ( isset($args['method']) ) { - unset($args['method']); - $args['method'] = 'DELETE'; - } - + $args['method'] = 'DELETE'; $this->response = wp_remote_request($url, $args); return $this; } /** - * @access public * @inheritdoc */ public function getStatusCode() : int @@ -250,7 +223,6 @@ public function getStatusCode() : int } /** - * @access public * @inheritdoc */ public function getBody() : string @@ -261,7 +233,6 @@ public function getBody() : string } /** - * @access public * @inheritdoc */ public function getHeader(string $header) : string @@ -273,7 +244,6 @@ public function getHeader(string $header) : string } /** - * @access public * @inheritdoc */ public function getHeaders() @@ -284,7 +254,6 @@ public function getHeaders() } /** - * @access public * @inheritdoc */ public function getMessage() : string @@ -295,7 +264,6 @@ public function getMessage() : string } /** - * @access public * @inheritdoc */ public function hasError() : bool @@ -307,7 +275,6 @@ public function hasError() : bool } /** - * @access public * @inheritdoc */ public function getError() @@ -316,20 +283,31 @@ public function getError() } /** - * @access public * @inheritdoc */ - public static function addQueryArg($arg, string $url) : string + public function getReport() : array { - return add_query_arg($arg, $url); + return [ + 'request' => [ + 'url' => $this->baseUrl, + 'endpoint' => $this->endpoint, + 'method' => $this->method, + 'headers' => $this->headers, + 'body' => $this->body + ], + 'response' => [ + 'code' => $this->getStatusCode(), + 'message' => $this->getMessage(), + 'error' => $this->getError() + ] + ]; } /** - * @access public * @inheritdoc */ - public static function buildQuery(array $args) : string + public static function addQueryArg($arg, string $url) : string { - return Stringify::buildQuery($args); + return add_query_arg($arg, $url); } } diff --git a/src/inc/Server.php b/src/inc/Server.php index 9c054cc7..206c4a31 100644 --- a/src/inc/Server.php +++ b/src/inc/Server.php @@ -18,7 +18,7 @@ final class Server { /** * Get _SERVER value. - * + * * @access public * @param string $key * @param bool $format @@ -27,9 +27,7 @@ final class Server public static function get(?string $key = null, $format = true) { if ( $key ) { - if ( $format ) { - $key = Stringify::undash($key, true); - } + if ( $format ) $key = Stringify::undash($key, true); return self::isSetted($key) ? $_SERVER[$key] : null; } return self::isSetted() ? $_SERVER : null; @@ -37,7 +35,7 @@ public static function get(?string $key = null, $format = true) /** * Set _SERVER value. - * + * * @access public * @param string $key * @param mixed $value @@ -46,15 +44,13 @@ public static function get(?string $key = null, $format = true) */ public static function set(string $key, $value = null, $format = true) { - if ( $format ) { - $value = Stringify::undash($key, true); - } + if ( $format ) $value = Stringify::undash($key, true); $_SERVER[$key] = $value; } /** * Check _SERVER value. - * + * * @access public * @param string $key * @param bool $format @@ -63,9 +59,7 @@ public static function set(string $key, $value = null, $format = true) public static function isSetted(?string $key = null, $format = true) : bool { if ( $key ) { - if ( $format ) { - $key = Stringify::undash($key, true); - } + if ( $format ) $key = Stringify::undash($key, true); return isset($_SERVER[$key]); } return isset($_SERVER) && !empty($_SERVER); @@ -73,7 +67,7 @@ public static function isSetted(?string $key = null, $format = true) : bool /** * Unset _SERVER value. - * + * * @access public * @param string $key * @return void @@ -136,7 +130,7 @@ public static function getIp(?string $domain = null) */ public static function getProtocol() { - return self::isSsl() ? 'https://' : 'http://'; + return (self::isSsl()) ? 'https://' : 'http://'; } /** @@ -153,16 +147,17 @@ public static function getCountryCode() 'http-cf-ipcountry', 'http-x-country-code' ]; + foreach ($headers as $header) { if ( self::isSetted($header) ) { $code = self::get($header); if ( !empty($code) ) { $code = Stringify::stripSlash($code); return Stringify::uppercase($code); - break; } } } + return false; } @@ -189,10 +184,8 @@ public static function redirect(string $location, int $status = 301) public static function getBaseUrl() : string { $url = self::get('http-host'); - if ( self::isSsl() ) { - return "https://{$url}"; - } - return "http://{$url}"; + $schema = (self::isSsl()) ? 'https://' : 'http://'; + return "{$schema}}{$url}"; } /** @@ -222,9 +215,13 @@ public static function getCurrentUrl($escape = false) : string * @param string $url * @return string */ - public static function parseBaseUrl($url = '') + public static function parseBaseUrl(string $url) : string { - if ( !empty($url) && ($url = Stringify::parseUrl($url)) ) { + if ( empty($url) ) { + return $url; + } + + if ( ($url = Stringify::parseUrl($url)) ) { unset($url['path']); $tmp = ''; if ( isset($url['scheme']) ) { @@ -235,12 +232,13 @@ public static function parseBaseUrl($url = '') } $url = $tmp; } - return (string)$url; + + return $url; } /** * Check external server status code. - * + * * @access public * @param string $url * @param array $args @@ -332,6 +330,7 @@ public static function isDown(string $url, $args = []) return true; } } + } else { if ( $request->getBody() !== $args['response'] ) { return true; @@ -350,10 +349,7 @@ public static function isDown(string $url, $args = []) */ public static function isBasicAuth() : bool { - if ( self::isSetted('php-auth-user') && self::isSetted('php-auth-pw') ) { - return true; - } - return false; + return (self::getBasicAuthUser() && self::getBasicAuthPwd()); } /** @@ -364,7 +360,7 @@ public static function isBasicAuth() : bool */ public static function getBasicAuthUser() : string { - return self::isSetted('php-auth-user') ? self::get('php-auth-user') : ''; + return self::get('php-auth-user') ?: ''; } /** @@ -375,7 +371,7 @@ public static function getBasicAuthUser() : string */ public static function getBasicAuthPwd() : string { - return self::isSetted('php-auth-pw') ? self::get('php-auth-pw') : ''; + return self::get('php-auth-pw') ?: ''; } /** @@ -432,8 +428,7 @@ public static function isSsl() : bool } /** - * Check if SSL verify is required in request, - * Maybe remote server requires (SNI), + * Check if SSL verify is required in request. * Fix (SNI) SSL verification. * * @access public @@ -444,11 +439,37 @@ public static function maybeRequireSSL(array $args) : array { $hasCurl = TypeCheck::isFunction('curl_init'); if ( isset($args['sslverify']) && !$args['sslverify'] ) { + // Force sslverify when cUrl not used if ( !$hasCurl ) { $args['sslverify'] = true; } + } return $args; } + + /** + * Get domain name from URL. + * + * @access public + * @param string $url + * @return string + */ + public static function getDomain(?string $url = null) : string + { + if ( !$url ) { + $url = self::getCurrentUrl(true); + } + + $pieces = Stringify::parseUrl($url); + $domain = isset($pieces['host']) ? $pieces['host'] : $pieces['path']; + $pattern = '/(?P[a-z0-9][a-z0-9\\-]{1,63}\\.[a-z\\.]{2,6})$/i'; + + if ( ($domain = Stringify::match($pattern, $domain)) ) { + return $domain; + } + + return $url; + } } diff --git a/src/inc/Session.php b/src/inc/Session.php index 23726121..c31ac372 100644 --- a/src/inc/Session.php +++ b/src/inc/Session.php @@ -43,7 +43,9 @@ public static function register(int $time = 60) { self::set('--session-id', session_id()); self::set('--session-time', intval($time)); - self::set('--session-start', Date::newTime(0, 0, self::get('--session-time'))); + + $time = self::get('--session-time'); + self::set('--session-start', Date::newTime(0, 0, $time)); } /** @@ -139,7 +141,8 @@ public static function isExpired() : bool */ public static function renew() { - self::set('--session-start', Date::newTime(0, 0, self::get('--session-time'))); + $time = self::get('--session-time'); + self::set('--session-start', Date::newTime(0, 0, $time)); } /** diff --git a/src/inc/Stringify.php b/src/inc/Stringify.php index c4308d88..714ae32f 100644 --- a/src/inc/Stringify.php +++ b/src/inc/Stringify.php @@ -14,8 +14,6 @@ namespace VanillePlugin\inc; -use PHPUnit\Util\Type; - /** * Advanced custom I/O helper and string manipulation, * @see https://wordpress.org/about/security/. @@ -643,7 +641,7 @@ public static function sanitizeTitle(string $string, ?string $fallback = null, s /** * Sanitize key, * [Filter: sanitize_key]. - * + * * @access public * @param string $string * @return string @@ -656,7 +654,7 @@ public static function sanitizeKey(string $string) /** * Sanitize email, * [Filter: sanitize_email]. - * + * * @access public * @param string $string * @return string @@ -668,7 +666,7 @@ public static function sanitizeEmail(string $string) : string /** * Sanitize hex color (with #). - * + * * @access public * @param string $string * @return string @@ -681,7 +679,7 @@ public static function sanitizeColor(string $string) : string /** * Sanitize HTML class, * [Filter: sanitize_html_class]. - * + * * @access public * @param string $string * @param string $fallback @@ -697,7 +695,7 @@ public static function sanitizeHtmlClass(string $string, ?string $fallback = nul * Replacing whitespace with dashes, * [Filter: sanitize_file_name], * [Filter: sanitize_file_name_chars]. - * + * * @access public * @param string $string * @return string @@ -710,7 +708,7 @@ public static function sanitizeFilename(string $string) : string /** * Sanitize mime type, * [Filter: sanitize_mime_type]. - * + * * @access public * @param string $string * @return string @@ -722,7 +720,7 @@ public static function sanitizeMimeType(string $string) : string /** * Sanitize SQL 'order by' clause. - * + * * @access public * @param string $string * @return string @@ -986,10 +984,10 @@ public static function parseUrl(string $url, int $component = -1) /** * Build query args from string (URL toolkit). - * + * * [PHP_QUERY_RFC1738: 1] * [PHP_QUERY_RFC3986: 2] - * + * * @access public * @param mixed $args * @param string $prefix, Numeric index for args (array) @@ -1094,4 +1092,41 @@ public static function break() : string { return PHP_EOL; } + + /** + * Generate key from args. + * + * @access public + * @param string $item + * @param array $args + * @return string + */ + public static function generateKey(string $item, array $args = []) : string + { + $key = $item; + + foreach ($args as $name => $value) { + + if ( TypeCheck::isNull($value) || TypeCheck::isEmpty($value) ) { + continue; + } + + if ( $value === 0 ) { + $value = '0'; + + } elseif ( TypeCheck::isFalse($value) ) { + $value = 'false'; + + } elseif ( TypeCheck::isTrue($value) ) { + $value = 'true'; + + } elseif ( TypeCheck::isArray($value) ) { + $value = implode('-', $value); + } + + $key .= "-{$name}-{$value}"; + } + + return self::slugify($key); + } } diff --git a/src/inc/System.php b/src/inc/System.php index 1bb4f7eb..fdfdaa4e 100644 --- a/src/inc/System.php +++ b/src/inc/System.php @@ -291,8 +291,8 @@ public static function getCpuUsage() : array if ( self::getOsName() == 'windows' ) { if ( TypeCheck::isClass('COM') ) { $system = new \COM('WinMgmts:\\\\.'); - $cpu = $system->InstancesOf('Win32_Processor'); - $load = 0; + $cpu = $system->InstancesOf('Win32_Processor'); + $load = 0; $count = 0; foreach ($cpu as $key => $core) { $load += $core->LoadPercentage; diff --git a/src/inc/Table.php b/src/inc/Table.php index adcdf4b5..86c99d9e 100644 --- a/src/inc/Table.php +++ b/src/inc/Table.php @@ -14,7 +14,7 @@ namespace VanillePlugin\inc; -if ( !TypeCheck::isFunction('WP_List_Table') ) { +if ( !TypeCheck::isFunction('\WP_List_Table') ) { require_once Globals::rootDir('wp-admin/includes/class-wp-list-table.php'); } @@ -144,6 +144,14 @@ public function get_columns() : array return $this->columns; } + /** + * @inheritdoc + */ + public function getColumns() : array + { + return $this->get_columns(); + } + /** * @inheritdoc */ @@ -158,6 +166,14 @@ public function get_sortable_columns() : array return $this->sortable; } + /** + * @inheritdoc + */ + public function getSortableColumns() : array + { + return $this->get_sortable_columns(); + } + /** * @inheritdoc */ @@ -166,6 +182,14 @@ public function get_hidden_columns() : array return $this->hidden; } + /** + * @inheritdoc + */ + public function getHiddenColumns() : array + { + return $this->get_hidden_columns(); + } + /** * @inheritdoc */ @@ -174,6 +198,14 @@ public function column_default($item, $name) return $item[$name]; } + /** + * @inheritdoc + */ + public function columnDefault($item, $name) + { + return $this->column_default($item, $name); + } + /** * @inheritdoc */ @@ -183,8 +215,9 @@ public function prepare_items() if ( $this->pagination == true ) { $current = $this->get_pagenum(); - $total = count($this->data); - $this->data = array_slice($this->data, (($current - 1) * $this->limit), $this->limit); + $total = count($this->data); + $offset = (($current - 1) * $this->limit); + $this->data = Arrayify::slice($this->data, $offset, $this->limit); $this->set_pagination_args([ 'total_items' => $total, @@ -204,6 +237,14 @@ public function prepare_items() $this->items = $this->data; } + /** + * @inheritdoc + */ + public function prepareItems() + { + $this->prepare_items(); + } + /** * Open form output. * @@ -213,9 +254,10 @@ public function prepare_items() protected function openForm() { $type = ($this->type) ? $this->type : 'data'; + $page = HttpRequest::get('page'); $output = '
'; $output .= '
'; - $output .= ''; + $output .= ''; echo $output; } diff --git a/src/inc/Tokenizer.php b/src/inc/Tokenizer.php index 6a9455a2..3221b30a 100644 --- a/src/inc/Tokenizer.php +++ b/src/inc/Tokenizer.php @@ -16,7 +16,7 @@ /** * Built-in tokenizer class, - * @see JWT for external use is recommended. + * JWT for external use is recommended. */ class Tokenizer { diff --git a/src/inc/TypeCheck.php b/src/inc/TypeCheck.php index 6b5df224..df71231a 100644 --- a/src/inc/TypeCheck.php +++ b/src/inc/TypeCheck.php @@ -18,7 +18,7 @@ final class TypeCheck { /** * Check string. - * + * * @access public * @param mixed $value * @return bool @@ -30,14 +30,14 @@ public static function isString($value) : bool /** * Check object. - * + * * @access public * @param mixed $value * @param string $class * @param bool $string, Allow string * @return bool */ - public static function isObject($value, $class = null, bool $string = false) : bool + public static function isObject($value, ?string $class = null, bool $string = false) : bool { if ( $class ) { return is_a($value, $class, $string); @@ -47,7 +47,7 @@ public static function isObject($value, $class = null, bool $string = false) : b /** * Check array. - * + * * @access public * @param mixed $value * @return bool @@ -59,7 +59,7 @@ public static function isArray($value) : bool /** * Check iterator. - * + * * @access public * @param mixed $value * @return bool @@ -71,7 +71,7 @@ public static function isIterator($value) : bool /** * Check int. - * + * * @access public * @param mixed $value * @return bool @@ -83,7 +83,7 @@ public static function isInt($value) : bool /** * Check numeric (string cast). - * + * * @access public * @param mixed $value * @return bool @@ -95,7 +95,7 @@ public static function isNumeric($value) : bool /** * Check float. - * + * * @access public * @param mixed $value * @param bool $string @@ -111,7 +111,7 @@ public static function isFloat($value, bool $string = false) : bool /** * Check bool. - * + * * @access public * @param mixed $value * @return bool @@ -123,7 +123,7 @@ public static function isBool($value) : bool /** * Check null. - * + * * @access public * @param mixed $value * @return bool @@ -135,7 +135,7 @@ public static function isNull($value) : bool /** * Check false. - * + * * @access public * @param mixed $value * @return bool @@ -147,7 +147,7 @@ public static function isFalse($value) : bool /** * Check true. - * + * * @access public * @param mixed $value * @return bool @@ -159,7 +159,7 @@ public static function isTrue($value) : bool /** * Check empty (string or array). - * + * * @access public * @param mixed $value * @return bool @@ -177,7 +177,7 @@ public static function isEmpty($value) : bool /** * Check NAN (Not a number). - * + * * @access public * @param mixed $value * @return bool @@ -189,7 +189,7 @@ public static function isNan($value) : bool /** * Check callable. - * + * * @access public * @param mixed $value * @return bool @@ -201,7 +201,7 @@ public static function isCallable($value) : bool /** * Check function. - * + * * @access public * @param string $function * @return bool @@ -213,7 +213,7 @@ public static function isFunction(string $function) : bool /** * Check class. - * + * * @access public * @param string $class * @param bool $autoload @@ -226,20 +226,20 @@ public static function isClass(string $class, bool $autoload = true) : bool /** * Check sub class. - * + * * @access public - * @param string $sub + * @param mixed $sub * @param string $class * @return bool */ - public static function isSubClassOf(string $sub, string $class) : bool + public static function isSubClassOf($sub, string $class) : bool { return is_subclass_of($sub, $class); } /** * Check interface. - * + * * @access public * @param string $interface * @param bool $autoload @@ -252,7 +252,7 @@ public static function isInterface(string $interface, bool $autoload = true) : b /** * Check interface. - * + * * @access public * @param mixed $class * @param string $interface @@ -272,7 +272,7 @@ public static function hasInterface($class, string $interface, bool $short = tru /** * Check method. - * + * * @access public * @param mixed $object * @param string $method @@ -285,7 +285,7 @@ public static function hasMethod($object, string $method) : bool /** * Check countable. - * + * * @access public * @param mixed $value * @return bool @@ -297,7 +297,7 @@ public static function isCountable($value) : bool /** * Check ressource. - * + * * @access public * @param mixed $value * @return bool @@ -309,7 +309,7 @@ public static function isResource($value) : bool /** * Check scalar. - * + * * @access public * @param mixed $value * @return bool @@ -321,7 +321,7 @@ public static function isScalar($value) : bool /** * Check stream. - * + * * @access public * @param string $path * @return bool diff --git a/src/inc/User.php b/src/inc/User.php index f1902779..9e827b7a 100644 --- a/src/inc/User.php +++ b/src/inc/User.php @@ -128,7 +128,7 @@ public static function current(bool $format = true) { $user = wp_get_current_user(); if ( $format ) { - return self::format($user); + return Format::user($user); } return $user; } @@ -146,7 +146,7 @@ public static function getBy(string $key, $value, bool $format = true) { $user = get_user_by($key, $value); if ( $format ) { - return self::format($user); + return Format::user($user); } return $user; } @@ -198,7 +198,7 @@ public static function getByMeta(string $key, $value, bool $format = true) : arr if ( $format ) { $wrapper = []; foreach ($users as $user) { - $wrapper[] = self::format($user); + $wrapper[] = Format::user($user); } return $wrapper; } @@ -217,7 +217,7 @@ public static function all(bool $format = true) : array $users = get_users(); if ( $format ) { $users = Arrayify::map(function($user) { - return self::format($user); + return Format::user($user); }, $users); } return $users; @@ -756,29 +756,4 @@ public static function can($id = null, string $cap = 'edit_posts', $args = null) } return user_can($id, $cap, $args); } - - /** - * Get user formatted data. - * - * @access private - * @param mixed $user - * @return mixed - */ - private static function format($user) - { - if ( TypeCheck::isObject($user) ) { - $name = $user->data->display_name; - if ( empty($name) ) { - $name = $user->data->user_nicename; - } - return [ - 'id' => $user->data->ID, - 'login' => $user->data->user_login, - 'name' => $name, - 'email' => $user->data->user_email, - 'hash' => $user->data->user_pass - ]; - } - return $user; - } } diff --git a/src/inc/Xml.php b/src/inc/Xml.php index 206c5da5..b4295e46 100644 --- a/src/inc/Xml.php +++ b/src/inc/Xml.php @@ -18,7 +18,7 @@ final class Xml { /** * Parse XML string. - * + * * [NOCDATA: 16384]. * [VERSION: 20908]. * diff --git a/src/int/RequestInterface.php b/src/int/RequestInterface.php index f356b200..9382b557 100644 --- a/src/int/RequestInterface.php +++ b/src/int/RequestInterface.php @@ -41,7 +41,7 @@ function setBaseUrl(string $url) : self; function setArgs(array $args = []) : self; /** - * Add/Override single request arg. + * Add or override single request arg. * * @param string $arg * @param mixed $value @@ -50,15 +50,15 @@ function setArgs(array $args = []) : self; function addArg(string $arg, $value = null); /** - * Set/Reset request headers. - + * Set or reset request headers. + * * @param array $headers * @return object */ function setHeaders(array $headers = []) : self; /** - * Add/Override single request header. + * Add or override single request header. * * @param string $header * @param mixed $value @@ -67,15 +67,15 @@ function setHeaders(array $headers = []) : self; function addHeader(string $header, $value = null); /** - * Set/Reset request cookies. - + * Set or reset request cookies. + * * @param array $cookies * @return object */ function setCookies(array $cookies = []) : self; /** - * Add/Override single request cookie. + * Add or override single request cookie. * * @param string $cookie * @param mixed $value @@ -84,15 +84,15 @@ function setCookies(array $cookies = []) : self; function addCookie(string $cookie, $value = null); /** - * Set/Reset request body. - + * Set or reset request body. + * * @param array $body * @return object */ function setBody(array $body = []) : self; /** - * Add/Override single request body. + * Add or override single request body. * * @param string $body * @param mixed $value @@ -102,7 +102,7 @@ function addBody(string $body, $value = null); /** * Send request. - + * * @param string $url * @return object */ @@ -214,19 +214,18 @@ function hasError() : bool; function getError(); /** - * Add arg to query. + * Get request report. * - * @param mixed $arg - * @param string $url - * @return string + * @return array */ - static function addQueryArg($arg, string $url) : string; + function getReport() : array; /** - * Build query args from string (Alias). + * Add arg to query. * - * @param array $args + * @param mixed $arg + * @param string $url * @return string */ - static function buildQuery(array $args) : string; + static function addQueryArg($arg, string $url) : string; } diff --git a/src/int/UpdaterInterface.php b/src/int/UpdaterInterface.php index 0eba3e91..278e7591 100644 --- a/src/int/UpdaterInterface.php +++ b/src/int/UpdaterInterface.php @@ -17,9 +17,9 @@ interface UpdaterInterface { /** - * Init updater, - * [action : admin_init]. - * + * Init updater. + * [action : admin-init]. + * * @param string $host * @param array $args */ @@ -27,7 +27,8 @@ function __construct(string $host, array $args = []); /** * Get plugin info. - * + * [Filter: plugins-api]. + * * @param mixed $transient * @param string $action * @param object $args @@ -37,7 +38,8 @@ function getInfo($transient, string $action, object $args); /** * Check plugin update. - * + * [Filter: pre-transient-update-{$transient}]. + * * @param mixed $transient * @return object */ @@ -45,15 +47,25 @@ function checkUpdate($transient) : object; /** * Check plugin translation update. - * + * [Filter: pre-transient-update-{$transient}]. + * * @param mixed $transient * @return object */ function checkTranslation($transient) : object; /** - * Clear plugin updates cache, - * [Filter: upgrader_process_complete]. + * Filter updater request. + * [Filter: http-request-args]. + * + * @param array $args + * @return array + */ + function filterRequest(array $args) : array; + + /** + * Clear plugin updates cache. + * [Action: upgrader-process-complete]. * * @param object $upgrader * @param array $options @@ -61,15 +73,6 @@ function checkTranslation($transient) : object; */ function clearCache(object $upgrader, array $options); - /** - * Filter updater args, - * Allow unsafe updater URLs for non SSL. - * - * @param array $args - * @return array - */ - function filterArgs(array $args) : array; - /** * Get update status. * diff --git a/src/lib/API.php b/src/lib/API.php index 85673592..dbf64f12 100644 --- a/src/lib/API.php +++ b/src/lib/API.php @@ -19,16 +19,15 @@ }; /** - * Advanced request client helper. + * Plugin API helper. + * @uses Cache */ class API extends Request { - use \VanillePlugin\VanillePluginConfig, - \VanillePlugin\tr\TraitSecurable; + Use \VanillePlugin\VanillePluginOption; /** * @access public - * @var string Server down code */ public const DOWN = 429; @@ -36,30 +35,38 @@ class API extends Request * @access protected * @var object $logger, API logger * @var object $debug, Debug status + * @var object $cache, Cached response */ protected $logger; protected $hasDebug = false; + /** + * @access private + * @var bool $isCached, Cache status + * @var mixed $data, Cache data + * @var string $key, Cache key + */ + private $isCached = false; + private $cache = []; + private $cacheKey; + /** * Init request client. - * + * * @inheritdoc */ public function __construct(string $method = 'GET', array $args = [], ?string $baseUrl = null) { - // Set args $this->method = $method; $this->baseUrl = $baseUrl; + $this->args = $this->mergeArray([ - 'timeout' => 30, + 'timeout' => 3, 'redirection' => 0, 'sslverify' => true ], Server::maybeRequireSSL($args)); - // Set logger - $this->logger = new Logger(); - - // Set debug status + $this->logger = new Logger(); $this->hasDebug = $this->hasDebug(); // Reset config @@ -67,36 +74,43 @@ public function __construct(string $method = 'GET', array $args = [], ?string $b } /** - * Send request and log response. - * * @inheritdoc */ public function send(?string $url = null) : self { - parent::send($url); - if ( $this->hasError() && $this->hasDebug ) { - $log = [ - 'request' => [ - 'url' => "{$this->baseUrl}{$url}", - 'method' => $this->method, - 'headers' => $this->headers, - 'body' => $this->body - ], - 'response' => $this->decodeJson($this->getBody(), true) - ]; - $this->logger->debug($log, true); + $this->cacheKey = $this->generateKey('api', [ + 'url' => "{$this->baseUrl}{$url}", + 'method' => $this->method, + 'headers' => $this->headers, + 'body' => $this->body + ]); + + $this->cache = $this->getPluginCache( + $this->cacheKey, + $this->isCached + ); + + if ( !$this->isCached ) { + parent::send($url); + if ( $this->hasError() && $this->hasDebug ) { + $this->logger->debug($this->getReport(), true); + } } + + // Reset config + $this->resetConfig(); + return $this; } /** - * Set API authentication. + * Set authentication. * * @access public * @param string $token * @return void */ - public function setAuthentication(string $token) + public function setAuth(string $token) { $this->addHeader( 'Authorization', @@ -105,14 +119,14 @@ public function setAuthentication(string $token) } /** - * Set API basic authentication. - * + * Set authentication. + * * @access public * @param string $user * @param string $pswd * @return void */ - public function setBasicAuthentication(string $user, string $pswd) + public function setBasicAuth(string $user, string $pswd) { $token = $this->base64("{$user}:{$pswd}"); $this->addHeader( @@ -122,70 +136,86 @@ public function setBasicAuthentication(string $user, string $pswd) } /** - * Get API formated response from body (JSON). - * + * Get formated response from body (JSON). + * * @access public - * @param bool $isArray - * @return mixed + * @return array */ - public function getResponse(bool $isArray = true) + public function response() : array { - if ( !$this->hasError() ) { - return $this->decodeJson($this->getBody(), $isArray); + if ( $this->isCached ) { + return $this->cache ?: []; } - return false; + + $data = $this->decodeJson($this->getBody(), true); + $this->setPluginCache($this->cacheKey, $data); + + return $data; } /** - * Get API formated response from body (XML). - * + * Get formated response from body (XML). + * * @access public * @return mixed */ - public function getXmlResponse() + public function responseXml() { - if ( !$this->hasError() ) { - return $this->parseXml($this->getBody()); + if ( $this->isCached ) { + return $this->cache; } - return false; + + $data = $this->parseXml($this->getBody()); + $this->setPluginCache($this->cacheKey, $data); + + return $data; } /** - * Check whether API response has status (JSON). - * + * Check whether response has status (JSON). + * * @access public * @param string $status * @return bool */ public function hasStatus(string $status) : bool { - if ( !$this->hasError() ) { - $body = $this->decodeJson($this->getBody(), true); - if ( isset($body['status']) && $body['status'] == $status ) { - return true; - } - } - return false; + return $this->has('status', $status); } /** - * Check whether API response has content (JSON). - * + * Check whether response has content (JSON). + * * @access public * @return bool */ public function hasContent() : bool { - if ( !$this->hasError() ) { - $body = $this->decodeJson($this->getBody(), true); - return (isset($body['content']) && !empty($body['content'])); + return $this->has('content'); + } + + /** + * Check whether response has content (JSON). + * + * @access public + * @param string $item + * @param string $value + * @return bool + */ + public function has(string $item, ?string $value = null) : bool + { + $response = $this->response(); + if ( isset($response[$item]) ) { + if ( $value ) { + return ($response[$item] == $value); + } + return !empty($response[$item]); } return false; } /** - * Check API response code, - * Down when response code lower than expected code (Default 429) or equals 0. + * Check remote server status. * * @access public * @param int $code @@ -195,24 +225,35 @@ public function isDown(int $code = self::DOWN) : bool { if ( !$this->getStatusCode() ) { return true; - - } elseif ( $this->getStatusCode() >= intval($code) ) { + } + if ( $this->getStatusCode() >= intval($code) ) { return true; } return false; } /** - * Force disabling SSL verification. - * + * Disable SSL verification. + * * @access public * @return void */ - public function forceDisableSSL() + public function noSSL() { $this->args['sslverify'] = false; } + /** + * Check cache status. + * + * @access public + * @return bool + */ + public function isCached() : bool + { + return $this->isCached; + } + /** * Instance API. * @@ -224,6 +265,6 @@ public function forceDisableSSL() */ public static function instance(string $name, $path = 'api', ...$args) { - return (new Loader())->i($path, $name, $args); + return (new Loader())->i($path, $name, ...$args); } } diff --git a/src/lib/Ajax.php b/src/lib/Ajax.php index b01d3fd1..1605c10b 100644 --- a/src/lib/Ajax.php +++ b/src/lib/Ajax.php @@ -20,13 +20,10 @@ /** * Plugin AJAX manager. - * @uses Front actions requires admin hook for authenticated users. */ final class Ajax implements AjaxCoreInterface { - use \VanillePlugin\VanillePluginConfig, - \VanillePlugin\tr\TraitRequestable, - \VanillePlugin\tr\TraitHookable; + use \VanillePlugin\VanillePluginOption; /** * @access private @@ -67,8 +64,15 @@ public function callback() { foreach ($this->actions as $action) { if ( $this->isAction($action) ) { + + $this->verifyToken($action); + if ( $this->isAdminCallable() ) { + $this->verifyPermission(); + } + $action = $this->camelcase($action); $this->callable->{$action}(); + break; } } die(); @@ -111,7 +115,7 @@ private function isFrontCallable() : bool /** * Init admin actions. - * [Action: wp_ajax_{namespace}-{action}]. + * [Action: wp-ajax-{namespace}-{action}]. * * @access private * @return void @@ -120,7 +124,7 @@ private function initAdminActions() { foreach ($this->actions as $action) { $this->addAction( - "wp_ajax_{$this->applyNamespace($action)}", + "wp-ajax-{$this->applyNamespace($action)}", [$this, 'callback'] ); } @@ -128,7 +132,7 @@ private function initAdminActions() /** * Init front actions. - * [Action: wp_ajax_nopriv_{namespace}-{action}]. + * [Action: wp-ajax-nopriv-{namespace}-{action}]. * * @access private * @return void @@ -137,7 +141,7 @@ private function initFrontActions() { foreach ($this->actions as $action) { $this->addAction( - "wp_ajax_nopriv_{$this->applyNamespace($action)}", + "wp-ajax-nopriv-{$this->applyNamespace($action)}", [$this, 'callback'] ); } diff --git a/src/lib/Asset.php b/src/lib/Asset.php index 20f82864..4f7ff78e 100644 --- a/src/lib/Asset.php +++ b/src/lib/Asset.php @@ -15,7 +15,7 @@ namespace VanillePlugin\lib; /** - * Plugin custom assets manager. + * Plugin assets manager. */ final class Asset { @@ -128,6 +128,7 @@ public function setCdn(string $url) : self * * @access public * @return void + * @todo */ public function download() { @@ -224,7 +225,6 @@ private function check(?string $path = null) : bool foreach ($files as $file) { if ( !$this->isFile("{$this->dir}/{$asset}/{$file}") ) { return false; - break; } } } @@ -274,7 +274,7 @@ private function get() { $wrapper = []; foreach ($this->assets as $asset => $files) { - $wrapper[$asset] = $this->mapArray(function($file){ + $wrapper[$asset] = $this->mapArray(function($file) { return $this->getFileName($file); }, $files); } diff --git a/src/lib/Backup.php b/src/lib/Backup.php index 95fb1f93..d9efedd0 100644 --- a/src/lib/Backup.php +++ b/src/lib/Backup.php @@ -76,11 +76,12 @@ public function setOptions(array $options) public function export(bool $asFile = false) { // Init options + $data = []; if ( $this->options ) { foreach ($this->options as $key => $type) { $temp = $this->applyNamespace($key); $value = $this->getOption($temp, $type); - $wrapper['options'][$key] = $value; + $data['options'][$key] = $value; } } @@ -88,16 +89,14 @@ public function export(bool $asFile = false) if ( $this->tables ) { foreach ($this->tables as $table) { if ( $this->hasTable($table) ) { - $wrapper['tables'][$table] = $this->all($table); + $data['tables'][$table] = $this->all($table); } } } // Encrypt backup - $encrypt = $this->getCryptor($wrapper); - $prefix = $this->applyNameSpace('backup'); - $encrypt->setPrefix($prefix); - $backup = $encrypt->encrypt(); + $prefix = $this->applyNameSpace('backup'); + $backup = $this->encrypt($data, $prefix); if ( $asFile ) { $date = $this->getDate('now', 'd-m-Y'); @@ -129,11 +128,8 @@ public function import(string $backup, bool $isFile = false) : bool if ( !empty($backup) ) { - $encrypt = $this->getCryptor($backup); - $prefix = $this->applyNameSpace('backup'); - $encrypt->setPrefix($prefix); - - if ( ($backup = $encrypt->decrypt()) ) { + $prefix = $this->applyNameSpace('backup'); + if ( ($backup = $this->decrypt($backup, $prefix)) ) { // Backup options if ( isset($backup['options']) ) { diff --git a/src/lib/Cache.php b/src/lib/Cache.php index 6639696c..2c777f9b 100644 --- a/src/lib/Cache.php +++ b/src/lib/Cache.php @@ -14,305 +14,147 @@ namespace VanillePlugin\lib; -use VanillePlugin\exc\CacheException; -use VanillePlugin\inc\Cache as ObjectCache; -use VanilleThird\Cache as ThirdCache; -use VanilleCache\Cache as FileCache; - /** * Plugin cache manager. */ final class Cache { - use \VanillePlugin\VanillePluginConfig; - - /** - * @access private - * @var string FILECACHE, File cache - * @var string THIRDCACHE, Third cache - */ - private const FILECACHE = 'VanilleCache\Cache'; - private const THIRDCACHE = 'VanilleThird\Cache'; + use \VanillePlugin\VanillePluginOption; /** - * @access private - * @var string $key, Cache key - * @var string $tag, Cache tag - * @var array $path, Cache path + * @access public + * @var string INTERNAL, Internal cache + * @var string THIRD, Third-Party cache */ - private $key; - private $tag; - private $path; - - /** - * Init cache path. - * - * @param string $key - * @param string $tag - */ - public function __construct(?string $key = null, ?string $tag = null) - { - // Set cache key - $this->setKey($key); - - // Set cache tag - $this->setTag($tag); - - // Set cache path - $this->path[] = $this->getTempPath(); - $this->path[] = $this->getCachePath(); - - // Reset config - $this->resetConfig(); - } + public const INTERNAL = '\VanilleCache\Cache'; + public const THIRD = '\VanilleThird\Cache'; /** * Get cache value. * * @access public - * @param mixed $default + * @param string $key + * @param bool $status + * @param bool $group * @return mixed */ - public function get($default = null) - { - if ( !$this->key ) { - throw new CacheException( - CacheException::undefinedCacheKey() - ); - } - - $data = null; - - if ( $this->hasThirdCache() ) { - $data = ObjectCache::get($this->key); - - } elseif ( $this->hasFileCache() ) { - $data = (new FileCache())->get($this->key); - } - - if ( $this->isType('null', $data)) { - $data = $default; - } - - return $data; - } - - /** - * Check cache. - * - * @access public - * @return bool - */ - public function isCached() : bool + public function get(string $key, ?bool &$status = null, ?string $group = null) { - if ( !$this->key ) { - throw new CacheException( - CacheException::undefinedCacheKey() - ); - } - - if ( $this->hasThirdCache() ) { - return (ObjectCache::get($this->key) !== false); - } - - if ( $this->hasFileCache() ) { - return (new FileCache())->setKey($this->key)->isCached(); + if ( $this->hasInternalCache() ) { + if ( !$this->hasPluginFilter('get-cache') ) { + $instance = self::INTERNAL; + $cache = new $instance(); + return $cache->get($key, $status); + } } - - return false; + return $this->getPluginCache($key, $status, $group); } /** * Set cache value. * * @access public + * @param string $key * @param mixed $value * @param int $ttl * @return bool */ - public function set($value, ?int $ttl = null) : bool + public function set(string $key, $value, ?int $ttl = null, ?string $group = null) : bool { - if ( !$this->key ) { - throw new CacheException( - CacheException::undefinedCacheKey() - ); - } - - if ( $this->hasThirdCache() ) { - return ObjectCache::set($this->key, $value, (string)$this->tag, (int)$ttl); - } - - if ( $this->hasFileCache() ) { - return (new FileCache())->setKey($this->key)->set($value, $this->tag, $ttl); + if ( $this->hasInternalCache() ) { + if ( !$this->hasPluginFilter('set-cache') ) { + $instance = self::INTERNAL; + $cache = new $instance; + return $cache->set($key, $value, $ttl, $group); + } } - return false; + return $this->setPluginCache($key, $value, $ttl, $group); } /** * Delete cache. * * @access public + * @param string $key * @return bool */ - public function delete() : bool + public function delete(string $key, ?string $group = null) : bool { - if ( !$this->key ) { - throw new CacheException( - CacheException::undefinedCacheKey() - ); - } - - if ( $this->hasThirdCache() ) { - return ObjectCache::delete($this->key); - } - - if ( $this->hasFileCache() ) { - return (new FileCache())->delete($this->key); + if ( $this->hasInternalCache() ) { + if ( !$this->hasPluginFilter('delete-cache') ) { + $instance = self::INTERNAL; + $cache = new $instance; + return $cache->delete($key); + } } - return false; - } - - /** - * Delete cache by tag(s). - * - * @access public - * @param mixed $tag - * @return bool - */ - public function deleteByTag($tag) : bool - { - if ( $this->hasFileCache() ) { - return (new FileCache())->deleteByTag($tag); - } + return $this->deletePluginCache($key, $group); } /** * Purge any cache. - * + * * @access public * @param bool $force * @return bool */ public function purge(bool $force = false) : bool { - $stauts = 0; - - if ( $this->hasThirdCache() ) { - $stauts += (int)ThirdCache::purge(); - $stauts += (int)ObjectCache::purge(); + $count = 0; + $count += (int)$this->purgePluginCache(); + + if ( $this->hasInternalCache() ) { + if ( !$this->hasPluginFilter('purge-cache') ) { + $instance = self::INTERNAL; + $cache = new $instance; + $count += (int)$cache::purge(); + } } - if ( $this->hasFileCache() ) { - $stauts += (int)(new FileCache())->purge(); + if ( $this->hasThirdCache() ) { + $cache = self::THIRD; + $count += (int)$cache::purge(); } if ( $force ) { - foreach ($this->path as $path) { - $stauts += (int)$this->clearDir($path, [ + $path[] = $this->getTempPath(); + $path[] = $this->getCachePath(); + foreach ($path as $path) { + $count += (int)$this->clearDir($path, [ $this->getNameSpace() ]); } } - return (bool)$stauts; + return (bool)$count; } /** - * Generate cache key. - * - * @access public - * @param string $item - * @param array $args - * @return string - */ - public function generateKey(string $item, array $args = []) : string - { - $key = $item; - - foreach ($args as $name => $value) { - - if ( $this->isType('array', $value) - || $this->isType('null', $value) - || $this->isType('empty', $value) ) { - continue; - } - - if ( $value === 0 ) { - $value = '0'; - - } elseif ( $this->isType('false', $value) ) { - $value = 'false'; - - } elseif ( $this->isType('true', $value) ) { - $value = 'true'; - } - - $key .= "-{$name}-{$value}"; - } - - return $key; - } - - /** - * Set cache key. - * - * @access public - * @param string $key - * @return object - */ - public function setKey(?string $key = null) : self - { - if ( $key ) { - $this->key = $this->applyNamespace($key); - } - return $this; - } - - /** - * Set cache tag. - * - * @access public - * @param string $tag - * @return object - */ - public function setTag(?string $tag = null) : self - { - if ( $tag ) { - $this->tag = $tag; - - } else { - if ( $this->key ) { - $tag = explode('-', $this->key); - $this->tag = $tag[1] ?? $this->getNameSpace(); - } - } - return $this; - } - - /** - * Check third cache. + * Check third-party cache. * * @access public * @return bool */ public function hasThirdCache() : bool { - if ( $this->isType('class', self::THIRDCACHE) ) { - return ThirdCache::isActive(); + if ( $this->isType('class', self::THIRD) ) { + $cache = self::THIRD; + if ( $this->hasObject('method', $cache, 'isActive') ) { + return $cache::isActive(); + } } return false; } /** - * Check file cache. + * Check internal cache. * * @access public * @return bool */ - public function hasFileCache() : bool + public function hasInternalCache() : bool { - return $this->isType('class', self::FILECACHE); + return $this->isType('class', self::INTERNAL); } } diff --git a/src/lib/Hook.php b/src/lib/Hook.php index 555d63d1..30604864 100644 --- a/src/lib/Hook.php +++ b/src/lib/Hook.php @@ -15,8 +15,7 @@ namespace VanillePlugin\lib; /** - * Plugin custom admin hooks. - * @internal + * Plugin hooks manager. */ final class Hook { diff --git a/src/lib/Loader.php b/src/lib/Loader.php index 1ed59366..fed011ed 100644 --- a/src/lib/Loader.php +++ b/src/lib/Loader.php @@ -15,8 +15,7 @@ namespace VanillePlugin\lib; /** - * Plugin custom functions loader. - * @internal + * Plugin functions loader. */ class Loader { @@ -64,7 +63,7 @@ public function instance($path, $className, ...$args) if ( isset($files[$className]) ) { if ( $this->isType('class', $files[$className]) ) { $class = $files[$className]; - return new $class($args); + return new $class(...$args); } } } @@ -82,7 +81,7 @@ public function instance($path, $className, ...$args) */ public function i($path, $className, ...$args) { - return $this->instance($path, $className, $args); + return $this->instance($path, $className, ...$args); } /** diff --git a/src/lib/Migrate.php b/src/lib/Migrate.php index 47d016c3..cbaf74d6 100644 --- a/src/lib/Migrate.php +++ b/src/lib/Migrate.php @@ -238,20 +238,6 @@ public function unlock() : bool ); } - /** - * Instance database table. - * - * @access public - * @param string $name - * @param string $path - * @param mixed $args - * @return mixed - */ - public static function instance(string $name, $path = 'db', ...$args) - { - return (new Loader())->i($path, $name, $args); - } - /** * Parse table name for upgrade. * diff --git a/src/lib/Mobile.php b/src/lib/Mobile.php index 1470b067..20755351 100644 --- a/src/lib/Mobile.php +++ b/src/lib/Mobile.php @@ -18,6 +18,9 @@ HttpRequest, Server, Globals, Stringify }; +/** + * Plugin mobile helper. + */ class Mobile extends View { use \VanillePlugin\tr\TraitLoggable; diff --git a/src/lib/Model.php b/src/lib/Model.php index 74210d05..1404e380 100644 --- a/src/lib/Model.php +++ b/src/lib/Model.php @@ -15,13 +15,10 @@ namespace VanillePlugin\lib; use VanillePlugin\exc\ModelException; -use VanillePlugin\lib\{ - Orm, OrmQuery -}; /** - * Helper class for database table model, - * Using cache. + * Plugin table helper. + * @uses Cache */ class Model extends Orm { @@ -63,20 +60,19 @@ public function render() : string */ public function get($id) : array { - $key = "model-{$this->table}-{$id}"; - - if ( !($data = $this->getPluginCache($key)) ) { + $key = "model-{$this->table}-{$id}"; + $data = $this->getPluginCache($key, $status); + if ( !$status ) { $where = ["{$this->key}" => (int)$id]; - $data = $this->query(new OrmQuery([ + $data = $this->query(new OrmQuery([ 'result' => 'row', 'where' => $where ])); $this->setPluginCache($key, $data); - } - return (array)$data; + return $data ?: []; } /** @@ -157,14 +153,45 @@ public function remove($id) : bool */ public function fetch() : array { - $key = "model-{$this->table}-all"; + $key = "model-{$this->table}-all"; + $data = $this->getPluginCache($key, $status); - if ( !($data = $this->getPluginCache($key)) ) { + if ( !$status ) { $data = $this->all(); $this->setPluginCache($key, $data); } - return (array)$data; + return $data ?: []; + } + + /** + * Get cached item. + * + * @access public + * @param string $key + * @param bool $status + * @return array + */ + public static function getCached(string $key, ?bool &$status = null) : array + { + $sub = basename(static::class); + $key = "model-{$sub}-{$key}"; + $data = (new Cache())->get($key, $status); + return $data ?: []; + } + + /** + * Instance database table. + * + * @access public + * @param string $name + * @param string $path + * @param mixed $args + * @return mixed + */ + public static function instance(string $name, $path = 'db', ...$args) + { + return (new Loader())->i($path, $name, ...$args); } /** diff --git a/src/lib/Orm.php b/src/lib/Orm.php index 9747f5bc..e4527055 100644 --- a/src/lib/Orm.php +++ b/src/lib/Orm.php @@ -20,8 +20,8 @@ }; /** - * Helper class for database CRUD architecture, - * Using secured ORM style. + * Plugin CRUD manager. + * @uses ORM style */ class Orm extends Db implements OrmInterface { @@ -268,7 +268,7 @@ public function sum(string $column, ?string $table = null) */ public function all(?string $table = null) : array { - $sql = "SELECT * FROM `{$this->getTable($table)}`;"; + $sql = "SELECT * FROM `{$this->getTable($table)}`;"; return $this->getResult($sql); } diff --git a/src/lib/OrmQuery.php b/src/lib/OrmQuery.php index ba2f6d16..50399829 100644 --- a/src/lib/OrmQuery.php +++ b/src/lib/OrmQuery.php @@ -17,8 +17,7 @@ use VanillePlugin\int\OrmQueryInterface; /** - * Helper class for array based ORM query (Read-only), - * @uses Database API recommended. + * Plugin ORM query builder (Read-only). */ final class OrmQuery implements OrmQueryInterface { diff --git a/src/lib/Queue.php b/src/lib/Queue.php index 255939ff..e04fa53e 100644 --- a/src/lib/Queue.php +++ b/src/lib/Queue.php @@ -15,8 +15,7 @@ namespace VanillePlugin\lib; /** - * Helper class for tasks queueing. - * @uses Batch queueing is recommended. + * Plugin queue manager. */ class Queue { diff --git a/src/lib/Requirement.php b/src/lib/Requirement.php index 78a12dbe..867d56de 100644 --- a/src/lib/Requirement.php +++ b/src/lib/Requirement.php @@ -252,7 +252,7 @@ public function requireModules() if ( isset($module->override) ) { // Overrided module check - $name = $module->override->name ?? ''; + $name = $module->override->name ?? ''; $value = $module->override->value ?? ''; if ( !$this->isActivated($module->callable) && !$this->isConfig($name,$value) ) { diff --git a/src/lib/Rewrite.php b/src/lib/Rewrite.php index e1b6711d..43d7c7bc 100644 --- a/src/lib/Rewrite.php +++ b/src/lib/Rewrite.php @@ -15,7 +15,7 @@ namespace VanillePlugin\lib; /** - * Plugin rewrite. + * Plugin rewrite manager. */ final class Rewrite { @@ -102,7 +102,7 @@ public function addVars($vars = []) /** * Apply rules, - * [Action: admin_init]. + * [Action: admin-init]. * * @access public * @param int $priority @@ -110,12 +110,12 @@ public function addVars($vars = []) */ public function applyRules(int $priority = 10) { - $this->addFilter('mod_rewrite_rules', [$this, 'getRules'], $priority); + $this->addFilter('rewrite-rules', [$this, 'getRules'], $priority); } /** * Remove rules, - * [Action: admin_init]. + * [Action: admin-init]. * * @access public * @param int $priority @@ -123,12 +123,12 @@ public function applyRules(int $priority = 10) */ public function removeRules(int $priority = 10) : bool { - return $this->removeFilter('mod_rewrite_rules', [$this, 'getRules'], $priority); + return $this->removeFilter('rewrite-rules', [$this, 'getRules'], $priority); } /** * Get rules, - * [Filter: mod_rewrite_rules]. + * [Filter: rewrite-rules]. * * @access public * @param string $rules diff --git a/src/lib/Shortcode.php b/src/lib/Shortcode.php index d9eb8833..ee7922b5 100644 --- a/src/lib/Shortcode.php +++ b/src/lib/Shortcode.php @@ -17,6 +17,9 @@ use VanillePlugin\inc\Shortcode as Core; use VanillePlugin\int\CallableInterface; +/** + * Plugin shortcode manager. + */ class Shortcode extends View { /** @@ -161,7 +164,7 @@ public function setAtts(array $atts = []) */ public static function instance(string $name, $path = 'shortcode', ...$args) { - return (new Loader())->i($path, $name, $args); + return (new Loader())->i($path, $name, ...$args); } /** @@ -233,6 +236,43 @@ protected function setAttribute(string $attr, $value) $this->atts[$attr] = $value; } + /** + * Set attribute (Alias). + * + * @access protected + * @param string $attr + * @param mixed $value + * @return void + */ + protected function setAttr(string $attr, $value) + { + $this->setAttribute($attr, $value); + } + + /** + * Get attribute. + * + * @access protected + * @param string $attr + * @return mixed + */ + protected function getAttribute(string $attr) + { + return $this->atts[$attr] ?? null; + } + + /** + * Get attribute (Alias). + * + * @access protected + * @param string $attr + * @return mixed + */ + protected function getAttr(string $attr) + { + return $this->getAttribute($attr); + } + /** * Assign content to shortcode. * @@ -370,7 +410,7 @@ protected function hasAttribute(array $atts, string $attr) : bool protected function hasFlag(array $atts, string $attr) : bool { $flags = []; - $attr = $this->formatAttrName($attr); + $attr = $this->formatAttrName($attr); foreach ($atts as $key => $name) { if ( $this->isType('int', $key) && $this->isType('string', $name) ) { $flags[] = $this->formatAttrName($name); diff --git a/src/lib/Updater.php b/src/lib/Updater.php index 7b9653c3..eb17def1 100644 --- a/src/lib/Updater.php +++ b/src/lib/Updater.php @@ -15,10 +15,9 @@ namespace VanillePlugin\lib; use VanillePlugin\int\UpdaterInterface; -use \stdClass; /** - * Wrapper class for self-hosted plugin. + * Plugin update manager (self-hosted). */ class Updater implements UpdaterInterface { @@ -83,57 +82,20 @@ public function __construct(?string $host = null, array $args = []) unset($this->args['translationUrl']); unset($this->args['assetUrl']); - /** - * Get plugin info, - * [Filter: plugins_api]. - * - * @see getInfo@self - * @property priority 10 - * @property count 3 - */ - $this->addFilter('plugins_api', [$this, 'getInfo'], 10, 3); - - /** - * Check plugin update, - * [Filter: pre_set_site_transient_{$transient}], - * [Filter: site_transient_update_{$transient}]. - * - * @see checkUpdate@self - * @property priority 10 - * @property count 1 - */ - $this->addFilter('pre_set_site_transient_update_plugins', [$this, 'checkUpdate']); - - /** - * Check plugin translation update, - * [Filter: pre_set_site_transient_{$transient}], - * [Filter: site_transient_update_{$transient}]. - * - * @see checkTranslation@self - * @property priority 10 - * @property count 1 - */ - $this->addFilter('pre_set_site_transient_update_plugins', [$this, 'checkTranslation']); - - /** - * Clear plugin updates cache, - * [Filter: upgrader_process_complete]. - * - * @see clearCache@self - * @property priority 10 - * @property count 2 - */ - $this->addFilter('upgrader_process_complete', [$this, 'clearCache'], 10, 2); - - /** - * Filter updater args, - * [Filter: http_request_args]. - * - * @see filterArgs@self - * @property priority 20 - * @property count 1 - */ - $this->addFilter('http_request_args', [$this, 'filterArgs'], 20); + // Get plugin info + $this->addFilter('plugins-api', [$this, 'getInfo'], 10, 3); + + // Check plugin update + $this->addFilter('pre-transient-update-plugins', [$this, 'checkUpdate']); + + // Check plugin translation update. + $this->addFilter('pre-transient-update-plugins', [$this, 'checkTranslation']); + + // Filter updater request + $this->addFilter('http-request-args', [$this, 'filterRequest'], 20); + + // Clear plugin updates cache + $this->addAction('upgrader-process-complete', [$this, 'clearCache'], 10, 2); // Reset config $this->resetConfig(); @@ -179,7 +141,7 @@ public function checkUpdate($transient) : object { // Fix transient if ( !$this->isType('object', $transient) ) { - $transient = new stdClass(); + $transient = new \stdClass(); } // Fetch update @@ -207,7 +169,7 @@ public function checkTranslation($transient) : object { // Fix transient if ( !$this->isType('object', $transient) ) { - $transient = new stdClass(); + $transient = new \stdClass(); } // Check translation API URL @@ -223,7 +185,7 @@ public function checkTranslation($transient) : object // Fix translation transient if ( !isset($transient->translations) ) { - $transient = new stdClass(); + $transient = new \stdClass(); $transient->translations = []; } @@ -231,6 +193,7 @@ public function checkTranslation($transient) : object foreach ($transient->translations as $key => $translation) { if ( $translation['slug'] == $this->getNameSpace() ) { unset($transient->translations[$key]); + break; } } @@ -250,11 +213,11 @@ public function clearCache(object $upgrader, array $options) { if ( $options['action'] == 'update' && $options['type'] == 'plugin' ) { if ( isset($options['plugins']) ) { - foreach($options['plugins'] as $plugin) { + foreach ($options['plugins'] as $plugin) { if ( $plugin == $this->getMainFile() ) { - $this->deletePluginTransient($this->applyNamespace('get-info')); - $this->deletePluginTransient($this->applyNamespace('check-update')); - $this->deletePluginTransient($this->applyNamespace('check-translation')); + $this->purgePluginTransients(); + $this->purgePluginCache(); + break; } } } @@ -264,7 +227,7 @@ public function clearCache(object $upgrader, array $options) /** * @inheritdoc */ - public function filterArgs(array $args) : array + public function filterRequest(array $args) : array { if ( isset($args['reject_unsafe_urls']) ) { $args['reject_unsafe_urls'] = $this->hasSsl(); @@ -338,10 +301,10 @@ protected function fetch(string $action, string $url) if ( $this->isType('array', $this->auth) ) { $user = $this->auth[0] ?? ''; $pswd = $this->auth[1] ?? ''; - $api->setBasicAuthentication($user, $pswd); + $api->setBasicAuth($user, $pswd); } elseif ( $this->isType('string', $this->auth) ) { - $api->setAuthentication($this->auth); + $api->setAuth($this->auth); } } @@ -363,7 +326,7 @@ protected function fetch(string $action, string $url) /** * Set updater license into request body. - * + * * @access protected * @param array $body * @return array @@ -380,7 +343,7 @@ protected function setLicense($body) : array /** * Get updater user-agent (UA). - * + * * @access protected * @return string */ @@ -404,7 +367,7 @@ protected function getTimeout() : int /** * Check updater API SSL. * [Filter: {plugin}-updater-ssl]. - * + * * @access protected * @return bool */ @@ -440,14 +403,14 @@ protected function isValid(string $action, $response) : bool /** * Get updater default transient. - * + * * @access protected * @param string $action * @return object */ protected function getDefaultTransient(string $action) : object { - $transient = new stdClass(); + $transient = new \stdClass(); $transient->name = $this->pluginHeader['Name']; $transient->slug = $this->getNameSpace(); @@ -455,7 +418,7 @@ protected function getDefaultTransient(string $action) : object $transient->id = $this->slugify($this->pluginHeader['Name']); $transient->plugin = $this->getMainFile(); $transient->new_version = $this->version; - $transient->compatibility = new stdClass(); + $transient->compatibility = new \stdClass(); } elseif ( $action == 'info' ) { diff --git a/src/tr/TraitCacheable.php b/src/tr/TraitCacheable.php index a8636231..0339e57b 100644 --- a/src/tr/TraitCacheable.php +++ b/src/tr/TraitCacheable.php @@ -27,9 +27,9 @@ trait TraitCacheable * @access protected * @inheritdoc */ - protected function getCache($key, ?string $group = null) + protected function getCache($key, ?bool &$status = null, ?string $group = null) { - return Cache::get($key, (string)$group); + return Cache::get($key, (string)$group, false, $status); } /** diff --git a/src/tr/TraitFormattable.php b/src/tr/TraitFormattable.php index d2a48d52..5fc74a3c 100644 --- a/src/tr/TraitFormattable.php +++ b/src/tr/TraitFormattable.php @@ -147,7 +147,7 @@ protected function unSlash($value) /** * Strip slashes in quotes or single quotes. - * + * * @access protected * @inheritdoc */ @@ -158,7 +158,7 @@ protected function stripSlash($value) /** * Search string. - * + * * @access protected * @inheritdoc */ @@ -273,6 +273,17 @@ protected function breakString() : string return Stringify::break(); } + /** + * Generate key from args. + * + * @access protected + * @inheritdoc + */ + protected function generateKey(string $item, array $args = []) : string + { + return Stringify::generateKey($item, $args); + } + /** * Check array item. * @@ -473,7 +484,7 @@ protected function encodeJson($value) /** * Encode JSON using flags. - * + * * @access protected * @inheritdoc */ @@ -561,7 +572,7 @@ protected function isPluginVersion(string $file, string $version, string $operat /** * Check value type. - * + * * @access protected * @inheritdoc */ @@ -649,21 +660,16 @@ protected function isType($type, $value) : bool } /** - * Check object inherit. - * + * Check object. + * * @access protected * @inheritdoc - * @todo hasObject => hasItem */ protected function hasObject($type, $object, $item) : bool { switch ($this->lowercase($type)) { case 'interface': - $i = $this->lowercase($item); - if ( !$this->hasString($i, 'interface') ) { - $item = $this->capitalize($item); - $item = "{$item}Interface"; - } + $item = $this->toInterface($item); return TypeCheck::hasInterface($object, $item); break; @@ -703,4 +709,20 @@ protected function toArray(object $object) : array { return Converter::toArray($object); } + + /** + * Convert string to interface. + * + * @access protected + * @inheritdoc + */ + protected function toInterface(string $string) : string + { + $i = $this->lowercase($string); + if ( !$this->hasString($i, 'interface') ) { + $string = $this->capitalize($string); + $string = "{$string}Interface"; + } + return $string; + } } diff --git a/src/tr/TraitHookable.php b/src/tr/TraitHookable.php index b76e9dc8..92b124a3 100644 --- a/src/tr/TraitHookable.php +++ b/src/tr/TraitHookable.php @@ -136,9 +136,9 @@ protected function removeFilter(string $hook, $callback, int $priority = 10) : b * @access protected * @inheritdoc */ - protected function applyFilter(string $hook, $value, $args = null) + protected function applyFilter(string $hook, $value, ...$args) { - return Hook::applyFilter($hook, $value, $args); + return Hook::applyFilter($hook, $value, ...$args); } /** diff --git a/src/tr/TraitIO.php b/src/tr/TraitIO.php index 96659028..6772b9b3 100644 --- a/src/tr/TraitIO.php +++ b/src/tr/TraitIO.php @@ -214,7 +214,7 @@ protected function uncompressArchive(string $archive, string $to = '', $remove = */ private function secureRemove(string $path, array $secure = []) : bool { - $paths = explode('/', $path); + $paths = explode('/', $path); $secure = Arrayify::merge(['storage'], $secure); foreach ($secure as $include) { if ( !Arrayify::inArray($include, $paths) ) { diff --git a/src/tr/TraitRequestable.php b/src/tr/TraitRequestable.php index 45197b84..2f0d549c 100644 --- a/src/tr/TraitRequestable.php +++ b/src/tr/TraitRequestable.php @@ -16,7 +16,7 @@ use VanillePlugin\inc\{ HttpRequest, HttpPost, HttpGet, - Response, Request, Server, Stringify + Response, Server, Stringify }; trait TraitRequestable @@ -185,7 +185,7 @@ protected function isSsl() : bool /** * Check if SSL verify is required in request. - * + * * @access protected * @inheritdoc */ @@ -195,35 +195,24 @@ protected function maybeRequireSSL(array $args) : array } /** - * Parse URL. - * + * Get domain name from URL. + * * @access protected * @inheritdoc */ - protected function parseUrl(string $url, int $component = -1) + protected function getDomainName(?string $url = null) : string { - return Stringify::parseUrl($url, $component); + return Server::getDomain($url); } /** - * Build query args from string. - * + * Parse URL. + * * @access protected * @inheritdoc */ - protected function buildQuery($args, string $prefix = '', ?string $sep = '&', int $enc = 1) : string - { - return Stringify::buildQuery($args, $prefix, $sep, $enc); - } - - /** - * Get HTTP client. - * - * @access protected - * @inheritdoc - */ - protected function getHttpClient(string $method = 'GET', array $args = [], ?string $baseUrl = null) : Request + protected function parseUrl(string $url, int $component = -1) { - return new Request($method, $args, $baseUrl); + return Stringify::parseUrl($url, $component); } } diff --git a/src/tr/TraitSecurable.php b/src/tr/TraitSecurable.php index 03f005f5..c711e157 100644 --- a/src/tr/TraitSecurable.php +++ b/src/tr/TraitSecurable.php @@ -119,26 +119,16 @@ protected function generateToken(int $length = 16, bool $special = false) : stri return Tokenizer::generate($length, $special); } - /** - * Get encryption object. - * - * @access protected - * @inheritdoc - */ - protected function getCryptor($data, ?string $key = 'v8t1pQ92PN', ?string $vector = 'ZRfvSPsFQ', ?int $length = 16) : Encryption - { - return new Encryption($data, $key, $vector, $length); - } - /** * Encrypt data. * * @access protected * @inheritdoc */ - protected function encrypt($data) : string + protected function encrypt($data, string $prefix = Encryption::PREFIX) : string { - return (new Encryption($data))->bypass()->encrypt(); + $cryptor = new Encryption($data); + return $cryptor->setPrefix($prefix)->encrypt(); } /** @@ -147,8 +137,9 @@ protected function encrypt($data) : string * @access protected * @inheritdoc */ - protected function decrypt($data) + protected function decrypt($data, string $prefix = Encryption::PREFIX) { - return (new Encryption($data))->decrypt(); + $cryptor = new Encryption($data); + return $cryptor->setPrefix($prefix)->decrypt(); } } diff --git a/src/tr/TraitTranslatable.php b/src/tr/TraitTranslatable.php index 0ca2b166..3d1a9f6a 100644 --- a/src/tr/TraitTranslatable.php +++ b/src/tr/TraitTranslatable.php @@ -116,11 +116,13 @@ protected function hasTranslator() : bool */ protected function normalizeLocale(string $locale) : string { - $lang = Localisation::parseLang($locale); + $lang = Localisation::parseLang($locale); $region = Localisation::parseRegion($locale); + if ( $lang === $region ) { return $lang; } + return Localisation::normalizeLocale($locale); } }