From c1adbcb8374567a8770959b59842b5f850fffdab Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Fri, 29 Aug 2025 15:31:08 -0700 Subject: [PATCH 1/2] chore: adds php 7.4 compatibiliy checking --- composer.json | 1 + composer.lock | 193 ++++++++++++++++++++++++++++++++++++++++++++++++- phpcs.xml.dist | 9 +++ 3 files changed, 201 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 9ae7d43d..5ca727a0 100644 --- a/composer.json +++ b/composer.json @@ -34,6 +34,7 @@ "guzzlehttp/psr7": "^1.0 || ^2.0", "php-http/curl-client": "^2.0", "php-http/mock-client": "^1.0", + "phpcompatibility/php-compatibility": "dev-develop", "phpstan/phpstan": "~2.1", "phpunit/phpunit": "^9.5 || ^10.0", "slevomat/coding-standard": "^8.20", diff --git a/composer.lock b/composer.lock index 61d7f347..d6a5af90 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": "c71f76f0ed18fb72bfdab0b94774e240", + "content-hash": "893f04e6854aa23afd7dcd0cabfe1def", "packages": [ { "name": "php-http/discovery", @@ -1260,6 +1260,193 @@ }, "time": "2024-10-31T10:30:18+00:00" }, + { + "name": "phpcompatibility/php-compatibility", + "version": "dev-develop", + "source": { + "type": "git", + "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", + "reference": "6e10469b0f3827862b37df2ac2b7ec4580ce888f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/6e10469b0f3827862b37df2ac2b7ec4580ce888f", + "reference": "6e10469b0f3827862b37df2ac2b7ec4580ce888f", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "phpcsstandards/phpcsutils": "^1.1.0", + "squizlabs/php_codesniffer": "^3.13.0" + }, + "replace": { + "wimg/php-compatibility": "*" + }, + "require-dev": { + "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.5.32 || ^11.3.3", + "yoast/phpunit-polyfills": "^1.0.5 || ^2.0 || ^3.0" + }, + "suggest": { + "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" + ], + "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" + } + ], + "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", + "homepage": "https://techblog.wimgodden.be/tag/codesniffer/", + "keywords": [ + "compatibility", + "phpcs", + "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" + }, + "funding": [ + { + "url": "https://github.com/PHPCompatibility", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcompatibility", + "type": "thanks_dev" + } + ], + "time": "2025-08-20T03:33:09+00:00" + }, + { + "name": "phpcsstandards/phpcsutils", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/PHPCSUtils.git", + "reference": "f7eb16f2fa4237d5db9e8fed8050239bee17a9bd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/f7eb16f2fa4237d5db9e8fed8050239bee17a9bd", + "reference": "f7eb16f2fa4237d5db9e8fed8050239bee17a9bd", + "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.13.0 || ^4.0" + }, + "require-dev": { + "ext-filter": "*", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcsstandards/phpcsdevcs": "^1.1.6", + "yoast/phpunit-polyfills": "^1.1.0 || ^2.0.0 || ^3.0.0" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-stable": "1.x-dev", + "dev-develop": "1.x-dev" + } + }, + "autoload": { + "classmap": [ + "PHPCSUtils/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "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", + "phpcs4", + "standards", + "static analysis", + "tokens", + "utility" + ], + "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" + }, + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2025-08-10T01:04:45+00:00" + }, { "name": "phpstan/phpdoc-parser", "version": "2.2.0", @@ -3332,7 +3519,9 @@ ], "aliases": [], "minimum-stability": "dev", - "stability-flags": {}, + "stability-flags": { + "phpcompatibility/php-compatibility": 20 + }, "prefer-stable": true, "prefer-lowest": false, "platform": { diff --git a/phpcs.xml.dist b/phpcs.xml.dist index 45a481c3..2e49db44 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -21,6 +21,15 @@ + + + + + + + + + From 31d0d809d0db0a07a58225cbd372cca3db8a9bd7 Mon Sep 17 00:00:00 2001 From: Jason Adams Date: Fri, 29 Aug 2025 15:31:46 -0700 Subject: [PATCH 2/2] fix: adds str_contains polyfill and uses it when possible --- src/Providers/Http/DTO/Request.php | 2 +- src/polyfills.php | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Providers/Http/DTO/Request.php b/src/Providers/Http/DTO/Request.php index c896d024..bb015fb9 100644 --- a/src/Providers/Http/DTO/Request.php +++ b/src/Providers/Http/DTO/Request.php @@ -114,7 +114,7 @@ public function getUri(): string { // If GET request with data, append as query parameters if ($this->method === HttpMethodEnum::GET() && $this->data !== null && !empty($this->data)) { - $separator = strpos($this->uri, '?') === false ? '?' : '&'; + $separator = str_contains($this->uri, '?') ? '&' : '?'; return $this->uri . $separator . http_build_query($this->data); } diff --git a/src/polyfills.php b/src/polyfills.php index 51db0bed..dc5d5557 100644 --- a/src/polyfills.php +++ b/src/polyfills.php @@ -57,6 +57,26 @@ function str_starts_with(string $haystack, string $needle): bool } } +if (!function_exists('str_contains')) { + /** + * Checks if a string contains a given substring. + * + * @since n.e.x.t + * + * @param string $haystack The string to search in. + * @param string $needle The substring to search for. + * @return bool True if $haystack contains $needle, false otherwise. + */ + function str_contains(string $haystack, string $needle): bool + { + if ('' === $needle) { + return true; + } + + return false !== strpos($haystack, $needle); + } +} + if (!function_exists('str_ends_with')) { /** * Checks if a string ends with a given substring.