From b1ecdbeecf623c1ca76c29f32febbb14fae9e135 Mon Sep 17 00:00:00 2001 From: Luiz Bills Date: Thu, 5 Dec 2024 11:47:47 -0300 Subject: [PATCH] v2.3.5 --- .editorconfig | 3 +- .gitignore | 2 +- CHANGELOG.md | 7 ++++ composer.json | 20 +++++---- composer.lock | 43 +++++++++---------- config.php | 3 +- core/Config.php | 51 +++++++++++++++++++---- core/Dependencies.php | 44 ++++++++++++++++---- core/Loader.php | 24 ++++++++--- core/Main.php | 28 +++++++++++-- core/Traits/Common_Helpers.php | 50 +++++++++++++++++++---- core/Traits/Config_Helpers.php | 13 ++++++ core/Traits/Debug_Helpers.php | 25 ++++-------- core/Traits/Log_Helpers.php | 59 +++++++++++++++++++++++++++ core/Traits/String_Helpers.php | 68 +++++++++++++++++++++++++++---- core/Traits/Template_Helpers.php | 29 ++++++++++--- core/Traits/Throw_Helpers.php | 24 ++++++++++- core/Traits/WordPress_Helpers.php | 40 ++++++++++++++++-- core/VERSION | 2 +- docs/README.md | 1 - main.php | 52 +++++++++-------------- package-lock.json | 43 +++++++++++++++++-- readme.txt | 11 +++-- scripts/build | 30 ++++++-------- 24 files changed, 508 insertions(+), 164 deletions(-) create mode 100644 core/Traits/Log_Helpers.php delete mode 100644 docs/README.md diff --git a/.editorconfig b/.editorconfig index 025b7d4..1ba1c29 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,15 +3,14 @@ root = true [*] end_of_line = lf insert_final_newline = true +indent_size = 4 [*.php] charset = utf-8 trim_trailing_whitespace = true indent_style = tab -indent_size = 4 [*.{json, html, js, css}] charset = utf-8 trim_trailing_whitespace = true indent_style = space -indent_size = 4 diff --git a/.gitignore b/.gitignore index 9f20605..a43029c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ /vendor/ /node_modules/ -/wp-build/ +*.zip *.log *.min.js *.min.css diff --git a/CHANGELOG.md b/CHANGELOG.md index 4653910..3d3209c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. +## 2.3.5 - 2024-12-05 + +[Source code changes](https://github.com/luizbills/shipping-simulator-for-woocommerce/compare/2.3.4...2.3.5) + +- Tested up to WordPress 6.7 +- Minor fixes + ## 2.3.4 - 2024-08-26 [Source code changes](https://github.com/luizbills/shipping-simulator-for-woocommerce/compare/2.3.3...2.3.4) diff --git a/composer.json b/composer.json index 0bdcf6a..b093492 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,6 @@ { "require": { + "php": ">=7.4", "ext-mbstring": "*" }, "require-dev": { @@ -7,14 +8,6 @@ "php-stubs/woocommerce-stubs": "^7.4", "phpstan/phpstan": "^1.10" }, - "scripts": { - "check": "phpstan", - "build": "./scripts/build", - "deploy": "./scripts/svn-push", - "update-trunk": "./scripts/svn-push --only-trunk", - "make-pot": "wp i18n make-pot . languages/wc-shipping-simulator.pot", - "upgrade-core": "./scripts/upgrade-core" - }, "autoload": { "psr-4": { "Shipping_Simulator\\": [ @@ -25,6 +18,17 @@ ] } }, + "config": { + "platform-check": false + }, + "scripts": { + "build": "./scripts/build", + "deploy": "./scripts/svn-push", + "update-trunk": "./scripts/svn-push --only-trunk", + "make-pot": "wp i18n make-pot . languages/wc-shipping-simulator.pot", + "upgrade-core": "./scripts/upgrade-core", + "check": "phpstan" + }, "wp-plugin-base": { "namespace": "Shipping_Simulator", "text-domain": "wc-shipping-simulator" diff --git a/composer.lock b/composer.lock index b2ed90c..414976f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9c662064b44b6d2499ffbe1ba7c988b8", + "content-hash": "0ebffebf507b02320f4e68797ef498f0", "packages": [], "packages-dev": [ { @@ -53,16 +53,16 @@ }, { "name": "php-stubs/wordpress-stubs", - "version": "v6.6.0", + "version": "v6.7.1", "source": { "type": "git", "url": "https://github.com/php-stubs/wordpress-stubs.git", - "reference": "86e8753e89d59849276dcdd91b9a7dd78bb4abe2" + "reference": "83448e918bf06d1ed3d67ceb6a985fc266a02fd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/86e8753e89d59849276dcdd91b9a7dd78bb4abe2", - "reference": "86e8753e89d59849276dcdd91b9a7dd78bb4abe2", + "url": "https://api.github.com/repos/php-stubs/wordpress-stubs/zipball/83448e918bf06d1ed3d67ceb6a985fc266a02fd1", + "reference": "83448e918bf06d1ed3d67ceb6a985fc266a02fd1", "shasum": "" }, "require-dev": { @@ -71,9 +71,9 @@ "php": "^7.4 || ^8.0", "php-stubs/generator": "^0.8.3", "phpdocumentor/reflection-docblock": "^5.4.1", - "phpstan/phpstan": "^1.10.49", + "phpstan/phpstan": "^1.11", "phpunit/phpunit": "^9.5", - "szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset": "^1.0", + "szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset": "^1.1.1", "wp-coding-standards/wpcs": "3.1.0 as 2.3.0" }, "suggest": { @@ -95,22 +95,22 @@ ], "support": { "issues": "https://github.com/php-stubs/wordpress-stubs/issues", - "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.6.0" + "source": "https://github.com/php-stubs/wordpress-stubs/tree/v6.7.1" }, - "time": "2024-07-17T08:50:38+00:00" + "time": "2024-11-24T03:57:09+00:00" }, { "name": "phpstan/phpstan", - "version": "1.11.11", + "version": "1.12.12", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "707c2aed5d8d0075666e673a5e71440c1d01a5a3" + "reference": "b5ae1b88f471d3fd4ba1aa0046234b5ca3776dd0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/707c2aed5d8d0075666e673a5e71440c1d01a5a3", - "reference": "707c2aed5d8d0075666e673a5e71440c1d01a5a3", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/b5ae1b88f471d3fd4ba1aa0046234b5ca3776dd0", + "reference": "b5ae1b88f471d3fd4ba1aa0046234b5ca3776dd0", "shasum": "" }, "require": { @@ -155,24 +155,24 @@ "type": "github" } ], - "time": "2024-08-19T14:37:29+00:00" + "time": "2024-11-28T22:13:23+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.30.0", + "version": "v1.31.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "ec444d3f3f6505bb28d11afa41e75faadebc10a1" + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/ec444d3f3f6505bb28d11afa41e75faadebc10a1", - "reference": "ec444d3f3f6505bb28d11afa41e75faadebc10a1", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { @@ -215,7 +215,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.30.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.31.0" }, "funding": [ { @@ -231,7 +231,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T15:07:36+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "szepeviktor/phpstan-wordpress", @@ -303,6 +303,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { + "php": ">=7.4", "ext-mbstring": "*" }, "platform-dev": [], diff --git a/config.php b/config.php index c712dbe..ffb7ae9 100644 --- a/config.php +++ b/config.php @@ -1,11 +1,10 @@ 'wc-shipping-simulator', 'PREFIX' => 'wc_shipping_simulator_', - 'LANGUAGES_DIR' => 'languages', 'TEMPLATES_DIR' => 'templates', 'DONATION_URL' => 'https://luizpb.com/donate/', 'PLUGIN_REVIEWS' => 'https://wordpress.org/support/plugin/shipping-simulator-for-woocommerce/reviews/?filter=5#new-post', diff --git a/core/Config.php b/core/Config.php index 61ef141..451c9c6 100644 --- a/core/Config.php +++ b/core/Config.php @@ -2,19 +2,34 @@ namespace Shipping_Simulator\Core; -abstract class Config { +final class Config { + /** @var array */ protected static $values = []; + /** + * @param string $main_file The file that contains the plugin headers + * @return void + * @throws \Exception + */ public static function init ( $main_file ) { if ( self::get_size() > 0 ) { - throw new \Error( __CLASS__ . ' already initialized' ); + throw new \Exception( __CLASS__ . ' already initialized' ); } $root = dirname( $main_file ); $config = require $root . '/config.php'; if ( ! is_array( $config ) ) { - throw new \Error( $root . '/config.php must return an Array' ); + throw new \Exception( $root . '/config.php must return an Array' ); + } + + if ( + function_exists( 'wp_get_environment_type' ) + && in_array( \wp_get_environment_type(), [ 'local', 'development' ] ) + && file_exists( $root . '/config.dev.php' ) + ) { + $config_dev = include $root . '/config.dev.php'; + $config = array_replace( $config, $config_dev ); } foreach ( $config as $key => $value ) { @@ -27,12 +42,12 @@ public static function init ( $main_file ) { $slug = isset( self::$values[ 'SLUG' ] ) ? self::$values[ 'SLUG' ] : false; if ( ! $slug || ! is_string( $slug ) ) { - throw new \Error( $root . '/config.php must define a string SLUG (Recommended: only alphanumeric and dashes)' ); + throw new \Exception( $root . '/config.php must define a string SLUG (Recommended: only alphanumeric and dashes)' ); } $prefix = isset( self::$values[ 'PREFIX' ] ) ? self::$values[ 'PREFIX' ] : false; if ( ! $prefix || ! is_string( $prefix ) ) { - throw new \Error( $root . '/config.php must define a string PREFIX (only alphanumeric and underscores)' ); + throw new \Exception( $root . '/config.php must define a string PREFIX (only alphanumeric and underscores)' ); } self::$values[ 'FILE'] = $main_file; @@ -40,31 +55,51 @@ public static function init ( $main_file ) { $data = \get_file_data( $main_file, [ 'Plugin Name', 'Version' ] ); self::$values[ 'NAME' ] = __( $data[0], 'wc-shipping-simulator' ); - self::$values[ 'VERSION' ] = $data[1] ? $data[1] : '0.0.0'; + self::$values[ 'VERSION' ] = $data[1] ? $data[1] : false; } + /** + * @param string $key + * @param mixed $value + * @return mixed The value + * @throws \Exception + */ public static function set ( $key, $value ) { $key = mb_strtoupper( $key ); if ( isset( self::$values[ $key ] ) ) { - throw new \Error( __METHOD__ . ": Key \"$key\" has already been assigned. No key can be assigned more than once." ); + throw new \Exception( __METHOD__ . ": Key \"$key\" has already been assigned. No key can be assigned more than once." ); } self::$values[ $key ] = $value; return $value; } + /** + * @param string $key + * @param mixed $default + * @return mixed + * @throws \Exception + */ public static function get ( $key, $default = null ) { $key = \mb_strtoupper( $key ); $value = isset( self::$values[ $key ] ) ? self::$values[ $key ] : $default; if ( null === $value ) { - throw new \Error( __METHOD__ . ": Undefined key $key" ); + throw new \Exception( __METHOD__ . ": Undefined key $key" ); } return $value; } + /** + * @return int<0, max> + */ public static function get_size () { return count( self::$values ); } + /** + * @param string $string + * @param string $sep + * @return string + */ public static function sanitize_slug ( $string, $sep = '-' ) { $slug = \strtolower( \remove_accents( $string ) ); // Convert to ASCII // Standard replacements diff --git a/core/Dependencies.php b/core/Dependencies.php index e92b1d4..61adc17 100644 --- a/core/Dependencies.php +++ b/core/Dependencies.php @@ -2,19 +2,26 @@ namespace Shipping_Simulator\Core; -abstract class Dependencies { +final class Dependencies { + /** @var array */ protected static $dependencies; + + /** @var bool */ protected static $initialized = false; + /** + * @return void + * @throws \Exception + */ public static function init () { if ( self::$initialized ) { - throw new \Error( __CLASS__ . ' already initialized' ); + throw new \Exception( __CLASS__ . ' already initialized' ); } $root = Config::get( 'DIR' ); self::$dependencies = include_once $root . '/dependencies.php'; if ( ! is_array( self::$dependencies ) ) { - throw new \Error( $root . '/dependencies.php must return an Array' ); + throw new \Exception( $root . '/dependencies.php must return an Array' ); } \add_action( 'plugins_loaded', [ __CLASS__, 'maybe_start_plugin' ], 0 ); @@ -22,6 +29,9 @@ public static function init () { self::$initialized = true; } + /** + * @return void + */ public static function maybe_start_plugin () { $result = self::check_dependencies(); @@ -32,6 +42,10 @@ public static function maybe_start_plugin () { } } + /** + * @return array{success: bool, messages: array} + * @throws \Exception + */ public static function check_dependencies () { $result = [ 'success' => null, @@ -47,7 +61,7 @@ public static function check_dependencies () { // check the message if ( ! is_string( $message ) || '' === trim( $message ) ) { $id = is_integer( $key ) ? '#' . ( 1 + $key ) : $key; - throw new \Error( "Dependency $id has an invalid 'message': its must be a string and and it cannot be empty." ); + throw new \Exception( "Dependency $id has an invalid 'message': its must be a string and and it cannot be empty." ); } // check the requirement @@ -71,12 +85,17 @@ public static function check_dependencies () { return $result; } + /** + * @param string $shortcut + * @return bool + * @throws \Exception + */ protected static function handle_shortcut ( $shortcut ) { $parts = explode( ':', $shortcut ); $value = trim( implode( ':', array_slice( $parts, 1 ) ) ); $type = trim( $parts[0] ); if ( ! $value || ! $type ) { - throw new \Error( "Invalid shortcut syntax: $shortcut" ); + throw new \Exception( "Invalid shortcut syntax: $shortcut" ); } switch ( $type ) { case 'class': @@ -101,17 +120,24 @@ protected static function handle_shortcut ( $shortcut ) { break; } - throw new \Error( "Unexpected shortcut: $shortcut" ); + throw new \Exception( "Unexpected shortcut: $shortcut" ); } + /** + * @param array $messages + * @return void + */ protected static function display_notice_missing_deps ( $messages ) { if ( ! \is_admin() ) return; if ( ! \current_user_can( 'install_plugins' ) ) return; if ( 0 === count( $messages ) ) return; - \usort( $messages, function ( $a, $b ) { - return $b['is_error'] <=> $a['is_error']; - } ); + \usort( + $messages, + function ( $a, $b ) { + return $b['is_error'] <=> $a['is_error']; + } + ); \add_action( 'admin_notices', function () use ( $messages ) { echo "

