diff --git a/.gitattributes b/.gitattributes
index aece42002b..66460898b5 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -7,6 +7,5 @@
/.editorconfig export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
-/.pre-commit-config.yaml export-ignore
/TESTING.md export-ignore
/TROUBLESHOOTING.md export-ignore
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index ff838cd55d..1de997ffa7 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -4,12 +4,16 @@ updates:
directory: "/"
schedule:
interval: "daily"
+ commit-message:
+ prefix: ⬆
versioning-strategy: "increase"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
+ commit-message:
+ prefix: ⬆
labels:
- "cleanup-no-release-required"
- "dependencies"
@@ -19,4 +23,6 @@ updates:
directory: "/"
schedule:
interval: "daily"
+ commit-message:
+ prefix: ⬆
versioning-strategy: "increase"
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index eb6ae594a4..8c4b3522e8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,9 +20,10 @@ jobs:
- '8.1'
- '8.2'
- '8.3'
+ - '8.4'
future-release: [false]
include:
- - php-version: '8.4'
+ - php-version: '8.5'
future-release: true
fail-fast: false
name: PHP ${{ matrix.php-version }}
@@ -40,11 +41,7 @@ jobs:
persist-credentials: false
- name: Test
- run: bash tests/ci.sh
+ run: bash tests/run.sh
env:
CI_PHP_VERSION: ${{ matrix.php-version }}
CI_PHP_FUTURE_RELEASE: ${{ matrix.future-release }}
-
- - name: Static analysis
- run: 'vendor/bin/psalm --config="tests/psalm.xml"'
- if: ${{ !matrix.future-release }}
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 048143a3d0..cf77ee245f 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -30,7 +30,7 @@ jobs:
- name: flake8 changed files
if: steps.changed-files.outputs.any_changed == 'true'
run: |
- flake8 ${{ steps.changed-files.outputs.all_changed_files }}
+ flake8 --config="tests/setup.cfg" ${{ steps.changed-files.outputs.all_changed_files }}
- name: isort changed files
if: steps.changed-files.outputs.any_changed == 'true'
diff --git a/.github/workflows/pre-commit-auto-update.yml b/.github/workflows/pre-commit-auto-update.yml
index 74f8c58b55..726704f501 100644
--- a/.github/workflows/pre-commit-auto-update.yml
+++ b/.github/workflows/pre-commit-auto-update.yml
@@ -20,7 +20,7 @@ jobs:
set -x
python -m pip install --upgrade pip
pip install pre-commit
- pre-commit autoupdate
+ pre-commit autoupdate --config="tests/.pre-commit-config.yaml"
- name: Gather changes
id: gather-changes
@@ -34,7 +34,7 @@ jobs:
- name: Create or update pull request
id: cpr
- uses: peter-evans/create-pull-request@v6
+ uses: peter-evans/create-pull-request@v7
with:
commit-message: Update pre-commit dependencies
labels: cleanup-no-release-required, dependencies, github_actions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f3d148c534..7674b80db2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,11 @@ backwards-incompatible changes that will affect existing usage.
+## 11.0.1 - 2025-01-13
+
+- Increase Psalm strictness ([#909](https://github.com/php-curl-class/php-curl-class/pull/909))
+- Increase PHPStan strictness ([#908](https://github.com/php-curl-class/php-curl-class/pull/908))
+
## 11.0.0 - 2024-08-22
- Drop support for PHP 7.3 ([#889](https://github.com/php-curl-class/php-curl-class/pull/889))
diff --git a/README.md b/README.md
index b706f557a4..78d47a8ab3 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,10 @@
# PHP Curl Class: HTTP requests made easy
-[](https://github.com/php-curl-class/php-curl-class/releases/)
-[](https://github.com/php-curl-class/php-curl-class/blob/master/LICENSE)
-[](https://github.com/php-curl-class/php-curl-class/actions/workflows/ci.yml)
-[](https://github.com/php-curl-class/php-curl-class/releases/)
-[](https://github.com/php-curl-class/php-curl-class/releases/)
+[](https://github.com/php-curl-class/php-curl-class/releases/)
+[](https://github.com/php-curl-class/php-curl-class/blob/master/LICENSE)
+[](https://github.com/php-curl-class/php-curl-class/actions/workflows/ci.yml)
+[](https://github.com/php-curl-class/php-curl-class/releases/)
+[](https://github.com/php-curl-class/php-curl-class/releases/)
PHP Curl Class makes it easy to send HTTP requests and integrate with web APIs.
@@ -12,18 +12,18 @@ PHP Curl Class makes it easy to send HTTP requests and integrate with web APIs.
---
-- [Installation](#installation)
-- [Requirements](#requirements)
-- [Quick Start and Examples](#quick-start-and-examples)
-- [Available Methods](#available-methods)
-- [Security](#security)
-- [Troubleshooting](#troubleshooting)
-- [Testing](#testing)
-- [Contributing](#contributing)
+- [⚙️ Installation](#%EF%B8%8F-installation)
+- [📋 Requirements](#-requirements)
+- [🚀 Quick Start and Examples](#-quick-start-and-examples)
+- [📖 Available Methods](#-available-methods)
+- [🔒 Security](#-security)
+- [🛠️ Troubleshooting](#%EF%B8%8F-troubleshooting)
+- [🧪 Testing](#-testing)
+- [🤝 Contributing](#-contributing)
---
-### Installation
+### ⚙️ Installation
To install PHP Curl Class, run the following command:
@@ -35,11 +35,11 @@ To install the latest commit version:
Installation instructions to use the `composer` command can be found on https://github.com/composer/composer.
-### Requirements
+### 📋 Requirements
-PHP Curl Class works with PHP 8.3, 8.2, 8.1, 8.0, and 7.4.
+PHP Curl Class works with PHP 8.4, 8.3, 8.2, 8.1, 8.0, and 7.4.
-### Quick Start and Examples
+### 🚀 Quick Start and Examples
More examples are available under [/examples](https://github.com/php-curl-class/php-curl-class/tree/master/examples).
@@ -194,7 +194,7 @@ $multi_curl->start(); // Blocks until all items in the queue have been processed
More examples are available under [/examples](https://github.com/php-curl-class/php-curl-class/tree/master/examples).
-### Available Methods
+### 📖 Available Methods
```php
Curl::__construct($base_url = null, $options = [])
Curl::__destruct()
@@ -329,6 +329,7 @@ MultiCurl::close()
MultiCurl::complete($callback)
MultiCurl::disableTimeout()
MultiCurl::error($callback)
+MultiCurl::getActiveCurls()
MultiCurl::getOpt($option)
MultiCurl::removeHeader($key)
MultiCurl::setAutoReferer($auto_referer = true)
@@ -376,19 +377,19 @@ MultiCurl::unsetProxy()
MultiCurl::verbose($on = true, $output = 'STDERR')
```
-### Security
+### 🔒 Security
See [SECURITY](https://github.com/php-curl-class/php-curl-class/blob/master/SECURITY.md) for security considerations.
-### Troubleshooting
+### 🛠️ Troubleshooting
See [TROUBLESHOOTING](https://github.com/php-curl-class/php-curl-class/blob/master/TROUBLESHOOTING.md) for help troubleshooting.
-### Testing
+### 🧪 Testing
See [TESTING](https://github.com/php-curl-class/php-curl-class/blob/master/TESTING.md) for testing information.
-### Contributing
+### 🤝 Contributing
1. Check for open issues or open a new issue to start a discussion around a bug or feature.
1. Fork the repository on GitHub to start making your changes.
diff --git a/TESTING.md b/TESTING.md
index 2516486bb3..aeaf8f627a 100644
--- a/TESTING.md
+++ b/TESTING.md
@@ -30,4 +30,4 @@ cd php-curl-class/
### Continuous Integration Tests
-Continuous integration runs [tests/ci.sh](https://github.com/php-curl-class/php-curl-class/blob/master/tests/ci.sh) on supported PHP versions and is configured with [.github/workflows/ci.yml](https://github.com/php-curl-class/php-curl-class/blob/master/.github/workflows/ci.yml).
+Continuous integration runs [tests/run.sh](https://github.com/php-curl-class/php-curl-class/blob/master/tests/run.sh) on supported PHP versions and is configured with [.github/workflows/ci.yml](https://github.com/php-curl-class/php-curl-class/blob/master/.github/workflows/ci.yml).
diff --git a/composer.json b/composer.json
index 78222991bc..8eb824cf50 100644
--- a/composer.json
+++ b/composer.json
@@ -27,9 +27,9 @@
"friendsofphp/php-cs-fixer": "*",
"phpcompatibility/php-compatibility": "dev-develop",
"phpcsstandards/phpcsutils": "@alpha",
+ "phpstan/phpstan": "*",
"phpunit/phpunit": "*",
- "squizlabs/php_codesniffer": "*",
- "vimeo/psalm": ">=5.25.0"
+ "squizlabs/php_codesniffer": "*"
},
"suggest": {
"ext-mbstring": "*"
diff --git a/scripts/bump_major_version.php b/scripts/bump_major_version.php
index 7ca2f6c2c5..77b03069a4 100755
--- a/scripts/bump_major_version.php
+++ b/scripts/bump_major_version.php
@@ -5,7 +5,7 @@
$current_version = Curl\Curl::VERSION;
list($major, $_, $__) = explode('.', $current_version);
-$new_version = implode('.', [(string)((int)$major += 1), '0', '0']);
+$new_version = implode('.', [(string)((int)$major + 1), '0', '0']);
foreach (
[
diff --git a/scripts/bump_minor_version.php b/scripts/bump_minor_version.php
index a960450689..0de25185e0 100755
--- a/scripts/bump_minor_version.php
+++ b/scripts/bump_minor_version.php
@@ -5,7 +5,7 @@
$current_version = Curl\Curl::VERSION;
list($major, $minor, $_) = explode('.', $current_version);
-$new_version = implode('.', [$major, (string)((int)$minor += 1), '0']);
+$new_version = implode('.', [$major, (string)((int)$minor + 1), '0']);
foreach (
[
diff --git a/scripts/bump_patch_version.php b/scripts/bump_patch_version.php
index df57314295..0b6804ae3a 100755
--- a/scripts/bump_patch_version.php
+++ b/scripts/bump_patch_version.php
@@ -5,7 +5,7 @@
$current_version = Curl\Curl::VERSION;
list($major, $minor, $patch) = explode('.', $current_version);
-$new_version = implode('.', [$major, $minor, (string)((int)$patch += 1)]);
+$new_version = implode('.', [$major, $minor, (string)((int)$patch + 1)]);
foreach (
[
diff --git a/scripts/make_release_requirements.txt b/scripts/make_release_requirements.txt
index e325a4d70a..73dcd7ed81 100644
--- a/scripts/make_release_requirements.txt
+++ b/scripts/make_release_requirements.txt
@@ -12,20 +12,20 @@ cffi==1.16.0
# pynacl
charset-normalizer==3.3.2
# via requests
-cryptography==42.0.5
+cryptography==43.0.1
# via pyjwt
deprecated==1.2.14
# via pygithub
gitdb==4.0.11
# via gitpython
-gitpython==3.1.43
- # via -r make_release_requirements.in
+gitpython==3.1.44
+ # via -r scripts/make_release_requirements.in
idna==3.7
# via requests
pycparser==2.22
# via cffi
-pygithub==2.3.0
- # via -r make_release_requirements.in
+pygithub==2.5.0
+ # via -r scripts/make_release_requirements.in
pyjwt[crypto]==2.8.0
# via pygithub
pynacl==1.5.0
diff --git a/scripts/update_readme_methods.sh b/scripts/update_readme_methods.sh
index 4a658c161e..5c8574513e 100755
--- a/scripts/update_readme_methods.sh
+++ b/scripts/update_readme_methods.sh
@@ -4,11 +4,11 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "${SCRIPT_DIR}/.."
before=$(head -n $(
- grep --context="0" --line-number --max-count="1" "### Available Methods" "README.md" |
+ grep --context="0" --line-number --max-count="1" "### 📖 Available Methods" "README.md" |
perl -pe 's/^(\d+):.*/\1/') "README.md")
after=$(tail -n +$(
- grep --context="0" --line-number --max-count="1" "### Security" "README.md" |
+ grep --context="0" --line-number --max-count="1" "### 🔒 Security" "README.md" |
perl -pe 's/^(\d+):.*/\1/') "README.md")
echo "${before}" > "README.md"
@@ -48,10 +48,23 @@ echo "${after}" >> "README.md"
# Update table of contents.
script=$(cat <<'EOF'
$data = file_get_contents('README.md');
- preg_match_all('/^### ([\w ]+)/m', $data, $matches);
+ preg_match_all('/^### (.*)/m', $data, $matches);
$toc = [];
foreach ($matches['1'] as $match) {
- $href = '#' . str_replace(' ', '-', strtolower($match));
+ $slug = urlencode(
+ strtolower(
+ str_replace(
+ ' ',
+ '-',
+ preg_replace(
+ '/[^A-Za-z\x{FE0F} ]/u',
+ '',
+ $match,
+ ),
+ )
+ )
+ );
+ $href = '#' . $slug;
$toc[] = '- [' . $match . '](' . $href . ')';
}
$toc = implode("\n", $toc);
diff --git a/src/Curl/CaseInsensitiveArray.php b/src/Curl/CaseInsensitiveArray.php
index e12901775e..72b757a7e7 100644
--- a/src/Curl/CaseInsensitiveArray.php
+++ b/src/Curl/CaseInsensitiveArray.php
@@ -88,7 +88,7 @@ public function offsetSet($offset, $value)
#[\ReturnTypeWillChange]
public function offsetExists($offset)
{
- return (bool) array_key_exists(strtolower($offset), $this->data);
+ return array_key_exists(strtolower($offset), $this->data);
}
/**
@@ -129,20 +129,18 @@ public function offsetGet($offset)
/**
* Count
*
- * @param void
* @return int The number of elements stored in the array.
* @see https://secure.php.net/manual/en/countable.count.php
*/
#[\ReturnTypeWillChange]
public function count()
{
- return (int) count($this->data);
+ return count($this->data);
}
/**
* Current
*
- * @param void
* @return mixed Data at the current position.
* @see https://secure.php.net/manual/en/iterator.current.php
*/
@@ -155,7 +153,6 @@ public function current()
/**
* Next
*
- * @param void
* @return void
* @see https://secure.php.net/manual/en/iterator.next.php
*/
@@ -168,7 +165,6 @@ public function next()
/**
* Key
*
- * @param void
* @return mixed Case-sensitive key at current position.
* @see https://secure.php.net/manual/en/iterator.key.php
*/
@@ -188,13 +184,12 @@ public function key()
#[\ReturnTypeWillChange]
public function valid()
{
- return (bool) (key($this->data) !== null);
+ return (key($this->data) !== null);
}
/**
* Rewind
*
- * @param void
* @return void
* @see https://secure.php.net/manual/en/iterator.rewind.php
*/
diff --git a/src/Curl/Curl.php b/src/Curl/Curl.php
index 739177c214..d71118f1c9 100644
--- a/src/Curl/Curl.php
+++ b/src/Curl/Curl.php
@@ -6,7 +6,7 @@
class Curl extends BaseCurl
{
- public const VERSION = '11.0.0';
+ public const VERSION = '11.0.1';
public const DEFAULT_TIMEOUT = 30;
public $curl = null;
@@ -1812,9 +1812,11 @@ private function buildCookies()
if (count($this->cookies)) {
// Avoid using http_build_query() as unnecessary encoding is performed.
// http_build_query($this->cookies, '', '; ');
- $this->setOpt(CURLOPT_COOKIE, implode('; ', array_map(function ($k, $v) {
- return $k . '=' . $v;
- }, array_keys($this->cookies), array_values($this->cookies))));
+ $cookies = [];
+ foreach ($this->cookies as $key => $value) {
+ $cookies[] = $key . '=' . $value;
+ }
+ $this->setOpt(CURLOPT_COOKIE, implode('; ', $cookies));
}
}
diff --git a/src/Curl/Decoder.php b/src/Curl/Decoder.php
index 5f9821973a..b2aa0417db 100644
--- a/src/Curl/Decoder.php
+++ b/src/Curl/Decoder.php
@@ -18,7 +18,7 @@ public static function decodeJson()
{
$args = func_get_args();
$response = call_user_func_array('json_decode', $args);
- if ($response === null) {
+ if ($response === null && isset($args['0'])) {
$response = $args['0'];
}
return $response;
@@ -37,7 +37,7 @@ public static function decodeXml()
{
$args = func_get_args();
$response = @call_user_func_array('simplexml_load_string', $args);
- if ($response === false) {
+ if ($response === false && array_key_exists('0', $args)) {
$response = $args['0'];
}
return $response;
diff --git a/src/Curl/MultiCurl.php b/src/Curl/MultiCurl.php
index 5f3d9f617c..f6c00a8c86 100644
--- a/src/Curl/MultiCurl.php
+++ b/src/Curl/MultiCurl.php
@@ -578,6 +578,7 @@ public function setRateLimit($rate_limit)
$unit = strtolower($matches['3']);
// Convert interval to seconds based on unit.
+ $interval_seconds = '';
if ($unit === 's') {
$interval_seconds = $interval * 1;
} elseif ($unit === 'm') {
@@ -925,7 +926,7 @@ private function hasRequestQuota()
*/
private function waitUntilRequestQuotaAvailable()
{
- $sleep_until = $this->currentStartTime + $this->intervalSeconds;
+ $sleep_until = (float)($this->currentStartTime + $this->intervalSeconds);
$sleep_seconds = $sleep_until - microtime(true);
// Avoid using time_sleep_until() as it appears to be less precise and not sleep long enough.
diff --git a/.pre-commit-config.yaml b/tests/.pre-commit-config.yaml
similarity index 83%
rename from .pre-commit-config.yaml
rename to tests/.pre-commit-config.yaml
index 0966ee676d..c177426968 100644
--- a/.pre-commit-config.yaml
+++ b/tests/.pre-commit-config.yaml
@@ -6,13 +6,13 @@
# $ brew install pre-commit
#
# 2. Install hooks
-# $ pre-commit install
+# $ pre-commit install --config="tests/.pre-commit-config.yaml"
#
# 3. Optionally, enable automatic updates
-# $ pre-commit autoupdate
+# $ pre-commit autoupdate --config="tests/.pre-commit-config.yaml"
repos:
- repo: https://github.com/psf/black
- rev: 24.8.0
+ rev: 24.10.0
hooks:
- id: black
name: black
@@ -21,6 +21,7 @@ repos:
rev: 7.1.1
hooks:
- id: flake8
+ args: ["--config", "tests/setup.cfg"]
- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
diff --git a/tests/PHPCurlClass/UrlTest.php b/tests/PHPCurlClass/UrlTest.php
index 1d445f77ea..397793565e 100644
--- a/tests/PHPCurlClass/UrlTest.php
+++ b/tests/PHPCurlClass/UrlTest.php
@@ -11,8 +11,12 @@ class UrlTest extends \PHPUnit\Framework\TestCase
public function testUrlPaths()
{
$urls_file = gzopen(__DIR__ . '/urls.csv.gz', 'r');
- fgetcsv($urls_file); // header
- while (($test = fgetcsv($urls_file)) !== false) {
+ $length = null;
+ $separator = ",";
+ $enclosure = "\"";
+ $escape = "\\";
+ fgetcsv($urls_file, $length, $separator, $enclosure, $escape); // header
+ while (($test = fgetcsv($urls_file, $length, $separator, $enclosure, $escape)) !== false) {
$url = new Url($test[0], $test[1]);
$actual_url = (string)$url;
$expected_url = $test[2];
diff --git a/tests/check_static_analysis.sh b/tests/check_static_analysis.sh
deleted file mode 100755
index 2b1198fc52..0000000000
--- a/tests/check_static_analysis.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/env bash
-
-SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
-cd "${SCRIPT_DIR}"
-
-# Run commands from the project root directory.
-cd ..
-
-set -x
-
-vendor/bin/psalm --config="tests/psalm.xml"
diff --git a/tests/display_errors.inc.sh b/tests/display_errors.inc.sh
new file mode 100644
index 0000000000..3ae4ce73c5
--- /dev/null
+++ b/tests/display_errors.inc.sh
@@ -0,0 +1,11 @@
+error_count="${#errors[@]}"
+if [[ "${error_count}" -ge 1 ]]; then
+ echo -e "\nErrors found: ${error_count}"
+
+ iter=0
+ for value in "${errors[@]}"; do
+ ((iter++))
+ echo -e "\nError ${iter} of ${error_count}:"
+ echo "${value}" | perl -pe 's/^(.*)$/\t\1/'
+ done
+fi
diff --git a/tests/phpstan-baseline.neon b/tests/phpstan-baseline.neon
new file mode 100644
index 0000000000..cde552e0fc
--- /dev/null
+++ b/tests/phpstan-baseline.neon
@@ -0,0 +1,13 @@
+parameters:
+ ignoreErrors:
+ -
+ message: '#^Class CurlHandle not found\.$#'
+ identifier: class.notFound
+ count: 2
+ path: ../src/Curl/Curl.php
+
+ -
+ message: '#^Class CurlMultiHandle not found\.$#'
+ identifier: class.notFound
+ count: 2
+ path: ../src/Curl/MultiCurl.php
diff --git a/tests/phpstan.neon b/tests/phpstan.neon
new file mode 100644
index 0000000000..dafd9478e0
--- /dev/null
+++ b/tests/phpstan.neon
@@ -0,0 +1,15 @@
+includes:
+ - phpstan-baseline.neon
+
+parameters:
+ reportUnmatchedIgnoredErrors: false
+
+ # TODO: Increase rule level to be more strict.
+ level: 3
+
+ # TODO: Remove all exclusions except vendor/ and fix related errors.
+ excludePaths:
+ - ../examples/*
+ - ../tests/*
+ - ../vendor/*
+ - ../www/*
diff --git a/tests/psalm-baseline.xml b/tests/psalm-baseline.xml
new file mode 100644
index 0000000000..867a21c21d
--- /dev/null
+++ b/tests/psalm-baseline.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/tests/psalm.xml b/tests/psalm.xml
index 79b8a77f32..d56152c69a 100644
--- a/tests/psalm.xml
+++ b/tests/psalm.xml
@@ -1,10 +1,12 @@
+
diff --git a/tests/run.sh b/tests/run.sh
index ca4c2ca7f1..9b98225765 100755
--- a/tests/run.sh
+++ b/tests/run.sh
@@ -1,63 +1,25 @@
#!/usr/bin/env bash
-remove_expectWarning() {
- # Fix "Call to undefined method CurlTest\CurlTest::expectWarning()".
- if sed v < /dev/null 2> /dev/null; then
- sed -i"" -e "/->expectWarning(/d" "./PHPCurlClass/PHP"*
- else
- sed -i "" -e "/->expectWarning(/d" "./PHPCurlClass/PHP"*
- fi
-}
-
-replace_assertStringContainsString() {
- # -->assertStringContainsString(
- # +->assertContains(
- find='->assertStringContainsString('
- replace='->assertContains('
- if sed v < /dev/null 2> /dev/null; then
- sed -i"" -e "s/${find}/${replace}/" "./PHPCurlClass/PHP"*
- else
- sed -i "" -e "s/${find}/${replace}/" "./PHPCurlClass/PHP"*
- fi
-}
-
-replace_assertMatchesRegularExpression() {
- # -->assertMatchesRegularExpression(
- # +->assertRegExp(
- find='->assertMatchesRegularExpression('
- replace='->assertRegExp('
- if sed v < /dev/null 2> /dev/null; then
- sed -i"" -e"s/${find}/${replace}/" "./PHPCurlClass/PHP"*
- else
- sed -i "" -e"s/${find}/${replace}/" "./PHPCurlClass/PHP"*
- fi
-}
-
-phpunit_v6_5_shim() {
- remove_expectWarning
- replace_assertMatchesRegularExpression
- replace_assertStringContainsString
-}
-
-phpunit_v7_5_shim() {
- remove_expectWarning
- replace_assertMatchesRegularExpression
-}
-
-phpunit_v8_5_shim() {
- remove_expectWarning
- replace_assertMatchesRegularExpression
-}
+set -x
-phpunit_v9_shim() {
- replace_assertMatchesRegularExpression
-}
+if [[ "${CI}" == "true" ]]; then
+ composer self-update
+
+ # TODO: Add "vimeo/psalm" back into composer.json under "require-dev" when
+ # vimeo/psalm supports PHP 8.4 (https://github.com/vimeo/psalm/issues/11107):
+ # "require-dev": {
+ # "vimeo/psalm": ">=5.26.1"
+ # },
+ #
+ # TODO: Remove this workaround that only installs vimeo/psalm on PHP < 8.4 when
+ # vimeo/psalm supports PHP 8.4 (https://github.com/vimeo/psalm/issues/11107):
+ if [[ $(echo "${CI_PHP_VERSION} < 8.4" | bc -l) -eq 1 ]]; then
+ composer require --dev "vimeo/psalm:>=5.26.1"
+ fi
-phpunit_v10_shim() {
- remove_expectWarning
-}
+ composer install --prefer-source --no-interaction
+fi
-set -x
# Use composer's phpunit and phpcs by adding composer bin directory to the path environment variable.
export PATH="${PWD}/vendor/bin:${PATH}"
@@ -65,88 +27,26 @@ export PATH="${PWD}/vendor/bin:${PATH}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "${SCRIPT_DIR}"
+source "set_vars.inc.sh"
+
echo "CI_PHP_VERSION: ${CI_PHP_VERSION}"
echo "CI_PHP_FUTURE_RELEASE: ${CI_PHP_FUTURE_RELEASE}"
php -r "var_dump(phpversion());"
php -r "var_dump(curl_version());"
-# Let test server know we should allow testing.
-export PHP_CURL_CLASS_TEST_MODE_ENABLED="yes"
-
-# Start test servers. Run servers on different ports to allow simultaneous
-# requests without blocking.
-server_count=7
-declare -A pids
-for i in $(seq 0 $(("${server_count}" - 1))); do
- port=8000
- (( port += $i ))
-
- php -S "127.0.0.1:${port}" server.php &> /dev/null &
- pids["${i}"]="${!}"
-done
-
errors=()
-source "check_syntax.sh"
-
-# Determine which phpunit to use.
-if [[ -f "../vendor/bin/phpunit" ]]; then
- phpunit_to_use="../vendor/bin/phpunit"
-else
- phpunit_to_use="phpunit"
-fi
-
-phpunit_version="$("${phpunit_to_use}" --version | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+")"
-echo "phpunit_version: ${phpunit_version}"
-
-extra_args="${@}"
-if [[ "${phpunit_version}" == "6.5."* ]]; then
- phpunit_v6_5_shim
- phpunit_args=" --debug --verbose --fail-on-risky ${extra_args}"
-elif [[ "${phpunit_version}" == "7.5."* ]]; then
- phpunit_v7_5_shim
- phpunit_args=" --debug --verbose --fail-on-risky ${extra_args}"
-elif [[ "${phpunit_version}" == "8.5."* ]]; then
- phpunit_v8_5_shim
- phpunit_args=" --debug --verbose --fail-on-risky ${extra_args}"
-elif [[ "${phpunit_version}" == "9."* ]]; then
- phpunit_v9_shim
- phpunit_args=" --debug --verbose --fail-on-risky ${extra_args}"
-elif [[ "${phpunit_version}" == "10."* ]]; then
- phpunit_v10_shim
- phpunit_args=" --display-incomplete --display-skipped --display-deprecations --display-errors --display-notices --display-warnings --fail-on-risky ${extra_args}"
-fi
+source "run_syntax_check.sh"
-# Run tests.
-"${phpunit_to_use}" --version
-"${phpunit_to_use}" \
- --configuration "phpunit.xml" \
- ${phpunit_args}
-if [[ "${?}" -ne 0 ]]; then
- echo "Error: phpunit command failed"
- errors+=("phpunit command failed")
-fi
+source "run_coding_standards_check.sh"
-source "check_coding_standards.sh"
+source "run_phpunit.sh"
-set +x
+source "run_static_analysis_check_phpstan.sh"
-error_count="${#errors[@]}"
-if [[ "${error_count}" -ge 1 ]]; then
- echo -e "\nErrors found: ${error_count}"
-
- iter=0
- for value in "${errors[@]}"; do
- ((iter++))
- echo -e "\nError ${iter} of ${error_count}:"
- echo "${value}" | perl -pe 's/^(.*)$/\t\1/'
- done
-fi
+source "run_static_analysis_check_psalm.sh"
-# Stop test servers.
-for pid in "${pids[@]}"; do
- kill "${pid}" &> /dev/null &
-done
+source "display_errors.inc.sh"
if [[ "${CI_PHP_FUTURE_RELEASE}" != "true" ]]; then
exit "${#errors[@]}"
diff --git a/tests/check_coding_standards.sh b/tests/run_coding_standards_check.sh
similarity index 93%
rename from tests/check_coding_standards.sh
rename to tests/run_coding_standards_check.sh
index b1ab3a65bc..f3f76f1197 100755
--- a/tests/check_coding_standards.sh
+++ b/tests/run_coding_standards_check.sh
@@ -1,8 +1,12 @@
+#!/usr/bin/env bash
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "${SCRIPT_DIR}"
+source "set_vars.inc.sh"
+
# Run commands from the project root directory.
-cd ..
+pushd ..
# Enforce line ending consistency in php files.
crlf_file=$(find . -type "f" -iname "*.php" ! -path "*/vendor/*" -exec grep --color=always --files-with-matches $'\r' {} \;)
@@ -114,6 +118,11 @@ if [[ "${?}" -ne 0 ]]; then
errors+=("found PHP_CodeSniffer coding standard violation(s)")
fi
+# TODO: Remove this workaround that only runs php-cs-fixer on PHP < 8.4 when
+# php-cs-fixer supports PHP 8.4.
+# 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
@@ -121,3 +130,7 @@ if [[ "${?}" -ne 0 ]]; then
echo "Error: found PHP-CS-Fixer coding standard violation(s)"
errors+=("found PHP-CS-Fixer coding standard violation(s)")
fi
+
+fi
+
+popd
diff --git a/tests/ci.sh b/tests/run_phpunit.sh
similarity index 73%
rename from tests/ci.sh
rename to tests/run_phpunit.sh
index 6b5489cc1d..01b8bd2b7d 100755
--- a/tests/ci.sh
+++ b/tests/run_phpunit.sh
@@ -27,9 +27,9 @@ replace_assertMatchesRegularExpression() {
find='->assertMatchesRegularExpression('
replace='->assertRegExp('
if sed v < /dev/null 2> /dev/null; then
- sed -i"" -e"s/${find}/${replace}/" "./PHPCurlClass/PHP"*
+ sed -i"" -e "s/${find}/${replace}/" "./PHPCurlClass/PHP"*
else
- sed -i "" -e"s/${find}/${replace}/" "./PHPCurlClass/PHP"*
+ sed -i "" -e "s/${find}/${replace}/" "./PHPCurlClass/PHP"*
fi
}
@@ -57,22 +57,9 @@ phpunit_v10_shim() {
remove_expectWarning
}
-set -x
-
-composer self-update
-composer install --prefer-source --no-interaction
-
-# Use composer's phpunit and phpcs by adding composer bin directory to the path environment variable.
-export PATH="${PWD}/vendor/bin:${PATH}"
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "${SCRIPT_DIR}"
-echo "CI_PHP_VERSION: ${CI_PHP_VERSION}"
-echo "CI_PHP_FUTURE_RELEASE: ${CI_PHP_FUTURE_RELEASE}"
-php -r "var_dump(phpversion());"
-php -r "var_dump(curl_version());"
-
# Let test server know we should allow testing.
export PHP_CURL_CLASS_TEST_MODE_ENABLED="yes"
@@ -88,10 +75,6 @@ for i in $(seq 0 $(("${server_count}" - 1))); do
pids["${i}"]="${!}"
done
-errors=()
-
-source "check_syntax.sh"
-
# Determine which phpunit to use.
if [[ -f "../vendor/bin/phpunit" ]]; then
phpunit_to_use="../vendor/bin/phpunit"
@@ -130,29 +113,7 @@ if [[ "${?}" -ne 0 ]]; then
errors+=("phpunit command failed")
fi
-source "check_coding_standards.sh"
-
-set +x
-
-error_count="${#errors[@]}"
-if [[ "${error_count}" -ge 1 ]]; then
- echo -e "\nErrors found: ${error_count}"
-
- iter=0
- for value in "${errors[@]}"; do
- ((iter++))
- echo -e "\nError ${iter} of ${error_count}:"
- echo "${value}" | perl -pe 's/^(.*)$/\t\1/'
- done
-fi
-
# Stop test servers.
for pid in "${pids[@]}"; do
- kill "${pid}" &> /dev/null &
+ kill "${pid}" &> /dev/null &
done
-
-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}."
-fi
diff --git a/tests/run_static_analysis_check_phpstan.sh b/tests/run_static_analysis_check_phpstan.sh
new file mode 100755
index 0000000000..59121951af
--- /dev/null
+++ b/tests/run_static_analysis_check_phpstan.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+cd "${SCRIPT_DIR}"
+
+source "set_vars.inc.sh"
+
+# Run commands from the project root directory.
+pushd ..
+
+set -x
+
+if [[ $(echo "${CI_PHP_VERSION} >= 7.4" | bc -l) -eq 1 ]]; then
+ vendor/bin/phpstan analyse --ansi --configuration="tests/phpstan.neon" .
+ if [[ "${?}" -ne 0 ]]; then
+ echo "Error: phpstan static analysis check failed"
+ errors+=("phpstan static analysis check failed")
+ fi
+else
+ echo "Skipped running phpstan check"
+fi
+
+popd
diff --git a/tests/run_static_analysis_check_psalm.sh b/tests/run_static_analysis_check_psalm.sh
new file mode 100755
index 0000000000..9cfae37163
--- /dev/null
+++ b/tests/run_static_analysis_check_psalm.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+cd "${SCRIPT_DIR}"
+
+source "set_vars.inc.sh"
+
+# Run commands from the project root directory.
+pushd ..
+
+set -x
+
+# TODO: Remove exclusion that skips running psalm on PHP 8.4 when psalm
+# supports PHP 8.4 (https://github.com/vimeo/psalm/issues/11107).
+if [[ $(echo "${CI_PHP_VERSION} < 8.4" | bc -l) -eq 1 ]]; then
+ vendor/bin/psalm --config="tests/psalm.xml"
+ if [[ "${?}" -ne 0 ]]; then
+ echo "Error: psalm static analysis check failed"
+ errors+=("psalm static analysis check failed")
+ fi
+else
+ echo "Skipped running psalm check"
+fi
+
+popd
diff --git a/tests/check_syntax.sh b/tests/run_syntax_check.sh
similarity index 66%
rename from tests/check_syntax.sh
rename to tests/run_syntax_check.sh
index 223cb522f4..ae0b8cc409 100755
--- a/tests/check_syntax.sh
+++ b/tests/run_syntax_check.sh
@@ -1,9 +1,16 @@
+#!/usr/bin/env bash
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "${SCRIPT_DIR}"
+# Run commands from the project root directory.
+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
+find . -type "f" -iname "*.php" ! -path "*/vendor/*" | xargs -L "1" php -l
if [[ "${?}" -ne 0 ]]; then
echo "Error: php syntax checks failed"
errors+=("php syntax checks failed")
fi
+
+popd
diff --git a/tests/set_vars.inc.sh b/tests/set_vars.inc.sh
new file mode 100644
index 0000000000..dc33f7b01e
--- /dev/null
+++ b/tests/set_vars.inc.sh
@@ -0,0 +1,4 @@
+# Use installed version when variable not set.
+if [[ -z "${CI_PHP_VERSION}" ]]; then
+ CI_PHP_VERSION="$(php -r "echo preg_replace('/^([0-9]+\.[0-9]+)\.[0-9]+/', '\$1', phpversion());")"
+fi
diff --git a/setup.cfg b/tests/setup.cfg
similarity index 100%
rename from setup.cfg
rename to tests/setup.cfg
diff --git a/tests/skip_slow_tests.sh b/tests/skip_slow_tests.sh
index 59b4b9b935..9ba74745ee 100755
--- a/tests/skip_slow_tests.sh
+++ b/tests/skip_slow_tests.sh
@@ -1,3 +1,5 @@
+#!/usr/bin/env bash
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "${SCRIPT_DIR}"
diff --git a/tests/test_all.sh b/tests/test_all.sh
index 11b09b3512..118e747ecc 100755
--- a/tests/test_all.sh
+++ b/tests/test_all.sh
@@ -1,3 +1,5 @@
+#!/usr/bin/env bash
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "${SCRIPT_DIR}"