diff --git a/SECURITY.md b/SECURITY.md index ae159ad..7bfe647 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -3,10 +3,10 @@ ## Supported Versions Versions that are currently being supported with security updates. -| Version | Supported | -| ------- | ------------------ | -| 1.7.15.1 | :white_check_mark: | -| <= 1.7.13 | :x: | +| Version | Supported | +| ------- | ------------------ | +| 1.7.15.2 | :white_check_mark: | +| <= 1.7.15.1 | :x: | ## Reporting a Vulnerability diff --git a/blueprint.json b/blueprint.json index 2025797..e3b8284 100644 --- a/blueprint.json +++ b/blueprint.json @@ -1,7 +1,7 @@ { "landingPage": "\/wp-admin\/plugins.php", "preferredVersions": { - "php": "8.0", + "php": "7.4", "wp": "latest" }, "phpExtensionBundles": [ @@ -15,7 +15,7 @@ "step": "installPlugin", "pluginZipFile": { "resource": "url", - "url": "https:\/\/downloads.wordpress.org\/plugin\/cooked.1.7.16.zip" + "url": "https:\/\/downloads.wordpress.org\/plugin\/cooked.1.7.15.2.zip" }, "options": { "activate": true diff --git a/composer.json b/composer.json index 4844954..eac297c 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,6 @@ { "require": { + "php": ">=7.4.0", "nxp/math-executor": "^2.3" } } diff --git a/composer.lock b/composer.lock index ecc71aa..12a1adb 100644 --- a/composer.lock +++ b/composer.lock @@ -4,28 +4,27 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e3ee5ad1b602664668a28615cdc4d69c", + "content-hash": "7ff1f391379b9a05f016928ce4c93286", "packages": [ { "name": "nxp/math-executor", - "version": "v2.3.6", + "version": "v2.3.2", "source": { "type": "git", "url": "https://github.com/neonxp/MathExecutor.git", - "reference": "dca855e25f8ba6ab019c2fe9bd8065d4713d00de" + "reference": "c59f4cd15317754d2b50bd4bff2243012e815790" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/neonxp/MathExecutor/zipball/dca855e25f8ba6ab019c2fe9bd8065d4713d00de", - "reference": "dca855e25f8ba6ab019c2fe9bd8065d4713d00de", + "url": "https://api.github.com/repos/neonxp/MathExecutor/zipball/c59f4cd15317754d2b50bd4bff2243012e815790", + "reference": "c59f4cd15317754d2b50bd4bff2243012e815790", "shasum": "" }, "require": { - "php": ">=8.0 <8.4" + "php": ">=7.4" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.8", - "phpstan/phpstan": "^1.9", "phpunit/phpunit": ">=9.0" }, "type": "library", @@ -60,9 +59,9 @@ ], "support": { "issues": "https://github.com/neonxp/MathExecutor/issues", - "source": "https://github.com/neonxp/MathExecutor/tree/v2.3.6" + "source": "https://github.com/neonxp/MathExecutor/tree/v2.3.2" }, - "time": "2024-02-15T22:51:27+00:00" + "time": "2022-12-08T16:15:34+00:00" } ], "packages-dev": [], @@ -71,7 +70,9 @@ "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, - "platform": [], + "platform": { + "php": ">=7.4.0" + }, "platform-dev": [], "plugin-api-version": "2.6.0" } diff --git a/cooked.php b/cooked.php index 15414ee..7535764 100644 --- a/cooked.php +++ b/cooked.php @@ -6,7 +6,7 @@ Description: A recipe plugin for WordPress. Author: Boxy Studio Author URI: https://boxystudio.com -Version: 1.7.16 +Version: 1.7.15.2 Text Domain: cooked Domain Path: languages License: GPL2 @@ -30,7 +30,7 @@ require_once __DIR__ . '/vendor/autoload.php'; -define( 'COOKED_VERSION', '1.7.16' ); +define( 'COOKED_VERSION', '1.7.15.2' ); define( 'COOKED_DEV', true ); if ( ! class_exists( 'Cooked_Plugin' ) ) : diff --git a/includes/class.cooked-recipes.php b/includes/class.cooked-recipes.php index e699ba6..161998d 100644 --- a/includes/class.cooked-recipes.php +++ b/includes/class.cooked-recipes.php @@ -385,10 +385,10 @@ public function filter_recipes_by_taxonomy() { $selected = isset($_GET[$taxonomy]) ? sanitize_title($_GET[$taxonomy]) : ''; $info_taxonomy = get_taxonomy($taxonomy); $taxonomy_label = $info_taxonomy->label; - + /* translators: For showing "All" of a taxonomy (ex: "All Burgers") */ $all_string = sprintf( esc_html__( "All %s", "cooked" ), $taxonomy_label ); - + wp_dropdown_categories(array( 'show_option_all' => $all_string, 'taxonomy' => $taxonomy, @@ -750,19 +750,19 @@ public static function serving_size_switcher( $servings ){ $half = $default / 2; $double = $default * 2; $triple = $default * 3; - + /* translators: singular and plural quarter "serving" size */ $quarter_string = sprintf( esc_html( _n('Quarter (%s Serving)','Quarter (%s Servings)',$quarter,'cooked')),$quarter ); - + /* translators: singular and plural quarter "serving" size */ $half_string = sprintf( esc_html( _n('Half (%s Serving)','Half (%s Servings)',$half,'cooked')),$half ); - + /* translators: singular and plural quarter "serving" size */ $default_string = sprintf( esc_html( _n('Default (%s Serving)','Default (%s Servings)',$default,'cooked')),$default ); - + /* translators: singular and plural quarter "serving" size */ $double_string = sprintf( esc_html__( 'Double (%s Servings)','cooked'),$double ); - + /* translators: singular and plural quarter "serving" size */ $triple_string = sprintf( esc_html__( 'Triple (%s Servings)','cooked'),$triple ); @@ -780,14 +780,14 @@ public static function serving_size_switcher( $servings ){ echo ''; echo '' . esc_html__('Yields','cooked') . ''; if ( !$printing && !$switcher_disabled ): - + /* translators: singular and plural "serving" sizes */ $servings_string = sprintf( esc_html( _n( '%s Serving', '%s Servings', $servings, 'cooked' ) ), $servings ); - + echo '' . $servings_string . ''; echo ''; else: @@ -892,10 +892,10 @@ public static function single_direction( $dir, $number = false, $plain_text = fa if ( $plain_text ): return $content; else: - + /* translators: singular and plural "steps" */ $step_string = sprintf( esc_html__( 'Step %d', 'cooked' ), $step ); - + echo '
'; echo ( $number ? '' . esc_html($number) . '' : '' ); echo '
' . do_shortcode( $content ) . ( $image ? wpautop( $image ) : '' ) . '
'; diff --git a/readme.txt b/readme.txt index 068b21e..00fb2e0 100644 --- a/readme.txt +++ b/readme.txt @@ -2,8 +2,8 @@ Contributors: boxystudio, xjsv Tags: recipe, recipes, food, cooking, nutrition Requires at least: 4.7 -Tested up to: 6.5 -Stable tag: 1.7.16 +Tested up to: 6.5.2 +Stable tag: 1.7.15.2 Requires PHP: 7.4 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html @@ -75,12 +75,14 @@ Be sure to check the [Cooked Documentation](http://docs.cooked.pro/collection/1- == Upgrade Notice == -Version 1.7.15.1 fixes the CVE-2023-44477 Auth. (contributor+) Stored Cross-Site Scripting (XSS) vulnerability. +Version 1.7.15.2 is a hotfix to correct the composer platform error issue. == Changelog == -= 1.7.16 = -* Security improvements. += 1.7.15.2 = +* **FIX:** Composer detected issues in your platform error discovered by @ianrlp. +* **FIX:** PHP undefined variable $hours_left discovered and fixed by @addyh. +* **TWEAK:** Security improvements thanks to @addyh. = 1.7.15.1 = * **FIX:** Addressed the CVE-2023-44477 security vulnerability. diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 58997bb..0e8a34e 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -2,28 +2,27 @@ "packages": [ { "name": "nxp/math-executor", - "version": "v2.3.6", - "version_normalized": "2.3.6.0", + "version": "v2.3.2", + "version_normalized": "2.3.2.0", "source": { "type": "git", "url": "https://github.com/neonxp/MathExecutor.git", - "reference": "dca855e25f8ba6ab019c2fe9bd8065d4713d00de" + "reference": "c59f4cd15317754d2b50bd4bff2243012e815790" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/neonxp/MathExecutor/zipball/dca855e25f8ba6ab019c2fe9bd8065d4713d00de", - "reference": "dca855e25f8ba6ab019c2fe9bd8065d4713d00de", + "url": "https://api.github.com/repos/neonxp/MathExecutor/zipball/c59f4cd15317754d2b50bd4bff2243012e815790", + "reference": "c59f4cd15317754d2b50bd4bff2243012e815790", "shasum": "" }, "require": { - "php": ">=8.0 <8.4" + "php": ">=7.4" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.8", - "phpstan/phpstan": "^1.9", "phpunit/phpunit": ">=9.0" }, - "time": "2024-02-15T22:51:27+00:00", + "time": "2022-12-08T16:15:34+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -57,7 +56,7 @@ ], "support": { "issues": "https://github.com/neonxp/MathExecutor/issues", - "source": "https://github.com/neonxp/MathExecutor/tree/v2.3.6" + "source": "https://github.com/neonxp/MathExecutor/tree/v2.3.2" }, "install-path": "../nxp/math-executor" } diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index fa3f297..32b380f 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -1,9 +1,9 @@ array( 'name' => '__root__', - 'pretty_version' => '1.0.0+no-version-set', - 'version' => '1.0.0.0', - 'reference' => null, + 'pretty_version' => 'dev-develop', + 'version' => 'dev-develop', + 'reference' => '75dca48e2d226d4b55dabb6ee423531200c8e694', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -11,18 +11,18 @@ ), 'versions' => array( '__root__' => array( - 'pretty_version' => '1.0.0+no-version-set', - 'version' => '1.0.0.0', - 'reference' => null, + 'pretty_version' => 'dev-develop', + 'version' => 'dev-develop', + 'reference' => '75dca48e2d226d4b55dabb6ee423531200c8e694', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => false, ), 'nxp/math-executor' => array( - 'pretty_version' => 'v2.3.6', - 'version' => '2.3.6.0', - 'reference' => 'dca855e25f8ba6ab019c2fe9bd8065d4713d00de', + 'pretty_version' => 'v2.3.2', + 'version' => '2.3.2.0', + 'reference' => 'c59f4cd15317754d2b50bd4bff2243012e815790', 'type' => 'library', 'install_path' => __DIR__ . '/../nxp/math-executor', 'aliases' => array(), diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php index adfb472..580fa96 100644 --- a/vendor/composer/platform_check.php +++ b/vendor/composer/platform_check.php @@ -4,8 +4,8 @@ $issues = array(); -if (!(PHP_VERSION_ID >= 80000)) { - $issues[] = 'Your Composer dependencies require a PHP version ">= 8.0.0". You are running ' . PHP_VERSION . '.'; +if (!(PHP_VERSION_ID >= 70400)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 7.4.0". You are running ' . PHP_VERSION . '.'; } if ($issues) { diff --git a/vendor/nxp/math-executor/.github/workflows/tests.yml b/vendor/nxp/math-executor/.github/workflows/tests.yml index 7596322..4967599 100644 --- a/vendor/nxp/math-executor/.github/workflows/tests.yml +++ b/vendor/nxp/math-executor/.github/workflows/tests.yml @@ -8,7 +8,7 @@ jobs: strategy: fail-fast: false matrix: - php: [8.3, 8.2, 8.1, 8.0] + php: [8.2, 8.1, 8.0, 7.4] dependency-version: [prefer-lowest, prefer-stable] os: [ubuntu-latest, windows-latest] diff --git a/vendor/nxp/math-executor/.gitignore b/vendor/nxp/math-executor/.gitignore index 1054073..9aedff4 100644 --- a/vendor/nxp/math-executor/.gitignore +++ b/vendor/nxp/math-executor/.gitignore @@ -1,7 +1,6 @@ vendor/ .idea/ composer.lock -.phpunit.cache .phpunit.result.cache .vscode .php-cs-fixer.cache diff --git a/vendor/nxp/math-executor/.php-cs-fixer.php b/vendor/nxp/math-executor/.php-cs-fixer.php index b661109..2ec098c 100644 --- a/vendor/nxp/math-executor/.php-cs-fixer.php +++ b/vendor/nxp/math-executor/.php-cs-fixer.php @@ -65,11 +65,11 @@ // PHP code must use the long ` true, // Spaces should be properly placed in a function declaration. - 'function_declaration' => ['closure_function_spacing'=>'none', 'closure_fn_spacing'=>'none'], + 'function_declaration' => ['closure_function_spacing'=>'none'], // Replace core functions calls returning constants with the constants. 'function_to_constant' => true, // Ensure single space between function's argument and its typehint. - 'type_declaration_spaces' => true, + 'function_typehint_space' => true, // Renames PHPDoc tags. 'general_phpdoc_tag_rename' => true, // Function `implode` must be called with 2 arguments in the documented order. @@ -148,6 +148,8 @@ 'no_short_bool_cast' => true, // When making a method or function call, there MUST NOT be a space between the method or function name and the opening parenthesis. 'no_spaces_after_function_name' => true, + // There MUST NOT be a space after the opening parenthesis. There MUST NOT be a space before the closing parenthesis. + 'no_spaces_inside_parenthesis' => true, // Removes `@param`, `@return` and `@var` tags that don't provide any useful information. 'no_superfluous_phpdoc_tags' => true, // Remove trailing whitespace at the end of non-blank lines. @@ -227,7 +229,7 @@ // A PHP file without end tag must always end with a single empty line feed. 'single_blank_line_at_eof' => true, // There should be exactly one blank line before a namespace declaration. - 'blank_lines_before_namespace' => ['max_line_breaks' => 2, 'min_line_breaks' => 2], + 'single_blank_line_before_namespace' => true, // There MUST NOT be more than one property or constant declared per statement. 'single_class_element_per_statement' => true, // There MUST be one use keyword per declaration. @@ -240,8 +242,6 @@ 'single_quote' => true, // Each trait `use` must be done as single statement. 'single_trait_insert_per_statement' => true, - // There MUST NOT be a space after the opening parenthesis. There MUST NOT be a space before the closing parenthesis. - 'spaces_inside_parentheses' => false, // Replace all `<>` with `!=`. 'standardize_not_equals' => true, // Lambdas not (indirect) referencing `$this` must be declared `static`. diff --git a/vendor/nxp/math-executor/README.md b/vendor/nxp/math-executor/README.md index d446dbc..0e88f34 100644 --- a/vendor/nxp/math-executor/README.md +++ b/vendor/nxp/math-executor/README.md @@ -1,11 +1,11 @@ -# MathExecutor [![Tests](https://github.com/neonxp/MathExecutor/workflows/Tests/badge.svg)](https://github.com/neonxp/MathExecutor/actions?query=workflow%3ATests) ![](https://img.shields.io/badge/PHPStan-level%206-brightgreen.svg?style=flat) +# MathExecutor [![Tests](https://github.com/neonxp/MathExecutor/workflows/Tests/badge.svg)](https://github.com/neonxp/MathExecutor/actions?query=workflow%3ATests) # A simple and extensible math expressions calculator ## Features: * Built in support for +, -, *, /, % and power (^) operators -* Parentheses () and arrays [] are fully supported -* Logical operators (==, !=, <, <, >=, <=, &&, ||, !) +* Paratheses () and arrays [] are fully supported +* Logical operators (==, !=, <, <, >=, <=, &&, ||) * Built in support for most PHP math functions * Support for BCMath Arbitrary Precision Math * Support for variable number of function parameters and optional function parameters @@ -40,35 +40,21 @@ Default functions: * abs * acos (arccos) * acosh -* arccos -* arccosec -* arccot -* arccotan -* arccsc (arccosec) * arcctg (arccot, arccotan) * arcsec -* arcsin -* arctan -* arctg +* arccsc (arccosec) * array * asin (arcsin) * atan (atn, arctan, arctg) * atan2 * atanh -* atn * avg * bindec * ceil * cos -* cosec * cosec (csc) * cosh -* cot -* cotan -* cotg -* csc * ctg (cot, cotan, cotg, ctn) -* ctn * decbin * dechex * decoct @@ -81,13 +67,10 @@ Default functions: * hypot * if * intdiv -* lg -* ln * log (ln) * log10 (lg) * log1p * max -* median * min * octdec * pi @@ -100,8 +83,6 @@ Default functions: * sqrt * tan (tn, tg) * tanh -* tg -* tn Add custom function to executor: ```php @@ -115,9 +96,9 @@ $executor->calculate('round(17.119, 2)'); // 17.12 ``` Variable number of parameters: ```php -$executor->addFunction('average', function(...$args) {return array_sum($args) / count($args);}); -$executor->calculate('average(1,3)'); // 2 -$executor->calculate('average(1, 3, 4, 8)'); // 4 +$executor->addFunction('avarage', function(...$args) {return array_sum($args) / count($args);}); +$executor->calculate('avarage(1,3)'); // 2 +$executor->calculate('avarage(1, 3, 4, 8)'); // 4 ``` ## Operators: @@ -144,7 +125,7 @@ $executor->addOperator(new Operator( ``` ## Logical operators: -Logical operators (==, !=, <, <, >=, <=, &&, ||, !) are supported, but logically they can only return true (1) or false (0). In order to leverage them, use the built in **if** function: +Logical operators (==, !=, <, <, >=, <=, &&, ||) are supported, but logically they can only return true (1) or false (0). In order to leverage them, use the built in **if** function: ``` if($a > $b, $a - $b, $b - $a) diff --git a/vendor/nxp/math-executor/composer.json b/vendor/nxp/math-executor/composer.json index 6edd148..6d3759d 100644 --- a/vendor/nxp/math-executor/composer.json +++ b/vendor/nxp/math-executor/composer.json @@ -28,12 +28,11 @@ }, "require": { - "php": ">=8.0 <8.4" + "php": ">=7.4" }, "require-dev": { "phpunit/phpunit": ">=9.0", - "friendsofphp/php-cs-fixer": "^3.8", - "phpstan/phpstan": "^1.9" + "friendsofphp/php-cs-fixer": "^3.8" }, "autoload": { "psr-4": { diff --git a/vendor/nxp/math-executor/phpstan.neon b/vendor/nxp/math-executor/phpstan.neon new file mode 100644 index 0000000..bed17ae --- /dev/null +++ b/vendor/nxp/math-executor/phpstan.neon @@ -0,0 +1,9 @@ +parameters: + level: 6 + paths: + - ./ + excludes_analyse: + - vendor/* + - tests/* + bootstrapFiles: + - vendor/autoload.php \ No newline at end of file diff --git a/vendor/nxp/math-executor/phpstan.neon.dist b/vendor/nxp/math-executor/phpstan.neon.dist deleted file mode 100644 index b05dc95..0000000 --- a/vendor/nxp/math-executor/phpstan.neon.dist +++ /dev/null @@ -1,7 +0,0 @@ -parameters: - level: 6 - errorFormat: raw - editorUrl: '%%file%% %%line%% %%column%%: %%error%%' - paths: - - src - - tests diff --git a/vendor/nxp/math-executor/phpunit.xml.dist b/vendor/nxp/math-executor/phpunit.xml.dist index 56bd7e0..d515f51 100644 --- a/vendor/nxp/math-executor/phpunit.xml.dist +++ b/vendor/nxp/math-executor/phpunit.xml.dist @@ -1,14 +1,19 @@ - - - - ./tests/ - - - + + + + + + ./tests/ + + + \ No newline at end of file diff --git a/vendor/nxp/math-executor/src/NXP/Classes/Calculator.php b/vendor/nxp/math-executor/src/NXP/Classes/Calculator.php index 80dee36..6b63503 100644 --- a/vendor/nxp/math-executor/src/NXP/Classes/Calculator.php +++ b/vendor/nxp/math-executor/src/NXP/Classes/Calculator.php @@ -20,14 +20,22 @@ */ class Calculator { + /** @var array */ + private array $functions = []; + + /** @var array */ + private array $operators = []; + /** * @todo PHP8: Use constructor property promotion -> public function __construct(private array $functions, private array $operators) * * @param array $functions * @param array $operators */ - public function __construct(private array $functions, private array $operators) + public function __construct(array $functions, array $operators) { + $this->functions = $functions; + $this->operators = $operators; } /** diff --git a/vendor/nxp/math-executor/src/NXP/Classes/CustomFunction.php b/vendor/nxp/math-executor/src/NXP/Classes/CustomFunction.php index e4cdd76..85db379 100644 --- a/vendor/nxp/math-executor/src/NXP/Classes/CustomFunction.php +++ b/vendor/nxp/math-executor/src/NXP/Classes/CustomFunction.php @@ -8,6 +8,8 @@ class CustomFunction { + public string $name = ''; + /** * @var callable $function */ @@ -24,8 +26,9 @@ class CustomFunction * * @throws ReflectionException */ - public function __construct(public string $name, callable $function) + public function __construct(string $name, callable $function) { + $this->name = $name; $this->function = $function; $reflection = (new ReflectionFunction($function)); $this->isVariadic = $reflection->isVariadic(); diff --git a/vendor/nxp/math-executor/src/NXP/Classes/Operator.php b/vendor/nxp/math-executor/src/NXP/Classes/Operator.php index 231b1d9..7dee06d 100644 --- a/vendor/nxp/math-executor/src/NXP/Classes/Operator.php +++ b/vendor/nxp/math-executor/src/NXP/Classes/Operator.php @@ -7,6 +7,12 @@ class Operator { + public string $operator = ''; + + public bool $isRightAssoc = false; + + public int $priority = 0; + /** * @var callable(\SplStack) */ @@ -17,8 +23,11 @@ class Operator /** * Operator constructor. */ - public function __construct(public string $operator, public bool $isRightAssoc, public int $priority, callable $function) + public function __construct(string $operator, bool $isRightAssoc, int $priority, callable $function) { + $this->operator = $operator; + $this->isRightAssoc = $isRightAssoc; + $this->priority = $priority; $this->function = $function; $reflection = new ReflectionFunction($function); $this->places = $reflection->getNumberOfParameters(); diff --git a/vendor/nxp/math-executor/src/NXP/Classes/Token.php b/vendor/nxp/math-executor/src/NXP/Classes/Token.php index ae460a9..7532e77 100644 --- a/vendor/nxp/math-executor/src/NXP/Classes/Token.php +++ b/vendor/nxp/math-executor/src/NXP/Classes/Token.php @@ -22,13 +22,22 @@ class Token public const Space = 'space'; + public string $type = self::Literal; + + public $value; + + public ?string $name; + public ?int $paramCount = null;//to store function parameter count in stack /** * Token constructor. * */ - public function __construct(public string $type, public mixed $value, public ?string $name = null) + public function __construct(string $type, $value, ?string $name = null) { + $this->type = $type; + $this->value = $value; + $this->name = $name; } } diff --git a/vendor/nxp/math-executor/src/NXP/Classes/Tokenizer.php b/vendor/nxp/math-executor/src/NXP/Classes/Tokenizer.php index e3c3e6a..a74bff6 100644 --- a/vendor/nxp/math-executor/src/NXP/Classes/Tokenizer.php +++ b/vendor/nxp/math-executor/src/NXP/Classes/Tokenizer.php @@ -23,12 +23,17 @@ class Tokenizer /** @var array */ public array $tokens = []; + private string $input = ''; + private string $numberBuffer = ''; private string $stringBuffer = ''; private bool $allowNegative = true; + /** @var array */ + private array $operators = []; + private bool $inSingleQuotedString = false; private bool $inDoubleQuotedString = false; @@ -37,8 +42,10 @@ class Tokenizer * Tokenizer constructor. * @param Operator[] $operators */ - public function __construct(private string $input, private array $operators) + public function __construct(string $input, array $operators) { + $this->input = $input; + $this->operators = $operators; } public function tokenize() : self @@ -133,16 +140,14 @@ public function tokenize() : self $this->allowNegative = false; break; - /** @noinspection PhpMissingBreakStatementInspection */ case 'e' === \strtolower($ch): - if (\strlen($this->numberBuffer) && \str_contains($this->numberBuffer, '.')) { + if (\strlen($this->numberBuffer) && false !== \strpos($this->numberBuffer, '.')) { $this->numberBuffer .= 'e'; $this->allowNegative = false; break; } - // no break // Intentionally fall through case $this->isAlpha($ch): @@ -209,7 +214,6 @@ public function tokenize() : self continue 2; } - // could be in exponent, in which case negative should be added to the numberBuffer if ($this->numberBuffer && 'e' == $this->numberBuffer[\strlen($this->numberBuffer) - 1]) { $this->numberBuffer .= $ch; @@ -326,7 +330,7 @@ public function buildReversePolishNotation() : array break; } $tokens[] = $ctoken; - } catch (RuntimeException) { + } catch (RuntimeException $e) { throw new IncorrectBracketsException(); } } diff --git a/vendor/nxp/math-executor/src/NXP/MathExecutor.php b/vendor/nxp/math-executor/src/NXP/MathExecutor.php index ff0553d..e991586 100644 --- a/vendor/nxp/math-executor/src/NXP/MathExecutor.php +++ b/vendor/nxp/math-executor/src/NXP/MathExecutor.php @@ -85,10 +85,10 @@ public function addOperator(Operator $operator) : self /** * Execute expression * + * @throws Exception\IncorrectBracketsException * @throws Exception\IncorrectExpressionException * @throws Exception\UnknownOperatorException * @throws UnknownVariableException - * @throws Exception\IncorrectBracketsException * @return int|float|string|null */ public function execute(string $expression, bool $cache = true) @@ -113,7 +113,7 @@ public function execute(string $expression, bool $cache = true) /** * Add function to executor * - * @param string $name Name of function + * @param string $name Name of function * @param callable|null $function Function * * @throws ReflectionException @@ -140,8 +140,9 @@ public function getVars() : array * Get a specific var * * @throws UnknownVariableException if VarNotFoundHandler is not set + * @return int|float */ - public function getVar(string $variable) : mixed + public function getVar(string $variable) { if (! \array_key_exists($variable, $this->variables)) { if ($this->onVarNotFound) { @@ -159,7 +160,7 @@ public function getVar(string $variable) : mixed * * @throws MathExecutorException if the value is invalid based on the default or custom validator */ - public function setVar(string $variable, mixed $value) : self + public function setVar(string $variable, $value) : self { if ($this->onVarValidation) { \call_user_func($this->onVarValidation, $variable, $value); @@ -182,8 +183,8 @@ public function varExists(string $variable) : bool /** * Add variables to executor * - * @param array $variables - * @param bool $clear Clear previous variables + * @param array $variables + * @param bool $clear Clear previous variables * @throws \Exception */ public function setVars(array $variables, bool $clear = true) : self @@ -272,6 +273,8 @@ public function getFunctions() : array /** * Remove a specific operator + * + * @return array of operator class names */ public function removeOperator(string $operator) : self { @@ -285,7 +288,7 @@ public function removeOperator(string $operator) : self */ public function setDivisionByZeroIsZero() : self { - $this->addOperator(new Operator('/', false, 180, static fn($a, $b) => 0 == $b ? 0 : $a / $b)); + $this->addOperator(new Operator('/', false, 180, static fn ($a, $b) => 0 == $b ? 0 : $a / $b)); return $this; } @@ -311,23 +314,23 @@ public function clearCache() : self public function useBCMath(int $scale = 2) : self { - \bcscale($scale); - $this->addOperator(new Operator('+', false, 170, static fn($a, $b) => \bcadd("{$a}", "{$b}"))); - $this->addOperator(new Operator('-', false, 170, static fn($a, $b) => \bcsub("{$a}", "{$b}"))); - $this->addOperator(new Operator('uNeg', false, 200, static fn($a) => \bcsub('0.0', "{$a}"))); - $this->addOperator(new Operator('*', false, 180, static fn($a, $b) => \bcmul("{$a}", "{$b}"))); - $this->addOperator(new Operator('/', false, 180, static function($a, $b) { - /** @todo PHP8: Use throw as expression -> static fn($a, $b) => 0 == $b ? throw new DivisionByZeroException() : $a / $b */ - if (0 == $b) { - throw new DivisionByZeroException(); - } - - return \bcdiv("{$a}", "{$b}"); - })); - $this->addOperator(new Operator('^', true, 220, static fn($a, $b) => \bcpow("{$a}", "{$b}"))); - $this->addOperator(new Operator('%', false, 180, static fn($a, $b) => \bcmod("{$a}", "{$b}"))); - - return $this; + \bcscale($scale); + $this->addOperator(new Operator('+', false, 170, static fn ($a, $b) => \bcadd("{$a}", "{$b}"))); + $this->addOperator(new Operator('-', false, 170, static fn ($a, $b) => \bcsub("{$a}", "{$b}"))); + $this->addOperator(new Operator('uNeg', false, 200, static fn ($a) => \bcsub('0.0', "{$a}"))); + $this->addOperator(new Operator('*', false, 180, static fn ($a, $b) => \bcmul("{$a}", "{$b}"))); + $this->addOperator(new Operator('/', false, 180, static function($a, $b) { + /** @todo PHP8: Use throw as expression -> static fn($a, $b) => 0 == $b ? throw new DivisionByZeroException() : $a / $b */ + if (0 == $b) { + throw new DivisionByZeroException(); + } + + return \bcdiv("{$a}", "{$b}"); + })); + $this->addOperator(new Operator('^', true, 220, static fn ($a, $b) => \bcpow("{$a}", "{$b}"))); + $this->addOperator(new Operator('%', false, 180, static fn ($a, $b) => \bcmod("{$a}", "{$b}"))); + + return $this; } /** @@ -359,16 +362,15 @@ protected function addDefaults() : self protected function defaultOperators() : array { return [ - '+' => [static fn($a, $b) => $a + $b, 170, false], - '-' => [static fn($a, $b) => $a - $b, 170, false], + '+' => [static fn ($a, $b) => $a + $b, 170, false], + '-' => [static fn ($a, $b) => $a - $b, 170, false], // unary positive token - 'uPos' => [static fn($a) => $a, 200, false], + 'uPos' => [static fn ($a) => $a, 200, false], // unary minus token - 'uNeg' => [static fn($a) => 0 - $a, 200, false], - '*' => [static fn($a, $b) => $a * $b, 180, false], + 'uNeg' => [static fn ($a) => 0 - $a, 200, false], + '*' => [static fn ($a, $b) => $a * $b, 180, false], '/' => [ - static function($a, $b) { - /** @todo PHP8: Use throw as expression -> static fn($a, $b) => 0 == $b ? throw new DivisionByZeroException() : $a / $b */ + static function($a, $b) { /** @todo PHP8: Use throw as expression -> static fn($a, $b) => 0 == $b ? throw new DivisionByZeroException() : $a / $b */ if (0 == $b) { throw new DivisionByZeroException(); } @@ -378,17 +380,16 @@ static function($a, $b) { 180, false ], - '^' => [static fn($a, $b) => $a ** $b, 220, true], - '%' => [static fn($a, $b) => $a % $b, 180, false], - '&&' => [static fn($a, $b) => $a && $b, 100, false], - '||' => [static fn($a, $b) => $a || $b, 90, false], - '==' => [static fn($a, $b) => \is_string($a) || \is_string($b) ? 0 == \strcmp((string)$a, (string)$b) : $a == $b, 140, false], - '!=' => [static fn($a, $b) => \is_string($a) || \is_string($b) ? 0 != \strcmp((string)$a, (string)$b) : $a != $b, 140, false], - '>=' => [static fn($a, $b) => $a >= $b, 150, false], - '>' => [static fn($a, $b) => $a > $b, 150, false], - '<=' => [static fn($a, $b) => $a <= $b, 150, false], - '<' => [static fn($a, $b) => $a < $b, 150, false], - '!' => [static fn($a) => ! $a, 190, false], + '^' => [static fn ($a, $b) => \pow($a, $b), 220, true], + '%' => [static fn ($a, $b) => $a % $b, 180, false], + '&&' => [static fn ($a, $b) => $a && $b, 100, false], + '||' => [static fn ($a, $b) => $a || $b, 90, false], + '==' => [static fn ($a, $b) => \is_string($a) || \is_string($b) ? 0 == \strcmp($a, $b) : $a == $b, 140, false], + '!=' => [static fn ($a, $b) => \is_string($a) || \is_string($b) ? 0 != \strcmp($a, $b) : $a != $b, 140, false], + '>=' => [static fn ($a, $b) => $a >= $b, 150, false], + '>' => [static fn ($a, $b) => $a > $b, 150, false], + '<=' => [static fn ($a, $b) => $a <= $b, 150, false], + '<' => [static fn ($a, $b) => $a < $b, 150, false], ]; } @@ -401,28 +402,28 @@ static function($a, $b) { protected function defaultFunctions() : array { return [ - 'abs' => static fn($arg) => \abs($arg), - 'acos' => static fn($arg) => \acos($arg), - 'acosh' => static fn($arg) => \acosh($arg), - 'arcsin' => static fn($arg) => \asin($arg), - 'arcctg' => static fn($arg) => M_PI / 2 - \atan($arg), - 'arccot' => static fn($arg) => M_PI / 2 - \atan($arg), - 'arccotan' => static fn($arg) => M_PI / 2 - \atan($arg), - 'arcsec' => static fn($arg) => \acos(1 / $arg), - 'arccosec' => static fn($arg) => \asin(1 / $arg), - 'arccsc' => static fn($arg) => \asin(1 / $arg), - 'arccos' => static fn($arg) => \acos($arg), - 'arctan' => static fn($arg) => \atan($arg), - 'arctg' => static fn($arg) => \atan($arg), - 'array' => static fn(...$args) => $args, - 'asin' => static fn($arg) => \asin($arg), - 'atan' => static fn($arg) => \atan($arg), - 'atan2' => static fn($arg1, $arg2) => \atan2($arg1, $arg2), - 'atanh' => static fn($arg) => \atanh($arg), - 'atn' => static fn($arg) => \atan($arg), + 'abs' => static fn ($arg) => \abs($arg), + 'acos' => static fn ($arg) => \acos($arg), + 'acosh' => static fn ($arg) => \acosh($arg), + 'arcsin' => static fn ($arg) => \asin($arg), + 'arcctg' => static fn ($arg) => M_PI / 2 - \atan($arg), + 'arccot' => static fn ($arg) => M_PI / 2 - \atan($arg), + 'arccotan' => static fn ($arg) => M_PI / 2 - \atan($arg), + 'arcsec' => static fn ($arg) => \acos(1 / $arg), + 'arccosec' => static fn ($arg) => \asin(1 / $arg), + 'arccsc' => static fn ($arg) => \asin(1 / $arg), + 'arccos' => static fn ($arg) => \acos($arg), + 'arctan' => static fn ($arg) => \atan($arg), + 'arctg' => static fn ($arg) => \atan($arg), + 'array' => static fn (...$args) => $args, + 'asin' => static fn ($arg) => \asin($arg), + 'atan' => static fn ($arg) => \atan($arg), + 'atan2' => static fn ($arg1, $arg2) => \atan2($arg1, $arg2), + 'atanh' => static fn ($arg) => \atanh($arg), + 'atn' => static fn ($arg) => \atan($arg), 'avg' => static function($arg1, ...$args) { - if (\is_array($arg1)) { - if (0 === \count($arg1)) { + if (\is_array($arg1)){ + if (0 === \count($arg1)){ throw new \InvalidArgumentException('avg() must have at least one argument!'); } @@ -433,27 +434,27 @@ protected function defaultFunctions() : array return \array_sum($args) / \count($args); }, - 'bindec' => static fn($arg) => \bindec($arg), - 'ceil' => static fn($arg) => \ceil($arg), - 'cos' => static fn($arg) => \cos($arg), - 'cosec' => static fn($arg) => 1 / \sin($arg), - 'csc' => static fn($arg) => 1 / \sin($arg), - 'cosh' => static fn($arg) => \cosh($arg), - 'ctg' => static fn($arg) => \cos($arg) / \sin($arg), - 'cot' => static fn($arg) => \cos($arg) / \sin($arg), - 'cotan' => static fn($arg) => \cos($arg) / \sin($arg), - 'cotg' => static fn($arg) => \cos($arg) / \sin($arg), - 'ctn' => static fn($arg) => \cos($arg) / \sin($arg), - 'decbin' => static fn($arg) => \decbin($arg), - 'dechex' => static fn($arg) => \dechex($arg), - 'decoct' => static fn($arg) => \decoct($arg), - 'deg2rad' => static fn($arg) => \deg2rad($arg), - 'exp' => static fn($arg) => \exp($arg), - 'expm1' => static fn($arg) => \expm1($arg), - 'floor' => static fn($arg) => \floor($arg), - 'fmod' => static fn($arg1, $arg2) => \fmod($arg1, $arg2), - 'hexdec' => static fn($arg) => \hexdec($arg), - 'hypot' => static fn($arg1, $arg2) => \hypot($arg1, $arg2), + 'bindec' => static fn ($arg) => \bindec($arg), + 'ceil' => static fn ($arg) => \ceil($arg), + 'cos' => static fn ($arg) => \cos($arg), + 'cosec' => static fn ($arg) => 1 / \sin($arg), + 'csc' => static fn ($arg) => 1 / \sin($arg), + 'cosh' => static fn ($arg) => \cosh($arg), + 'ctg' => static fn ($arg) => \cos($arg) / \sin($arg), + 'cot' => static fn ($arg) => \cos($arg) / \sin($arg), + 'cotan' => static fn ($arg) => \cos($arg) / \sin($arg), + 'cotg' => static fn ($arg) => \cos($arg) / \sin($arg), + 'ctn' => static fn ($arg) => \cos($arg) / \sin($arg), + 'decbin' => static fn ($arg) => \decbin($arg), + 'dechex' => static fn ($arg) => \dechex($arg), + 'decoct' => static fn ($arg) => \decoct($arg), + 'deg2rad' => static fn ($arg) => \deg2rad($arg), + 'exp' => static fn ($arg) => \exp($arg), + 'expm1' => static fn ($arg) => \expm1($arg), + 'floor' => static fn ($arg) => \floor($arg), + 'fmod' => static fn ($arg1, $arg2) => \fmod($arg1, $arg2), + 'hexdec' => static fn ($arg) => \hexdec($arg), + 'hypot' => static fn ($arg1, $arg2) => \hypot($arg1, $arg2), 'if' => function($expr, $trueval, $falseval) { if (true === $expr || false === $expr) { $exres = $expr; @@ -467,56 +468,39 @@ protected function defaultFunctions() : array return $this->execute($falseval); }, - 'intdiv' => static fn($arg1, $arg2) => \intdiv($arg1, $arg2), - 'ln' => static fn($arg1, $arg2 = M_E) => \log($arg1, $arg2), - 'lg' => static fn($arg) => \log10($arg), - 'log' => static fn($arg1, $arg2 = M_E) => \log($arg1, $arg2), - 'log10' => static fn($arg) => \log10($arg), - 'log1p' => static fn($arg) => \log1p($arg), + 'intdiv' => static fn ($arg1, $arg2) => \intdiv($arg1, $arg2), + 'ln' => static fn ($arg) => \log($arg), + 'lg' => static fn ($arg) => \log10($arg), + 'log' => static fn ($arg) => \log($arg), + 'log10' => static fn ($arg) => \log10($arg), + 'log1p' => static fn ($arg) => \log1p($arg), 'max' => static function($arg1, ...$args) { - if (\is_array($arg1) && 0 === \count($arg1)) { + if (\is_array($arg1) && 0 === \count($arg1)){ throw new \InvalidArgumentException('max() must have at least one argument!'); } return \max(\is_array($arg1) ? $arg1 : [$arg1, ...$args]); }, - 'median' => static function($arg1, ...$args) { - if (\is_array($arg1)) { - if (0 === \count($arg1)) { - throw new \InvalidArgumentException('Array must contain at least one element!'); - } - - $finalArgs = $arg1; - } else { - $finalArgs = [$arg1, ...$args]; - } - - $count = \count($finalArgs); - \sort($finalArgs); - $index = \floor($count / 2); - - return ($count & 1) ? $finalArgs[$index] : ($finalArgs[$index - 1] + $finalArgs[$index]) / 2; - }, 'min' => static function($arg1, ...$args) { - if (\is_array($arg1) && 0 === \count($arg1)) { + if (\is_array($arg1) && 0 === \count($arg1)){ throw new \InvalidArgumentException('min() must have at least one argument!'); } return \min(\is_array($arg1) ? $arg1 : [$arg1, ...$args]); }, - 'octdec' => static fn($arg) => \octdec($arg), - 'pi' => static fn() => M_PI, - 'pow' => static fn($arg1, $arg2) => $arg1 ** $arg2, - 'rad2deg' => static fn($arg) => \rad2deg($arg), - 'round' => static fn($num, int $precision = 0) => \round($num, $precision), - 'sin' => static fn($arg) => \sin($arg), - 'sinh' => static fn($arg) => \sinh($arg), - 'sec' => static fn($arg) => 1 / \cos($arg), - 'sqrt' => static fn($arg) => \sqrt($arg), - 'tan' => static fn($arg) => \tan($arg), - 'tanh' => static fn($arg) => \tanh($arg), - 'tn' => static fn($arg) => \tan($arg), - 'tg' => static fn($arg) => \tan($arg) + 'octdec' => static fn ($arg) => \octdec($arg), + 'pi' => static fn () => M_PI, + 'pow' => static fn ($arg1, $arg2) => $arg1 ** $arg2, + 'rad2deg' => static fn ($arg) => \rad2deg($arg), + 'round' => static fn ($num, int $precision = 0) => \round($num, $precision), + 'sin' => static fn ($arg) => \sin($arg), + 'sinh' => static fn ($arg) => \sinh($arg), + 'sec' => static fn ($arg) => 1 / \cos($arg), + 'sqrt' => static fn ($arg) => \sqrt($arg), + 'tan' => static fn ($arg) => \tan($arg), + 'tanh' => static fn ($arg) => \tanh($arg), + 'tn' => static fn ($arg) => \tan($arg), + 'tg' => static fn ($arg) => \tan($arg) ]; } @@ -537,7 +521,7 @@ protected function defaultVars() : array * Default variable validation, ensures that the value is a scalar or array. * @throws MathExecutorException if the value is not a scalar */ - protected function defaultVarValidation(string $variable, mixed $value) : void + protected function defaultVarValidation(string $variable, $value) : void { if (! \is_scalar($value) && ! \is_array($value) && null !== $value) { $type = \gettype($value); diff --git a/vendor/nxp/math-executor/tests/MathTest.php b/vendor/nxp/math-executor/tests/MathTest.php index b3b78e1..0c87c45 100644 --- a/vendor/nxp/math-executor/tests/MathTest.php +++ b/vendor/nxp/math-executor/tests/MathTest.php @@ -31,13 +31,12 @@ public function testCalculating(string $expression) : void $calculator = new MathExecutor(); /** @var float $phpResult */ - $phpResult = 0.0; eval('$phpResult = ' . $expression . ';'); try { $result = $calculator->execute($expression); } catch (Exception $e) { - $this->fail(\sprintf('Exception: %s (%s:%d), expression was: %s', $e::class, $e->getFile(), $e->getLine(), $expression)); + $this->fail(\sprintf('Exception: %s (%s:%d), expression was: %s', \get_class($e), $e->getFile(), $e->getLine(), $expression)); } $this->assertEquals($phpResult, $result, "Expression was: {$expression}"); } @@ -48,10 +47,8 @@ public function testCalculating(string $expression) : void * Most tests can go in here. The idea is that each expression will be evaluated by MathExecutor and by PHP with eval. * The results should be the same. If they are not, then the test fails. No need to add extra test unless you are doing * something more complex and not a simple mathmatical expression. - * - * @return array> */ - public static function providerExpressions() + public function providerExpressions() { return [ ['-5'], @@ -97,7 +94,6 @@ public static function providerExpressions() ['hypot(1.5, 3.5)'], ['intdiv(10, 2)'], ['log(1.5)'], - ['log(1.5, 3)'], ['log10(1.5)'], ['log1p(1.5)'], ['max(1.5, 3.5)'], @@ -257,15 +253,6 @@ public static function providerExpressions() ['7 % 4'], ['99 % 4'], ['123 % 7'], - - ['!(1||0)'], - ['!(1&&0)'], - ['!(1)'], - ['!(0)'], - ['! 1'], - ['! 0'], - ['!1'], - ['!0'], ]; } @@ -283,13 +270,12 @@ public function testBCMathCalculating(string $expression, string $expected = '') } /** @var float $phpResult */ - $phpResult = 0.0; eval('$phpResult = ' . $expected . ';'); try { $result = $calculator->execute($expression); } catch (Exception $e) { - $this->fail(\sprintf('Exception: %s (%s:%d), expression was: %s', $e::class, $e->getFile(), $e->getLine(), $expression)); + $this->fail(\sprintf('Exception: %s (%s:%d), expression was: %s', \get_class($e), $e->getFile(), $e->getLine(), $expression)); } $this->assertEquals($phpResult, $result, "Expression was: {$expression}"); } @@ -300,10 +286,8 @@ public function testBCMathCalculating(string $expression, string $expected = '') * Most tests can go in here. The idea is that each expression will be evaluated by MathExecutor and by PHP with eval. * The results should be the same. If they are not, then the test fails. No need to add extra test unless you are doing * something more complex and not a simple mathmatical expression. - * - * @return array> */ - public static function bcMathExpressions() + public function bcMathExpressions() { return [ ['-5'], @@ -503,15 +487,6 @@ public static function bcMathExpressions() ['7 % 4'], ['99 % 4'], ['123 % 7'], - - ['!(1||0)'], - ['!(1&&0)'], - ['!(1)'], - ['!(0)'], - ['! 1'], - ['! 0'], - ['!1'], - ['!0'], ]; } @@ -530,10 +505,8 @@ public function testIncorrectExpressionException(string $expression) : void * Incorrect Expressions data provider * * These expressions should not pass validation - * - * @return array> */ - public static function incorrectExpressions() + public function incorrectExpressions() { return [ ['1 * + '], @@ -597,21 +570,6 @@ public function testVariableIncorrectExpressionException() : void $this->assertEquals(0.0, $calculator->execute('$ + $four')); } - public function testNotVariableOperator() : void - { - $calculator = new MathExecutor(); - $calculator->setVar('one', 1); - $calculator->setVar('zero', 0); - $this->assertEquals(false, $calculator->execute('! $one')); - $this->assertEquals(false, $calculator->execute('!$one')); - $this->assertEquals(false, $calculator->execute('! ($one)')); - $this->assertEquals(false, $calculator->execute('!($one)')); - $this->assertEquals(true, $calculator->execute('! $zero')); - $this->assertEquals(true, $calculator->execute('!$zero')); - $this->assertEquals(true, $calculator->execute('! ($zero)')); - $this->assertEquals(true, $calculator->execute('!($zero)')); - } - public function testExponentiation() : void { $calculator = new MathExecutor(); @@ -634,7 +592,9 @@ public function testStringEscape() : void $this->assertEquals("'teststring", $calculator->execute("'\'teststring'")); $this->assertEquals("teststring'", $calculator->execute("'teststring\''")); - $calculator->addFunction('concat', static fn($arg1, $arg2) => $arg1 . $arg2); + $calculator->addFunction('concat', static function($arg1, $arg2) { + return $arg1 . $arg2; + }); $this->assertEquals('test"ing', $calculator->execute('concat("test\"","ing")')); $this->assertEquals("test'ing", $calculator->execute("concat('test\'','ing')")); } @@ -648,7 +608,7 @@ public function testArrays() : void $this->assertEquals(\max([1, 5, 2]), $calculator->execute('max(array(1, 5, 2))')); $calculator->addFunction('arr_with_max_elements', static function($arg1, ...$args) { $args = \is_array($arg1) ? $arg1 : [$arg1, ...$args]; - \usort($args, static fn($arr1, $arr2) => (\is_countable($arr2) ? \count($arr2) : 0) <=> \count($arr1)); + \usort($args, static fn ($arr1, $arr2) => \count($arr2) <=> \count($arr1)); return $args[0]; }); @@ -659,7 +619,9 @@ public function testFunctionParameterOrder() : void { $calculator = new MathExecutor(); - $calculator->addFunction('concat', static fn($arg1, $arg2) => $arg1 . $arg2); + $calculator->addFunction('concat', static function($arg1, $arg2) { + return $arg1 . $arg2; + }); $this->assertEquals('testing', $calculator->execute('concat("test","ing")')); $this->assertEquals('testing', $calculator->execute("concat('test','ing')")); } @@ -667,34 +629,37 @@ public function testFunctionParameterOrder() : void public function testFunction() : void { $calculator = new MathExecutor(); - $calculator->addFunction('round', static fn($arg) => \round($arg)); + $calculator->addFunction('round', static function($arg) { + return \round($arg); + }); $this->assertEquals(\round(100 / 30), $calculator->execute('round(100/30)')); } public function testFunctionUnlimitedParameters() : void { $calculator = new MathExecutor(); - $calculator->addFunction('give_me_an_array', static fn() => [5, 3, 7, 9, 8]); + $calculator->addFunction('give_me_an_array', static function() { + return [5, 3, 7, 9, 8]; + }); $this->assertEquals(6.4, $calculator->execute('avg(give_me_an_array())')); $this->assertEquals(10, $calculator->execute('avg(12,8,15,5)')); $this->assertEquals(3, $calculator->execute('min(give_me_an_array())')); $this->assertEquals(1, $calculator->execute('min(1,2,3)')); $this->assertEquals(9, $calculator->execute('max(give_me_an_array())')); $this->assertEquals(3, $calculator->execute('max(1,2,3)')); - $this->assertEquals(7, $calculator->execute('median(give_me_an_array())')); - $this->assertEquals(4, $calculator->execute('median(1,3,5,7)')); $calculator->setVar('monthly_salaries', [100, 200, 300]); $this->assertEquals([100, 200, 300], $calculator->execute('$monthly_salaries')); $this->assertEquals(200, $calculator->execute('avg($monthly_salaries)')); $this->assertEquals(\min([100, 200, 300]), $calculator->execute('min($monthly_salaries)')); $this->assertEquals(\max([100, 200, 300]), $calculator->execute('max($monthly_salaries)')); - $this->assertEquals(200, $calculator->execute('median($monthly_salaries)')); } public function testFunctionOptionalParameters() : void { $calculator = new MathExecutor(); - $calculator->addFunction('round', static fn($num, $precision = 0) => \round($num, $precision)); + $calculator->addFunction('round', static function($num, $precision = 0) { + return \round($num, $precision); + }); $this->assertEquals(\round(11.176), $calculator->execute('round(11.176)')); $this->assertEquals(\round(11.176, 2), $calculator->execute('round(11.176,2)')); } @@ -703,7 +668,9 @@ public function testFunctionIncorrectNumberOfParameters() : void { $calculator = new MathExecutor(); $this->expectException(IncorrectNumberOfFunctionParametersException::class); - $calculator->addFunction('myfunc', static fn($arg1, $arg2) => $arg1 + $arg2); + $calculator->addFunction('myfunc', static function($arg1, $arg2) { + return $arg1 + $arg2; + }); $calculator->execute('myfunc(1)'); } @@ -711,7 +678,9 @@ public function testFunctionIncorrectNumberOfParametersTooMany() : void { $calculator = new MathExecutor(); $this->expectException(IncorrectNumberOfFunctionParametersException::class); - $calculator->addFunction('myfunc', static fn($arg1, $arg2) => $arg1 + $arg2); + $calculator->addFunction('myfunc', static function($arg1, $arg2) { + return $arg1 + $arg2; + }); $calculator->execute('myfunc(1,2,3)'); } @@ -721,57 +690,57 @@ public function testFunctionIf() : void $this->assertEquals( 30, $calculator->execute( - 'if(100 > 99, 30, 0)' - ), + 'if(100 > 99, 30, 0)' + ), 'Expression failed: if(100 > 99, 30, 0)' ); $this->assertEquals( 0, $calculator->execute( - 'if(100 < 99, 30, 0)' - ), + 'if(100 < 99, 30, 0)' + ), 'Expression failed: if(100 < 99, 30, 0)' ); $this->assertEquals( 30, $calculator->execute( - 'if(98 < 99 && sin(1) < 1, 30, 0)' - ), + 'if(98 < 99 && sin(1) < 1, 30, 0)' + ), 'Expression failed: if(98 < 99 && sin(1) < 1, 30, 0)' ); $this->assertEquals( 40, $calculator->execute( - 'if(98 < 99 && sin(1) < 1, max(30, 40), 0)' - ), + 'if(98 < 99 && sin(1) < 1, max(30, 40), 0)' + ), 'Expression failed: if(98 < 99 && sin(1) < 1, max(30, 40), 0)' ); $this->assertEquals( 40, $calculator->execute( - 'if(98 < 99 && sin(1) < 1, if(10 > 5, max(30, 40), 1), 0)' - ), + 'if(98 < 99 && sin(1) < 1, if(10 > 5, max(30, 40), 1), 0)' + ), 'Expression failed: if(98 < 99 && sin(1) < 1, if(10 > 5, max(30, 40), 1), 0)' ); $this->assertEquals( 20, $calculator->execute( - 'if(98 < 99 && sin(1) > 1, if(10 > 5, max(30, 40), 1), if(4 <= 4, 20, 21))' - ), + 'if(98 < 99 && sin(1) > 1, if(10 > 5, max(30, 40), 1), if(4 <= 4, 20, 21))' + ), 'Expression failed: if(98 < 99 && sin(1) > 1, if(10 > 5, max(30, 40), 1), if(4 <= 4, 20, 21))' ); $this->assertEquals( \cos(2), $calculator->execute( - 'if(98 < 99 && sin(1) >= 1, max(30, 40), cos(2))' - ), + 'if(98 < 99 && sin(1) >= 1, max(30, 40), cos(2))' + ), 'Expression failed: if(98 < 99 && sin(1) >= 1, max(30, 40), cos(2))' ); $this->assertEquals( \cos(2), $calculator->execute( - 'if(cos(2), cos(2), 0)' - ), + 'if(cos(2), cos(2), 0)' + ), 'Expression failed: if(cos(2), cos(2), 0)' ); $trx_amount = 100000; @@ -780,15 +749,15 @@ public function testFunctionIf() : void $this->assertEquals( $trx_amount * 0.03, $calculator->execute( - 'if($trx_amount < 40000, $trx_amount * 0.06, $trx_amount * 0.03)' - ), + 'if($trx_amount < 40000, $trx_amount * 0.06, $trx_amount * 0.03)' + ), 'Expression failed: if($trx_amount < 40000, $trx_amount * 0.06, $trx_amount * 0.03)' ); $this->assertEquals( $trx_amount * 0.03, $calculator->execute( - 'if($trx_amount < 40000, $trx_amount * 0.06, if($trx_amount < 60000, $trx_amount * 0.05, $trx_amount * 0.03))' - ), + 'if($trx_amount < 40000, $trx_amount * 0.06, if($trx_amount < 60000, $trx_amount * 0.05, $trx_amount * 0.03))' + ), 'Expression failed: if($trx_amount < 40000, $trx_amount * 0.06, if($trx_amount < 60000, $trx_amount * 0.05, $trx_amount * 0.03))' ); $trx_amount = 39000; @@ -796,8 +765,8 @@ public function testFunctionIf() : void $this->assertEquals( $trx_amount * 0.06, $calculator->execute( - 'if($trx_amount < 40000, $trx_amount * 0.06, if($trx_amount < 60000, $trx_amount * 0.05, $trx_amount * 0.03))' - ), + 'if($trx_amount < 40000, $trx_amount * 0.06, if($trx_amount < 60000, $trx_amount * 0.05, $trx_amount * 0.03))' + ), 'Expression failed: if($trx_amount < 40000, $trx_amount * 0.06, if($trx_amount < 60000, $trx_amount * 0.05, $trx_amount * 0.03))' ); $trx_amount = 59000; @@ -805,16 +774,16 @@ public function testFunctionIf() : void $this->assertEquals( $trx_amount * 0.05, $calculator->execute( - 'if($trx_amount < 40000, $trx_amount * 0.06, if($trx_amount < 60000, $trx_amount * 0.05, $trx_amount * 0.03))' - ), + 'if($trx_amount < 40000, $trx_amount * 0.06, if($trx_amount < 60000, $trx_amount * 0.05, $trx_amount * 0.03))' + ), 'Expression failed: if($trx_amount < 40000, $trx_amount * 0.06, if($trx_amount < 60000, $trx_amount * 0.05, $trx_amount * 0.03))' ); $this->expectException(IncorrectNumberOfFunctionParametersException::class); $this->assertEquals( 0.0, $calculator->execute( - 'if($trx_amount < 40000, $trx_amount * 0.06)' - ), + 'if($trx_amount < 40000, $trx_amount * 0.06)' + ), 'Expression failed: if($trx_amount < 40000, $trx_amount * 0.06)' ); } @@ -863,7 +832,9 @@ public function testEvaluateFunctionParameters() : void $calculator = new MathExecutor(); $calculator->addFunction( 'round', - static fn($value, $decimals) => \round($value, $decimals) + static function($value, $decimals) { + return \round($value, $decimals); + } ); $expression = 'round(100 * 1.111111, 2)'; $phpResult = 0; @@ -877,7 +848,9 @@ public function testEvaluateFunctionParameters() : void public function testFunctionsWithQuotes() : void { $calculator = new MathExecutor(); - $calculator->addFunction('concat', static fn($first, $second) => $first . $second); + $calculator->addFunction('concat', static function($first, $second) { + return $first . $second; + }); $this->assertEquals('testing', $calculator->execute('concat("test", "ing")')); $this->assertEquals('testing', $calculator->execute("concat('test', 'ing')")); } @@ -1048,7 +1021,6 @@ public function testSetCustomVarValidator() : void if (\is_scalar($variable) || null === $variable) { return; } - // Allow variables of type DateTime, but not others if (! $variable instanceof \DateTime) { throw new MathExecutorException('Invalid variable type'); @@ -1101,14 +1073,14 @@ public function testVarExists() : void /** * @dataProvider providerExpressionValues */ - public function testCalculatingValues(string $expression, mixed $value) : void + public function testCalculatingValues($expression, $value) : void { $calculator = new MathExecutor(); try { $result = $calculator->execute($expression); } catch (Exception $e) { - $this->fail(\sprintf('Exception: %s (%s:%d), expression was: %s', $e::class, $e->getFile(), $e->getLine(), $expression)); + $this->fail(\sprintf('Exception: %s (%s:%d), expression was: %s', \get_class($e), $e->getFile(), $e->getLine(), $expression)); } $this->assertEquals($value, $result, "{$expression} did not evaluate to {$value}"); } @@ -1119,10 +1091,8 @@ public function testCalculatingValues(string $expression, mixed $value) : void * Most tests can go in here. The idea is that each expression will be evaluated by MathExecutor and by PHP directly. * The results should be the same. If they are not, then the test fails. No need to add extra test unless you are doing * something more complex and not a simple mathmatical expression. - * - * @return array> */ - public static function providerExpressionValues() + public function providerExpressionValues() { return [ ['arccos(0.5)', \acos(0.5)], @@ -1149,7 +1119,6 @@ public static function providerExpressionValues() ['decbin(10)', \decbin(10)], ['lg(2)', \log10(2)], ['ln(2)', \log(2)], - ['ln(2, 5)', \log(2, 5)], ['sec(4)', 1 / \cos(4)], ['tg(4)', \tan(4)], ];