"; diff --git a/core/Loader.php b/core/Loader.php index 088acdd..5da5384 100644 --- a/core/Loader.php +++ b/core/Loader.php @@ -2,13 +2,20 @@ namespace Shipping_Simulator\Core; -abstract class Loader { +final class Loader { + /** @var bool */ protected static $initialized = false; + + /** @var string */ protected static $main_file; + /** + * @return void + * @throws \Exception + */ public static function init () { if ( self::$initialized ) { - throw new \Error( __CLASS__ . ' already initialized' ); + throw new \Exception( __CLASS__ . ' already initialized' ); } self::$main_file = Config::get( 'FILE' ); @@ -17,16 +24,23 @@ public static function init () { self::$initialized = true; } + /** + * @return string + */ public static function get_hook_start_plugin () { return 'start_plugin_' . self::$main_file; } + /** + * @return void + * @throws \Exception + */ public static function load_classes () { $root = Config::get( 'DIR' ); $loader = include_once $root . '/loader.php'; if ( ! is_array( $loader ) ) { - throw new \Error( $root . '/loader.php must return an Array' ); + throw new \Exception( $root . '/loader.php must return an Array' ); } $classes = []; @@ -53,7 +67,7 @@ public static function load_classes () { $loaded = false; if ( is_string( $class_name ) && ! \class_exists( $class_name ) ) { - throw new \Error( 'class ' . $class_name . ' does not exist' ); + throw new \Exception( 'class ' . $class_name . ' does not exist' ); } $instance = is_string( $class_name ) ? new $class_name() : $class_name; @@ -75,7 +89,7 @@ public static function load_classes () { } if ( ! $loaded ) { - throw new \Error( "class $class_name must have at least one of the following methods: __start, __activation (static) or __deactivation (static)" ); + throw new \Exception( "class $class_name must have at least one of the following methods: __start, __activation (static) or __deactivation (static)" ); } } } diff --git a/core/Main.php b/core/Main.php index 8cdf808..8417cfe 100644 --- a/core/Main.php +++ b/core/Main.php @@ -2,17 +2,37 @@ namespace Shipping_Simulator\Core; -abstract class Main { - protected static $classes_to_load = []; - protected static $dependencies = []; +final class Main { + /** + * @param string $main_file The file that contains the plugin headers + * @return void + */ public static function start_plugin ( $main_file ) { if ( ! file_exists( $main_file ) ) { - throw new \Error( 'Invalid plugin main file path in ' . __CLASS__ ); + throw new \Exception( 'Invalid plugin main file path in ' . __CLASS__ ); } Config::init( $main_file ); Loader::init(); Dependencies::init(); + + add_action( 'init', [ __CLASS__, 'load_textdomain' ], 0 ); + } + + /** + * Loads the plugin translations + * @return void + */ + public static function load_textdomain () { + $languages_dir = Config::get( 'DOMAIN_PATH', 'languages' ); + $path = Config::get( 'DIR' ) . "/$languages_dir"; + if ( file_exists( $path ) && is_dir( $path ) ) { + \load_plugin_textdomain( + 'wc-shipping-simulator', + false, + dirname( plugin_basename( Config::get( 'FILE' ) ) ) . "/$languages_dir/" + ); + } } } diff --git a/core/Traits/Common_Helpers.php b/core/Traits/Common_Helpers.php index f52d4f4..fbb376b 100644 --- a/core/Traits/Common_Helpers.php +++ b/core/Traits/Common_Helpers.php @@ -2,21 +2,44 @@ namespace Shipping_Simulator\Core\Traits; +use Shipping_Simulator\Core\Traits\Log_Helpers; use Shipping_Simulator\Core\Config; trait Common_Helpers { - // Get the value if set, otherwise return a default value or `null`. Prevents notices when data is not set. - public static function get ( &$var, $default = null ) { - return $var ?? $default; + + use Log_Helpers; + + /** + * Get the value if set, otherwise return a default value or `null`. + * Prevents notices when data is not set. + * + * @param mixed $var + * @param mixed $default + * @return mixed + */ + public static function get ( &$var, $default = null, $clean = true ) { + $value = isset( $var ) ? $var : $default; + return $clean && is_scalar( $value ) ? \sanitize_text_field( $value ) : $value; } - // Get the constant if set, otherwise return a default value or `null`. + /** + * Get the constant if set, otherwise return a default value. + * + * @param string $name The constant name + * @param mixed $default + * @return mixed + */ public static function get_defined ( $name, $default = null ) { return defined( $name ) ? constant( $name ) : $default; } - // returns `false` ONLY IF $var is null, empty array/object or empty string - // note: `$var = false` returns `true` (because $var is filled with a boolean) + /** + * Returns `false` ONLY IF $var is null, empty array/object or empty string + * Note: `$var = false` returns `true` (because $var is filled with a boolean) + * + * @param mixed $var + * @return bool + */ public static function filled ( $var ) { if ( null === $var ) return false; if ( is_string( $var ) && '' === trim( $var ) ) return false; @@ -25,13 +48,22 @@ public static function filled ( $var ) { return \apply_filters( self::prefix( 'is_value_filled' ), true, $var ); } - // example: turns "Hello World" into "hello-world" + /** + * @param string $string + * @param string $sep + * @return string + */ public static function sanitize_slug ( $string, $sep = '-' ) { return Config::sanitize_slug( $string, $sep ); } - // appends the plugin prefix (defined in /config.php) - // example: h::prefix( 'something' ) returns "your_prefix_something" + /** + * Appends the plugin prefix (defined in /config.php). + * Example: h::prefix( 'something' ) returns "your_prefix_something" + * + * @param string $appends + * @return string + */ public static function prefix ( $appends = '' ) { return Config::get( 'PREFIX' ) . $appends; } diff --git a/core/Traits/Config_Helpers.php b/core/Traits/Config_Helpers.php index 2bd5eb4..9a88797 100644 --- a/core/Traits/Config_Helpers.php +++ b/core/Traits/Config_Helpers.php @@ -5,10 +5,23 @@ use Shipping_Simulator\Core\Config; trait Config_Helpers { + + /** + * @param string $key + * @param mixed $default + * @return mixed + * @throws \Exception + */ public static function config_get ( $key, $default = null ) { return Config::get( $key, $default ); } + /** + * @param string $key + * @param mixed $value + * @return mixed The value + * @throws \Exception + */ public static function config_set ( $key, $value ) { return Config::set( $key, $value ); } diff --git a/core/Traits/Debug_Helpers.php b/core/Traits/Debug_Helpers.php index 2d4ffba..fa648d0 100644 --- a/core/Traits/Debug_Helpers.php +++ b/core/Traits/Debug_Helpers.php @@ -5,6 +5,13 @@ use Shipping_Simulator\Core\Config; trait Debug_Helpers { + + /** + * Dump and die + * + * @param mixed ...$values + * @return void|never + */ public static function dd ( ...$values ) { if ( ! WP_DEBUG ) return; foreach ( $values as $v ) { @@ -14,22 +21,4 @@ public static function dd ( ...$values ) { } die; } - - public static function log ( ...$values ) { - $debug_log_enabled = WP_DEBUG && defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG; - if ( ! $debug_log_enabled ) return; - $message = ''; - foreach ( $values as $value ) { - if ( \is_string( $value ) ) { - $message .= $value; - } else { - ob_start(); - var_dump( $value ); - $message .= ob_get_clean(); - } - $message .= ' '; - } - $slug = Config::get( 'SLUG' ); - \error_log( "[$slug] $message" ); - } } diff --git a/core/Traits/Log_Helpers.php b/core/Traits/Log_Helpers.php new file mode 100644 index 0000000..5d421fb --- /dev/null +++ b/core/Traits/Log_Helpers.php @@ -0,0 +1,59 @@ +getMessage(); + $file = $err->getFile(); + $line = $err->getLine(); + + $message = sprintf( + __( '%1$s in %2$s on line %3$s', 'woocommerce' ), $error, $file, $line, + ); + $message .= PHP_EOL . 'Stack trace:' . PHP_EOL . $err->getTraceAsString() . PHP_EOL; + } else { + $message = $err; + } + + self::log( $message ); + + if ( function_exists( 'wc_get_logger' ) ) { + $logger = \wc_get_logger(); + $prefix = '[' . Config::get( 'SLUG' ) . ']'; + $logger->critical( "$prefix $message", [ 'source' => 'fatal-errors' ]); + } + + return $message; + } +} diff --git a/core/Traits/String_Helpers.php b/core/Traits/String_Helpers.php index 1411d18..adfc168 100644 --- a/core/Traits/String_Helpers.php +++ b/core/Traits/String_Helpers.php @@ -3,38 +3,90 @@ namespace Shipping_Simulator\Core\Traits; trait String_Helpers { - public static function str_length ( $string, $encoding = null ) { - return \mb_strlen( $string, $encoding ? $encoding : 'UTF-8' ); + + /** + * @param string $string + * @param string $encoding + * @return int<0, max> + */ + public static function str_length ( $string, $encoding = 'UTF-8' ) { + return \mb_strlen( $string, $encoding ); + } + + /** + * @param string $string + * @param string $encoding + * @return string + */ + public static function str_lower ( $string, $encoding = 'UTF-8' ) { + return \mb_strtolower( $string, $encoding ); } - public static function str_lower ( $string, $encoding = null ) { - return \mb_strtolower( $string, $encoding ? $encoding : 'UTF-8' ); + /** + * @param string $string + * @param string $encoding + * @return string + */ + public static function str_upper ( $string, $encoding = 'UTF-8' ) { + return \mb_strtoupper( $string, $encoding ); } - public static function str_upper ( $string, $encoding = null ) { - return \mb_strtoupper( $string, $encoding ? $encoding : 'UTF-8' ); + /** + * @param string $string + * @param string $encoding + * @return bool + */ + public static function str_contains ( $string, $search, $encoding = 'UTF-8' ) { + return $search !== '' && mb_strpos( $string, $search, 0, $encoding ) !== false; } + /** + * @param string $string + * @param string $search + * @return string + */ public static function str_before ( $string, $search ) { return '' === $search ? $string : \explode( $search, $string )[0]; } + /** + * @param string $string + * @param string $search + * @return string + */ public static function str_after ( $string, $search ) { return '' === $search ? $string : \array_reverse( \explode( $search, $string, 2 ) )[0]; } + /** + * @param string $string + * @param string $search + * @return bool + */ public static function str_starts_with ( $string, $search ) { return self::str_after( $string, $search ) !== $string; } + /** + * @param string $string + * @param string $search + * @return bool + */ public static function str_ends_with ( $string, $search ) { return self::str_before( $string, $search ) !== $string; } - // usage: `h::str_mask( 'XXX.XXX.XXX-XX', '83699642062' ); // outputs 836.996.420-62` + /** + * Usage: h::str_mask( 'XXX.XXX.XXX-XX', '83699642062' ); // outputs 836.996.420-62 + * + * @param string $string + * @param string $mask + * @param string $symbol + * @return string + */ public static function str_mask ( $string, $mask, $symbol = 'X' ) { $result = ''; - for ( $i = 0, $k = 0; $i < \strlen( $mask ); ++$i ) { + for ( $i = 0, $k = 0; $i < self::str_length( $mask ); ++$i ) { if ( $mask[ $i ] === $symbol ) { if ( isset( $string[ $k ] ) ) $result .= $string[ $k++ ]; } else { diff --git a/core/Traits/Template_Helpers.php b/core/Traits/Template_Helpers.php index 44c757a..b98674f 100644 --- a/core/Traits/Template_Helpers.php +++ b/core/Traits/Template_Helpers.php @@ -7,7 +7,12 @@ trait Template_Helpers { use Config_Helpers; - // remove evil tags: script, style, link, iframe + /** + * Remove evil tags: script, style, link, iframe + * + * @param string $html + * @return string The sanitized html + */ public static function safe_html ( $html ) { // remove all script and style tags with code $html = \preg_replace( '/<(script|style)[^>]*?>.*?<\/\\1>/si', '', $html ); @@ -16,7 +21,14 @@ public static function safe_html ( $html ) { return $html; } - // TEMPLATE RENDERER + /** + * Returns a template rendered with the arguments (2nd parameter). + * + * @param string $template_path + * @param array $args + * @return string - The rendered template + * @throws \Exception + */ public static function get_template ( $template_path, $args = [] ) { $args = \apply_filters( self::prefix( 'get_template_args' ), $args, $template_path ); $full_path = self::get_template_path( $template_path ); @@ -27,22 +39,29 @@ public static function get_template ( $template_path, $args = [] ) { require $full_path; $html = \ob_get_clean(); } catch ( \Throwable $e ) { + self::log_critical( $e ); if ( self::get_defined( 'WP_DEBUG' ) && current_user_can( 'administrator' ) ) { - $error = wp_slash( "Error while rendering template '$template_path': " . $e->getMessage() ); - $html = ''; + echo '

