From 065a027640049f5cf59013e21ea5a9cd73da76fc Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Fri, 3 Jan 2025 17:26:15 -0500 Subject: [PATCH 01/40] Update phone validation regex to accept only numbers and correct amount --- mailchimp.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mailchimp.php b/mailchimp.php index f9870e5..263e2f7 100644 --- a/mailchimp.php +++ b/mailchimp.php @@ -1061,7 +1061,7 @@ function mailchimp_sf_merge_validate_phone( $opt_val, $data ) { $opt_val = ''; } - if ( ! preg_match( '/[0-9]{0,3}-[0-9]{0,3}-[0-9]{0,4}/A', $opt_val ) ) { + if ( ! preg_match( '/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/', $opt_val ) ) { /* translators: %s: field name */ $message = sprintf( esc_html__( '%s must consist of only numbers', 'mailchimp' ), esc_html( $data['name'] ) ); $error = new WP_Error( 'mc_phone_validation', $message ); From c4a7d56eb9690d414929c6863eeaf1171a194798 Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Fri, 3 Jan 2025 18:58:27 -0500 Subject: [PATCH 02/40] Strip whitespace from beginning, middle, and end of phone number --- mailchimp.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/mailchimp.php b/mailchimp.php index 263e2f7..7a946a6 100644 --- a/mailchimp.php +++ b/mailchimp.php @@ -1046,16 +1046,22 @@ function mailchimp_sf_merge_submit( $mv ) { * * @param array $opt_val Option value * @param array $data Data - * @return void + * @return void|WP_Error */ function mailchimp_sf_merge_validate_phone( $opt_val, $data ) { - // This filters out all 'falsey' elements + // Filter out falsy values $opt_val = array_filter( $opt_val ); - // If they weren't all empty + + // If they were all empty if ( ! $opt_val ) { return; } + // Trim whitespace + $opt_val = array_map( 'trim', $opt_val ); // Beginning and end + $opt_val = array_map( fn($s) => preg_replace( '/\s/', '', $s ), $opt_val ); // Middle + + // Check string length $opt_val = implode( '-', $opt_val ); if ( strlen( $opt_val ) < 12 ) { $opt_val = ''; From 37b58b1f2f648776ebff5076b1dee1e0e80b11da Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Fri, 3 Jan 2025 19:01:41 -0500 Subject: [PATCH 03/40] Add custom message for not enough digits --- mailchimp.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/mailchimp.php b/mailchimp.php index 7a946a6..c882d40 100644 --- a/mailchimp.php +++ b/mailchimp.php @@ -1061,17 +1061,18 @@ function mailchimp_sf_merge_validate_phone( $opt_val, $data ) { $opt_val = array_map( 'trim', $opt_val ); // Beginning and end $opt_val = array_map( fn($s) => preg_replace( '/\s/', '', $s ), $opt_val ); // Middle - // Check string length + // Format number for validation $opt_val = implode( '-', $opt_val ); - if ( strlen( $opt_val ) < 12 ) { - $opt_val = ''; - } - if ( ! preg_match( '/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/', $opt_val ) ) { + // Check string length + if ( strlen( $opt_val ) < 12 ) { + /* translators: %s: field name */ + $message = sprintf( esc_html__( '%s must contain the correct amount of digits', 'mailchimp' ), esc_html( $data['name'] ) ); + $opt_val = new WP_Error( 'mc_phone_validation', $message ); + } else if ( ! preg_match( '/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/', $opt_val ) ) { /* translators: %s: field name */ $message = sprintf( esc_html__( '%s must consist of only numbers', 'mailchimp' ), esc_html( $data['name'] ) ); - $error = new WP_Error( 'mc_phone_validation', $message ); - return $error; + $opt_val = new WP_Error( 'mc_phone_validation', $message ); } return $opt_val; From ff888a8710e8511817771ebd95fcb52f7501bf66 Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Fri, 3 Jan 2025 19:12:17 -0500 Subject: [PATCH 04/40] Refactor if else ladder to switch statement for readability --- mailchimp.php | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/mailchimp.php b/mailchimp.php index c882d40..8ed5d6e 100644 --- a/mailchimp.php +++ b/mailchimp.php @@ -1046,7 +1046,7 @@ function mailchimp_sf_merge_submit( $mv ) { * * @param array $opt_val Option value * @param array $data Data - * @return void|WP_Error + * @return array|WP_Error */ function mailchimp_sf_merge_validate_phone( $opt_val, $data ) { // Filter out falsy values @@ -1054,7 +1054,7 @@ function mailchimp_sf_merge_validate_phone( $opt_val, $data ) { // If they were all empty if ( ! $opt_val ) { - return; + return $opt_val; } // Trim whitespace @@ -1064,15 +1064,34 @@ function mailchimp_sf_merge_validate_phone( $opt_val, $data ) { // Format number for validation $opt_val = implode( '-', $opt_val ); - // Check string length - if ( strlen( $opt_val ) < 12 ) { - /* translators: %s: field name */ - $message = sprintf( esc_html__( '%s must contain the correct amount of digits', 'mailchimp' ), esc_html( $data['name'] ) ); - $opt_val = new WP_Error( 'mc_phone_validation', $message ); - } else if ( ! preg_match( '/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/', $opt_val ) ) { - /* translators: %s: field name */ - $message = sprintf( esc_html__( '%s must consist of only numbers', 'mailchimp' ), esc_html( $data['name'] ) ); - $opt_val = new WP_Error( 'mc_phone_validation', $message ); + switch ( true ) { + /** + * Phone number must be 12 characters long + */ + case strlen( $opt_val ) < 12: + $message = sprintf( + esc_html__( '%s must contain the correct amount of digits', 'mailchimp' ), + esc_html( $data['name'] ) + ); + $opt_val = new WP_Error( 'mc_phone_validation', $message ); + break; + + /** + * Phone number must consist of only numbers + */ + case ! preg_match( '/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/', $opt_val ): + $message = sprintf( + esc_html__( '%s must consist of only numbers', 'mailchimp' ), + esc_html( $data['name'] ) + ); + $opt_val = new WP_Error( 'mc_phone_validation', $message ); + break; + + /** + * No issues, pass validation + */ + default: + break; } return $opt_val; From 232852f53474dd304b892e3de3bbb48cb17b2093 Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Fri, 3 Jan 2025 19:14:18 -0500 Subject: [PATCH 05/40] Add back translators. Fix linting. --- mailchimp.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mailchimp.php b/mailchimp.php index 8ed5d6e..6974115 100644 --- a/mailchimp.php +++ b/mailchimp.php @@ -1059,7 +1059,7 @@ function mailchimp_sf_merge_validate_phone( $opt_val, $data ) { // Trim whitespace $opt_val = array_map( 'trim', $opt_val ); // Beginning and end - $opt_val = array_map( fn($s) => preg_replace( '/\s/', '', $s ), $opt_val ); // Middle + $opt_val = array_map( fn( $s ) => preg_replace( '/\s/', '', $s ), $opt_val ); // Middle // Format number for validation $opt_val = implode( '-', $opt_val ); @@ -1070,6 +1070,7 @@ function mailchimp_sf_merge_validate_phone( $opt_val, $data ) { */ case strlen( $opt_val ) < 12: $message = sprintf( + /* translators: %s: field name */ esc_html__( '%s must contain the correct amount of digits', 'mailchimp' ), esc_html( $data['name'] ) ); @@ -1081,6 +1082,7 @@ function mailchimp_sf_merge_validate_phone( $opt_val, $data ) { */ case ! preg_match( '/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/', $opt_val ): $message = sprintf( + /* translators: %s: field name */ esc_html__( '%s must consist of only numbers', 'mailchimp' ), esc_html( $data['name'] ) ); From 891f9e9372e5adb89efd5b005fbf1356a9be2f6d Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Fri, 3 Jan 2025 19:33:32 -0500 Subject: [PATCH 06/40] Add comment --- mailchimp.php | 1 + 1 file changed, 1 insertion(+) diff --git a/mailchimp.php b/mailchimp.php index 6974115..92c3eb9 100644 --- a/mailchimp.php +++ b/mailchimp.php @@ -1067,6 +1067,7 @@ function mailchimp_sf_merge_validate_phone( $opt_val, $data ) { switch ( true ) { /** * Phone number must be 12 characters long + * 10 digits [0-9] and 2 dashes "-" */ case strlen( $opt_val ) < 12: $message = sprintf( From f203326dbe6d55a0327cc7969bab3e951d825e93 Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 15:05:11 -0500 Subject: [PATCH 07/40] Replace arrow function with anonymous function for php compatibility --- mailchimp.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/mailchimp.php b/mailchimp.php index 92c3eb9..8bf626a 100644 --- a/mailchimp.php +++ b/mailchimp.php @@ -1057,9 +1057,16 @@ function mailchimp_sf_merge_validate_phone( $opt_val, $data ) { return $opt_val; } - // Trim whitespace - $opt_val = array_map( 'trim', $opt_val ); // Beginning and end - $opt_val = array_map( fn( $s ) => preg_replace( '/\s/', '', $s ), $opt_val ); // Middle + // Trim Whitespace - Beginning and end + $opt_val = array_map( 'trim', $opt_val ); + + // Trim Whitespace - Middle + $opt_val = array_map( + function ( $s ) { + return preg_replace( '/\s/', '', $s ); + }, + $opt_val + ); // Format number for validation $opt_val = implode( '-', $opt_val ); From 23a2876c99f1b158c5c8eac6d2394aeeb27327ee Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 15:59:06 -0500 Subject: [PATCH 08/40] Add phpunit, wp_mock, and scaffold --- composer.json | 9 +- composer.lock | 1924 +++++++++++++++++++++++- phpunit.xml.dist | 20 + tests/unit/bootstrap.php | 29 + tests/unit/test-address-validation.php | 68 + 5 files changed, 2043 insertions(+), 7 deletions(-) create mode 100644 phpunit.xml.dist create mode 100644 tests/unit/bootstrap.php create mode 100644 tests/unit/test-address-validation.php diff --git a/composer.json b/composer.json index 2f2b77a..39f07aa 100644 --- a/composer.json +++ b/composer.json @@ -12,11 +12,13 @@ ], "prefer-stable": true, "require": { - "php": ">=7.0" + "php": ">=7.0", + "10up/wp_mock": "^0.4.2" }, "require-dev": { "10up/phpcs-composer": "^3.0", - "sirbrillig/phpcs-changed": "^2.11" + "sirbrillig/phpcs-changed": "^2.11", + "phpunit/phpunit": "^11.5" }, "config": { "allow-plugins": { @@ -24,6 +26,7 @@ } }, "scripts": { - "lint": "phpcs --standard=./phpcs.xml -p -s ." + "lint": "phpcs --standard=./phpcs.xml -p -s .", + "test": "phpunit" } } diff --git a/composer.lock b/composer.lock index a2b433e..0b2cb1f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,1924 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b4631e7ae4a2f6a3795a92a813440087", - "packages": [], + "content-hash": "a1df9b6fcf44e9806613a6acc1df6bcc", + "packages": [ + { + "name": "10up/wp_mock", + "version": "0.4.2", + "source": { + "type": "git", + "url": "https://github.com/10up/wp_mock.git", + "reference": "9019226eb50df275aa86bb15bfc98a619601ee49" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/10up/wp_mock/zipball/9019226eb50df275aa86bb15bfc98a619601ee49", + "reference": "9019226eb50df275aa86bb15bfc98a619601ee49", + "shasum": "" + }, + "require": { + "antecedent/patchwork": "^2.1", + "mockery/mockery": "^1.0", + "php": ">=7.1", + "phpunit/phpunit": ">=7.0" + }, + "require-dev": { + "behat/behat": "^3.0", + "php-coveralls/php-coveralls": "^2.1", + "sebastian/comparator": ">=1.2.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "WP_Mock\\": "./php/WP_Mock" + }, + "classmap": [ + "php/WP_Mock.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "description": "A mocking library to take the pain out of unit testing for WordPress", + "support": { + "issues": "https://github.com/10up/wp_mock/issues", + "source": "https://github.com/10up/wp_mock/tree/master" + }, + "time": "2019-03-16T03:44:39+00:00" + }, + { + "name": "antecedent/patchwork", + "version": "2.2.1", + "source": { + "type": "git", + "url": "https://github.com/antecedent/patchwork.git", + "reference": "1bf183a3e1bd094f231a2128b9ecc5363c269245" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/antecedent/patchwork/zipball/1bf183a3e1bd094f231a2128b9ecc5363c269245", + "reference": "1bf183a3e1bd094f231a2128b9ecc5363c269245", + "shasum": "" + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "phpunit/phpunit": ">=4" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignas Rudaitis", + "email": "ignas.rudaitis@gmail.com" + } + ], + "description": "Method redefinition (monkey-patching) functionality for PHP.", + "homepage": "https://antecedent.github.io/patchwork/", + "keywords": [ + "aop", + "aspect", + "interception", + "monkeypatching", + "redefinition", + "runkit", + "testing" + ], + "support": { + "issues": "https://github.com/antecedent/patchwork/issues", + "source": "https://github.com/antecedent/patchwork/tree/2.2.1" + }, + "time": "2024-12-11T10:19:54+00:00" + }, + { + "name": "hamcrest/hamcrest-php", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/hamcrest/hamcrest-php.git", + "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "reference": "8c3d0a3f6af734494ad8f6fbbee0ba92422859f3", + "shasum": "" + }, + "require": { + "php": "^5.3|^7.0|^8.0" + }, + "replace": { + "cordoval/hamcrest-php": "*", + "davedevelopment/hamcrest-php": "*", + "kodova/hamcrest-php": "*" + }, + "require-dev": { + "phpunit/php-file-iterator": "^1.4 || ^2.0", + "phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "classmap": [ + "hamcrest" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "This is the PHP port of Hamcrest Matchers", + "keywords": [ + "test" + ], + "support": { + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1" + }, + "time": "2020-07-09T08:09:16+00:00" + }, + { + "name": "mockery/mockery", + "version": "1.6.12", + "source": { + "type": "git", + "url": "https://github.com/mockery/mockery.git", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mockery/mockery/zipball/1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "reference": "1f4efdd7d3beafe9807b08156dfcb176d18f1699", + "shasum": "" + }, + "require": { + "hamcrest/hamcrest-php": "^2.0.1", + "lib-pcre": ">=7.0", + "php": ">=7.3" + }, + "conflict": { + "phpunit/phpunit": "<8.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.5 || ^9.6.17", + "symplify/easy-coding-standard": "^12.1.14" + }, + "type": "library", + "autoload": { + "files": [ + "library/helpers.php", + "library/Mockery.php" + ], + "psr-4": { + "Mockery\\": "library/Mockery" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "PΓ‘draic Brady", + "email": "padraic.brady@gmail.com", + "homepage": "https://github.com/padraic", + "role": "Author" + }, + { + "name": "Dave Marshall", + "email": "dave.marshall@atstsolutions.co.uk", + "homepage": "https://davedevelopment.co.uk", + "role": "Developer" + }, + { + "name": "Nathanael Esayeas", + "email": "nathanael.esayeas@protonmail.com", + "homepage": "https://github.com/ghostwriter", + "role": "Lead Developer" + } + ], + "description": "Mockery is a simple yet flexible PHP mock object framework", + "homepage": "https://github.com/mockery/mockery", + "keywords": [ + "BDD", + "TDD", + "library", + "mock", + "mock objects", + "mockery", + "stub", + "test", + "test double", + "testing" + ], + "support": { + "docs": "https://docs.mockery.io/", + "issues": "https://github.com/mockery/mockery/issues", + "rss": "https://github.com/mockery/mockery/releases.atom", + "security": "https://github.com/mockery/mockery/security/advisories", + "source": "https://github.com/mockery/mockery" + }, + "time": "2024-05-16T03:13:13+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.12.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2024-11-08T17:47:46+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.4.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "447a020a1f875a434d62f2a401f53b82a396e494" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", + "reference": "447a020a1f875a434d62f2a401f53b82a396e494", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" + }, + "time": "2024-12-30T11:07:19+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "11.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "418c59fd080954f8c4aa5631d9502ecda2387118" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/418c59fd080954f8c4aa5631d9502ecda2387118", + "reference": "418c59fd080954f8c4aa5631d9502ecda2387118", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^5.3.1", + "php": ">=8.2", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-text-template": "^4.0.1", + "sebastian/code-unit-reverse-lookup": "^4.0.1", + "sebastian/complexity": "^4.0.1", + "sebastian/environment": "^7.2.0", + "sebastian/lines-of-code": "^3.0.1", + "sebastian/version": "^5.0.2", + "theseer/tokenizer": "^1.2.3" + }, + "require-dev": { + "phpunit/phpunit": "^11.5.0" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "11.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-12-11T12:34:27+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "5.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-08-27T05:02:59+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:07:44+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:08:43+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "7.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:09:35+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "11.5.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "153d0531b9f7e883c5053160cad6dd5ac28140b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/153d0531b9f7e883c5053160cad6dd5ac28140b3", + "reference": "153d0531b9f7e883c5053160cad6dd5ac28140b3", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.12.1", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0.8", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-invoker": "^5.0.1", + "phpunit/php-text-template": "^4.0.1", + "phpunit/php-timer": "^7.0.1", + "sebastian/cli-parser": "^3.0.2", + "sebastian/code-unit": "^3.0.2", + "sebastian/comparator": "^6.2.1", + "sebastian/diff": "^6.0.2", + "sebastian/environment": "^7.2.0", + "sebastian/exporter": "^6.3.0", + "sebastian/global-state": "^7.0.2", + "sebastian/object-enumerator": "^6.0.1", + "sebastian/type": "^5.1.0", + "sebastian/version": "^5.0.2", + "staabm/side-effects-detector": "^1.0.5" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "11.5-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.2" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2024-12-21T05:51:08+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:41:36+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca", + "reference": "ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-12-12T09:59:06+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:45:54+00:00" + }, + { + "name": "sebastian/comparator", + "version": "6.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "d4e47a769525c4dd38cea90e5dcd435ddbbc7115" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/d4e47a769525c4dd38cea90e5dcd435ddbbc7115", + "reference": "d4e47a769525c4dd38cea90e5dcd435ddbbc7115", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.4" + }, + "suggest": { + "ext-bcmath": "For comparing BcMath\\Number objects" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2025-01-06T10:28:19+00:00" + }, + { + "name": "sebastian/complexity", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:49:50+00:00" + }, + { + "name": "sebastian/diff", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:53:05+00:00" + }, + { + "name": "sebastian/environment", + "version": "7.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:54:44+00:00" + }, + { + "name": "sebastian/exporter", + "version": "6.3.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/3473f61172093b2da7de1fb5782e1f24cc036dc3", + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-12-05T09:17:50+00:00" + }, + { + "name": "sebastian/global-state", + "version": "7.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:57:36+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:58:38+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "6.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:00:13+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:01:32+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:10:34+00:00" + }, + { + "name": "sebastian/type", + "version": "5.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/461b9c5da241511a2a0e8f240814fb23ce5c0aac", + "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/5.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-09-17T13:12:04+00:00" + }, + { + "name": "sebastian/version", + "version": "5.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-10-09T05:16:32+00:00" + }, + { + "name": "staabm/side-effects-detector", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2024-10-20T05:08:20+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:36:25+00:00" + } + ], "packages-dev": [ { "name": "10up/phpcs-composer", @@ -810,12 +2726,12 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { "php": ">=7.0" }, - "platform-dev": [], + "platform-dev": {}, "plugin-api-version": "2.6.0" } diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..ba04346 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,20 @@ + + + + + ./tests/unit + + + + + + + \ No newline at end of file diff --git a/tests/unit/bootstrap.php b/tests/unit/bootstrap.php new file mode 100644 index 0000000..30746ec --- /dev/null +++ b/tests/unit/bootstrap.php @@ -0,0 +1,29 @@ +instance = new SafeSvg\safe_svg(); // TODO: Delete this, I don't think we need to instantiate any classes for our test + } + + /** + * Tear down WP Mock. + * + * @return void + */ + public function tearDown(): void { + \WP_Mock::tearDown(); + } + + /** + * Test allow_svg function. + * + * @return void + */ + public function test_tests_are_running() { + $this->assertTrue(true, 'This is a placeholder test to make sure the tests are running'); + + // \WP_Mock::userFunction( + // 'get_option', + // array( + // 'args' => [ 'safe_svg_upload_roles', [] ], + // 'return' => [ 'editor' ], + // ) + // ); + + // \WP_Mock::userFunction( + // 'current_user_can', + // array( + // 'args' => 'safe_svg_upload_svg', + // 'return' => true, + // ) + // ); + + // $allowed_svg = $this->instance->allow_svg( array() ); + // $this->assertNotEmpty( $allowed_svg ); + // $this->assertContains( 'image/svg+xml', $allowed_svg ); + } +} \ No newline at end of file From b5ef904f218c773a26f2348995841e49b7cd7867 Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 16:48:46 -0500 Subject: [PATCH 09/40] Modularize validate phone number This enables us to just import the merge_validate_phone instead of loading the entire Mailchimp plugin --- .../validation/class-mailchimp-validation.php | 36 +++++++++ includes/validation/merge-fields.php | 76 +++++++++++++++++++ mailchimp.php | 75 +++--------------- 3 files changed, 121 insertions(+), 66 deletions(-) create mode 100644 includes/validation/class-mailchimp-validation.php create mode 100644 includes/validation/merge-fields.php diff --git a/includes/validation/class-mailchimp-validation.php b/includes/validation/class-mailchimp-validation.php new file mode 100644 index 0000000..0879658 --- /dev/null +++ b/includes/validation/class-mailchimp-validation.php @@ -0,0 +1,36 @@ +require_validation_functions(); + } + + /** + * Require validation functions + * + * TODO: Refactor this once autoloading is enabled + * + * @return void + */ + private function require_validation_functions() { + include_once MCSF_DIR . 'includes/validation/merge-fields.php'; + } +} diff --git a/includes/validation/merge-fields.php b/includes/validation/merge-fields.php new file mode 100644 index 0000000..f2dd49f --- /dev/null +++ b/includes/validation/merge-fields.php @@ -0,0 +1,76 @@ +init(); +// Init Validation functions. +require_once plugin_dir_path( __FILE__ ) . 'includes/validation/class-mailchimp-validation.php'; +$validation = new Mailchimp_Validation(); +$validation->init(); + /** * Do the following plugin setup steps here * @@ -1041,72 +1050,6 @@ function mailchimp_sf_merge_submit( $mv ) { return $merge; } -/** - * Validate phone - * - * @param array $opt_val Option value - * @param array $data Data - * @return array|WP_Error - */ -function mailchimp_sf_merge_validate_phone( $opt_val, $data ) { - // Filter out falsy values - $opt_val = array_filter( $opt_val ); - - // If they were all empty - if ( ! $opt_val ) { - return $opt_val; - } - - // Trim Whitespace - Beginning and end - $opt_val = array_map( 'trim', $opt_val ); - - // Trim Whitespace - Middle - $opt_val = array_map( - function ( $s ) { - return preg_replace( '/\s/', '', $s ); - }, - $opt_val - ); - - // Format number for validation - $opt_val = implode( '-', $opt_val ); - - switch ( true ) { - /** - * Phone number must be 12 characters long - * 10 digits [0-9] and 2 dashes "-" - */ - case strlen( $opt_val ) < 12: - $message = sprintf( - /* translators: %s: field name */ - esc_html__( '%s must contain the correct amount of digits', 'mailchimp' ), - esc_html( $data['name'] ) - ); - $opt_val = new WP_Error( 'mc_phone_validation', $message ); - break; - - /** - * Phone number must consist of only numbers - */ - case ! preg_match( '/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/', $opt_val ): - $message = sprintf( - /* translators: %s: field name */ - esc_html__( '%s must consist of only numbers', 'mailchimp' ), - esc_html( $data['name'] ) - ); - $opt_val = new WP_Error( 'mc_phone_validation', $message ); - break; - - /** - * No issues, pass validation - */ - default: - break; - } - - return $opt_val; -} - /** * Validate address * From 9613ca8867f66d3bd8cab496f9c7b9fa6ca0c5e7 Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 16:49:36 -0500 Subject: [PATCH 10/40] Rename function to follow 10up namespace standards --- includes/validation/merge-fields.php | 2 +- mailchimp.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/validation/merge-fields.php b/includes/validation/merge-fields.php index f2dd49f..a388666 100644 --- a/includes/validation/merge-fields.php +++ b/includes/validation/merge-fields.php @@ -16,7 +16,7 @@ * @param array $data Data * @return array|WP_Error */ -function mailchimp_sf_merge_validate_phone( $opt_val, $data ) { +function merge_validate_phone( $opt_val, $data ) { // Filter out falsy values $opt_val = array_filter( $opt_val ); diff --git a/mailchimp.php b/mailchimp.php index 460ffef..21ccefb 100644 --- a/mailchimp.php +++ b/mailchimp.php @@ -36,7 +36,7 @@ // Validation use Mailchimp\WordPress\Includes\Validation\Mailchimp_Validation; -use function Mailchimp\WordPress\Includes\Validation\{ mailchimp_sf_merge_validate_phone }; +use function Mailchimp\WordPress\Includes\Validation\{ merge_validate_phone }; // Version constant for easy CSS refreshes define( 'MCSF_VER', '1.6.2' ); @@ -1014,7 +1014,7 @@ function mailchimp_sf_merge_submit( $mv ) { // Handle phone number logic if ( isset( $mv_var['options']['phone_format'] ) && 'phone' === $mv_var['type'] && 'US' === $mv_var['options']['phone_format'] ) { - $opt_val = mailchimp_sf_merge_validate_phone( $opt_val, $mv_var ); + $opt_val = merge_validate_phone( $opt_val, $mv_var ); if ( is_wp_error( $opt_val ) ) { return $opt_val; } From 363cd6a88ef5e895722019afba15a3ad229c85ab Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 16:57:54 -0500 Subject: [PATCH 11/40] Move address validation to validation module --- includes/validation/merge-fields.php | 39 ++++++++++++++++++++++++++++ mailchimp.php | 31 +--------------------- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/includes/validation/merge-fields.php b/includes/validation/merge-fields.php index a388666..7e6f992 100644 --- a/includes/validation/merge-fields.php +++ b/includes/validation/merge-fields.php @@ -8,6 +8,7 @@ namespace Mailchimp\WordPress\Includes\Validation; use WP_Error; +use stdClass; /** * Validate phone @@ -74,3 +75,41 @@ function ( $s ) { return $opt_val; } + +/** + * Validate address + * + * @param array $opt_val Option value + * @param array $data Data + * @return mixed + */ +function mailchimp_sf_merge_validate_address( $opt_val, $data ) { + if ( 'Y' === $data['required'] ) { + if ( empty( $opt_val['addr1'] ) || empty( $opt_val['city'] ) ) { + /* translators: %s: field name */ + $message = sprintf( esc_html__( 'You must fill in %s.', 'mailchimp' ), esc_html( $data['name'] ) ); + $error = new WP_Error( 'invalid_address_merge', $message ); + return $error; + } + /** + * Condition + * 1) If the address is not required and + * 2) address line 1 or city is empty + * + * Result + * Then don't send address to Mailchimp + * Return false skips merge formatting in `mailchimp_sf_merge_submit` + */ + } elseif ( empty( $opt_val['addr1'] ) || empty( $opt_val['city'] ) ) { + return false; + } + + $merge = new stdClass(); + $merge->addr1 = $opt_val['addr1']; + $merge->addr2 = $opt_val['addr2']; + $merge->city = $opt_val['city']; + $merge->state = $opt_val['state']; + $merge->zip = $opt_val['zip']; + $merge->country = $opt_val['country']; + return $merge; +} diff --git a/mailchimp.php b/mailchimp.php index 21ccefb..6c47839 100644 --- a/mailchimp.php +++ b/mailchimp.php @@ -36,7 +36,7 @@ // Validation use Mailchimp\WordPress\Includes\Validation\Mailchimp_Validation; -use function Mailchimp\WordPress\Includes\Validation\{ merge_validate_phone }; +use function Mailchimp\WordPress\Includes\Validation\{ merge_validate_phone, mailchimp_sf_merge_validate_address }; // Version constant for easy CSS refreshes define( 'MCSF_VER', '1.6.2' ); @@ -1050,35 +1050,6 @@ function mailchimp_sf_merge_submit( $mv ) { return $merge; } -/** - * Validate address - * - * @param array $opt_val Option value - * @param array $data Data - * @return mixed - */ -function mailchimp_sf_merge_validate_address( $opt_val, $data ) { - if ( 'Y' === $data['required'] ) { - if ( empty( $opt_val['addr1'] ) || empty( $opt_val['city'] ) ) { - /* translators: %s: field name */ - $message = sprintf( esc_html__( 'You must fill in %s.', 'mailchimp' ), esc_html( $data['name'] ) ); - $error = new WP_Error( 'invalid_address_merge', $message ); - return $error; - } - } elseif ( empty( $opt_val['addr1'] ) || empty( $opt_val['city'] ) ) { - return false; - } - - $merge = new stdClass(); - $merge->addr1 = $opt_val['addr1']; - $merge->addr2 = $opt_val['addr2']; - $merge->city = $opt_val['city']; - $merge->state = $opt_val['state']; - $merge->zip = $opt_val['zip']; - $merge->country = $opt_val['country']; - return $merge; -} - /** * Merge remove empty * From 6184f01d0ffec03347676635260d58755de01aef Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 16:58:43 -0500 Subject: [PATCH 12/40] Rename mailchimp_sf_merge_validate_address to merge_validate_address Following 10up namespace standards with functions --- includes/validation/merge-fields.php | 2 +- mailchimp.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/validation/merge-fields.php b/includes/validation/merge-fields.php index 7e6f992..e6de212 100644 --- a/includes/validation/merge-fields.php +++ b/includes/validation/merge-fields.php @@ -83,7 +83,7 @@ function ( $s ) { * @param array $data Data * @return mixed */ -function mailchimp_sf_merge_validate_address( $opt_val, $data ) { +function merge_validate_address( $opt_val, $data ) { if ( 'Y' === $data['required'] ) { if ( empty( $opt_val['addr1'] ) || empty( $opt_val['city'] ) ) { /* translators: %s: field name */ diff --git a/mailchimp.php b/mailchimp.php index 6c47839..9e7c9c6 100644 --- a/mailchimp.php +++ b/mailchimp.php @@ -36,7 +36,7 @@ // Validation use Mailchimp\WordPress\Includes\Validation\Mailchimp_Validation; -use function Mailchimp\WordPress\Includes\Validation\{ merge_validate_phone, mailchimp_sf_merge_validate_address }; +use function Mailchimp\WordPress\Includes\Validation\{ merge_validate_phone, merge_validate_address }; // Version constant for easy CSS refreshes define( 'MCSF_VER', '1.6.2' ); @@ -1019,7 +1019,7 @@ function mailchimp_sf_merge_submit( $mv ) { return $opt_val; } } elseif ( is_array( $opt_val ) && 'address' === $mv_var['type'] ) { // Handle address logic - $validate = mailchimp_sf_merge_validate_address( $opt_val, $mv_var ); + $validate = merge_validate_address( $opt_val, $mv_var ); if ( is_wp_error( $validate ) ) { return $validate; } From 4caf3cbcc56a6e7d012a0192e16e8e767c9d63b0 Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 17:40:45 -0500 Subject: [PATCH 13/40] Debug phpunit tests --- composer.json | 8 +- composer.lock | 2024 +++++++++-------- phpunit.xml.dist | 2 +- ...lidation.php => AddressValidationTest.php} | 22 +- tests/unit/bootstrap.php | 26 +- 5 files changed, 1082 insertions(+), 1000 deletions(-) rename tests/unit/{test-address-validation.php => AddressValidationTest.php} (73%) diff --git a/composer.json b/composer.json index 39f07aa..ce3b1b9 100644 --- a/composer.json +++ b/composer.json @@ -12,13 +12,13 @@ ], "prefer-stable": true, "require": { - "php": ">=7.0", - "10up/wp_mock": "^0.4.2" + "php": ">=7.0" }, "require-dev": { "10up/phpcs-composer": "^3.0", "sirbrillig/phpcs-changed": "^2.11", - "phpunit/phpunit": "^11.5" + "yoast/phpunit-polyfills": "^3.0", + "10up/wp_mock": "^0.4.2" }, "config": { "allow-plugins": { @@ -27,6 +27,6 @@ }, "scripts": { "lint": "phpcs --standard=./phpcs.xml -p -s .", - "test": "phpunit" + "test": "vendor/bin/phpunit" } } diff --git a/composer.lock b/composer.lock index 0b2cb1f..8efc7f6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,49 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a1df9b6fcf44e9806613a6acc1df6bcc", - "packages": [ + "content-hash": "bb7bd60a5f4b3b02adb1f52a754e9794", + "packages": [], + "packages-dev": [ + { + "name": "10up/phpcs-composer", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/10up/phpcs-composer.git", + "reference": "04fe5f0d61948f9e38e9cd037a5ee50dcdbf4688" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/10up/phpcs-composer/zipball/04fe5f0d61948f9e38e9cd037a5ee50dcdbf4688", + "reference": "04fe5f0d61948f9e38e9cd037a5ee50dcdbf4688", + "shasum": "" + }, + "require": { + "automattic/vipwpcs": "^3.0", + "phpcompatibility/phpcompatibility-wp": "^2" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "*", + "phpcompatibility/php-compatibility": "dev-develop as 9.99.99" + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "10up", + "homepage": "https://10up.com/" + } + ], + "description": "10up's PHP CodeSniffer Ruleset", + "support": { + "issues": "https://github.com/10up/phpcs-composer/issues", + "source": "https://github.com/10up/phpcs-composer/tree/3.0.0" + }, + "time": "2023-12-14T15:37:22+00:00" + }, { "name": "10up/wp_mock", "version": "0.4.2", @@ -99,6 +140,138 @@ }, "time": "2024-12-11T10:19:54+00:00" }, + { + "name": "automattic/vipwpcs", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/Automattic/VIP-Coding-Standards.git", + "reference": "2b1d206d81b74ed999023cffd924f862ff2753c8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Automattic/VIP-Coding-Standards/zipball/2b1d206d81b74ed999023cffd924f862ff2753c8", + "reference": "2b1d206d81b74ed999023cffd924f862ff2753c8", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "phpcsstandards/phpcsextra": "^1.2.1", + "phpcsstandards/phpcsutils": "^1.0.11", + "sirbrillig/phpcs-variable-analysis": "^2.11.18", + "squizlabs/php_codesniffer": "^3.9.2", + "wp-coding-standards/wpcs": "^3.1.0" + }, + "require-dev": { + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "php-parallel-lint/php-parallel-lint": "^1.3.2", + "phpcompatibility/php-compatibility": "^9", + "phpcsstandards/phpcsdevtools": "^1.0", + "phpunit/phpunit": "^4 || ^5 || ^6 || ^7 || ^8 || ^9" + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Contributors", + "homepage": "https://github.com/Automattic/VIP-Coding-Standards/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress VIP minimum coding conventions", + "keywords": [ + "phpcs", + "standards", + "static analysis", + "wordpress" + ], + "support": { + "issues": "https://github.com/Automattic/VIP-Coding-Standards/issues", + "source": "https://github.com/Automattic/VIP-Coding-Standards", + "wiki": "https://github.com/Automattic/VIP-Coding-Standards/wiki" + }, + "time": "2024-05-10T20:31:09+00:00" + }, + { + "name": "dealerdirect/phpcodesniffer-composer-installer", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/composer-installer.git", + "reference": "4be43904336affa5c2f70744a348312336afd0da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/4be43904336affa5c2f70744a348312336afd0da", + "reference": "4be43904336affa5c2f70744a348312336afd0da", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0", + "php": ">=5.4", + "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + }, + "require-dev": { + "composer/composer": "*", + "ext-json": "*", + "ext-zip": "*", + "php-parallel-lint/php-parallel-lint": "^1.3.1", + "phpcompatibility/php-compatibility": "^9.0", + "yoast/phpunit-polyfills": "^1.0" + }, + "type": "composer-plugin", + "extra": { + "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + }, + "autoload": { + "psr-4": { + "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Franck Nijhof", + "email": "franck.nijhof@dealerdirect.com", + "homepage": "http://www.frenck.nl", + "role": "Developer / IT Manager" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer Standards Composer Installer Plugin", + "homepage": "http://www.dealerdirect.com", + "keywords": [ + "PHPCodeSniffer", + "PHP_CodeSniffer", + "code quality", + "codesniffer", + "composer", + "installer", + "phpcbf", + "phpcs", + "plugin", + "qa", + "quality", + "standard", + "standards", + "style guide", + "stylecheck", + "tests" + ], + "support": { + "issues": "https://github.com/PHPCSStandards/composer-installer/issues", + "source": "https://github.com/PHPCSStandards/composer-installer" + }, + "time": "2023-01-05T11:28:13+00:00" + }, { "name": "hamcrest/hamcrest-php", "version": "v2.0.1", @@ -470,386 +643,418 @@ "time": "2022-02-21T01:04:05+00:00" }, { - "name": "phpunit/php-code-coverage", - "version": "11.0.8", + "name": "phpcompatibility/php-compatibility", + "version": "9.3.5", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "418c59fd080954f8c4aa5631d9502ecda2387118" + "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", + "reference": "9fb324479acf6f39452e0655d2429cc0d3914243" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/418c59fd080954f8c4aa5631d9502ecda2387118", - "reference": "418c59fd080954f8c4aa5631d9502ecda2387118", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9fb324479acf6f39452e0655d2429cc0d3914243", + "reference": "9fb324479acf6f39452e0655d2429cc0d3914243", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-libxml": "*", - "ext-xmlwriter": "*", - "nikic/php-parser": "^5.3.1", - "php": ">=8.2", - "phpunit/php-file-iterator": "^5.1.0", - "phpunit/php-text-template": "^4.0.1", - "sebastian/code-unit-reverse-lookup": "^4.0.1", - "sebastian/complexity": "^4.0.1", - "sebastian/environment": "^7.2.0", - "sebastian/lines-of-code": "^3.0.1", - "sebastian/version": "^5.0.2", - "theseer/tokenizer": "^1.2.3" + "php": ">=5.3", + "squizlabs/php_codesniffer": "^2.3 || ^3.0.2" + }, + "conflict": { + "squizlabs/php_codesniffer": "2.6.2" }, "require-dev": { - "phpunit/phpunit": "^11.5.0" + "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0" }, "suggest": { - "ext-pcov": "PHP extension that provides line coverage", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "11.0.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] + "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." }, + "type": "phpcodesniffer-standard", "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "LGPL-3.0-or-later" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", + "name": "Wim Godden", + "homepage": "https://github.com/wimg", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors" } ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", + "homepage": "http://techblog.wimgodden.be/tag/codesniffer/", "keywords": [ - "coverage", - "testing", - "xunit" + "compatibility", + "phpcs", + "standards" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.8" + "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues", + "source": "https://github.com/PHPCompatibility/PHPCompatibility" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-12-11T12:34:27+00:00" + "time": "2019-12-27T09:44:58+00:00" }, { - "name": "phpunit/php-file-iterator", - "version": "5.1.0", + "name": "phpcompatibility/phpcompatibility-paragonie", + "version": "1.3.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" + "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git", + "reference": "293975b465e0e709b571cbf0c957c6c0a7b9a2ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", - "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/293975b465e0e709b571cbf0c957c6c0a7b9a2ac", + "reference": "293975b465e0e709b571cbf0c957c6c0a7b9a2ac", "shasum": "" }, "require": { - "php": ">=8.2" + "phpcompatibility/php-compatibility": "^9.0" }, "require-dev": { - "phpunit/phpunit": "^11.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "paragonie/random_compat": "dev-master", + "paragonie/sodium_compat": "dev-master" }, - "autoload": { - "classmap": [ - "src/" - ] + "suggest": { + "dealerdirect/phpcodesniffer-composer-installer": "^1.0 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." }, + "type": "phpcodesniffer-standard", "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "LGPL-3.0-or-later" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", + "name": "Wim Godden", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", "role": "lead" } ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "description": "A set of rulesets for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by the Paragonie polyfill libraries.", + "homepage": "http://phpcompatibility.com/", "keywords": [ - "filesystem", - "iterator" + "compatibility", + "paragonie", + "phpcs", + "polyfill", + "standards", + "static analysis" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" + "issues": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues", + "security": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/security/policy", + "source": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/PHPCompatibility", "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" } ], - "time": "2024-08-27T05:02:59+00:00" + "time": "2024-04-24T21:30:46+00:00" }, { - "name": "phpunit/php-invoker", - "version": "5.0.1", + "name": "phpcompatibility/phpcompatibility-wp", + "version": "2.1.5", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" + "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git", + "reference": "01c1ff2704a58e46f0cb1ca9d06aee07b3589082" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", - "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/01c1ff2704a58e46f0cb1ca9d06aee07b3589082", + "reference": "01c1ff2704a58e46f0cb1ca9d06aee07b3589082", "shasum": "" }, "require": { - "php": ">=8.2" + "phpcompatibility/php-compatibility": "^9.0", + "phpcompatibility/phpcompatibility-paragonie": "^1.0" }, "require-dev": { - "ext-pcntl": "*", - "phpunit/phpunit": "^11.0" + "dealerdirect/phpcodesniffer-composer-installer": "^1.0" }, "suggest": { - "ext-pcntl": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "5.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] + "dealerdirect/phpcodesniffer-composer-installer": "^1.0 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." }, + "type": "phpcodesniffer-standard", "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "LGPL-3.0-or-later" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", + "name": "Wim Godden", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", "role": "lead" } ], - "description": "Invoke callables with a timeout", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "description": "A ruleset for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by WordPress.", + "homepage": "http://phpcompatibility.com/", "keywords": [ - "process" + "compatibility", + "phpcs", + "standards", + "static analysis", + "wordpress" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" + "issues": "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues", + "security": "https://github.com/PHPCompatibility/PHPCompatibilityWP/security/policy", + "source": "https://github.com/PHPCompatibility/PHPCompatibilityWP" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/PHPCompatibility", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" } ], - "time": "2024-07-03T05:07:44+00:00" + "time": "2024-04-24T21:37:59+00:00" }, { - "name": "phpunit/php-text-template", - "version": "4.0.1", + "name": "phpcsstandards/phpcsextra", + "version": "1.2.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" + "url": "https://github.com/PHPCSStandards/PHPCSExtra.git", + "reference": "11d387c6642b6e4acaf0bd9bf5203b8cca1ec489" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", - "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSExtra/zipball/11d387c6642b6e4acaf0bd9bf5203b8cca1ec489", + "reference": "11d387c6642b6e4acaf0bd9bf5203b8cca1ec489", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=5.4", + "phpcsstandards/phpcsutils": "^1.0.9", + "squizlabs/php_codesniffer": "^3.8.0" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.3.2", + "phpcsstandards/phpcsdevcs": "^1.1.6", + "phpcsstandards/phpcsdevtools": "^1.2.1", + "phpunit/phpunit": "^4.5 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" }, - "type": "library", + "type": "phpcodesniffer-standard", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-stable": "1.x-dev", + "dev-develop": "1.x-dev" } }, - "autoload": { - "classmap": [ - "src/" - ] - }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "LGPL-3.0-or-later" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHPCSExtra/graphs/contributors" } ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "description": "A collection of sniffs and standards for use with PHP_CodeSniffer.", "keywords": [ - "template" + "PHP_CodeSniffer", + "phpcbf", + "phpcodesniffer-standard", + "phpcs", + "standards", + "static analysis" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" + "issues": "https://github.com/PHPCSStandards/PHPCSExtra/issues", + "security": "https://github.com/PHPCSStandards/PHPCSExtra/security/policy", + "source": "https://github.com/PHPCSStandards/PHPCSExtra" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" } ], - "time": "2024-07-03T05:08:43+00:00" + "time": "2023-12-08T16:49:07+00:00" }, { - "name": "phpunit/php-timer", - "version": "7.0.1", + "name": "phpcsstandards/phpcsutils", + "version": "1.0.12", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" + "url": "https://github.com/PHPCSStandards/PHPCSUtils.git", + "reference": "87b233b00daf83fb70f40c9a28692be017ea7c6c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", - "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/87b233b00daf83fb70f40c9a28692be017ea7c6c", + "reference": "87b233b00daf83fb70f40c9a28692be017ea7c6c", "shasum": "" }, "require": { - "php": ">=8.2" + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7 || ^1.0", + "php": ">=5.4", + "squizlabs/php_codesniffer": "^3.10.0 || 4.0.x-dev@dev" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "ext-filter": "*", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.3.2", + "phpcsstandards/phpcsdevcs": "^1.1.6", + "yoast/phpunit-polyfills": "^1.1.0 || ^2.0.0" }, - "type": "library", + "type": "phpcodesniffer-standard", "extra": { "branch-alias": { - "dev-main": "7.0-dev" + "dev-stable": "1.x-dev", + "dev-develop": "1.x-dev" } }, "autoload": { "classmap": [ - "src/" + "PHPCSUtils/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "LGPL-3.0-or-later" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHPCSUtils/graphs/contributors" } ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", - "keywords": [ - "timer" + "description": "A suite of utility functions for use with PHP_CodeSniffer", + "homepage": "https://phpcsutils.com/", + "keywords": [ + "PHP_CodeSniffer", + "phpcbf", + "phpcodesniffer-standard", + "phpcs", + "phpcs3", + "standards", + "static analysis", + "tokens", + "utility" ], "support": { - "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "security": "https://github.com/sebastianbergmann/php-timer/security/policy", - "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" + "docs": "https://phpcsutils.com/", + "issues": "https://github.com/PHPCSStandards/PHPCSUtils/issues", + "security": "https://github.com/PHPCSStandards/PHPCSUtils/security/policy", + "source": "https://github.com/PHPCSStandards/PHPCSUtils" }, "funding": [ { - "url": "https://github.com/sebastianbergmann", + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" } ], - "time": "2024-07-03T05:09:35+00:00" + "time": "2024-05-20T13:34:27+00:00" }, { - "name": "phpunit/phpunit", - "version": "11.5.2", + "name": "phpunit/php-code-coverage", + "version": "11.0.8", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "153d0531b9f7e883c5053160cad6dd5ac28140b3" + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "418c59fd080954f8c4aa5631d9502ecda2387118" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/153d0531b9f7e883c5053160cad6dd5ac28140b3", - "reference": "153d0531b9f7e883c5053160cad6dd5ac28140b3", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/418c59fd080954f8c4aa5631d9502ecda2387118", + "reference": "418c59fd080954f8c4aa5631d9502ecda2387118", "shasum": "" }, "require": { "ext-dom": "*", - "ext-json": "*", "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.12.1", - "phar-io/manifest": "^2.0.4", - "phar-io/version": "^3.2.1", + "nikic/php-parser": "^5.3.1", "php": ">=8.2", - "phpunit/php-code-coverage": "^11.0.8", "phpunit/php-file-iterator": "^5.1.0", - "phpunit/php-invoker": "^5.0.1", "phpunit/php-text-template": "^4.0.1", - "phpunit/php-timer": "^7.0.1", - "sebastian/cli-parser": "^3.0.2", - "sebastian/code-unit": "^3.0.2", - "sebastian/comparator": "^6.2.1", - "sebastian/diff": "^6.0.2", + "sebastian/code-unit-reverse-lookup": "^4.0.1", + "sebastian/complexity": "^4.0.1", "sebastian/environment": "^7.2.0", - "sebastian/exporter": "^6.3.0", - "sebastian/global-state": "^7.0.2", - "sebastian/object-enumerator": "^6.0.1", - "sebastian/type": "^5.1.0", + "sebastian/lines-of-code": "^3.0.1", "sebastian/version": "^5.0.2", - "staabm/side-effects-detector": "^1.0.5" + "theseer/tokenizer": "^1.2.3" + }, + "require-dev": { + "phpunit/phpunit": "^11.5.0" }, "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files" + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, - "bin": [ - "phpunit" - ], "type": "library", "extra": { "branch-alias": { - "dev-main": "11.5-dev" + "dev-main": "11.0.x-dev" } }, "autoload": { - "files": [ - "src/Framework/Assert/Functions.php" - ], "classmap": [ "src/" ] @@ -865,46 +1070,38 @@ "role": "lead" } ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", "keywords": [ - "phpunit", + "coverage", "testing", "xunit" ], "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.2" + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.8" }, "funding": [ - { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, { "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", - "type": "tidelift" } ], - "time": "2024-12-21T05:51:08+00:00" + "time": "2024-12-11T12:34:27+00:00" }, { - "name": "sebastian/cli-parser", - "version": "3.0.2", + "name": "phpunit/php-file-iterator", + "version": "5.1.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", - "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", "shasum": "" }, "require": { @@ -916,7 +1113,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -935,12 +1132,16 @@ "role": "lead" } ], - "description": "Library for parsing CLI options", - "homepage": "https://github.com/sebastianbergmann/cli-parser", + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], "support": { - "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" }, "funding": [ { @@ -948,32 +1149,36 @@ "type": "github" } ], - "time": "2024-07-03T04:41:36+00:00" + "time": "2024-08-27T05:02:59+00:00" }, { - "name": "sebastian/code-unit", - "version": "3.0.2", + "name": "phpunit/php-invoker", + "version": "5.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca" + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca", - "reference": "ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^11.5" + "ext-pcntl": "*", + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-pcntl": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -992,12 +1197,15 @@ "role": "lead" } ], - "description": "Collection of value objects that represent the PHP code units", - "homepage": "https://github.com/sebastianbergmann/code-unit", + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], "support": { - "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "security": "https://github.com/sebastianbergmann/code-unit/security/policy", - "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.2" + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" }, "funding": [ { @@ -1005,20 +1213,20 @@ "type": "github" } ], - "time": "2024-12-12T09:59:06+00:00" + "time": "2024-07-03T05:07:44+00:00" }, { - "name": "sebastian/code-unit-reverse-lookup", + "name": "phpunit/php-text-template", "version": "4.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "183a9b2632194febd219bb9246eee421dad8d45e" + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", - "reference": "183a9b2632194febd219bb9246eee421dad8d45e", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", "shasum": "" }, "require": { @@ -1045,15 +1253,19 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], "support": { - "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" }, "funding": [ { @@ -1061,39 +1273,32 @@ "type": "github" } ], - "time": "2024-07-03T04:45:54+00:00" + "time": "2024-07-03T05:08:43+00:00" }, { - "name": "sebastian/comparator", - "version": "6.3.0", + "name": "phpunit/php-timer", + "version": "7.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "d4e47a769525c4dd38cea90e5dcd435ddbbc7115" + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/d4e47a769525c4dd38cea90e5dcd435ddbbc7115", - "reference": "d4e47a769525c4dd38cea90e5dcd435ddbbc7115", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-mbstring": "*", - "php": ">=8.2", - "sebastian/diff": "^6.0", - "sebastian/exporter": "^6.0" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^11.4" - }, - "suggest": { - "ext-bcmath": "For comparing BcMath\\Number objects" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.2-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -1108,32 +1313,19 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "https://github.com/sebastianbergmann/comparator", + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ - "comparator", - "compare", - "equality" + "timer" ], "support": { - "issues": "https://github.com/sebastianbergmann/comparator/issues", - "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.0" + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" }, "funding": [ { @@ -1141,36 +1333,66 @@ "type": "github" } ], - "time": "2025-01-06T10:28:19+00:00" + "time": "2024-07-03T05:09:35+00:00" }, { - "name": "sebastian/complexity", - "version": "4.0.1", + "name": "phpunit/phpunit", + "version": "11.5.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "153d0531b9f7e883c5053160cad6dd5ac28140b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", - "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/153d0531b9f7e883c5053160cad6dd5ac28140b3", + "reference": "153d0531b9f7e883c5053160cad6dd5ac28140b3", "shasum": "" }, "require": { - "nikic/php-parser": "^5.0", - "php": ">=8.2" + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.12.1", + "phar-io/manifest": "^2.0.4", + "phar-io/version": "^3.2.1", + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0.8", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-invoker": "^5.0.1", + "phpunit/php-text-template": "^4.0.1", + "phpunit/php-timer": "^7.0.1", + "sebastian/cli-parser": "^3.0.2", + "sebastian/code-unit": "^3.0.2", + "sebastian/comparator": "^6.2.1", + "sebastian/diff": "^6.0.2", + "sebastian/environment": "^7.2.0", + "sebastian/exporter": "^6.3.0", + "sebastian/global-state": "^7.0.2", + "sebastian/object-enumerator": "^6.0.1", + "sebastian/type": "^5.1.0", + "sebastian/version": "^5.0.2", + "staabm/side-effects-detector": "^1.0.5" }, - "require-dev": { - "phpunit/phpunit": "^11.0" + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" }, + "bin": [ + "phpunit" + ], "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "11.5-dev" } }, "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], "classmap": [ "src/" ] @@ -1186,46 +1408,58 @@ "role": "lead" } ], - "description": "Library for calculating the complexity of PHP code units", - "homepage": "https://github.com/sebastianbergmann/complexity", + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], "support": { - "issues": "https://github.com/sebastianbergmann/complexity/issues", - "security": "https://github.com/sebastianbergmann/complexity/security/policy", - "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.2" }, "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" } ], - "time": "2024-07-03T04:49:50+00:00" + "time": "2024-12-21T05:51:08+00:00" }, { - "name": "sebastian/diff", - "version": "6.0.2", + "name": "sebastian/cli-parser", + "version": "3.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", - "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^11.0", - "symfony/process": "^4.2 || ^5" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -1240,25 +1474,16 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff", - "udiff", - "unidiff", - "unified diff" - ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { - "issues": "https://github.com/sebastianbergmann/diff/issues", - "security": "https://github.com/sebastianbergmann/diff/security/policy", - "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" }, "funding": [ { @@ -1266,35 +1491,32 @@ "type": "github" } ], - "time": "2024-07-03T04:53:05+00:00" + "time": "2024-07-03T04:41:36+00:00" }, { - "name": "sebastian/environment", - "version": "7.2.0", + "name": "sebastian/code-unit", + "version": "3.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5" + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", - "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca", + "reference": "ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^11.0" - }, - "suggest": { - "ext-posix": "*" + "phpunit/phpunit": "^11.5" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "7.2-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -1309,20 +1531,16 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "email": "sebastian@phpunit.de", + "role": "lead" } ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "https://github.com/sebastianbergmann/environment", - "keywords": [ - "Xdebug", - "environment", - "hhvm" - ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { - "issues": "https://github.com/sebastianbergmann/environment/issues", - "security": "https://github.com/sebastianbergmann/environment/security/policy", - "source": "https://github.com/sebastianbergmann/environment/tree/7.2.0" + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.2" }, "funding": [ { @@ -1330,34 +1548,32 @@ "type": "github" } ], - "time": "2024-07-03T04:54:44+00:00" + "time": "2024-12-12T09:59:06+00:00" }, { - "name": "sebastian/exporter", - "version": "6.3.0", + "name": "sebastian/code-unit-reverse-lookup", + "version": "4.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3" + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/3473f61172093b2da7de1fb5782e1f24cc036dc3", - "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e", "shasum": "" }, "require": { - "ext-mbstring": "*", - "php": ">=8.2", - "sebastian/recursion-context": "^6.0" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^11.3" + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.1-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -1373,34 +1589,14 @@ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" - }, - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" } ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "https://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" - ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { - "issues": "https://github.com/sebastianbergmann/exporter/issues", - "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.0" + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" }, "funding": [ { @@ -1408,35 +1604,39 @@ "type": "github" } ], - "time": "2024-12-05T09:17:50+00:00" + "time": "2024-07-03T04:45:54+00:00" }, { - "name": "sebastian/global-state", - "version": "7.0.2", + "name": "sebastian/comparator", + "version": "6.3.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "3be331570a721f9a4b5917f4209773de17f747d7" + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "d4e47a769525c4dd38cea90e5dcd435ddbbc7115" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", - "reference": "3be331570a721f9a4b5917f4209773de17f747d7", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/d4e47a769525c4dd38cea90e5dcd435ddbbc7115", + "reference": "d4e47a769525c4dd38cea90e5dcd435ddbbc7115", "shasum": "" }, "require": { + "ext-dom": "*", + "ext-mbstring": "*", "php": ">=8.2", - "sebastian/object-reflector": "^4.0", - "sebastian/recursion-context": "^6.0" + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" }, "require-dev": { - "ext-dom": "*", - "phpunit/phpunit": "^11.0" + "phpunit/phpunit": "^11.4" + }, + "suggest": { + "ext-bcmath": "For comparing BcMath\\Number objects" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "7.0-dev" + "dev-main": "6.2-dev" } }, "autoload": { @@ -1452,38 +1652,52 @@ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" } ], - "description": "Snapshotting of global state", - "homepage": "https://www.github.com/sebastianbergmann/global-state", + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", "keywords": [ - "global state" + "comparator", + "compare", + "equality" ], "support": { - "issues": "https://github.com/sebastianbergmann/global-state/issues", - "security": "https://github.com/sebastianbergmann/global-state/security/policy", - "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" - }, + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/6.3.0" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" } ], - "time": "2024-07-03T04:57:36+00:00" + "time": "2025-01-06T10:28:19+00:00" }, { - "name": "sebastian/lines-of-code", - "version": "3.0.1", + "name": "sebastian/complexity", + "version": "4.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", - "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", "shasum": "" }, "require": { @@ -1496,7 +1710,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -1515,12 +1729,12 @@ "role": "lead" } ], - "description": "Library for counting the lines of code in PHP source code", - "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", "support": { - "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" }, "funding": [ { @@ -1528,29 +1742,28 @@ "type": "github" } ], - "time": "2024-07-03T04:58:38+00:00" + "time": "2024-07-03T04:49:50+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "6.0.1", + "name": "sebastian/diff", + "version": "6.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "f5b498e631a74204185071eb41f33f38d64608aa" + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", - "reference": "f5b498e631a74204185071eb41f33f38d64608aa", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", "shasum": "" }, "require": { - "php": ">=8.2", - "sebastian/object-reflector": "^4.0", - "sebastian/recursion-context": "^6.0" + "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" }, "type": "library", "extra": { @@ -1571,14 +1784,24 @@ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" } ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], "support": { - "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" }, "funding": [ { @@ -1586,20 +1809,20 @@ "type": "github" } ], - "time": "2024-07-03T05:00:13+00:00" + "time": "2024-07-03T04:53:05+00:00" }, { - "name": "sebastian/object-reflector", - "version": "4.0.1", + "name": "sebastian/environment", + "version": "7.2.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", - "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", "shasum": "" }, "require": { @@ -1608,10 +1831,13 @@ "require-dev": { "phpunit/phpunit": "^11.0" }, + "suggest": { + "ext-posix": "*" + }, "type": "library", "extra": { "branch-alias": { - "dev-main": "4.0-dev" + "dev-main": "7.2-dev" } }, "autoload": { @@ -1629,12 +1855,17 @@ "email": "sebastian@phpunit.de" } ], - "description": "Allows reflection of object attributes, including inherited and non-public ones", - "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], "support": { - "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.0" }, "funding": [ { @@ -1642,32 +1873,34 @@ "type": "github" } ], - "time": "2024-07-03T05:01:32+00:00" + "time": "2024-07-03T04:54:44+00:00" }, { - "name": "sebastian/recursion-context", - "version": "6.0.2", + "name": "sebastian/exporter", + "version": "6.3.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", - "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/3473f61172093b2da7de1fb5782e1f24cc036dc3", + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3", "shasum": "" }, "require": { - "php": ">=8.2" + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.0-dev" + "dev-main": "6.1-dev" } }, "autoload": { @@ -1688,17 +1921,29 @@ "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, { "name": "Adam Harvey", "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "https://github.com/sebastianbergmann/recursion-context", + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], "support": { - "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.0" }, "funding": [ { @@ -1706,32 +1951,35 @@ "type": "github" } ], - "time": "2024-07-03T05:10:34+00:00" + "time": "2024-12-05T09:17:50+00:00" }, { - "name": "sebastian/type", - "version": "5.1.0", + "name": "sebastian/global-state", + "version": "7.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/type.git", - "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac" + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/461b9c5da241511a2a0e8f240814fb23ce5c0aac", - "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^11.3" + "ext-dom": "*", + "phpunit/phpunit": "^11.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.1-dev" + "dev-main": "7.0-dev" } }, "autoload": { @@ -1746,16 +1994,18 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], - "description": "Collection of value objects that represent the types of the PHP type system", - "homepage": "https://github.com/sebastianbergmann/type", + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], "support": { - "issues": "https://github.com/sebastianbergmann/type/issues", - "security": "https://github.com/sebastianbergmann/type/security/policy", - "source": "https://github.com/sebastianbergmann/type/tree/5.1.0" + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" }, "funding": [ { @@ -1763,29 +2013,33 @@ "type": "github" } ], - "time": "2024-09-17T13:12:04+00:00" + "time": "2024-07-03T04:57:36+00:00" }, { - "name": "sebastian/version", - "version": "5.0.2", + "name": "sebastian/lines-of-code", + "version": "3.0.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", - "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", "shasum": "" }, "require": { + "nikic/php-parser": "^5.0", "php": ">=8.2" }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, "type": "library", "extra": { "branch-alias": { - "dev-main": "5.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -1804,12 +2058,12 @@ "role": "lead" } ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "security": "https://github.com/sebastianbergmann/version/security/policy", - "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" }, "funding": [ { @@ -1817,81 +2071,92 @@ "type": "github" } ], - "time": "2024-10-09T05:16:32+00:00" + "time": "2024-07-03T04:58:38+00:00" }, { - "name": "staabm/side-effects-detector", - "version": "1.0.5", + "name": "sebastian/object-enumerator", + "version": "6.0.1", "source": { "type": "git", - "url": "https://github.com/staabm/side-effects-detector.git", - "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", - "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": "^7.4 || ^8.0" + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpstan/extension-installer": "^1.4.3", - "phpstan/phpstan": "^1.12.6", - "phpunit/phpunit": "^9.6.21", - "symfony/var-dumper": "^5.4.43", - "tomasvotruba/type-coverage": "1.0.0", - "tomasvotruba/unused-public": "1.0.0" + "phpunit/phpunit": "^11.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, "autoload": { "classmap": [ - "lib/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], - "description": "A static analysis tool to detect side effects in PHP code", - "keywords": [ - "static analysis" + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { - "issues": "https://github.com/staabm/side-effects-detector/issues", - "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" }, "funding": [ { - "url": "https://github.com/staabm", + "url": "https://github.com/sebastianbergmann", "type": "github" } ], - "time": "2024-10-20T05:08:20+00:00" + "time": "2024-07-03T05:00:13+00:00" }, { - "name": "theseer/tokenizer", - "version": "1.2.3", + "name": "sebastian/object-reflector", + "version": "4.0.1", "source": { "type": "git", - "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": "^7.2 || ^8.0" + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -1903,567 +2168,199 @@ ], "authors": [ { - "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" } ], - "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { - "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" }, "funding": [ { - "url": "https://github.com/theseer", + "url": "https://github.com/sebastianbergmann", "type": "github" } ], - "time": "2024-03-03T12:36:25+00:00" - } - ], - "packages-dev": [ - { - "name": "10up/phpcs-composer", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/10up/phpcs-composer.git", - "reference": "04fe5f0d61948f9e38e9cd037a5ee50dcdbf4688" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/10up/phpcs-composer/zipball/04fe5f0d61948f9e38e9cd037a5ee50dcdbf4688", - "reference": "04fe5f0d61948f9e38e9cd037a5ee50dcdbf4688", - "shasum": "" - }, - "require": { - "automattic/vipwpcs": "^3.0", - "phpcompatibility/phpcompatibility-wp": "^2" - }, - "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "*", - "phpcompatibility/php-compatibility": "dev-develop as 9.99.99" - }, - "type": "phpcodesniffer-standard", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "10up", - "homepage": "https://10up.com/" - } - ], - "description": "10up's PHP CodeSniffer Ruleset", - "support": { - "issues": "https://github.com/10up/phpcs-composer/issues", - "source": "https://github.com/10up/phpcs-composer/tree/3.0.0" - }, - "time": "2023-12-14T15:37:22+00:00" - }, - { - "name": "automattic/vipwpcs", - "version": "3.0.1", - "source": { - "type": "git", - "url": "https://github.com/Automattic/VIP-Coding-Standards.git", - "reference": "2b1d206d81b74ed999023cffd924f862ff2753c8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Automattic/VIP-Coding-Standards/zipball/2b1d206d81b74ed999023cffd924f862ff2753c8", - "reference": "2b1d206d81b74ed999023cffd924f862ff2753c8", - "shasum": "" - }, - "require": { - "php": ">=5.4", - "phpcsstandards/phpcsextra": "^1.2.1", - "phpcsstandards/phpcsutils": "^1.0.11", - "sirbrillig/phpcs-variable-analysis": "^2.11.18", - "squizlabs/php_codesniffer": "^3.9.2", - "wp-coding-standards/wpcs": "^3.1.0" - }, - "require-dev": { - "php-parallel-lint/php-console-highlighter": "^1.0.0", - "php-parallel-lint/php-parallel-lint": "^1.3.2", - "phpcompatibility/php-compatibility": "^9", - "phpcsstandards/phpcsdevtools": "^1.0", - "phpunit/phpunit": "^4 || ^5 || ^6 || ^7 || ^8 || ^9" - }, - "type": "phpcodesniffer-standard", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Contributors", - "homepage": "https://github.com/Automattic/VIP-Coding-Standards/graphs/contributors" - } - ], - "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress VIP minimum coding conventions", - "keywords": [ - "phpcs", - "standards", - "static analysis", - "wordpress" - ], - "support": { - "issues": "https://github.com/Automattic/VIP-Coding-Standards/issues", - "source": "https://github.com/Automattic/VIP-Coding-Standards", - "wiki": "https://github.com/Automattic/VIP-Coding-Standards/wiki" - }, - "time": "2024-05-10T20:31:09+00:00" + "time": "2024-07-03T05:01:32+00:00" }, { - "name": "dealerdirect/phpcodesniffer-composer-installer", - "version": "v1.0.0", + "name": "sebastian/recursion-context", + "version": "6.0.2", "source": { "type": "git", - "url": "https://github.com/PHPCSStandards/composer-installer.git", - "reference": "4be43904336affa5c2f70744a348312336afd0da" + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/4be43904336affa5c2f70744a348312336afd0da", - "reference": "4be43904336affa5c2f70744a348312336afd0da", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", "shasum": "" }, "require": { - "composer-plugin-api": "^1.0 || ^2.0", - "php": ">=5.4", - "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + "php": ">=8.2" }, "require-dev": { - "composer/composer": "*", - "ext-json": "*", - "ext-zip": "*", - "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpcompatibility/php-compatibility": "^9.0", - "yoast/phpunit-polyfills": "^1.0" + "phpunit/phpunit": "^11.0" }, - "type": "composer-plugin", + "type": "library", "extra": { - "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" - }, - "autoload": { - "psr-4": { - "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Franck Nijhof", - "email": "franck.nijhof@dealerdirect.com", - "homepage": "http://www.frenck.nl", - "role": "Developer / IT Manager" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" - } - ], - "description": "PHP_CodeSniffer Standards Composer Installer Plugin", - "homepage": "http://www.dealerdirect.com", - "keywords": [ - "PHPCodeSniffer", - "PHP_CodeSniffer", - "code quality", - "codesniffer", - "composer", - "installer", - "phpcbf", - "phpcs", - "plugin", - "qa", - "quality", - "standard", - "standards", - "style guide", - "stylecheck", - "tests" - ], - "support": { - "issues": "https://github.com/PHPCSStandards/composer-installer/issues", - "source": "https://github.com/PHPCSStandards/composer-installer" - }, - "time": "2023-01-05T11:28:13+00:00" - }, - { - "name": "phpcompatibility/php-compatibility", - "version": "9.3.5", - "source": { - "type": "git", - "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", - "reference": "9fb324479acf6f39452e0655d2429cc0d3914243" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9fb324479acf6f39452e0655d2429cc0d3914243", - "reference": "9fb324479acf6f39452e0655d2429cc0d3914243", - "shasum": "" - }, - "require": { - "php": ">=5.3", - "squizlabs/php_codesniffer": "^2.3 || ^3.0.2" - }, - "conflict": { - "squizlabs/php_codesniffer": "2.6.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0" - }, - "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.", - "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." - }, - "type": "phpcodesniffer-standard", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0-or-later" - ], - "authors": [ - { - "name": "Wim Godden", - "homepage": "https://github.com/wimg", - "role": "lead" - }, - { - "name": "Juliette Reinders Folmer", - "homepage": "https://github.com/jrfnl", - "role": "lead" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors" + "branch-alias": { + "dev-main": "6.0-dev" } - ], - "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", - "homepage": "http://techblog.wimgodden.be/tag/codesniffer/", - "keywords": [ - "compatibility", - "phpcs", - "standards" - ], - "support": { - "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues", - "source": "https://github.com/PHPCompatibility/PHPCompatibility" - }, - "time": "2019-12-27T09:44:58+00:00" - }, - { - "name": "phpcompatibility/phpcompatibility-paragonie", - "version": "1.3.3", - "source": { - "type": "git", - "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git", - "reference": "293975b465e0e709b571cbf0c957c6c0a7b9a2ac" }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/293975b465e0e709b571cbf0c957c6c0a7b9a2ac", - "reference": "293975b465e0e709b571cbf0c957c6c0a7b9a2ac", - "shasum": "" - }, - "require": { - "phpcompatibility/php-compatibility": "^9.0" - }, - "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "^1.0", - "paragonie/random_compat": "dev-master", - "paragonie/sodium_compat": "dev-master" - }, - "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^1.0 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", - "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + "autoload": { + "classmap": [ + "src/" + ] }, - "type": "phpcodesniffer-standard", "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL-3.0-or-later" + "BSD-3-Clause" ], "authors": [ { - "name": "Wim Godden", - "role": "lead" - }, - { - "name": "Juliette Reinders Folmer", - "role": "lead" - } - ], - "description": "A set of rulesets for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by the Paragonie polyfill libraries.", - "homepage": "http://phpcompatibility.com/", - "keywords": [ - "compatibility", - "paragonie", - "phpcs", - "polyfill", - "standards", - "static analysis" - ], - "support": { - "issues": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues", - "security": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/security/policy", - "source": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie" - }, - "funding": [ - { - "url": "https://github.com/PHPCompatibility", - "type": "github" - }, - { - "url": "https://github.com/jrfnl", - "type": "github" + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" }, { - "url": "https://opencollective.com/php_codesniffer", - "type": "open_collective" - } - ], - "time": "2024-04-24T21:30:46+00:00" - }, - { - "name": "phpcompatibility/phpcompatibility-wp", - "version": "2.1.5", - "source": { - "type": "git", - "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git", - "reference": "01c1ff2704a58e46f0cb1ca9d06aee07b3589082" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/01c1ff2704a58e46f0cb1ca9d06aee07b3589082", - "reference": "01c1ff2704a58e46f0cb1ca9d06aee07b3589082", - "shasum": "" - }, - "require": { - "phpcompatibility/php-compatibility": "^9.0", - "phpcompatibility/phpcompatibility-paragonie": "^1.0" - }, - "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "^1.0" - }, - "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^1.0 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", - "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." - }, - "type": "phpcodesniffer-standard", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "LGPL-3.0-or-later" - ], - "authors": [ - { - "name": "Wim Godden", - "role": "lead" + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" }, { - "name": "Juliette Reinders Folmer", - "role": "lead" + "name": "Adam Harvey", + "email": "aharvey@php.net" } ], - "description": "A ruleset for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by WordPress.", - "homepage": "http://phpcompatibility.com/", - "keywords": [ - "compatibility", - "phpcs", - "standards", - "static analysis", - "wordpress" - ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { - "issues": "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues", - "security": "https://github.com/PHPCompatibility/PHPCompatibilityWP/security/policy", - "source": "https://github.com/PHPCompatibility/PHPCompatibilityWP" + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" }, "funding": [ { - "url": "https://github.com/PHPCompatibility", - "type": "github" - }, - { - "url": "https://github.com/jrfnl", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://opencollective.com/php_codesniffer", - "type": "open_collective" } ], - "time": "2024-04-24T21:37:59+00:00" + "time": "2024-07-03T05:10:34+00:00" }, { - "name": "phpcsstandards/phpcsextra", - "version": "1.2.1", + "name": "sebastian/type", + "version": "5.1.0", "source": { "type": "git", - "url": "https://github.com/PHPCSStandards/PHPCSExtra.git", - "reference": "11d387c6642b6e4acaf0bd9bf5203b8cca1ec489" + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHPCSExtra/zipball/11d387c6642b6e4acaf0bd9bf5203b8cca1ec489", - "reference": "11d387c6642b6e4acaf0bd9bf5203b8cca1ec489", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/461b9c5da241511a2a0e8f240814fb23ce5c0aac", + "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac", "shasum": "" }, "require": { - "php": ">=5.4", - "phpcsstandards/phpcsutils": "^1.0.9", - "squizlabs/php_codesniffer": "^3.8.0" + "php": ">=8.2" }, "require-dev": { - "php-parallel-lint/php-console-highlighter": "^1.0", - "php-parallel-lint/php-parallel-lint": "^1.3.2", - "phpcsstandards/phpcsdevcs": "^1.1.6", - "phpcsstandards/phpcsdevtools": "^1.2.1", - "phpunit/phpunit": "^4.5 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^11.3" }, - "type": "phpcodesniffer-standard", + "type": "library", "extra": { "branch-alias": { - "dev-stable": "1.x-dev", - "dev-develop": "1.x-dev" + "dev-main": "5.1-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL-3.0-or-later" + "BSD-3-Clause" ], "authors": [ { - "name": "Juliette Reinders Folmer", - "homepage": "https://github.com/jrfnl", + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", "role": "lead" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCSStandards/PHPCSExtra/graphs/contributors" } ], - "description": "A collection of sniffs and standards for use with PHP_CodeSniffer.", - "keywords": [ - "PHP_CodeSniffer", - "phpcbf", - "phpcodesniffer-standard", - "phpcs", - "standards", - "static analysis" - ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", "support": { - "issues": "https://github.com/PHPCSStandards/PHPCSExtra/issues", - "security": "https://github.com/PHPCSStandards/PHPCSExtra/security/policy", - "source": "https://github.com/PHPCSStandards/PHPCSExtra" + "issues": "https://github.com/sebastianbergmann/type/issues", + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/5.1.0" }, "funding": [ { - "url": "https://github.com/PHPCSStandards", - "type": "github" - }, - { - "url": "https://github.com/jrfnl", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://opencollective.com/php_codesniffer", - "type": "open_collective" } ], - "time": "2023-12-08T16:49:07+00:00" + "time": "2024-09-17T13:12:04+00:00" }, { - "name": "phpcsstandards/phpcsutils", - "version": "1.0.12", + "name": "sebastian/version", + "version": "5.0.2", "source": { "type": "git", - "url": "https://github.com/PHPCSStandards/PHPCSUtils.git", - "reference": "87b233b00daf83fb70f40c9a28692be017ea7c6c" + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/87b233b00daf83fb70f40c9a28692be017ea7c6c", - "reference": "87b233b00daf83fb70f40c9a28692be017ea7c6c", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", "shasum": "" }, "require": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7 || ^1.0", - "php": ">=5.4", - "squizlabs/php_codesniffer": "^3.10.0 || 4.0.x-dev@dev" - }, - "require-dev": { - "ext-filter": "*", - "php-parallel-lint/php-console-highlighter": "^1.0", - "php-parallel-lint/php-parallel-lint": "^1.3.2", - "phpcsstandards/phpcsdevcs": "^1.1.6", - "yoast/phpunit-polyfills": "^1.1.0 || ^2.0.0" + "php": ">=8.2" }, - "type": "phpcodesniffer-standard", + "type": "library", "extra": { "branch-alias": { - "dev-stable": "1.x-dev", - "dev-develop": "1.x-dev" + "dev-main": "5.0-dev" } }, "autoload": { "classmap": [ - "PHPCSUtils/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL-3.0-or-later" + "BSD-3-Clause" ], "authors": [ { - "name": "Juliette Reinders Folmer", - "homepage": "https://github.com/jrfnl", + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", "role": "lead" - }, - { - "name": "Contributors", - "homepage": "https://github.com/PHPCSStandards/PHPCSUtils/graphs/contributors" } ], - "description": "A suite of utility functions for use with PHP_CodeSniffer", - "homepage": "https://phpcsutils.com/", - "keywords": [ - "PHP_CodeSniffer", - "phpcbf", - "phpcodesniffer-standard", - "phpcs", - "phpcs3", - "standards", - "static analysis", - "tokens", - "utility" - ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", "support": { - "docs": "https://phpcsutils.com/", - "issues": "https://github.com/PHPCSStandards/PHPCSUtils/issues", - "security": "https://github.com/PHPCSStandards/PHPCSUtils/security/policy", - "source": "https://github.com/PHPCSStandards/PHPCSUtils" + "issues": "https://github.com/sebastianbergmann/version/issues", + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" }, "funding": [ { - "url": "https://github.com/PHPCSStandards", - "type": "github" - }, - { - "url": "https://github.com/jrfnl", + "url": "https://github.com/sebastianbergmann", "type": "github" - }, - { - "url": "https://opencollective.com/php_codesniffer", - "type": "open_collective" } ], - "time": "2024-05-20T13:34:27+00:00" + "time": "2024-10-09T05:16:32+00:00" }, { "name": "sirbrillig/phpcs-changed", @@ -2657,6 +2554,108 @@ ], "time": "2024-05-22T21:24:41+00:00" }, + { + "name": "staabm/side-effects-detector", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2024-10-20T05:08:20+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:36:25+00:00" + }, { "name": "wp-coding-standards/wpcs", "version": "3.1.0", @@ -2722,6 +2721,69 @@ } ], "time": "2024-03-25T16:39:00+00:00" + }, + { + "name": "yoast/phpunit-polyfills", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/Yoast/PHPUnit-Polyfills.git", + "reference": "19e6d5fb8aad31f731f774f9646a10c64a8843d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/19e6d5fb8aad31f731f774f9646a10c64a8843d2", + "reference": "19e6d5fb8aad31f731f774f9646a10c64a8843d2", + "shasum": "" + }, + "require": { + "php": ">=7.0", + "phpunit/phpunit": "^6.4.4 || ^7.0 || ^8.0 || ^9.0 || ^11.0" + }, + "require-dev": { + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "yoast/yoastcs": "^3.1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "files": [ + "phpunitpolyfills-autoload.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Team Yoast", + "email": "support@yoast.com", + "homepage": "https://yoast.com" + }, + { + "name": "Contributors", + "homepage": "https://github.com/Yoast/PHPUnit-Polyfills/graphs/contributors" + } + ], + "description": "Set of polyfills for changed PHPUnit functionality to allow for creating PHPUnit cross-version compatible tests", + "homepage": "https://github.com/Yoast/PHPUnit-Polyfills", + "keywords": [ + "phpunit", + "polyfill", + "testing" + ], + "support": { + "issues": "https://github.com/Yoast/PHPUnit-Polyfills/issues", + "security": "https://github.com/Yoast/PHPUnit-Polyfills/security/policy", + "source": "https://github.com/Yoast/PHPUnit-Polyfills" + }, + "time": "2024-09-07T00:24:25+00:00" } ], "aliases": [], diff --git a/phpunit.xml.dist b/phpunit.xml.dist index ba04346..12a1bf1 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -10,7 +10,7 @@ > - ./tests/unit + ./tests/unit diff --git a/tests/unit/test-address-validation.php b/tests/unit/AddressValidationTest.php similarity index 73% rename from tests/unit/test-address-validation.php rename to tests/unit/AddressValidationTest.php index cae60a0..5a76b97 100644 --- a/tests/unit/test-address-validation.php +++ b/tests/unit/AddressValidationTest.php @@ -5,18 +5,19 @@ * @package mailchimp */ -use \WP_Mock\Tools\TestCase; +/** + * Using PHP Unit TestCase due to fatal error when using WP_Mock test case + * + * PHP Fatal error: Cannot override final method PHPUnit\Framework\TestCase::run() + * in /vendor/10up/wp_mock/php/WP_Mock/Tools/TestCase.php on line 299 + */ +use PHPUnit\Framework\TestCase; +// use WP_Mock\Tools\TestCase; /** * AddressValidationTest class tests the address validation. */ class AddressValidationTest extends TestCase { - /** - * instance of mailchimp class. - * - * @var object - */ - private $instance; /** * Set up our mocked WP functions. Rather than setting up a database we can mock the returns of core WordPress functions. @@ -24,8 +25,8 @@ class AddressValidationTest extends TestCase { * @return void */ public function setUp(): void { + parent::setUp(); \WP_Mock::setUp(); - // $this->instance = new SafeSvg\safe_svg(); // TODO: Delete this, I don't think we need to instantiate any classes for our test } /** @@ -35,14 +36,15 @@ public function setUp(): void { */ public function tearDown(): void { \WP_Mock::tearDown(); + parent::tearDown(); } /** - * Test allow_svg function. + * Test PHPUnit is working. * * @return void */ - public function test_tests_are_running() { + public function test_phpunit_working() { $this->assertTrue(true, 'This is a placeholder test to make sure the tests are running'); // \WP_Mock::userFunction( diff --git a/tests/unit/bootstrap.php b/tests/unit/bootstrap.php index 30746ec..36ce69d 100644 --- a/tests/unit/bootstrap.php +++ b/tests/unit/bootstrap.php @@ -16,14 +16,32 @@ /** * Mock functions preventing plugin from loading - * - * TODO: Modularize code being tested to avoid loading - * the entire plugin */ // \WP_Mock::userFunction( 'plugin_dir_url' ); // \WP_Mock::userFunction( 'plugin_dir_path' ); // \WP_Mock::userFunction( 'plugins_url' ); // \WP_Mock::userFunction( 'trailingslashit' ); // \WP_Mock::userFunction( 'remove_filter' ); +// (There are more) -require TEST_PLUGIN_DIR . '/mailchimp.php'; \ No newline at end of file +/** + * Strategy: + * - Unit testing only (no integration or end-to-end). + * - Mock WP core functions with WP_Mock (WP core is not loaded). + * - Promote long-term maintainability through modularization. + * + * Reasoning: + * This plugin is not modular and initializing the plugin + * will require mocking all of the WP core functions + * used in order to avoid fatal errors on loading. + * + * Instead, we'll require functionality as it's needed + * by first: + * + * 1) Modularizing the functionality into a namespaced file and then + * 2) Importing it directly into the test. + * + * End to end tests are handled in Cypress. Integration + * and E2E tests should be handled in Cypress. + */ +// require TEST_PLUGIN_DIR . '/mailchimp.php'; \ No newline at end of file From d77ec3e7aae864ad6f6543edcc5fec760f953a92 Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 17:42:18 -0500 Subject: [PATCH 14/40] Rename test --- ...ddressValidationTest.php => USPhoneNumberValidationTest.php} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename tests/unit/{AddressValidationTest.php => USPhoneNumberValidationTest.php} (96%) diff --git a/tests/unit/AddressValidationTest.php b/tests/unit/USPhoneNumberValidationTest.php similarity index 96% rename from tests/unit/AddressValidationTest.php rename to tests/unit/USPhoneNumberValidationTest.php index 5a76b97..9d37548 100644 --- a/tests/unit/AddressValidationTest.php +++ b/tests/unit/USPhoneNumberValidationTest.php @@ -17,7 +17,7 @@ /** * AddressValidationTest class tests the address validation. */ -class AddressValidationTest extends TestCase { +class USPhoneNumberValidationTest extends TestCase { /** * Set up our mocked WP functions. Rather than setting up a database we can mock the returns of core WordPress functions. From 9a68d59c158098cc8b6539a778c30476292d4faa Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 18:17:31 -0500 Subject: [PATCH 15/40] Modularize location detection class Give us the flexibility to set variables during testing and allows us to test that we are setting locations correctly --- .../class-mailchimp-location-detector.php | 131 ++++++++++++++++++ mailchimp.php | 53 +------ 2 files changed, 135 insertions(+), 49 deletions(-) create mode 100644 includes/utility/class-mailchimp-location-detector.php diff --git a/includes/utility/class-mailchimp-location-detector.php b/includes/utility/class-mailchimp-location-detector.php new file mode 100644 index 0000000..2640cf4 --- /dev/null +++ b/includes/utility/class-mailchimp-location-detector.php @@ -0,0 +1,131 @@ +file_path = $file_path; + $this->dir_path = dirname( $file_path ); + $this->dir_base = $dir_base ?? trailingslashit( basename( $this->dir_path ) ); // Default: mailchimp/ + $this->initialize_locations(); + } + + /** + * Initializes the plugin locations. + * + * @return void + */ + private function initialize_locations() { + $this->locations = array( + 'plugins' => array( + 'dir' => plugin_dir_path( $this->file_path ), + 'url' => plugins_url(), + ), + 'mu_plugins' => array( + 'dir' => plugin_dir_path( $this->file_path ), + 'url' => plugins_url(), + ), + 'template' => array( + 'dir' => trailingslashit( get_template_directory() ) . 'plugins/', + 'url' => trailingslashit( get_template_directory_uri() ) . 'plugins/', + ), + 'stylesheet' => array( + 'dir' => trailingslashit( get_stylesheet_directory() ) . 'plugins/', + 'url' => trailingslashit( get_stylesheet_directory_uri() ) . 'plugins/', + ), + ); + } + + /** + * Detects the plugin location. + * + * @return array Contains 'dir' and 'url'. + */ + private function detect_location(): array { + $dir_path = trailingslashit( plugin_dir_path( $this->file_path ) ); + $url_path = trailingslashit( plugins_url( '', $this->file_path ) ); + + foreach ( $this->locations as $key => $loc ) { + $dir = trailingslashit( $loc['dir'] ) . $this->dir_base; + $url = trailingslashit( $loc['url'] ) . $this->dir_base; + + if ( is_file( $dir . basename( $this->file_path ) ) ) { + $dir_path = $dir; + $url_path = $url; + break; + } + } + + return [ + 'dir' => $dir_path, + 'url' => $url_path, + ]; + } + + /** + * Defines the necessary constants. + * + * @return void + */ + public function init() { + $location = $this->detect_location(); + + if ( ! defined( 'MCSF_DIR' ) ) { + define( 'MCSF_DIR', $location['dir'] ); + } + + if ( ! defined( 'MCSF_URL' ) ) { + define( 'MCSF_URL', $location['url'] ); + } + } +} diff --git a/mailchimp.php b/mailchimp.php index 9e7c9c6..caea716 100644 --- a/mailchimp.php +++ b/mailchimp.php @@ -37,6 +37,7 @@ // Validation use Mailchimp\WordPress\Includes\Validation\Mailchimp_Validation; use function Mailchimp\WordPress\Includes\Validation\{ merge_validate_phone, merge_validate_address }; +use Mailchimp\WordPress\Includes\Utility\Mailchimp_Location_Detector; // Version constant for easy CSS refreshes define( 'MCSF_VER', '1.6.2' ); @@ -45,7 +46,9 @@ define( 'MCSF_CAP_THRESHOLD', 'manage_options' ); // Define our location constants, both MCSF_DIR and MCSF_URL -mailchimp_sf_where_am_i(); +require_once plugin_dir_path( __FILE__ ) . 'includes/utility/class-mailchimp-location-detector.php'; +$mailchimp_location_detector = new Mailchimp_Location_Detector( __FILE__ ); +$mailchimp_location_detector->init(); // Get our Mailchimp API class in scope if ( ! class_exists( 'MailChimp_API' ) ) { @@ -1207,54 +1210,6 @@ function mailchimp_sf_delete_options( $options = array() ) { /********************** * Utility Functions * **********************/ -/** - * Utility function to allow placement of plugin in plugins, mu-plugins, child or parent theme's plugins folders - * - * This function must be ran _very early_ in the load process, as it sets up important constants for the rest of the plugin - */ -function mailchimp_sf_where_am_i() { - $locations = array( - 'plugins' => array( - 'dir' => plugin_dir_path( __FILE__ ), - 'url' => plugins_url(), - ), - 'mu_plugins' => array( - 'dir' => plugin_dir_path( __FILE__ ), - 'url' => plugins_url(), - ), - 'template' => array( - 'dir' => trailingslashit( get_template_directory() ) . 'plugins/', - 'url' => trailingslashit( get_template_directory_uri() ) . 'plugins/', - ), - 'stylesheet' => array( - 'dir' => trailingslashit( get_stylesheet_directory() ) . 'plugins/', - 'url' => trailingslashit( get_stylesheet_directory_uri() ) . 'plugins/', - ), - ); - - // Set defaults - $mscf_dirbase = trailingslashit( basename( __DIR__ ) ); // Typically wp-mailchimp/ or mailchimp/ - $mscf_dir = trailingslashit( plugin_dir_path( __FILE__ ) ); - $mscf_url = trailingslashit( plugins_url( '', __FILE__ ) ); - - // Try our hands at finding the real location - foreach ( $locations as $key => $loc ) { - $dir = trailingslashit( $loc['dir'] ) . $mscf_dirbase; - $url = trailingslashit( $loc['url'] ) . $mscf_dirbase; - if ( is_file( $dir . basename( __FILE__ ) ) ) { - $mscf_dir = $dir; - $mscf_url = $url; - break; - } - } - - // Define our complete filesystem path - define( 'MCSF_DIR', $mscf_dir ); - - // Define our complete URL to the plugin folder - define( 'MCSF_URL', $mscf_url ); -} - /** * MODIFIED VERSION of wp_verify_nonce from WP Core. Core was not overridden to prevent problems when replacing From 546d76671b8e39c8343dbc276050d36a96a47c6e Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 18:18:50 -0500 Subject: [PATCH 16/40] Add commands to lint for compatibility and autofix lint errors --- composer.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/composer.json b/composer.json index ce3b1b9..0f69099 100644 --- a/composer.json +++ b/composer.json @@ -27,6 +27,8 @@ }, "scripts": { "lint": "phpcs --standard=./phpcs.xml -p -s .", + "lint:fix": "phpcbf --standard=./phpcs.xml -p -s .", + "lint:compat": "phpcs --standard=./phpcs-compat.xml -p -s .", "test": "vendor/bin/phpunit" } } From d81e0c33afabe72bff62b400337a86136ba5811f Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 19:27:58 -0500 Subject: [PATCH 17/40] Add helper function to create WP_Error --- includes/validation/merge-fields.php | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/includes/validation/merge-fields.php b/includes/validation/merge-fields.php index e6de212..8457557 100644 --- a/includes/validation/merge-fields.php +++ b/includes/validation/merge-fields.php @@ -51,7 +51,7 @@ function ( $s ) { esc_html__( '%s must contain the correct amount of digits', 'mailchimp' ), esc_html( $data['name'] ) ); - $opt_val = new WP_Error( 'mc_phone_validation', $message ); + $opt_val = create_wp_error( 'mc_phone_validation', $message ); break; /** @@ -63,7 +63,7 @@ function ( $s ) { esc_html__( '%s must consist of only numbers', 'mailchimp' ), esc_html( $data['name'] ) ); - $opt_val = new WP_Error( 'mc_phone_validation', $message ); + $opt_val = create_wp_error( 'mc_phone_validation', $message ); break; /** @@ -88,7 +88,7 @@ function merge_validate_address( $opt_val, $data ) { if ( empty( $opt_val['addr1'] ) || empty( $opt_val['city'] ) ) { /* translators: %s: field name */ $message = sprintf( esc_html__( 'You must fill in %s.', 'mailchimp' ), esc_html( $data['name'] ) ); - $error = new WP_Error( 'invalid_address_merge', $message ); + $error = create_wp_error( 'invalid_address_merge', $message ); return $error; } /** @@ -113,3 +113,18 @@ function merge_validate_address( $opt_val, $data ) { $merge->country = $opt_val['country']; return $merge; } + +/** + * Creates a WP_Error object for merge field validation errors. + * + * Enables tests to make assertions regarding error messages + * + * @param string $code Error code. + * @param string $message Error message. + * @param mixed $data Optional. Error data. Default is null. + * + * @return WP_Error + */ +function create_wp_error( string $code, string $message ): WP_Error { + return new WP_Error( $code, $message ); +} From 6d436bf1524734835726ecb4c67f0a898592bf08 Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 19:28:54 -0500 Subject: [PATCH 18/40] Define MCSF_DIR and MCSF_URL constants for testing --- tests/unit/bootstrap.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/unit/bootstrap.php b/tests/unit/bootstrap.php index 36ce69d..e047135 100644 --- a/tests/unit/bootstrap.php +++ b/tests/unit/bootstrap.php @@ -8,6 +8,9 @@ define( 'TEST_PLUGIN_DIR', dirname( dirname( __DIR__ ) ) . '/' ); +define ( 'MCSF_DIR', TEST_PLUGIN_DIR ); +define ( 'MCSF_URL', 'http://localhost:8888/wp-content/plugins/mailchimp/' ); + // First we need to load the composer autoloader so we can use WP Mock. require_once TEST_PLUGIN_DIR . '/vendor/autoload.php'; From 3ab8df79a97d050adfe212bdd96382dfcbfdfadd Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 19:29:06 -0500 Subject: [PATCH 19/40] First pass of us phone number validation tests --- tests/unit/USPhoneNumberValidationTest.php | 174 +++++++++++++++------ 1 file changed, 126 insertions(+), 48 deletions(-) diff --git a/tests/unit/USPhoneNumberValidationTest.php b/tests/unit/USPhoneNumberValidationTest.php index 9d37548..9f081d5 100644 --- a/tests/unit/USPhoneNumberValidationTest.php +++ b/tests/unit/USPhoneNumberValidationTest.php @@ -1,70 +1,148 @@ init(); /** - * AddressValidationTest class tests the address validation. + * USPhoneNumberValidationTest class tests phone number validation. */ class USPhoneNumberValidationTest extends TestCase { + public function setUp(): void { + parent::setUp(); + WP_Mock::setUp(); + } + + public function tearDown(): void { + WP_Mock::tearDown(); + Mockery::close(); + parent::tearDown(); + } + /** - * Set up our mocked WP functions. Rather than setting up a database we can mock the returns of core WordPress functions. + * Data provider for valid phone numbers. * - * @return void + * @return array */ - public function setUp(): void { - parent::setUp(); - \WP_Mock::setUp(); + public static function validPhoneNumbersProvider(): array { + return [ + [['123', '456', '7890'], ['name' => 'Phone']], + [['987', '654', '3210'], ['name' => 'Phone']], + ]; } /** - * Tear down WP Mock. + * Data provider for invalid phone numbers. * - * @return void + * @return array */ - public function tearDown(): void { - \WP_Mock::tearDown(); - parent::tearDown(); + public static function invalidPhoneNumbersProvider(): array { + return [ + [['123', '45!', '7890'], ['name' => 'Phone']], + [['123', '456', '78a0'], ['name' => 'Phone']], + ]; + } + + /** + * Data provider for too short phone numbers. + * + * @return array + */ + public static function tooShortPhoneNumbersProvider(): array { + return [ + [['12', '456', '789'], ['name' => 'Phone']], + [['', '45', '7890'], ['name' => 'Phone']], + ]; + } + + /** + * Data provider for too long phone numbers. + * + * @return array + */ + public static function tooLongPhoneNumbersProvider(): array { + return [ + [['1234', '567', '890'], ['name' => 'Phone']], + [['123', '4567', '8901'], ['name' => 'Phone']], + ]; + } + + /** + * Test valid phone numbers. + * + * @dataProvider validPhoneNumbersProvider + */ + public function testValidPhoneNumbers($phoneNumArray, $formData): void { + $result = merge_validate_phone($phoneNumArray, $formData); + + $expected = implode('-', $phoneNumArray); // Phone number connected with hyphen + $this->assertEquals($expected, $result); + } + + /** + * Test invalid phone numbers. + * + * @dataProvider invalidPhoneNumbersProvider + */ + public function testInvalidPhoneNumbers($phoneArr, $formData): void { + // Use Mockery to mock the WP_Error class + $mock = Mockery::mock('WP_Error'); + + // Mock the `create_wp_error` function + WP_Mock::userFunction('create_wp_error', [ + 'times' => 1, + 'args' => ['mc_phone_validation', WP_Mock\Functions::type('string')], + 'return' => new WP_Error('mc_phone_validation', 'Mocked error message'), + ]); + + // $mock->shouldReceive('get_error_code')->andReturn('mc_phone_validation'); + + // // Assert that WP_Error was constructed correctly + // $mock->shouldReceive('__construct') + // ->with('mc_phone_validation', Mockery::pattern('/must consist of only numbers/'), null) + // ->once(); + + // Function under test + $result = merge_validate_phone($phoneArr, $formData); + + // echo var_dump($result->get_error_code()); + + // Assert the function returned a WP_Error object + // $this->assertInstanceOf(WP_Error::class, $result); + // Assert the result is a WP_Error object + $this->assertInstanceOf(WP_Error::class, $result); + // $this->assertEquals('mc_phone_validation', $result->get_error_code()); + } + + /** + * Test too short phone numbers. + * + * @dataProvider tooShortPhoneNumbersProvider + */ + public function testTooShortPhoneNumbers($input, $data): void { + $result = merge_validate_phone($input, $data); + $this->assertInstanceOf(WP_Error::class, $result); + $this->assertEquals('mc_phone_validation', $result->get_error_code()); + $this->assertStringContainsString('must contain the correct amount of digits', $result->get_error_message()); } /** - * Test PHPUnit is working. + * Test too long phone numbers. * - * @return void + * @dataProvider tooLongPhoneNumbersProvider */ - public function test_phpunit_working() { - $this->assertTrue(true, 'This is a placeholder test to make sure the tests are running'); - - // \WP_Mock::userFunction( - // 'get_option', - // array( - // 'args' => [ 'safe_svg_upload_roles', [] ], - // 'return' => [ 'editor' ], - // ) - // ); - - // \WP_Mock::userFunction( - // 'current_user_can', - // array( - // 'args' => 'safe_svg_upload_svg', - // 'return' => true, - // ) - // ); - - // $allowed_svg = $this->instance->allow_svg( array() ); - // $this->assertNotEmpty( $allowed_svg ); - // $this->assertContains( 'image/svg+xml', $allowed_svg ); + public function testTooLongPhoneNumbers($input, $data): void { + $result = merge_validate_phone($input, $data); + $this->assertInstanceOf(WP_Error::class, $result); + $this->assertEquals('mc_phone_validation', $result->get_error_code()); + $this->assertStringContainsString('must contain the correct amount of digits', $result->get_error_message()); } -} \ No newline at end of file +} From 9d265e4156f953fe61a3c194e3dde58ebac4488f Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 19:59:32 -0500 Subject: [PATCH 20/40] Refactor merge validation into a class for testing --- includes/validation/merge-fields.php | 227 +++++++++++++++------------ 1 file changed, 123 insertions(+), 104 deletions(-) diff --git a/includes/validation/merge-fields.php b/includes/validation/merge-fields.php index 8457557..1adec58 100644 --- a/includes/validation/merge-fields.php +++ b/includes/validation/merge-fields.php @@ -1,6 +1,6 @@ create_wp_error( 'mc_phone_validation', $message ); + break; + + /** + * Phone number must consist of only numbers + */ + case ! preg_match( '/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/', $opt_val ): + $message = sprintf( + /* translators: %s: field name */ + esc_html__( '%s must consist of only numbers', 'mailchimp' ), + esc_html( $data['name'] ) + ); + $opt_val = $this->create_wp_error( 'mc_phone_validation', $message ); + break; + + /** + * No issues, pass validation + */ + default: + break; + } - // If they were all empty - if ( ! $opt_val ) { return $opt_val; } - // Trim Whitespace - Beginning and end - $opt_val = array_map( 'trim', $opt_val ); - - // Trim Whitespace - Middle - $opt_val = array_map( - function ( $s ) { - return preg_replace( '/\s/', '', $s ); - }, - $opt_val - ); - - // Format number for validation - $opt_val = implode( '-', $opt_val ); - - switch ( true ) { - /** - * Phone number must be 12 characters long - * 10 digits [0-9] and 2 dashes "-" - */ - case strlen( $opt_val ) < 12: - $message = sprintf( - /* translators: %s: field name */ - esc_html__( '%s must contain the correct amount of digits', 'mailchimp' ), - esc_html( $data['name'] ) - ); - $opt_val = create_wp_error( 'mc_phone_validation', $message ); - break; - - /** - * Phone number must consist of only numbers - */ - case ! preg_match( '/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/', $opt_val ): - $message = sprintf( + /** + * Validate address + * + * @param array $opt_val Option value + * @param array $data Data + * @return mixed + */ + public function validate_address( $opt_val, $data ) { + if ( 'Y' === $data['required'] ) { + if ( empty( $opt_val['addr1'] ) || empty( $opt_val['city'] ) ) { /* translators: %s: field name */ - esc_html__( '%s must consist of only numbers', 'mailchimp' ), - esc_html( $data['name'] ) - ); - $opt_val = create_wp_error( 'mc_phone_validation', $message ); - break; - - /** - * No issues, pass validation - */ - default: - break; - } + $message = sprintf( esc_html__( 'You must fill in %s.', 'mailchimp' ), esc_html( $data['name'] ) ); + $error = $this->create_wp_error( 'invalid_address_merge', $message ); + return $error; + } + /** + * Condition + * 1) If the address is not required and + * 2) address line 1 or city is empty + * + * Result + * Then don't send address to Mailchimp + * Return false skips merge formatting in `mailchimp_sf_merge_submit` + */ + } elseif ( empty( $opt_val['addr1'] ) || empty( $opt_val['city'] ) ) { + return false; + } - return $opt_val; -} + $merge = new stdClass(); + $merge->addr1 = $opt_val['addr1']; + $merge->addr2 = $opt_val['addr2']; + $merge->city = $opt_val['city']; + $merge->state = $opt_val['state']; + $merge->zip = $opt_val['zip']; + $merge->country = $opt_val['country']; + return $merge; + } -/** - * Validate address - * - * @param array $opt_val Option value - * @param array $data Data - * @return mixed - */ -function merge_validate_address( $opt_val, $data ) { - if ( 'Y' === $data['required'] ) { - if ( empty( $opt_val['addr1'] ) || empty( $opt_val['city'] ) ) { - /* translators: %s: field name */ - $message = sprintf( esc_html__( 'You must fill in %s.', 'mailchimp' ), esc_html( $data['name'] ) ); - $error = create_wp_error( 'invalid_address_merge', $message ); - return $error; - } - /** - * Condition - * 1) If the address is not required and - * 2) address line 1 or city is empty - * - * Result - * Then don't send address to Mailchimp - * Return false skips merge formatting in `mailchimp_sf_merge_submit` - */ - } elseif ( empty( $opt_val['addr1'] ) || empty( $opt_val['city'] ) ) { - return false; + /** + * Creates a WP_Error object for merge field validation errors. + * + * Enables tests to make assertions regarding error messages + * + * @param string $code Error code. + * @param string $message Error message. + * @param mixed $data Optional. Error data. Default is null. + * + * @return WP_Error + */ + private function create_wp_error( string $code, string $message ): WP_Error { + return new WP_Error( $code, $message ); } +} - $merge = new stdClass(); - $merge->addr1 = $opt_val['addr1']; - $merge->addr2 = $opt_val['addr2']; - $merge->city = $opt_val['city']; - $merge->state = $opt_val['state']; - $merge->zip = $opt_val['zip']; - $merge->country = $opt_val['country']; - return $merge; +// Expose methods as functions to maintain backward compatibility +// TODO: Introduce a DI Container (PHP DI) to manage dependency injection +function merge_validate_phone( $opt_val, $data ) { + $validator = new Validate_Merge_Fields(); + return $validator->validate_phone( $opt_val, $data ); } -/** - * Creates a WP_Error object for merge field validation errors. - * - * Enables tests to make assertions regarding error messages - * - * @param string $code Error code. - * @param string $message Error message. - * @param mixed $data Optional. Error data. Default is null. - * - * @return WP_Error - */ -function create_wp_error( string $code, string $message ): WP_Error { - return new WP_Error( $code, $message ); +function merge_validate_address( $opt_val, $data ) { + $validator = new Validate_Merge_Fields(); + return $validator->validate_address( $opt_val, $data ); } From ae3cf49903b6edf6ed3ce1f0f856db2d859bf88e Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 21:39:32 -0500 Subject: [PATCH 21/40] Add WP_Error factory for ease of unit testing Separate functions into another file Rename Validate_Merge_Field class file --- .../validation/class-mailchimp-validation.php | 3 +- ...ds.php => class-validate-merge-fields.php} | 55 +++++++++---------- includes/validation/functions.php | 41 ++++++++++++++ 3 files changed, 68 insertions(+), 31 deletions(-) rename includes/validation/{merge-fields.php => class-validate-merge-fields.php} (71%) create mode 100644 includes/validation/functions.php diff --git a/includes/validation/class-mailchimp-validation.php b/includes/validation/class-mailchimp-validation.php index 0879658..effe129 100644 --- a/includes/validation/class-mailchimp-validation.php +++ b/includes/validation/class-mailchimp-validation.php @@ -31,6 +31,7 @@ public function init() { * @return void */ private function require_validation_functions() { - include_once MCSF_DIR . 'includes/validation/merge-fields.php'; + include_once MCSF_DIR . 'includes/validation/class-validate-merge-fields.php'; + include_once MCSF_DIR . 'includes/validation/functions.php'; } } diff --git a/includes/validation/merge-fields.php b/includes/validation/class-validate-merge-fields.php similarity index 71% rename from includes/validation/merge-fields.php rename to includes/validation/class-validate-merge-fields.php index 1adec58..d5b31e0 100644 --- a/includes/validation/merge-fields.php +++ b/includes/validation/class-validate-merge-fields.php @@ -16,6 +16,28 @@ * Provides methods for validating merge fields. */ class Validate_Merge_Fields { + + /** + * Create WP_Error objects via factory + * + * Creating WP_Error objects via factory to allow for unit testing + * + * @var Callable + */ + private $wp_error_factory; + + /** + * Initialize with factory to allow for better unit testing + * + * @param Callable $wp_error_factory Factory to create WP_Error objects + */ + public function __construct( $wp_error_factory = null ) { + // Default to return WP_Error objects + $this->wp_error_factory = $wp_error_factory ?? function ( string $code, string $message, $data = null ) { + return new WP_Error( $code, $message, $data ); + }; + } + /** * Validate phone * @@ -57,7 +79,7 @@ function ( $s ) { esc_html__( '%s must contain the correct amount of digits', 'mailchimp' ), esc_html( $data['name'] ) ); - $opt_val = $this->create_wp_error( 'mc_phone_validation', $message ); + $opt_val = call_user_func( $this->wp_error_factory, 'mc_phone_validation', $message ); break; /** @@ -69,7 +91,7 @@ function ( $s ) { esc_html__( '%s must consist of only numbers', 'mailchimp' ), esc_html( $data['name'] ) ); - $opt_val = $this->create_wp_error( 'mc_phone_validation', $message ); + $opt_val = call_user_func( $this->wp_error_factory, 'mc_phone_validation', $message ); break; /** @@ -94,7 +116,7 @@ public function validate_address( $opt_val, $data ) { if ( empty( $opt_val['addr1'] ) || empty( $opt_val['city'] ) ) { /* translators: %s: field name */ $message = sprintf( esc_html__( 'You must fill in %s.', 'mailchimp' ), esc_html( $data['name'] ) ); - $error = $this->create_wp_error( 'invalid_address_merge', $message ); + $error = call_user_func( $this->wp_error_factory, 'invalid_address_merge', $message ); return $error; } /** @@ -119,31 +141,4 @@ public function validate_address( $opt_val, $data ) { $merge->country = $opt_val['country']; return $merge; } - - /** - * Creates a WP_Error object for merge field validation errors. - * - * Enables tests to make assertions regarding error messages - * - * @param string $code Error code. - * @param string $message Error message. - * @param mixed $data Optional. Error data. Default is null. - * - * @return WP_Error - */ - private function create_wp_error( string $code, string $message ): WP_Error { - return new WP_Error( $code, $message ); - } -} - -// Expose methods as functions to maintain backward compatibility -// TODO: Introduce a DI Container (PHP DI) to manage dependency injection -function merge_validate_phone( $opt_val, $data ) { - $validator = new Validate_Merge_Fields(); - return $validator->validate_phone( $opt_val, $data ); -} - -function merge_validate_address( $opt_val, $data ) { - $validator = new Validate_Merge_Fields(); - return $validator->validate_address( $opt_val, $data ); } diff --git a/includes/validation/functions.php b/includes/validation/functions.php new file mode 100644 index 0000000..1f99f5f --- /dev/null +++ b/includes/validation/functions.php @@ -0,0 +1,41 @@ +validate_phone( $opt_val, $data ); +} + +/** + * Expose merge_validate_address function to maintain backward compatibility. + * TODO: Introduce a DI Container (PHP DI) to manage dependency injection. + * + * @param array $opt_val array of input from user + * @param array $data other form data needed for error message + */ +function merge_validate_address( $opt_val, $data ) { + $validator = new Validate_Merge_Fields(); + return $validator->validate_address( $opt_val, $data ); +} From 1a3f9a27f9701292938272982eeeb7fb9d7e2ef0 Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 21:58:26 -0500 Subject: [PATCH 22/40] Update testInvalidPhoneNumbers with WP_Error factory FINALLYgit status! =) --- tests/unit/USPhoneNumberValidationTest.php | 63 ++++++++++++---------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/tests/unit/USPhoneNumberValidationTest.php b/tests/unit/USPhoneNumberValidationTest.php index 9f081d5..f6a8ef1 100644 --- a/tests/unit/USPhoneNumberValidationTest.php +++ b/tests/unit/USPhoneNumberValidationTest.php @@ -2,8 +2,9 @@ use PHPUnit\Framework\TestCase; use Mockery; -use function Mailchimp\WordPress\Includes\Validation\merge_validate_phone; +use Mailchimp\WordPress\Includes\Validation\Validate_Merge_Fields; use Mailchimp\WordPress\Includes\Validation\Mailchimp_Validation; +use WP_Error; // Require files manually // TODO: Remove this once we are using composer autoload @@ -81,7 +82,8 @@ public static function tooLongPhoneNumbersProvider(): array { * @dataProvider validPhoneNumbersProvider */ public function testValidPhoneNumbers($phoneNumArray, $formData): void { - $result = merge_validate_phone($phoneNumArray, $formData); + $validate_merge_fields = new Validate_Merge_Fields(); + $result = $validate_merge_fields->validate_phone($phoneNumArray, $formData); $expected = implode('-', $phoneNumArray); // Phone number connected with hyphen $this->assertEquals($expected, $result); @@ -93,33 +95,40 @@ public function testValidPhoneNumbers($phoneNumArray, $formData): void { * @dataProvider invalidPhoneNumbersProvider */ public function testInvalidPhoneNumbers($phoneArr, $formData): void { - // Use Mockery to mock the WP_Error class - $mock = Mockery::mock('WP_Error'); - - // Mock the `create_wp_error` function - WP_Mock::userFunction('create_wp_error', [ - 'times' => 1, - 'args' => ['mc_phone_validation', WP_Mock\Functions::type('string')], - 'return' => new WP_Error('mc_phone_validation', 'Mocked error message'), - ]); - - // $mock->shouldReceive('get_error_code')->andReturn('mc_phone_validation'); - - // // Assert that WP_Error was constructed correctly - // $mock->shouldReceive('__construct') - // ->with('mc_phone_validation', Mockery::pattern('/must consist of only numbers/'), null) - // ->once(); - - // Function under test - $result = merge_validate_phone($phoneArr, $formData); + // Step 1: Create a blank mocked WP_Error. + $wp_error = Mockery::mock( 'WP_Error' ); + + // Step 2: Mock the factory that creates WP_Error. + $wp_error_factory = function ( $code, $message, $data = null ) use ( $wp_error ) { + // Step 3: Make assertions against the properties we want the WP_Error object to contain + // and dynamically fill them to return what our validate functions will pass in. + $wp_error + ->shouldReceive( 'get_error_code' ) + ->andReturn( $code ); + $wp_error + ->shouldReceive( 'get_error_message' ) + ->with( $code ) + ->andReturn( $message ); + return $wp_error; + }; + + // Step 4: Run the validation + $validate_merge_fields = new Validate_Merge_Fields( $wp_error_factory ); + $result = $validate_merge_fields->validate_phone($phoneArr, $formData); + + // Step 5: Assert that what our validation logic does is what we expect it does + + // Is WP_Error + $this->assertInstanceOf(WP_Error::class, $result); - // echo var_dump($result->get_error_code()); + // Error code + $this->assertEquals(Validate_Merge_Fields::PHONE_VALIDATION_ERROR_CODE, $result->get_error_code()); - // Assert the function returned a WP_Error object - // $this->assertInstanceOf(WP_Error::class, $result); - // Assert the result is a WP_Error object - $this->assertInstanceOf(WP_Error::class, $result); - // $this->assertEquals('mc_phone_validation', $result->get_error_code()); + // Error message + $this->assertMatchesRegularExpression( + '/must consist of only numbers/', + $result->get_error_message(Validate_Merge_Fields::PHONE_VALIDATION_ERROR_CODE) + ); } /** From 86ad9acfb8de031c2f5712d1e8316ff5441e5b23 Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 22:04:40 -0500 Subject: [PATCH 23/40] Refactor validation to use class constants for error codes --- includes/validation/class-validate-merge-fields.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/includes/validation/class-validate-merge-fields.php b/includes/validation/class-validate-merge-fields.php index d5b31e0..7c27707 100644 --- a/includes/validation/class-validate-merge-fields.php +++ b/includes/validation/class-validate-merge-fields.php @@ -17,6 +17,10 @@ */ class Validate_Merge_Fields { + const PHONE_VALIDATION_ERROR_CODE = 'mc_phone_validation'; + + const ADDRESS_VALIDATION_ERROR_CODE = 'invalid_address_merge'; + /** * Create WP_Error objects via factory * @@ -79,7 +83,7 @@ function ( $s ) { esc_html__( '%s must contain the correct amount of digits', 'mailchimp' ), esc_html( $data['name'] ) ); - $opt_val = call_user_func( $this->wp_error_factory, 'mc_phone_validation', $message ); + $opt_val = call_user_func( $this->wp_error_factory, self::PHONE_VALIDATION_ERROR_CODE, $message ); break; /** @@ -91,7 +95,7 @@ function ( $s ) { esc_html__( '%s must consist of only numbers', 'mailchimp' ), esc_html( $data['name'] ) ); - $opt_val = call_user_func( $this->wp_error_factory, 'mc_phone_validation', $message ); + $opt_val = call_user_func( $this->wp_error_factory, self::PHONE_VALIDATION_ERROR_CODE, $message ); break; /** @@ -116,7 +120,7 @@ public function validate_address( $opt_val, $data ) { if ( empty( $opt_val['addr1'] ) || empty( $opt_val['city'] ) ) { /* translators: %s: field name */ $message = sprintf( esc_html__( 'You must fill in %s.', 'mailchimp' ), esc_html( $data['name'] ) ); - $error = call_user_func( $this->wp_error_factory, 'invalid_address_merge', $message ); + $error = call_user_func( $this->wp_error_factory, self::ADDRESS_VALIDATION_ERROR_CODE, $message ); return $error; } /** From 0f4dfa3d4b62cf55baf8a58aee4345081448e313 Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 22:04:55 -0500 Subject: [PATCH 24/40] Update tests to use WP_Error factory logic --- tests/unit/USPhoneNumberValidationTest.php | 46 +++++++++++++++++++--- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/tests/unit/USPhoneNumberValidationTest.php b/tests/unit/USPhoneNumberValidationTest.php index f6a8ef1..0d4eb02 100644 --- a/tests/unit/USPhoneNumberValidationTest.php +++ b/tests/unit/USPhoneNumberValidationTest.php @@ -137,10 +137,27 @@ public function testInvalidPhoneNumbers($phoneArr, $formData): void { * @dataProvider tooShortPhoneNumbersProvider */ public function testTooShortPhoneNumbers($input, $data): void { - $result = merge_validate_phone($input, $data); + $wp_error = Mockery::mock('WP_Error'); + $wp_error_factory = function ($code, $message, $data = null) use ($wp_error) { + $wp_error + ->shouldReceive('get_error_code') + ->andReturn($code); + $wp_error + ->shouldReceive('get_error_message') + ->with($code) + ->andReturn($message); + return $wp_error; + }; + + $validate_merge_fields = new Validate_Merge_Fields($wp_error_factory); + $result = $validate_merge_fields->validate_phone($input, $data); + $this->assertInstanceOf(WP_Error::class, $result); - $this->assertEquals('mc_phone_validation', $result->get_error_code()); - $this->assertStringContainsString('must contain the correct amount of digits', $result->get_error_message()); + $this->assertEquals(Validate_Merge_Fields::PHONE_VALIDATION_ERROR_CODE, $result->get_error_code()); + $this->assertMatchesRegularExpression( + '/must contain the correct amount of digits/', + $result->get_error_message(Validate_Merge_Fields::PHONE_VALIDATION_ERROR_CODE) + ); } /** @@ -149,9 +166,26 @@ public function testTooShortPhoneNumbers($input, $data): void { * @dataProvider tooLongPhoneNumbersProvider */ public function testTooLongPhoneNumbers($input, $data): void { - $result = merge_validate_phone($input, $data); + $wp_error = Mockery::mock('WP_Error'); + $wp_error_factory = function ($code, $message, $data = null) use ($wp_error) { + $wp_error + ->shouldReceive('get_error_code') + ->andReturn($code); + $wp_error + ->shouldReceive('get_error_message') + ->with($code) + ->andReturn($message); + return $wp_error; + }; + + $validate_merge_fields = new Validate_Merge_Fields($wp_error_factory); + $result = $validate_merge_fields->validate_phone($input, $data); + $this->assertInstanceOf(WP_Error::class, $result); - $this->assertEquals('mc_phone_validation', $result->get_error_code()); - $this->assertStringContainsString('must contain the correct amount of digits', $result->get_error_message()); + $this->assertEquals(Validate_Merge_Fields::PHONE_VALIDATION_ERROR_CODE, $result->get_error_code()); + $this->assertMatchesRegularExpression( + '/must contain the correct amount of digits/', + $result->get_error_message(Validate_Merge_Fields::PHONE_VALIDATION_ERROR_CODE) + ); } } From c0e0e745dce42be88c734edd37e35e74d8af7a23 Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 22:07:44 -0500 Subject: [PATCH 25/40] Remove test for long phone numbers No reason to test long phone numbers because that is not a possible scenario a user can enter --- tests/unit/USPhoneNumberValidationTest.php | 46 ++-------------------- 1 file changed, 4 insertions(+), 42 deletions(-) diff --git a/tests/unit/USPhoneNumberValidationTest.php b/tests/unit/USPhoneNumberValidationTest.php index 0d4eb02..194aff5 100644 --- a/tests/unit/USPhoneNumberValidationTest.php +++ b/tests/unit/USPhoneNumberValidationTest.php @@ -64,18 +64,6 @@ public static function tooShortPhoneNumbersProvider(): array { ]; } - /** - * Data provider for too long phone numbers. - * - * @return array - */ - public static function tooLongPhoneNumbersProvider(): array { - return [ - [['1234', '567', '890'], ['name' => 'Phone']], - [['123', '4567', '8901'], ['name' => 'Phone']], - ]; - } - /** * Test valid phone numbers. * @@ -96,7 +84,7 @@ public function testValidPhoneNumbers($phoneNumArray, $formData): void { */ public function testInvalidPhoneNumbers($phoneArr, $formData): void { // Step 1: Create a blank mocked WP_Error. - $wp_error = Mockery::mock( 'WP_Error' ); + $wp_error = Mockery::mock('WP_Error'); // Step 2: Mock the factory that creates WP_Error. $wp_error_factory = function ( $code, $message, $data = null ) use ( $wp_error ) { @@ -134,6 +122,9 @@ public function testInvalidPhoneNumbers($phoneArr, $formData): void { /** * Test too short phone numbers. * + * NOTE: No reason to test phone numbers that are too long + * because the input field limits the length a user can enter. + * * @dataProvider tooShortPhoneNumbersProvider */ public function testTooShortPhoneNumbers($input, $data): void { @@ -159,33 +150,4 @@ public function testTooShortPhoneNumbers($input, $data): void { $result->get_error_message(Validate_Merge_Fields::PHONE_VALIDATION_ERROR_CODE) ); } - - /** - * Test too long phone numbers. - * - * @dataProvider tooLongPhoneNumbersProvider - */ - public function testTooLongPhoneNumbers($input, $data): void { - $wp_error = Mockery::mock('WP_Error'); - $wp_error_factory = function ($code, $message, $data = null) use ($wp_error) { - $wp_error - ->shouldReceive('get_error_code') - ->andReturn($code); - $wp_error - ->shouldReceive('get_error_message') - ->with($code) - ->andReturn($message); - return $wp_error; - }; - - $validate_merge_fields = new Validate_Merge_Fields($wp_error_factory); - $result = $validate_merge_fields->validate_phone($input, $data); - - $this->assertInstanceOf(WP_Error::class, $result); - $this->assertEquals(Validate_Merge_Fields::PHONE_VALIDATION_ERROR_CODE, $result->get_error_code()); - $this->assertMatchesRegularExpression( - '/must contain the correct amount of digits/', - $result->get_error_message(Validate_Merge_Fields::PHONE_VALIDATION_ERROR_CODE) - ); - } } From 37cdcae00bedb3b6a32b4982ee40efaa38cb4030 Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 22:38:43 -0500 Subject: [PATCH 26/40] Adding more testing cases for invalid phone numbers and too short numbers --- .../class-validate-merge-fields.php | 2 +- tests/unit/USPhoneNumberValidationTest.php | 51 ++++++++++++++----- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/includes/validation/class-validate-merge-fields.php b/includes/validation/class-validate-merge-fields.php index 7c27707..cb66af0 100644 --- a/includes/validation/class-validate-merge-fields.php +++ b/includes/validation/class-validate-merge-fields.php @@ -89,7 +89,7 @@ function ( $s ) { /** * Phone number must consist of only numbers */ - case ! preg_match( '/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/', $opt_val ): + case ! preg_match( '/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/', $opt_val ): // Valid US digital format (e.g. 123-456-7890) $message = sprintf( /* translators: %s: field name */ esc_html__( '%s must consist of only numbers', 'mailchimp' ), diff --git a/tests/unit/USPhoneNumberValidationTest.php b/tests/unit/USPhoneNumberValidationTest.php index 194aff5..a31297f 100644 --- a/tests/unit/USPhoneNumberValidationTest.php +++ b/tests/unit/USPhoneNumberValidationTest.php @@ -40,17 +40,32 @@ public static function validPhoneNumbersProvider(): array { ]; } - /** - * Data provider for invalid phone numbers. - * - * @return array - */ - public static function invalidPhoneNumbersProvider(): array { - return [ - [['123', '45!', '7890'], ['name' => 'Phone']], - [['123', '456', '78a0'], ['name' => 'Phone']], - ]; - } +/** + * Data provider for invalid phone numbers. + * + * @return array + */ +public static function invalidPhoneNumbersProvider(): array { + return [ + // // Repeated characters - allowing for vanity phone edge cases, seems like overkill to validate + // [['111', '111', '1111'], ['name' => 'Phone']], + + // Special characters + [['123', '!@#', '7890'], ['name' => 'Phone']], + // Alphabets + [['abc', '456', '7890'], ['name' => 'Phone']], + // Mixed alphabets and numbers + [['12a', '456', '7b90'], ['name' => 'Phone']], + // Symbols like hyphens, slashes, or parentheses + [['123-', '456', '7890'], ['name' => 'Phone']], + [['123', '/456', '7890'], ['name' => 'Phone']], + [['(12', '456', '7890'], ['name' => 'Phone']], + // Decimal points + [['1.4', '567', '890'], ['name' => 'Phone']], + // Emoji or Unicode characters + [['123', 'πŸ“ž46', '7890'], ['name' => 'Phone']], + ]; +} /** * Data provider for too short phone numbers. @@ -59,8 +74,16 @@ public static function invalidPhoneNumbersProvider(): array { */ public static function tooShortPhoneNumbersProvider(): array { return [ - [['12', '456', '789'], ['name' => 'Phone']], - [['', '45', '7890'], ['name' => 'Phone']], + // [['', '', ''], ['name' => 'Phone']], // All empty is not an error, this is a black phone field + [['12 ', '456', '789'], ['name' => 'Phone']], // 1st box whitespace + [['123', '45 ', '7890'], ['name' => 'Phone']], // 2nd box whitespace + [['123', '456', ' 890'], ['name' => 'Phone']], // 3rd box whitespace + [['12', '456', '7890'], ['name' => 'Phone']], // 1st box short + [['123', '56', '7890'], ['name' => 'Phone']], // 2nd box short + [['123', '456', '890'], ['name' => 'Phone']], // 3rd box short + [[null, '456', '7890'], ['name' => 'Phone']], // Null values + // Control characters (tab) + [['123', "\r0", '7890'], ['name' => 'Phone']], ]; } @@ -107,7 +130,7 @@ public function testInvalidPhoneNumbers($phoneArr, $formData): void { // Step 5: Assert that what our validation logic does is what we expect it does // Is WP_Error - $this->assertInstanceOf(WP_Error::class, $result); + $this->assertInstanceOf(WP_Error::class, $result, "Result (Not WP_Error): {$result}"); // Error code $this->assertEquals(Validate_Merge_Fields::PHONE_VALIDATION_ERROR_CODE, $result->get_error_code()); From 8e87e49e16de884a4e94e9ebff2740d57e4bf8be Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 22:50:46 -0500 Subject: [PATCH 27/40] Fix invalid number test case --- tests/unit/USPhoneNumberValidationTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/USPhoneNumberValidationTest.php b/tests/unit/USPhoneNumberValidationTest.php index a31297f..cfd4dfd 100644 --- a/tests/unit/USPhoneNumberValidationTest.php +++ b/tests/unit/USPhoneNumberValidationTest.php @@ -49,7 +49,7 @@ public static function invalidPhoneNumbersProvider(): array { return [ // // Repeated characters - allowing for vanity phone edge cases, seems like overkill to validate // [['111', '111', '1111'], ['name' => 'Phone']], - + // Special characters [['123', '!@#', '7890'], ['name' => 'Phone']], // Alphabets @@ -61,7 +61,7 @@ public static function invalidPhoneNumbersProvider(): array { [['123', '/456', '7890'], ['name' => 'Phone']], [['(12', '456', '7890'], ['name' => 'Phone']], // Decimal points - [['1.4', '567', '890'], ['name' => 'Phone']], + [['1.4', '567', '8901'], ['name' => 'Phone']], // Emoji or Unicode characters [['123', 'πŸ“ž46', '7890'], ['name' => 'Phone']], ]; From 018228b765ea76fb17eaebf98c4c44f7c987fb23 Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 22:51:05 -0500 Subject: [PATCH 28/40] Declare strict types in validate --- includes/validation/class-validate-merge-fields.php | 1 + 1 file changed, 1 insertion(+) diff --git a/includes/validation/class-validate-merge-fields.php b/includes/validation/class-validate-merge-fields.php index cb66af0..9dc17c6 100644 --- a/includes/validation/class-validate-merge-fields.php +++ b/includes/validation/class-validate-merge-fields.php @@ -4,6 +4,7 @@ * * @package mailchimp */ +declare(strict_types=1); namespace Mailchimp\WordPress\Includes\Validation; From c7dc9e86dfc91bdaf671b745a29cd6dd9f21525f Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 22:51:40 -0500 Subject: [PATCH 29/40] Fix lint error --- includes/validation/class-validate-merge-fields.php | 1 + 1 file changed, 1 insertion(+) diff --git a/includes/validation/class-validate-merge-fields.php b/includes/validation/class-validate-merge-fields.php index 9dc17c6..ecee6f5 100644 --- a/includes/validation/class-validate-merge-fields.php +++ b/includes/validation/class-validate-merge-fields.php @@ -4,6 +4,7 @@ * * @package mailchimp */ + declare(strict_types=1); namespace Mailchimp\WordPress\Includes\Validation; From 7643c4ec676cc1e3f078da4308a7a535543a06a1 Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 22:53:22 -0500 Subject: [PATCH 30/40] Formatting adjustments --- tests/unit/USPhoneNumberValidationTest.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/unit/USPhoneNumberValidationTest.php b/tests/unit/USPhoneNumberValidationTest.php index cfd4dfd..7243efe 100644 --- a/tests/unit/USPhoneNumberValidationTest.php +++ b/tests/unit/USPhoneNumberValidationTest.php @@ -75,6 +75,7 @@ public static function invalidPhoneNumbersProvider(): array { public static function tooShortPhoneNumbersProvider(): array { return [ // [['', '', ''], ['name' => 'Phone']], // All empty is not an error, this is a black phone field + [['12 ', '456', '789'], ['name' => 'Phone']], // 1st box whitespace [['123', '45 ', '7890'], ['name' => 'Phone']], // 2nd box whitespace [['123', '456', ' 890'], ['name' => 'Phone']], // 3rd box whitespace @@ -82,8 +83,7 @@ public static function tooShortPhoneNumbersProvider(): array { [['123', '56', '7890'], ['name' => 'Phone']], // 2nd box short [['123', '456', '890'], ['name' => 'Phone']], // 3rd box short [[null, '456', '7890'], ['name' => 'Phone']], // Null values - // Control characters (tab) - [['123', "\r0", '7890'], ['name' => 'Phone']], + [['123', "\r0", '7890'], ['name' => 'Phone']], // Control characters (tab) ]; } @@ -114,12 +114,12 @@ public function testInvalidPhoneNumbers($phoneArr, $formData): void { // Step 3: Make assertions against the properties we want the WP_Error object to contain // and dynamically fill them to return what our validate functions will pass in. $wp_error - ->shouldReceive( 'get_error_code' ) - ->andReturn( $code ); + ->shouldReceive('get_error_code') + ->andReturn($code); $wp_error - ->shouldReceive( 'get_error_message' ) - ->with( $code ) - ->andReturn( $message ); + ->shouldReceive('get_error_message') + ->with($code) + ->andReturn($message); return $wp_error; }; From 03488099f4e1bbd5ec2a0759f609e713f89b5d4e Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 7 Jan 2025 23:15:55 -0500 Subject: [PATCH 31/40] Add phpcompatibility most recent sniffs --- composer.json | 3 ++- composer.lock | 67 +++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 54 insertions(+), 16 deletions(-) diff --git a/composer.json b/composer.json index 0f69099..5b020a5 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,8 @@ "10up/phpcs-composer": "^3.0", "sirbrillig/phpcs-changed": "^2.11", "yoast/phpunit-polyfills": "^3.0", - "10up/wp_mock": "^0.4.2" + "10up/wp_mock": "^0.4.2", + "phpcompatibility/php-compatibility": "dev-develop as 9.99.99" }, "config": { "allow-plugins": { diff --git a/composer.lock b/composer.lock index 8efc7f6..f082ec2 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": "bb7bd60a5f4b3b02adb1f52a754e9794", + "content-hash": "a6520f04d04a380a996467143ef129b3", "packages": [], "packages-dev": [ { @@ -644,33 +644,45 @@ }, { "name": "phpcompatibility/php-compatibility", - "version": "9.3.5", + "version": "dev-develop", "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", - "reference": "9fb324479acf6f39452e0655d2429cc0d3914243" + "reference": "02835e45d27f5d0ed1642d5c8a5e8bfd2c7d7796" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9fb324479acf6f39452e0655d2429cc0d3914243", - "reference": "9fb324479acf6f39452e0655d2429cc0d3914243", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/02835e45d27f5d0ed1642d5c8a5e8bfd2c7d7796", + "reference": "02835e45d27f5d0ed1642d5c8a5e8bfd2c7d7796", "shasum": "" }, "require": { - "php": ">=5.3", - "squizlabs/php_codesniffer": "^2.3 || ^3.0.2" + "php": ">=5.4", + "phpcsstandards/phpcsutils": "^1.0.12", + "squizlabs/php_codesniffer": "^3.10.0" }, - "conflict": { - "squizlabs/php_codesniffer": "2.6.2" + "replace": { + "wimg/php-compatibility": "*" }, "require-dev": { - "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0" + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcsstandards/phpcsdevcs": "^1.1.3", + "phpcsstandards/phpcsdevtools": "^1.2.0", + "phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4 || ^10.1.0", + "yoast/phpunit-polyfills": "^1.0.5 || ^2.0.0" }, "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.", "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." }, + "default-branch": true, "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev", + "dev-develop": "10.x-dev" + } + }, "notification-url": "https://packagist.org/downloads/", "license": [ "LGPL-3.0-or-later" @@ -696,13 +708,29 @@ "keywords": [ "compatibility", "phpcs", - "standards" + "standards", + "static analysis" ], "support": { "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues", + "security": "https://github.com/PHPCompatibility/PHPCompatibility/security/policy", "source": "https://github.com/PHPCompatibility/PHPCompatibility" }, - "time": "2019-12-27T09:44:58+00:00" + "funding": [ + { + "url": "https://github.com/PHPCompatibility", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + } + ], + "time": "2024-11-30T16:25:00+00:00" }, { "name": "phpcompatibility/phpcompatibility-paragonie", @@ -2786,9 +2814,18 @@ "time": "2024-09-07T00:24:25+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "phpcompatibility/php-compatibility", + "version": "dev-develop", + "alias": "9.99.99", + "alias_normalized": "9.99.99.0" + } + ], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": { + "phpcompatibility/php-compatibility": 20 + }, "prefer-stable": true, "prefer-lowest": false, "platform": { From 37ffabffd4c75315886f5f4d755c2203204ea853 Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Wed, 8 Jan 2025 16:24:28 -0500 Subject: [PATCH 32/40] Fix bug causing form to not submit on empty US phone numbers The form must return null when a field is not filled out. Other values will cause a validation failure --- .../class-validate-merge-fields.php | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/includes/validation/class-validate-merge-fields.php b/includes/validation/class-validate-merge-fields.php index ecee6f5..76ab9dc 100644 --- a/includes/validation/class-validate-merge-fields.php +++ b/includes/validation/class-validate-merge-fields.php @@ -47,17 +47,30 @@ public function __construct( $wp_error_factory = null ) { /** * Validate phone * + * Filters and formats the phone number for validation. Returns: + * - `string` on successful validation. + * - `null` if the field is optional and not filled out. + * - `WP_Error` on validation failure. + * * @param array $opt_val Option value * @param array $data Data - * @return array|WP_Error + * @return string|null|WP_Error */ public function validate_phone( $opt_val, $data ) { // Filter out falsy values $opt_val = array_filter( $opt_val ); - // If they were all empty + /** + * Conditions + * - Field is not filled out - skip validation + * - Field is empty after filtering falsy values + * + * MUST return null if field is optional and not filled out + * Any other value will cause a validation error that prevents form + * from submitting + */ if ( ! $opt_val ) { - return $opt_val; + return null; } // Trim Whitespace - Beginning and end From 1b71c592dd6067c8b95f21eff7555a9ba1a780c9 Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Wed, 8 Jan 2025 16:57:55 -0500 Subject: [PATCH 33/40] Phone number should be exactly 12 digits 10 numbers and 2 hyphens --- includes/validation/class-validate-merge-fields.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/validation/class-validate-merge-fields.php b/includes/validation/class-validate-merge-fields.php index 76ab9dc..0eede94 100644 --- a/includes/validation/class-validate-merge-fields.php +++ b/includes/validation/class-validate-merge-fields.php @@ -92,7 +92,7 @@ function ( $s ) { * Phone number must be 12 characters long * 10 digits [0-9] and 2 dashes "-" */ - case strlen( $opt_val ) < 12: + case strlen( $opt_val ) !== 12: $message = sprintf( /* translators: %s: field name */ esc_html__( '%s must contain the correct amount of digits', 'mailchimp' ), From bc69c44b902045ee5e6b26e3124007d22bac41c5 Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Wed, 8 Jan 2025 17:01:57 -0500 Subject: [PATCH 34/40] Update tests to ensure empty and falsy inputs return null Expand validation test cases --- tests/unit/USPhoneNumberValidationTest.php | 76 +++++++++++++++++++--- 1 file changed, 67 insertions(+), 9 deletions(-) diff --git a/tests/unit/USPhoneNumberValidationTest.php b/tests/unit/USPhoneNumberValidationTest.php index 7243efe..4d6e606 100644 --- a/tests/unit/USPhoneNumberValidationTest.php +++ b/tests/unit/USPhoneNumberValidationTest.php @@ -57,13 +57,15 @@ public static function invalidPhoneNumbersProvider(): array { // Mixed alphabets and numbers [['12a', '456', '7b90'], ['name' => 'Phone']], // Symbols like hyphens, slashes, or parentheses - [['123-', '456', '7890'], ['name' => 'Phone']], - [['123', '/456', '7890'], ['name' => 'Phone']], + [['12-', '456', '7890'], ['name' => 'Phone']], + [['123', '/45', '7890'], ['name' => 'Phone']], [['(12', '456', '7890'], ['name' => 'Phone']], - // Decimal points - [['1.4', '567', '8901'], ['name' => 'Phone']], - // Emoji or Unicode characters - [['123', 'πŸ“ž46', '7890'], ['name' => 'Phone']], + + [['1.4', '567', '8901'], ['name' => 'Phone']], // Decimal points + [['---', '---', '----'], ['name' => 'Phone']], // All hyphen + [['12_', '_45', '78__'], ['name' => 'Phone']], // Underscores + [['123', "---", '7890'], ['name' => 'Phone']], // Mix with placeholder dashes + [['123', "(45", '7890'], ['name' => 'Phone']], // Mix with partial input artifact ]; } @@ -74,7 +76,8 @@ public static function invalidPhoneNumbersProvider(): array { */ public static function tooShortPhoneNumbersProvider(): array { return [ - // [['', '', ''], ['name' => 'Phone']], // All empty is not an error, this is a black phone field + // Not sure how many characters emojis are, but they shouldn't pass validation + [['123', 'πŸ“ž46', '7890'], ['name' => 'Phone']], // Emoji or Unicode characters [['12 ', '456', '789'], ['name' => 'Phone']], // 1st box whitespace [['123', '45 ', '7890'], ['name' => 'Phone']], // 2nd box whitespace @@ -84,6 +87,46 @@ public static function tooShortPhoneNumbersProvider(): array { [['123', '456', '890'], ['name' => 'Phone']], // 3rd box short [[null, '456', '7890'], ['name' => 'Phone']], // Null values [['123', "\r0", '7890'], ['name' => 'Phone']], // Control characters (tab) + [[' ', ' ', ' '], ['name' => 'Phone']], // All whitespaces + [["\t", "\n", "\r"], ['name' => 'Phone']], // All control chars (whitespace) + [['(', ') ', '-'], ['name' => 'Phone']], // Input Mask Artifacts + [['\'', '\'', '\''], ['name' => 'Phone']], // Single-Quote or Similar Characters + [["\u00A0", "\u2007", "\u202F"], ['name' => 'Phone']], // Non-breaking space variants + [["\u200B", "\u2060", "\uFEFF"], ['name' => 'Phone']], // Invisible Unicode Characters + [[" ", " ", " "], ['name' => 'Phone']], // HTML entities and encodings + + // Falsy and real values mixed + [['123', '', '7890'], ['name' => 'Phone']], // Mix with empty string + [['123', null, '7890'], ['name' => 'Phone']], // Mix with null + [['123', false, '7890'], ['name' => 'Phone']], // Mix with false + [['123', [], '7890'], ['name' => 'Phone']], // Mix with array + [['123', 0, '7890'], ['name' => 'Phone']], // Mix with zero + [['123', "\t", '7890'], ['name' => 'Phone']], // Mix with tab character + [['123', "\n", '7890'], ['name' => 'Phone']], // Mix with newline + [['123', "\u200B", '7890'], ['name' => 'Phone']], // Mix with zero-width space + [['123', "__", '7890'], ['name' => 'Phone']], // Mix with underscore + [['123', " ", '7890'], ['name' => 'Phone']], // Mix with HTML entity + [['123', " ", '7890'], ['name' => 'Phone']], // Mix with numeric HTML entity + [['123', "\u00A0", '7890'], ['name' => 'Phone']], // Mix with non-breaking space + [['123', "\r", '7890'], ['name' => 'Phone']], // Mix with carriage return + ]; + } + + /** + * Data provider for falsy and blank phone numbers. + * + * @return array + */ + public static function falsyAndBlankPhoneNumbersProvider() { + return [ + [[], ['name' => 'Phone']], // Empty array + [['', '', ''], ['name' => 'Phone']], // All empty is not an error, this is a blank phone field + [[null, null, null], ['name' => 'Phone']], // All null + [[false, false, false], ['name' => 'Phone']], // All false + [[[], [], []], ['name' => 'Phone']], // All array + [[0, 0, 0], ['name' => 'Phone']], // All zero + [[false, '', 0], ['name' => 'Phone']], // Mixed falsy values + [[null, '', []], ['name' => 'Phone']], // Mixed falsy values ]; } @@ -150,7 +193,7 @@ public function testInvalidPhoneNumbers($phoneArr, $formData): void { * * @dataProvider tooShortPhoneNumbersProvider */ - public function testTooShortPhoneNumbers($input, $data): void { + public function testTooShortPhoneNumbers($phoneArr, $formData): void { $wp_error = Mockery::mock('WP_Error'); $wp_error_factory = function ($code, $message, $data = null) use ($wp_error) { $wp_error @@ -164,7 +207,7 @@ public function testTooShortPhoneNumbers($input, $data): void { }; $validate_merge_fields = new Validate_Merge_Fields($wp_error_factory); - $result = $validate_merge_fields->validate_phone($input, $data); + $result = $validate_merge_fields->validate_phone($phoneArr, $formData); $this->assertInstanceOf(WP_Error::class, $result); $this->assertEquals(Validate_Merge_Fields::PHONE_VALIDATION_ERROR_CODE, $result->get_error_code()); @@ -173,4 +216,19 @@ public function testTooShortPhoneNumbers($input, $data): void { $result->get_error_message(Validate_Merge_Fields::PHONE_VALIDATION_ERROR_CODE) ); } + + /** + * Test falsy and empty inputs return null. + * + * null must be returned for empty phone numbers in order to + * not throw validation errors + * + * @dataProvider falsyAndBlankPhoneNumbersProvider + */ + public function testFalsyAndEmptyPhoneNumbersReturnNull($phoneArr, $formData) { + $validate_merge_fields = new Validate_Merge_Fields(); + $result = $validate_merge_fields->validate_phone($phoneArr, $formData); + + $this->assertEquals(null, $result); + } } From cfabc94ec963ea3538983697e7e37ee317f8bb9d Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Thu, 9 Jan 2025 16:25:06 -0500 Subject: [PATCH 35/40] Add back original validation functions as deprecated --- includes/deprecated/deprecated-functions.php | 39 ++++++++++++++++++ .../validation/class-mailchimp-validation.php | 1 - includes/validation/functions.php | 41 ------------------- mailchimp.php | 7 ++-- 4 files changed, 43 insertions(+), 45 deletions(-) create mode 100644 includes/deprecated/deprecated-functions.php delete mode 100644 includes/validation/functions.php diff --git a/includes/deprecated/deprecated-functions.php b/includes/deprecated/deprecated-functions.php new file mode 100644 index 0000000..a9b53ec --- /dev/null +++ b/includes/deprecated/deprecated-functions.php @@ -0,0 +1,39 @@ +validate_phone( $opt_val, $data ); +} + +/** + * Validate address. + * + * This function has been deprecated since version 1.7.0 and will be removed in a future release. + * + * @deprecated 1.7.0 Use mailchimp_sf_validate_address() instead. + * + * @param array $opt_val Option value. + * @param array $data Data. + * @return void|WP_Error Returns an error object if validation fails, otherwise processes the value. + */ +function mailchimp_sf_merge_validate_address( $opt_val, $data ) { + $validator = new Validate_Merge_Fields(); + return $validator->validate_address( $opt_val, $data ); +} diff --git a/includes/validation/class-mailchimp-validation.php b/includes/validation/class-mailchimp-validation.php index effe129..9061035 100644 --- a/includes/validation/class-mailchimp-validation.php +++ b/includes/validation/class-mailchimp-validation.php @@ -32,6 +32,5 @@ public function init() { */ private function require_validation_functions() { include_once MCSF_DIR . 'includes/validation/class-validate-merge-fields.php'; - include_once MCSF_DIR . 'includes/validation/functions.php'; } } diff --git a/includes/validation/functions.php b/includes/validation/functions.php deleted file mode 100644 index 1f99f5f..0000000 --- a/includes/validation/functions.php +++ /dev/null @@ -1,41 +0,0 @@ -validate_phone( $opt_val, $data ); -} - -/** - * Expose merge_validate_address function to maintain backward compatibility. - * TODO: Introduce a DI Container (PHP DI) to manage dependency injection. - * - * @param array $opt_val array of input from user - * @param array $data other form data needed for error message - */ -function merge_validate_address( $opt_val, $data ) { - $validator = new Validate_Merge_Fields(); - return $validator->validate_address( $opt_val, $data ); -} diff --git a/mailchimp.php b/mailchimp.php index caea716..5cf77bb 100644 --- a/mailchimp.php +++ b/mailchimp.php @@ -36,7 +36,6 @@ // Validation use Mailchimp\WordPress\Includes\Validation\Mailchimp_Validation; -use function Mailchimp\WordPress\Includes\Validation\{ merge_validate_phone, merge_validate_address }; use Mailchimp\WordPress\Includes\Utility\Mailchimp_Location_Detector; // Version constant for easy CSS refreshes @@ -78,6 +77,8 @@ $validation = new Mailchimp_Validation(); $validation->init(); +require_once plugin_dir_path( __FILE__ ) . '/includes/deprecated/deprecated-functions.php'; + /** * Do the following plugin setup steps here * @@ -1017,12 +1018,12 @@ function mailchimp_sf_merge_submit( $mv ) { // Handle phone number logic if ( isset( $mv_var['options']['phone_format'] ) && 'phone' === $mv_var['type'] && 'US' === $mv_var['options']['phone_format'] ) { - $opt_val = merge_validate_phone( $opt_val, $mv_var ); + $opt_val = mailchimp_sf_merge_validate_phone( $opt_val, $mv_var ); if ( is_wp_error( $opt_val ) ) { return $opt_val; } } elseif ( is_array( $opt_val ) && 'address' === $mv_var['type'] ) { // Handle address logic - $validate = merge_validate_address( $opt_val, $mv_var ); + $validate = mailchimp_sf_merge_validate_address( $opt_val, $mv_var ); if ( is_wp_error( $validate ) ) { return $validate; } From f020f9155ec1aed189a038a4f2819c956bbe15d0 Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Thu, 9 Jan 2025 16:34:50 -0500 Subject: [PATCH 36/40] Add docblock comment to deprecated-functions.php --- includes/deprecated/deprecated-functions.php | 32 +++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/includes/deprecated/deprecated-functions.php b/includes/deprecated/deprecated-functions.php index a9b53ec..716b6b0 100644 --- a/includes/deprecated/deprecated-functions.php +++ b/includes/deprecated/deprecated-functions.php @@ -1,4 +1,18 @@ Date: Thu, 9 Jan 2025 16:39:47 -0500 Subject: [PATCH 37/40] Fix deprecation warnings on test --- tests/unit/USPhoneNumberValidationTest.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tests/unit/USPhoneNumberValidationTest.php b/tests/unit/USPhoneNumberValidationTest.php index 4d6e606..d2d1793 100644 --- a/tests/unit/USPhoneNumberValidationTest.php +++ b/tests/unit/USPhoneNumberValidationTest.php @@ -1,10 +1,8 @@ assertInstanceOf(WP_Error::class, $result, "Result (Not WP_Error): {$result}"); + $this->assertInstanceOf(\WP_Error::class, $result, "Result (Not WP_Error): {$result}"); // Error code $this->assertEquals(Validate_Merge_Fields::PHONE_VALIDATION_ERROR_CODE, $result->get_error_code()); @@ -194,7 +192,7 @@ public function testInvalidPhoneNumbers($phoneArr, $formData): void { * @dataProvider tooShortPhoneNumbersProvider */ public function testTooShortPhoneNumbers($phoneArr, $formData): void { - $wp_error = Mockery::mock('WP_Error'); + $wp_error = \Mockery::mock('WP_Error'); $wp_error_factory = function ($code, $message, $data = null) use ($wp_error) { $wp_error ->shouldReceive('get_error_code') @@ -209,7 +207,7 @@ public function testTooShortPhoneNumbers($phoneArr, $formData): void { $validate_merge_fields = new Validate_Merge_Fields($wp_error_factory); $result = $validate_merge_fields->validate_phone($phoneArr, $formData); - $this->assertInstanceOf(WP_Error::class, $result); + $this->assertInstanceOf(\WP_Error::class, $result); $this->assertEquals(Validate_Merge_Fields::PHONE_VALIDATION_ERROR_CODE, $result->get_error_code()); $this->assertMatchesRegularExpression( '/must contain the correct amount of digits/', From 2fcb0da7058b4fa356db1ee1cbcbd250777f2fbb Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 14 Jan 2025 22:34:58 -0500 Subject: [PATCH 38/40] Add _deprecate_function to mailchimp_sf_merge_validate_phone and mailchimp_sf_merge_validate_address --- includes/deprecated/deprecated-functions.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/includes/deprecated/deprecated-functions.php b/includes/deprecated/deprecated-functions.php index 716b6b0..9a68f10 100644 --- a/includes/deprecated/deprecated-functions.php +++ b/includes/deprecated/deprecated-functions.php @@ -33,6 +33,7 @@ * @return void|WP_Error Returns an error object if validation fails, otherwise processes the value. */ function mailchimp_sf_merge_validate_phone( $opt_val, $data ) { + _deprecated_function( __FUNCTION__, '1.6.2', 'Validate_Merge_Fields::validate_phone' ); $validator = new Validate_Merge_Fields(); return $validator->validate_phone( $opt_val, $data ); } @@ -50,6 +51,7 @@ function mailchimp_sf_merge_validate_phone( $opt_val, $data ) { * @return void|WP_Error Returns an error object if validation fails, otherwise processes the value. */ function mailchimp_sf_merge_validate_address( $opt_val, $data ) { + _deprecated_function( __FUNCTION__, '1.6.2', 'Validate_Merge_Fields::validate_address' ); $validator = new Validate_Merge_Fields(); return $validator->validate_address( $opt_val, $data ); } From e01d999cf5a975543d8001b56445a915e4a29a9b Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 14 Jan 2025 22:55:24 -0500 Subject: [PATCH 39/40] Add mailchimp_sf_where_am_i back as a deprecated function --- includes/deprecated/deprecated-functions.php | 19 +++++++++++++++++++ mailchimp.php | 5 +++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/includes/deprecated/deprecated-functions.php b/includes/deprecated/deprecated-functions.php index 9a68f10..c1d0d52 100644 --- a/includes/deprecated/deprecated-functions.php +++ b/includes/deprecated/deprecated-functions.php @@ -15,10 +15,12 @@ */ use Mailchimp\WordPress\Includes\Validation\Validate_Merge_Fields; +use Mailchimp\WordPress\Includes\Utility\Mailchimp_Location_Detector; // Require here in case this file is loaded before the mailchimp.php plugin entrypoint // TODO: Remove this after composer autoloading is merged into develop require_once dirname( __DIR__, 2 ) . '/includes/validation/class-mailchimp-validation.php'; +require_once dirname( __DIR__, 2 ) . '/includes/utility/class-mailchimp-location-detector.php'; /** * Validate phone. @@ -55,3 +57,20 @@ function mailchimp_sf_merge_validate_address( $opt_val, $data ) { $validator = new Validate_Merge_Fields(); return $validator->validate_address( $opt_val, $data ); } + +/** + * Initialize location detection. + * + * This function initializes the Mailchimp location detection logic but has been deprecated + * since version 1.6.2. Use the Mailchimp_Location_Detector::init method instead. + * + * @deprecated 1.6.2 Use Mailchimp_Location_Detector::init. + * + * @return void + */ +function mailchimp_sf_where_am_i() { + _deprecated_function( __FUNCTION__, '1.6.2', 'Mailchimp_Location_Detector::init' ); + $plugin_root_path = dirname( dirname( __DIR__ ) ) . '/mailchimp.php'; + $mailchimp_location_detector = new Mailchimp_Location_Detector( $plugin_root_path ); + $mailchimp_location_detector->init(); +} diff --git a/mailchimp.php b/mailchimp.php index 5cf77bb..3d500e1 100644 --- a/mailchimp.php +++ b/mailchimp.php @@ -44,6 +44,9 @@ // What's our permission (capability) threshold define( 'MCSF_CAP_THRESHOLD', 'manage_options' ); +// Keep deprecated functions high in the load order to include `mailchimp_sf_where_am_i` as soon as possible +require_once plugin_dir_path( __FILE__ ) . '/includes/deprecated/deprecated-functions.php'; + // Define our location constants, both MCSF_DIR and MCSF_URL require_once plugin_dir_path( __FILE__ ) . 'includes/utility/class-mailchimp-location-detector.php'; $mailchimp_location_detector = new Mailchimp_Location_Detector( __FILE__ ); @@ -77,8 +80,6 @@ $validation = new Mailchimp_Validation(); $validation->init(); -require_once plugin_dir_path( __FILE__ ) . '/includes/deprecated/deprecated-functions.php'; - /** * Do the following plugin setup steps here * From d4798130b3649095f90d398dffdaba64099c52cf Mon Sep 17 00:00:00 2001 From: MaxwellGarceau Date: Tue, 14 Jan 2025 22:56:07 -0500 Subject: [PATCH 40/40] Fix lint --- includes/deprecated/deprecated-functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/deprecated/deprecated-functions.php b/includes/deprecated/deprecated-functions.php index c1d0d52..b306cbe 100644 --- a/includes/deprecated/deprecated-functions.php +++ b/includes/deprecated/deprecated-functions.php @@ -70,7 +70,7 @@ function mailchimp_sf_merge_validate_address( $opt_val, $data ) { */ function mailchimp_sf_where_am_i() { _deprecated_function( __FUNCTION__, '1.6.2', 'Mailchimp_Location_Detector::init' ); - $plugin_root_path = dirname( dirname( __DIR__ ) ) . '/mailchimp.php'; + $plugin_root_path = dirname( dirname( __DIR__ ) ) . '/mailchimp.php'; $mailchimp_location_detector = new Mailchimp_Location_Detector( $plugin_root_path ); $mailchimp_location_detector->init(); }