diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1de997ffa7..5db0ad09b3 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -19,6 +19,14 @@ updates: - "dependencies" - "github_actions" + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "daily" + commit-message: + prefix: ⬆ + versioning-strategy: "increase" + - package-ecosystem: "pip" directory: "/" schedule: diff --git a/CHANGELOG.md b/CHANGELOG.md index 629f9cc364..f524323106 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ backwards-incompatible changes that will affect existing usage. +## 11.0.5 - 2025-03-11 + +- Fix PHPStan static analysis errors ([#929](https://github.com/php-curl-class/php-curl-class/pull/929)) + ## 11.0.4 - 2025-02-20 - Increase psalm strictness ([#925](https://github.com/php-curl-class/php-curl-class/pull/925)) diff --git a/composer.json b/composer.json index 0e7a8bbc24..8eb824cf50 100644 --- a/composer.json +++ b/composer.json @@ -29,8 +29,7 @@ "phpcsstandards/phpcsutils": "@alpha", "phpstan/phpstan": "*", "phpunit/phpunit": "*", - "squizlabs/php_codesniffer": "*", - "vimeo/psalm": ">=5.26.1" + "squizlabs/php_codesniffer": "*" }, "suggest": { "ext-mbstring": "*" diff --git a/scripts/make_release_requirements.txt b/scripts/make_release_requirements.txt index 133b5a34fd..f899ffe4d4 100644 --- a/scripts/make_release_requirements.txt +++ b/scripts/make_release_requirements.txt @@ -24,7 +24,7 @@ idna==3.7 # via requests pycparser==2.22 # via cffi -pygithub==2.6.0 +pygithub==2.6.1 # via -r scripts/make_release_requirements.in pyjwt[crypto]==2.8.0 # via pygithub diff --git a/src/Curl/Curl.php b/src/Curl/Curl.php index 8c1a9e94cd..6027cd6187 100644 --- a/src/Curl/Curl.php +++ b/src/Curl/Curl.php @@ -6,7 +6,7 @@ class Curl extends BaseCurl { - public const VERSION = '11.0.4'; + public const VERSION = '11.0.5'; public const DEFAULT_TIMEOUT = 30; public $curl = null; @@ -91,11 +91,6 @@ class Curl extends BaseCurl public $curlErrorCodeConstant; public $curlErrorCodeConstants; - public $curlOptionCodeConstants; - public $effectiveUrl; - public $rfc2616; - public $rfc6265; - public $totalTime; private static $deferredProperties = [ 'curlErrorCodeConstant', @@ -106,6 +101,7 @@ class Curl extends BaseCurl 'rfc6265', 'totalTime', ]; + private array $deferredValues = []; /** * Construct @@ -120,13 +116,13 @@ public function __construct($base_url = null, $options = []) throw new \ErrorException('cURL library is not loaded'); } - unset($this->curlErrorCodeConstant); - unset($this->curlErrorCodeConstants); - unset($this->curlOptionCodeConstants); - unset($this->effectiveUrl); - unset($this->rfc2616); - unset($this->rfc6265); - unset($this->totalTime); + unset($this->deferredValues['curlErrorCodeConstant']); + unset($this->deferredValues['curlErrorCodeConstants']); + unset($this->deferredValues['curlOptionCodeConstants']); + unset($this->deferredValues['effectiveUrl']); + unset($this->deferredValues['rfc2616']); + unset($this->deferredValues['rfc6265']); + unset($this->deferredValues['totalTime']); $this->curl = curl_init(); $this->initialize($base_url, $options); @@ -521,7 +517,7 @@ public function exec($ch = null) if ($this->curlError) { $curl_error_message = curl_strerror($this->curlErrorCode); - if ($this->curlErrorCodeConstant !== '') { + if (isset($this->curlErrorCodeConstant)) { $curl_error_message .= ' (' . $this->curlErrorCodeConstant . ')'; } @@ -561,9 +557,9 @@ public function exec($ch = null) $this->errorMessage = $this->curlError ? $this->curlErrorMessage : $this->httpErrorMessage; // Reset select deferred properties so that they may be recalculated. - unset($this->curlErrorCodeConstant); - unset($this->effectiveUrl); - unset($this->totalTime); + unset($this->deferredValues['curlErrorCodeConstant']); + unset($this->deferredValues['effectiveUrl']); + unset($this->deferredValues['totalTime']); // Reset content-length header possibly set from a PUT or SEARCH request. $this->unsetHeader('Content-Length'); @@ -1653,14 +1649,32 @@ public function __destruct() public function __get($name) { - $return = null; - if ( - in_array($name, self::$deferredProperties, true) && - is_callable([$this, $getter = 'get' . ucfirst($name)]) - ) { - $return = $this->$name = $this->$getter(); + if (in_array($name, self::$deferredProperties, true)) { + if (isset($this->deferredValues[$name])) { + return $this->deferredValues[$name]; + } elseif (is_callable([$this, $getter = 'get' . ucfirst($name)])) { + $this->deferredValues[$name] = $this->$getter(); + return $this->deferredValues[$name]; + } + } + + return null; + } + + public function __isset($name) + { + if (in_array($name, self::$deferredProperties, true)) { + if (isset($this->deferredValues[$name])) { + return true; + } elseif (is_callable([$this, $getter = 'get' . ucfirst($name)])) { + $this->deferredValues[$name] = $this->$getter(); + return true; + } else { + return false; + } } - return $return; + + return isset($this->$name); } /** @@ -1685,7 +1699,7 @@ function ($key) { */ private function getCurlErrorCodeConstant() { - $curl_const_by_code = $this->curlErrorCodeConstants; + $curl_const_by_code = $this->curlErrorCodeConstants ?? []; if (isset($curl_const_by_code[$this->curlErrorCode])) { return $curl_const_by_code[$this->curlErrorCode]; } diff --git a/tests/.pre-commit-config.yaml b/tests/.pre-commit-config.yaml index 953ea36ae0..11941f7561 100644 --- a/tests/.pre-commit-config.yaml +++ b/tests/.pre-commit-config.yaml @@ -23,7 +23,7 @@ repos: - id: flake8 args: ["--config", "tests/setup.cfg"] - repo: https://github.com/pycqa/isort - rev: 6.0.0 + rev: 6.0.1 hooks: - id: isort name: isort diff --git a/tests/display_errors.inc.sh b/tests/display_errors.inc.sh index 3ae4ce73c5..beec1d41ac 100644 --- a/tests/display_errors.inc.sh +++ b/tests/display_errors.inc.sh @@ -6,6 +6,6 @@ if [[ "${error_count}" -ge 1 ]]; then for value in "${errors[@]}"; do ((iter++)) echo -e "\nError ${iter} of ${error_count}:" - echo "${value}" | perl -pe 's/^(.*)$/\t\1/' + echo "❌ ${value}" | perl -pe 's/^(.*)$/\t\1/' done fi diff --git a/tests/display_warnings.inc.sh b/tests/display_warnings.inc.sh new file mode 100644 index 0000000000..e145ca550d --- /dev/null +++ b/tests/display_warnings.inc.sh @@ -0,0 +1,11 @@ +warning_count="${#warnings[@]}" +if [[ "${warning_count}" -ge 1 ]]; then + echo -e "\nWarnings found: ${warning_count}" + + iter=0 + for value in "${warnings[@]}"; do + ((iter++)) + echo -e "\nWarning ${iter} of ${warning_count}:" + echo "⚠️ ${value}" | perl -pe 's/^(.*)$/\t\1/' + done +fi diff --git a/tests/phpstan.neon b/tests/phpstan.neon index dafd9478e0..d933374d82 100644 --- a/tests/phpstan.neon +++ b/tests/phpstan.neon @@ -1,5 +1,6 @@ includes: - phpstan-baseline.neon + - phar://phpstan.phar/conf/bleedingEdge.neon parameters: reportUnmatchedIgnoredErrors: false diff --git a/tests/run.sh b/tests/run.sh index fd8240039b..e0b843252d 100755 --- a/tests/run.sh +++ b/tests/run.sh @@ -2,13 +2,31 @@ set -x +warnings=() errors=() if [[ "${CI}" == "true" ]]; then composer self-update + + # Skip attempting to install psalm on future PHP releases to avoid the + # following error that would otherwise block the remaining tests from + # running: + # Your requirements could not be resolved to an installable set of packages. + # + # Problem 1 + # - Root composer.json requires vimeo/psalm >=5.26.1 -> satisfiable by vimeo/psalm[5.26.1, 6.0.0, ..., 6.8.8]. + # - vimeo/psalm 5.26.1 requires php ^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 -> your php version (8.5.0-dev) does not satisfy that requirement. + # - vimeo/psalm[6.0.0, ..., 6.5.0] require php ~8.1.17 || ~8.2.4 || ~8.3.0 || ~8.4.0 -> your php version (8.5.0-dev) does not satisfy that requirement. + # - vimeo/psalm[6.5.1, ..., 6.8.8] require php ~8.1.31 || ~8.2.27 || ~8.3.16 || ~8.4.3 -> your php version (8.5.0-dev) does not satisfy that requirement. + # + # Error: Your requirements could not be resolved to an installable set of packages. + if ! "${CI_PHP_FUTURE_RELEASE}"; then + composer require --dev "vimeo/psalm:>=5.26.1" + fi + composer install --prefer-source --no-interaction if [[ "${?}" -ne 0 ]]; then - echo "Error: composer install failed" + echo "❌ Error: composer install failed" errors+=("composer install failed") fi fi @@ -38,10 +56,11 @@ source "run_static_analysis_check_psalm.sh" set +x +source "display_warnings.inc.sh" source "display_errors.inc.sh" if [[ "${CI_PHP_FUTURE_RELEASE}" != "true" ]]; then exit "${#errors[@]}" elif [[ "${#errors[@]}" -ne 0 ]]; then - echo "One or more tests failed, but allowed as the CI_PHP_FUTURE_RELEASE flag is on for PHP version ${CI_PHP_VERSION}." + echo "⚠️ One or more tests failed, but allowed as the CI_PHP_FUTURE_RELEASE flag is on for PHP version ${CI_PHP_VERSION}." fi diff --git a/tests/run_coding_standards_check.sh b/tests/run_coding_standards_check.sh index f3f76f1197..ccf99ef356 100755 --- a/tests/run_coding_standards_check.sh +++ b/tests/run_coding_standards_check.sh @@ -12,7 +12,7 @@ pushd .. crlf_file=$(find . -type "f" -iname "*.php" ! -path "*/vendor/*" -exec grep --color=always --files-with-matches $'\r' {} \;) if [[ ! -z "${crlf_file}" ]]; then result="$(echo "${crlf_file}" | perl -pe 's/(.*)/CRLF line terminators found in \1/')" - echo "${result}" + echo "❌ ${result}" errors+=("${result}") fi @@ -20,7 +20,7 @@ fi tab_char=$(find . -type "f" -iname "*.php" ! -path "*/vendor/*" -exec grep --color=always --line-number -H --perl-regexp "\t" {} \;) if [[ ! -z "${tab_char}" ]]; then result="$(echo -e "${tab_char}" | perl -pe 's/^(.*)$/Tab character found in \1/')" - echo "${result}" + echo "❌ ${result}" errors+=("${result}") fi @@ -68,7 +68,7 @@ EOF export -f "find_invalid_indentation" invalid_indentation=$(find . -type "f" -iname "*.php" ! -path "*/vendor/*" -exec bash -c 'find_invalid_indentation "{}"' \;) if [[ ! -z "${invalid_indentation}" ]]; then - echo "${invalid_indentation}" + echo "❌ ${invalid_indentation}" errors+=("${invalid_indentation}") fi @@ -76,7 +76,7 @@ fi trailing_whitespace=$(find . -type "f" -iname "*.php" ! -path "*/vendor/*" -exec grep --color=always --extended-regexp --line-number -H " +$" {} \;) if [[ ! -z "${trailing_whitespace}" ]]; then result="$(echo -e "${trailing_whitespace}" | perl -pe 's/^(.*)$/Trailing whitespace found in \1/')" - echo "${result}" + echo "❌ ${result}" errors+=("${result}") fi @@ -84,7 +84,7 @@ fi equal=$(find . -type "f" -iname "*.php" ! -path "*/vendor/*" -exec grep --color=always --extended-regexp --line-number -H "[^!=]==[^=]" {} \;) if [[ ! -z "${equal}" ]]; then result="$(echo -e "${equal}" | perl -pe 's/^(.*)$/Non-identical comparison operator found in \1/')" - echo "${result}" + echo "❌ ${result}" errors+=("${result}") fi @@ -92,7 +92,7 @@ fi elses=$(find . -type "f" -iname "*.php" ! -path "*/vendor/*" -exec grep --color=always --line-number -H --perl-regexp '^(\s+)?else(\s+)?{' {} \;) if [[ ! -z "${elses}" ]]; then result="$(echo -e "${elses}" | perl -pe 's/^(.*)$/Found newline before "else" statement in \1/')" - echo "${result}" + echo "❌ ${result}" errors+=("${result}") fi @@ -114,7 +114,7 @@ fi -s \ . if [[ "${?}" -ne 0 ]]; then - echo "Error: found PHP_CodeSniffer coding standard violation(s)" + echo "❌ Error: found PHP_CodeSniffer coding standard violation(s)" errors+=("found PHP_CodeSniffer coding standard violation(s)") fi @@ -123,14 +123,16 @@ fi # https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/pull/8300 if [[ $(echo "${CI_PHP_VERSION} < 8.4" | bc -l) -eq 1 ]]; then -# Run PHP-CS-Fixer. -vendor/bin/php-cs-fixer --version -vendor/bin/php-cs-fixer fix --ansi --config="tests/.php-cs-fixer.php" --diff --dry-run -if [[ "${?}" -ne 0 ]]; then - echo "Error: found PHP-CS-Fixer coding standard violation(s)" - errors+=("found PHP-CS-Fixer coding standard violation(s)") -fi - + # Run PHP-CS-Fixer. + vendor/bin/php-cs-fixer --version + vendor/bin/php-cs-fixer fix --ansi --config="tests/.php-cs-fixer.php" --diff --dry-run + if [[ "${?}" -ne 0 ]]; then + echo "❌ Error: found PHP-CS-Fixer coding standard violation(s)" + errors+=("found PHP-CS-Fixer coding standard violation(s)") + fi +else + echo "⚠️ Skipped running PHP-CS-Fixer coding standards check" + warnings+=("Skipped running PHP-CS-Fixer coding standards check") fi popd diff --git a/tests/run_phpunit.sh b/tests/run_phpunit.sh index d30f8ff485..40060d73fb 100755 --- a/tests/run_phpunit.sh +++ b/tests/run_phpunit.sh @@ -123,7 +123,7 @@ fi --configuration "phpunit.xml" \ ${phpunit_args} if [[ "${?}" -ne 0 ]]; then - echo "Error: phpunit command failed" + echo "❌ Error: phpunit command failed" errors+=("phpunit command failed") fi diff --git a/tests/run_static_analysis_check_phpstan.sh b/tests/run_static_analysis_check_phpstan.sh index 59121951af..fbb6b6ba07 100755 --- a/tests/run_static_analysis_check_phpstan.sh +++ b/tests/run_static_analysis_check_phpstan.sh @@ -11,13 +11,23 @@ pushd .. set -x if [[ $(echo "${CI_PHP_VERSION} >= 7.4" | bc -l) -eq 1 ]]; then - vendor/bin/phpstan analyse --ansi --configuration="tests/phpstan.neon" . + + phpstan_args=(--ansi --configuration="tests/phpstan.neon") + + # Increase memory limit on local development. + if [[ "${CI}" != "true" ]]; then + phpstan_args+=(--memory-limit=256M) + fi + + vendor/bin/phpstan --version + vendor/bin/phpstan analyse "${phpstan_args[@]}" . if [[ "${?}" -ne 0 ]]; then - echo "Error: phpstan static analysis check failed" + echo "❌ Error: phpstan static analysis check failed" errors+=("phpstan static analysis check failed") fi else - echo "Skipped running phpstan check" + echo "⚠️ Skipped running phpstan check" + warnings+=("Skipped running phpstan check") fi popd diff --git a/tests/run_static_analysis_check_psalm.sh b/tests/run_static_analysis_check_psalm.sh index d351d4c910..eb5870f2fb 100755 --- a/tests/run_static_analysis_check_psalm.sh +++ b/tests/run_static_analysis_check_psalm.sh @@ -10,17 +10,22 @@ pushd .. set -x -vendor/bin/psalm --version - -if [[ $(echo "${CI_PHP_VERSION} == 7.4" | bc -l) -eq 1 ]]; then - vendor/bin/psalm --config="tests/psalm_7.4.xml" +if [[ ! -f "vendor/bin/psalm" ]]; then + echo "⚠️ Skipped running psalm static analysis check" + warnings+=("Skipped running psalm static analysis check") else - vendor/bin/psalm --config="tests/psalm.xml" -fi - -if [[ "${?}" -ne 0 ]]; then - echo "Error: psalm static analysis check failed" - errors+=("psalm static analysis check failed") + vendor/bin/psalm --version + + if [[ $(echo "${CI_PHP_VERSION} == 7.4" | bc -l) -eq 1 ]]; then + vendor/bin/psalm --config="tests/psalm_7.4.xml" + else + vendor/bin/psalm --config="tests/psalm.xml" + fi + + if [[ "${?}" -ne 0 ]]; then + echo "❌ Error: psalm static analysis check failed" + errors+=("psalm static analysis check failed") + fi fi popd diff --git a/tests/run_syntax_check.sh b/tests/run_syntax_check.sh index ae0b8cc409..01a98868ab 100755 --- a/tests/run_syntax_check.sh +++ b/tests/run_syntax_check.sh @@ -9,7 +9,7 @@ pushd .. # Check syntax in php files. Use `xargs' over `find -exec' as xargs exits with a value of 1 when any command errors. find . -type "f" -iname "*.php" ! -path "*/vendor/*" | xargs -L "1" php -l if [[ "${?}" -ne 0 ]]; then - echo "Error: php syntax checks failed" + echo "❌ Error: php syntax checks failed" errors+=("php syntax checks failed") fi diff --git a/www/scripts/package.json b/www/scripts/package.json index ef97485627..20a3e12939 100644 --- a/www/scripts/package.json +++ b/www/scripts/package.json @@ -1,5 +1,5 @@ { "dependencies": { - "prismjs": "*" + "prismjs": "^1.29.0" } }