' . esc_html( wp_slash( "Error while rendering template '$template_path': " . $e->getMessage() ) ) . '
'; } else { - throw new \Error( $e ); + throw new \Exception( $e ); } } return $html; } + /** + * @param string $template_path + * @return string The template absolute path + */ public static function get_template_path ( $template_path ) { $template_path .= '.php' === substr( $template_path, -4 ) ? '' : '.php'; $full_path = self::get_templates_dir() . ltrim( $template_path, '/' ); return apply_filters( self::prefix( 'get_template_full_path' ), $full_path, $template_path ); } + /** + * @return string The directory that contains the plugin templates. + */ public static function get_templates_dir () { $templates = \trim( Config::get( 'TEMPLATES_DIR', 'templates' ), '/' ); return Config::get( 'DIR' ) . "/{$templates}/"; diff --git a/core/Traits/Throw_Helpers.php b/core/Traits/Throw_Helpers.php index 2a03440..e7a982c 100644 --- a/core/Traits/Throw_Helpers.php +++ b/core/Traits/Throw_Helpers.php @@ -3,10 +3,23 @@ namespace Shipping_Simulator\Core\Traits; trait Throw_Helpers { + + /** + * @return \Exception + */ public static function get_error_class () { - return \Error::class; + return \Exception::class; } + /** + * If the condition is falsy, throws a Exception. + * + * @param bool $condition + * @param callable|mixed $message + * @param \Throwable|null $exception_class + * @return void + * @throws \Throwable + */ public static function throw_if ( $condition, $message, $exception_class = null ) { if ( $condition ) { if ( ! is_string( $message ) && \is_callable( $message ) ) { @@ -17,6 +30,15 @@ public static function throw_if ( $condition, $message, $exception_class = null } } + /** + * If the $var is a WP_Error instance, throws a Exception. + * + * @param mixed $var + * @param string $code + * @param \Throwable|null $exception_class + * @return void + * @throws \Throwable + */ public static function throw_wp_error ( $var, $code = null, $exception_class = null ) { if ( \is_wp_error( $var ) ) self::throw_if( true, $var->get_error_message( $code ), $exception_class ); } diff --git a/core/Traits/WordPress_Helpers.php b/core/Traits/WordPress_Helpers.php index 709e625..49916c1 100644 --- a/core/Traits/WordPress_Helpers.php +++ b/core/Traits/WordPress_Helpers.php @@ -5,21 +5,41 @@ use Shipping_Simulator\Core\Config; trait WordPress_Helpers { + + /** + * Usage: `$script_url = h::plugin_url( 'assets/js/app.js' );` + * + * @param string $path + * @return string the link + */ public static function plugin_url ( $path = '' ) { - // usage: `$script_url = h::plugin_url( 'assets/js/app.js' );` return \plugins_url( $path, Config::get( 'FILE' ) ); } + /** + * @param boolean $raw + * @return string The plugin version + */ public static function get_plugin_version ( $raw = false ) { $version = Config::get( 'VERSION' ); return $raw ? $version : preg_replace( '/[^0-9.]/', '', $version ); } + /** + * Saves a WordPress transient prefixed with the plugin slug. + * + * @see https://developer.wordpress.org/apis/transients/ + * @see https://codex.wordpress.org/Easier_Expression_of_Time_Constants + * @param string $transient + * @param mixed $value + * @param integer $duration + * @return mixed + */ public static function set_transient ( $transient, $value, $duration = 0 ) { if ( is_callable( $value ) ) { $value = \call_user_func( $value ); } - if ( self::config_get( 'CACHE_ENABLED', true ) ) { + if ( Config::get( 'CACHE_ENABLED', true ) ) { $key = self::get_transient_key( $transient ); if ( ! self::filled( $value ) ) { return \delete_transient( $key ); @@ -37,12 +57,24 @@ public static function set_transient ( $transient, $value, $duration = 0 ) { return $value; } + /** + * @param string $transient + * @param mixed $default + * @return mixed + */ public static function get_transient ( $transient, $default = false ) { - $key = self::get_transient_key( $transient ); - $value = \get_transient( $key ); + $value = false; + if ( Config::get( 'CACHE_ENABLED', true ) ) { + $key = self::get_transient_key( $transient ); + $value = \get_transient( $key ); + } return false !== $value ? $value : $default; } + /** + * @param string $transient + * @return string + */ public static function get_transient_key ( $transient ) { return self::prefix( $transient ) . '_' . self::get_plugin_version(); } diff --git a/core/VERSION b/core/VERSION index 9c6d629..38f77a6 100644 --- a/core/VERSION +++ b/core/VERSION @@ -1 +1 @@ -1.6.1 +2.0.1 diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 4640904..0000000 --- a/docs/README.md +++ /dev/null @@ -1 +0,0 @@ -# TODO diff --git a/main.php b/main.php index 7e38a80..4bd7f7c 100644 --- a/main.php +++ b/main.php @@ -3,7 +3,7 @@ Plugin Name: Shipping Simulator for WooCommerce Plugin URI: https://github.com/luizbills/shipping-simulator-for-woocommerce Description: Allows your customers to calculate the shipping rates on the product page -Version: 2.3.4 +Version: 2.3.5 Requires at least: 4.9 Requires PHP: 7.4 Author: Luiz Bills @@ -27,43 +27,29 @@ */ // prevents your PHP files from being executed via direct browser access -defined( 'WPINC' ) || exit( 1 ); - -load_plugin_textdomain( 'wc-shipping-simulator', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' ); - -try { - // Check PHP Version - $php_expected = '7.4'; - $php_current = PHP_VERSION; - if ( version_compare( $php_current, $php_expected, '<' ) ) { - throw new Error( - sprintf( - // translators: the %s are PHP versions - esc_html__( "This plugin requires PHP version %s or later (your server PHP version is %s)", 'wc-shipping-simulator' ), - $php_expected, esc_html( $php_current ) - ) - ); - } - - // check composer autoload - $composer_autoload = __DIR__ . '/vendor/autoload.php'; - if ( ! file_exists( $composer_autoload ) ) { - throw new Error( $composer_autoload . ' does not exist' ); - } - include_once $composer_autoload; -} catch ( Throwable $e ) { - return add_action( 'admin_notices', function () use ( $e ) { +defined( 'ABSPATH' ) || exit( 1 ); + +$autoload = __DIR__ . '/vendor/autoload.php'; +if ( file_exists( $autoload ) ) { + // composer autoload + include $autoload; + // start the plugin + \Shipping_Simulator\Core\Main::start_plugin( __FILE__ ); +} else { + // display a error + return add_action( 'admin_notices', function () { + // error visible only for admin users if ( ! current_user_can( 'install_plugins' ) ) return; + + include_once ABSPATH . '/wp-includes/functions.php'; list( $plugin_name ) = get_file_data( __FILE__, [ 'plugin name' ] ); + $message = sprintf( - /* translators: %1$s is replaced with plugin name and %2$s with an error message */ - esc_html__( 'Error on %1$s plugin activation: %2$s', 'wc-shipping-simulator' ), + 'Error on %1$s plugin activation: %2$s', '' . esc_html( $plugin_name ) . '', - '
' . esc_html( $e->getMessage() ) . '' + 'Autoload file not found
Download this plugin from WordPress repository and avoid downloading from other sources (Github, etc).' ); + echo "

$message

"; } ); } - -// run the plugin -\Shipping_Simulator\Core\Main::start_plugin( __FILE__ ); diff --git a/package-lock.json b/package-lock.json index 2357810..7abbe79 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "loong64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -32,6 +33,7 @@ "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz", "integrity": "sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==", "dev": true, + "license": "ISC", "dependencies": { "d": "^1.0.1", "es5-ext": "^0.10.64", @@ -48,6 +50,7 @@ "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", "dev": true, + "license": "ISC", "dependencies": { "es5-ext": "^0.10.64", "type": "^2.7.2" @@ -62,6 +65,7 @@ "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", "dev": true, "hasInstallScript": true, + "license": "ISC", "dependencies": { "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.3", @@ -77,6 +81,7 @@ "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", "dev": true, + "license": "MIT", "dependencies": { "d": "1", "es5-ext": "^0.10.35", @@ -88,6 +93,7 @@ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", "dev": true, + "license": "ISC", "dependencies": { "d": "^1.0.2", "ext": "^1.7.0" @@ -101,6 +107,7 @@ "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", "dev": true, + "license": "ISC", "dependencies": { "d": "1", "es5-ext": "^0.10.46", @@ -114,6 +121,7 @@ "integrity": "sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -152,6 +160,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -168,6 +177,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -184,6 +194,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -200,6 +211,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -216,6 +228,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -232,6 +245,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -248,6 +262,7 @@ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -264,6 +279,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -280,6 +296,7 @@ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -296,6 +313,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -312,6 +330,7 @@ "mips64el" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -328,6 +347,7 @@ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -344,6 +364,7 @@ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -360,6 +381,7 @@ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -376,6 +398,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "netbsd" @@ -392,6 +415,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" @@ -408,6 +432,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "sunos" @@ -424,6 +449,7 @@ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -440,6 +466,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -456,6 +483,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -469,6 +497,7 @@ "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", "dev": true, + "license": "ISC", "dependencies": { "d": "^1.0.1", "es5-ext": "^0.10.62", @@ -484,6 +513,7 @@ "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", "dev": true, + "license": "MIT", "dependencies": { "d": "1", "es5-ext": "~0.10.14" @@ -494,6 +524,7 @@ "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", "dev": true, + "license": "ISC", "dependencies": { "type": "^2.7.2" } @@ -502,13 +533,15 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lru-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", "dev": true, + "license": "MIT", "dependencies": { "es5-ext": "~0.10.2" } @@ -518,6 +551,7 @@ "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.17.tgz", "integrity": "sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==", "dev": true, + "license": "ISC", "dependencies": { "d": "^1.0.2", "es5-ext": "^0.10.64", @@ -536,13 +570,15 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/timers-ext": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.8.tgz", "integrity": "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==", "dev": true, + "license": "ISC", "dependencies": { "es5-ext": "^0.10.64", "next-tick": "^1.1.0" @@ -555,7 +591,8 @@ "version": "2.7.3", "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", - "dev": true + "dev": true, + "license": "ISC" } } } diff --git a/readme.txt b/readme.txt index 435a5ef..86dc7cf 100644 --- a/readme.txt +++ b/readme.txt @@ -1,11 +1,11 @@ === Shipping Simulator for WooCommerce === Contributors: luizbills Donate link: https://luizpb.com/donate/ -Tags: woocommerce, shipping simulator, simulador de frete, brazil, calculadora de frete -Stable tag: 2.3.4 +Tags: woocommerce, shipping simulator, simulador de frete, brazil, brasil, calculadora de frete, shipping calculator, product +Stable tag: 2.3.5 Requires at least: 4.9 Requires PHP: 7.4 -Tested up to: 6.6 +Tested up to: 6.7 License: GPLv3 License URI: https://www.gnu.org/licenses/gpl-3.0.html @@ -50,6 +50,11 @@ You can ask for help in the [Plugin Forum](https://wordpress.org/support/plugin/ == Changelog == += v2.3.5 = + +- Tested up to WordPress 6.7 +- Minor fixes. + = v2.3.4 = - Tested up to WordPress 6.6 diff --git a/scripts/build b/scripts/build index 3430c0e..f94e537 100755 --- a/scripts/build +++ b/scripts/build @@ -23,7 +23,7 @@ cp -R $DIR $TMP_DIR cd $TMP_DIR # PHP syntax checker -if ! command -v php &> /dev/null +if command -v php &> /dev/null then echo "Checking PHP syntax..." find . -type f -name '*.php' ! -path './vendor/*' -print0 | while read -d $'\0' file @@ -61,24 +61,17 @@ fi # delete some dev files echo "Erasing development files..." +find $TMP_DIR -maxdepth 1 -type d -iname ".*" -exec rm -rf {} \; # delete hidden folders +find $TMP_DIR -maxdepth 1 -type f -iname ".*" -exec rm -rf {} \; # delete hidden files rm -rf $DEST_DIR -rm -rf .git -rm -rf .github -rm -rf tests -rm -rf docs -rm -rf scripts -rm -rf logs -rm -rf node_modules -rm -f .gitattributes -rm -f .gitignore -rm -f .gitmodules -rm -f .editorconfig -rm -f .prettierrc.json -rm -f package-lock.json -rm -f pnpm-lock.yaml -rm -f composer.lock -rm -f phpunit.xml -rm -f phpunit.xml.dist +rm -Rf node_modules +rm -Rf tests +rm -Rf docs +rm -Rf scripts +rm -Rf logs +rm -Rf *lock* +rm -f *phpunit.xml* +rm -f *phpstan* rm -f README.md rm -f CONTRIBUTING.md @@ -95,3 +88,4 @@ zip -qr "$DIR/$DEST_DIR/$PLUGIN_NAME.zip" "$PLUGIN_NAME" #zip tmp dir rm -rf $TMP_DIR echo "Zip file created in $DIR/$DEST_DIR/$PLUGIN_NAME.zip" +echo -e "\e[1;32mDone!\e[0m"