diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index b2aa2dd..307abf3 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,11 +1,12 @@
version: 2
updates:
-- package-ecosystem: composer
- directory: "/"
- schedule:
- interval: daily
- open-pull-requests-limit: 10
- ignore:
- - dependency-name: phpstan/phpstan
- versions:
- - 0.12.70
+ - package-ecosystem: composer
+ directory: "/"
+ schedule:
+ interval: daily
+ open-pull-requests-limit: 10
+ ignore:
+ - dependency-name: phpunit/phpunit
+ update-types: ["version-update:semver-patch"]
+ - dependency-name: phpstan/phpstan
+ update-types: ["version-update:semver-patch"]
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 27cc5d8..19f7612 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,66 +1,171 @@
name: CI
-on: [push]
+on:
+ push:
+ pull_request:
+
+permissions:
+ contents: read
+ actions: read
jobs:
composer:
runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ php: [ 8.2, 8.3, 8.4, 8.5 ]
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v6
- name: Cache Composer dependencies
- uses: actions/cache@v2
+ uses: actions/cache@v5
with:
path: /tmp/composer-cache
- key: ${{ runner.os }}-${{ hashFiles('**/composer.lock') }}
+ key: ${{ runner.os }}-${{ matrix.php }}-${{ hashFiles('**/composer.lock') }}
- - uses: php-actions/composer@v5
+ - name: Composer install
+ uses: php-actions/composer@v6
+ with:
+ php_version: ${{ matrix.php }}
+ php_extensions: pcntl
- name: Archive build
- run: mkdir /tmp/github-actions/ && tar -cvf /tmp/github-actions/build.tar ./
+ run: mkdir /tmp/github-actions/ && tar --exclude=".git" -cvf /tmp/github-actions/build.tar ./
- name: Upload build archive for test runners
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
- name: build-artifact
+ name: build-artifact-${{ matrix.php }}
path: /tmp/github-actions
+ retention-days: 1
phpunit:
runs-on: ubuntu-latest
- needs: [composer]
+ needs: [ composer ]
+ strategy:
+ matrix:
+ php: [ 8.2, 8.3, 8.4, 8.5 ]
+
+ outputs:
+ coverage: ${{ steps.store-coverage.outputs.coverage_text }}
steps:
- - uses: actions/download-artifact@v2
+ - uses: actions/download-artifact@v4
with:
- name: build-artifact
+ name: build-artifact-${{ matrix.php }}
path: /tmp/github-actions
- name: Extract build archive
run: tar -xvf /tmp/github-actions/build.tar ./
- name: PHP Unit tests
- uses: php-actions/phpunit@v2
+ uses: php-actions/phpunit@v4
+ env:
+ XDEBUG_MODE: cover
with:
- php_version: 8.0
+ php_version: ${{ matrix.php }}
php_extensions: xdebug
- configuration: test/phpunit/phpunit.xml
- bootstrap: vendor/autoload.php
+ coverage_text: _coverage/coverage.txt
+ coverage_clover: _coverage/clover.xml
+
+ - name: Store coverage data
+ uses: actions/upload-artifact@v4
+ with:
+ name: code-coverage-${{ matrix.php }}-${{ github.run_number }}
+ path: _coverage
+
+ coverage:
+ runs-on: ubuntu-latest
+ needs: [ phpunit ]
+ strategy:
+ matrix:
+ php: [ 8.2, 8.3, 8.4, 8.5 ]
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/download-artifact@v4
+ with:
+ name: code-coverage-${{ matrix.php }}-${{ github.run_number }}
+ path: _coverage
+
+ - name: Output coverage
+ run: cat "_coverage/coverage.txt"
+
+ - name: Upload to Codecov
+ uses: codecov/codecov-action@v5
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ slug: ${{ github.repository }}
phpstan:
runs-on: ubuntu-latest
- needs: [composer]
+ needs: [ composer ]
+ strategy:
+ matrix:
+ php: [ 8.2, 8.3, 8.4, 8.5 ]
steps:
- - uses: actions/download-artifact@v2
+ - uses: actions/download-artifact@v4
with:
- name: build-artifact
+ name: build-artifact-${{ matrix.php }}
path: /tmp/github-actions
- name: Extract build archive
run: tar -xvf /tmp/github-actions/build.tar ./
- name: PHP Static Analysis
- uses: php-actions/phpstan@v2
+ uses: php-actions/phpstan@v3
+ with:
+ php_version: ${{ matrix.php }}
+ path: src/
+ level: 6
+ memory_limit: 256M
+
+ phpmd:
+ runs-on: ubuntu-latest
+ needs: [ composer ]
+ strategy:
+ matrix:
+ php: [ 8.2, 8.3, 8.4, 8.5 ]
+
+ steps:
+ - uses: actions/download-artifact@v4
+ with:
+ name: build-artifact-${{ matrix.php }}
+ path: /tmp/github-actions
+
+ - name: Extract build archive
+ run: tar -xvf /tmp/github-actions/build.tar ./
+
+ - name: PHP Mess Detector
+ uses: php-actions/phpmd@v1
+ with:
+ php_version: ${{ matrix.php }}
+ path: src/
+ output: text
+ ruleset: phpmd.xml
+
+ phpcs:
+ runs-on: ubuntu-latest
+ needs: [ composer ]
+ strategy:
+ matrix:
+ php: [ 8.2, 8.3, 8.4, 8.5 ]
+
+ steps:
+ - uses: actions/download-artifact@v4
+ with:
+ name: build-artifact-${{ matrix.php }}
+ path: /tmp/github-actions
+
+ - name: Extract build archive
+ run: tar -xvf /tmp/github-actions/build.tar ./
+
+ - name: PHP Code Sniffer
+ uses: php-actions/phpcs@v1
with:
- path: src/
\ No newline at end of file
+ php_version: ${{ matrix.php }}
+ path: src/
+ standard: phpcs.xml
diff --git a/.gitignore b/.gitignore
index 3c5399a..e38702b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
/vendor
-/test/unit/_coverage
+/test/phpunit/_coverage
+/test/phpunit/.phpunit.cache
/.idea
-*.phar
\ No newline at end of file
+*.phar
diff --git a/.scrutinizer.yml b/.scrutinizer.yml
deleted file mode 100644
index 0e7d790..0000000
--- a/.scrutinizer.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-build:
- environment:
- php: 8.0.0
-
- nodes:
- analysis:
- tests:
- override:
- - php-scrutinizer-run
-
- tests-and-coverage:
- environment:
- php:
- ini:
- "xdebug.mode": coverage
- tests:
- override:
- - phpcs-run ./src
- - command: "vendor/bin/phpunit test/phpunit --coverage-clover test/phpunit/_coverage --whitelist src"
- coverage:
- file: "test/phpunit/_coverage"
- format: "php-clover"
-
-checks:
- php:
- code_rating: true
- duplication: true
-
-filter:
- excluded_paths:
- - test/*
- - vendor/*
\ No newline at end of file
diff --git a/README.md b/README.md
index c2f5e6a..6cac016 100644
--- a/README.md
+++ b/README.md
@@ -9,17 +9,17 @@ Sessions are addressed using dot notation, allowing for handling categories of s
-
+
-
+
-
+
## Example usage: Welcome a user by their first name or log out the user
@@ -41,3 +41,46 @@ else {
AuthenticationSystem::beginLogin($session->getStore("auth"));
}
```
+
+## Redis session storage
+
+This package now includes `GT\Session\RedisHandler` for shared session storage.
+It works with Redis-compatible backends such as Redis and Valkey, and is intended
+for deployments where application nodes are disposable and session state needs to
+survive traffic moving between servers.
+
+`RedisHandler` expects `save_path` to be a DSN rather than a filesystem path.
+It uses the `phpredis` extension at runtime.
+
+Example production config:
+
+```ini
+[session]
+handler=GT\Session\RedisHandler
+save_path=rediss://default:secret@example-redis.internal:25061/0?prefix=GT:&ttl=1440
+name=GT
+use_cookies=true
+```
+
+Supported DSN forms:
+
+- `redis://host:6379`
+- `redis://:password@host:6379/0`
+- `redis://username:password@host:6379/0`
+- `rediss://username:password@host:6379/0`
+
+Useful query parameters:
+
+- `prefix`: key prefix for stored sessions, defaults to `:`
+- `ttl`: session lifetime in seconds, defaults to `session.gc_maxlifetime`
+- `timeout`: connection timeout in seconds
+- `read_timeout`: socket read timeout in seconds
+- `persistent=1`: enable persistent connections
+- `persistent_id`: optional persistent connection pool id
+- `verify_peer=0` / `verify_peer_name=0`: optional TLS verification flags
+
+# Proudly sponsored by
+
+[JetBrains Open Source sponsorship program](https://www.jetbrains.com/community/opensource/)
+
+[](https://www.jetbrains.com/community/opensource/)
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..ee9f073
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,25 @@
+# Security Policy
+
+## Supported Versions
+
+All MAJOR versions of this package will receive security updates for **two years after the next major version is released**. For example, if version 4.0.0 is released, version 3.x will continue receiving security updates for two years from that date.
+
+Versions outside this window are considered end-of-life and will no longer receive updates, even for critical vulnerabilities.
+
+## Reporting a Vulnerability
+
+If you discover a security issue, please report it using GitHub's [**"Report a vulnerability"** feature](../../security/advisories/new) under the **Security** tab of this repository.
+
+When reporting, please include the following information to help us investigate quickly and thoroughly:
+
+- A clear description of the vulnerability and what part of the code it affects.
+- Steps to reproduce the issue, ideally including:
+ - The affected version
+ - A code snippet or minimal test case
+ - The expected vs. actual behavior
+- If applicable, an explanation of potential impact or severity.
+- Any suggested mitigations or patches (optional, but appreciated).
+
+Please do not disclose the vulnerability publicly until we've had a chance to investigate and publish a fix.
+
+We appreciate responsible disclosure and are committed to resolving issues promptly.
diff --git a/composer.json b/composer.json
index f78bd5a..d11c730 100644
--- a/composer.json
+++ b/composer.json
@@ -4,21 +4,48 @@
"license": "MIT",
"require": {
- "php": ">=7.2"
+ "php": ">=8.2",
+ "phpgt/typesafegetter": "^1.3"
+ },
+ "suggest": {
+ "ext-redis": "Required to use GT\\Session\\RedisHandler."
},
"require-dev": {
- "phpunit/phpunit": "9.*",
- "phpstan/phpstan": ">=0.12.64"
+ "phpstan/phpstan": "^2.1",
+ "phpunit/phpunit": "^10.1",
+ "phpmd/phpmd": "^2.13",
+ "squizlabs/php_codesniffer": "^3.7"
+ },
+
+ "scripts": {
+ "phpunit": "vendor/bin/phpunit --configuration phpunit.xml",
+ "phpstan": "vendor/bin/phpstan analyse --level 6 src --memory-limit 256M",
+ "phpcs": "vendor/bin/phpcs src --standard=phpcs.xml",
+ "phpmd": "vendor/bin/phpmd src/ text phpmd.xml",
+ "test": [
+ "@phpunit",
+ "@phpstan",
+ "@phpcs",
+ "@phpmd"
+ ]
},
"autoload": {
"psr-4": {
+ "GT\\Session\\": "./src",
"Gt\\Session\\": "./src"
}
},
"autoload-dev": {
"psr-4": {
- "Gt\\Session\\Test\\": "./test/phpunit"
+ "GT\\Session\\Test\\": "./test/phpunit"
+ }
+ },
+
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/PhpGt"
}
- }
-}
\ No newline at end of file
+ ]
+}
diff --git a/composer.lock b/composer.lock
index 909dfba..807a21f 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,39 +4,169 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "bb32584e49fdaeea326c284a7294f289",
- "packages": [],
+ "content-hash": "5bf8b129b89ebdbd2f4b53a66a2b077e",
+ "packages": [
+ {
+ "name": "phpgt/typesafegetter",
+ "version": "v1.3.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpgt/TypeSafeGetter.git",
+ "reference": "a0d339103828791989cbb81f760d252f3c2f8b8c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpgt/TypeSafeGetter/zipball/a0d339103828791989cbb81f760d252f3c2f8b8c",
+ "reference": "a0d339103828791989cbb81f760d252f3c2f8b8c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0"
+ },
+ "require-dev": {
+ "phpmd/phpmd": "^2.13",
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^10.1",
+ "squizlabs/php_codesniffer": "^3.7"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Gt\\TypeSafeGetter\\": "./src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Greg Bowler",
+ "email": "greg.bowler@g105b.com"
+ }
+ ],
+ "description": "An interface for objects that expose type-safe getter methods.",
+ "support": {
+ "issues": "https://github.com/phpgt/TypeSafeGetter/issues",
+ "source": "https://github.com/phpgt/TypeSafeGetter/tree/v1.3.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sponsors/PhpGt",
+ "type": "github"
+ }
+ ],
+ "time": "2026-03-10T22:28:01+00:00"
+ }
+ ],
"packages-dev": [
{
- "name": "doctrine/instantiator",
- "version": "1.4.0",
+ "name": "composer/pcre",
+ "version": "3.3.2",
"source": {
"type": "git",
- "url": "https://github.com/doctrine/instantiator.git",
- "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b"
+ "url": "https://github.com/composer/pcre.git",
+ "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/instantiator/zipball/d56bf6102915de5702778fe20f2de3b2fe570b5b",
- "reference": "d56bf6102915de5702778fe20f2de3b2fe570b5b",
+ "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
+ "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
"shasum": ""
},
"require": {
- "php": "^7.1 || ^8.0"
+ "php": "^7.4 || ^8.0"
+ },
+ "conflict": {
+ "phpstan/phpstan": "<1.11.10"
},
"require-dev": {
- "doctrine/coding-standard": "^8.0",
- "ext-pdo": "*",
- "ext-phar": "*",
- "phpbench/phpbench": "^0.13 || 1.0.0-alpha2",
- "phpstan/phpstan": "^0.12",
- "phpstan/phpstan-phpunit": "^0.12",
- "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
+ "phpstan/phpstan": "^1.12 || ^2",
+ "phpstan/phpstan-strict-rules": "^1 || ^2",
+ "phpunit/phpunit": "^8 || ^9"
+ },
+ "type": "library",
+ "extra": {
+ "phpstan": {
+ "includes": [
+ "extension.neon"
+ ]
+ },
+ "branch-alias": {
+ "dev-main": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\Pcre\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "PCRE wrapping library that offers type-safe preg_* replacements.",
+ "keywords": [
+ "PCRE",
+ "preg",
+ "regex",
+ "regular expression"
+ ],
+ "support": {
+ "issues": "https://github.com/composer/pcre/issues",
+ "source": "https://github.com/composer/pcre/tree/3.3.2"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-11-12T16:29:46+00:00"
+ },
+ {
+ "name": "composer/xdebug-handler",
+ "version": "3.0.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/xdebug-handler.git",
+ "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef",
+ "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef",
+ "shasum": ""
+ },
+ "require": {
+ "composer/pcre": "^1 || ^2 || ^3",
+ "php": "^7.2.5 || ^8.0",
+ "psr/log": "^1 || ^2 || ^3"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.0",
+ "phpstan/phpstan-strict-rules": "^1.1",
+ "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5"
},
"type": "library",
"autoload": {
"psr-4": {
- "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
+ "Composer\\XdebugHandler\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -45,66 +175,71 @@
],
"authors": [
{
- "name": "Marco Pivetta",
- "email": "ocramius@gmail.com",
- "homepage": "https://ocramius.github.io/"
+ "name": "John Stevenson",
+ "email": "john-stevenson@blueyonder.co.uk"
}
],
- "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
- "homepage": "https://www.doctrine-project.org/projects/instantiator.html",
+ "description": "Restarts a process without Xdebug.",
"keywords": [
- "constructor",
- "instantiate"
+ "Xdebug",
+ "performance"
],
+ "support": {
+ "irc": "ircs://irc.libera.chat:6697/composer",
+ "issues": "https://github.com/composer/xdebug-handler/issues",
+ "source": "https://github.com/composer/xdebug-handler/tree/3.0.5"
+ },
"funding": [
{
- "url": "https://www.doctrine-project.org/sponsorship.html",
+ "url": "https://packagist.com",
"type": "custom"
},
{
- "url": "https://www.patreon.com/phpdoctrine",
- "type": "patreon"
+ "url": "https://github.com/composer",
+ "type": "github"
},
{
- "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
- "time": "2020-11-10T18:47:58+00:00"
+ "time": "2024-05-06T16:37:16+00:00"
},
{
"name": "myclabs/deep-copy",
- "version": "1.10.2",
+ "version": "1.13.4",
"source": {
"type": "git",
"url": "https://github.com/myclabs/DeepCopy.git",
- "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220"
+ "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/776f831124e9c62e1a2c601ecc52e776d8bb7220",
- "reference": "776f831124e9c62e1a2c601ecc52e776d8bb7220",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a",
+ "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
- "replace": {
- "myclabs/deep-copy": "self.version"
+ "conflict": {
+ "doctrine/collections": "<1.6.8",
+ "doctrine/common": "<2.13.3 || >=3 <3.2.2"
},
"require-dev": {
- "doctrine/collections": "^1.0",
- "doctrine/common": "^2.6",
- "phpunit/phpunit": "^7.1"
+ "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": {
- "psr-4": {
- "DeepCopy\\": "src/DeepCopy/"
- },
"files": [
"src/DeepCopy/deep_copy.php"
- ]
+ ],
+ "psr-4": {
+ "DeepCopy\\": "src/DeepCopy/"
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -118,35 +253,41 @@
"object",
"object graph"
],
+ "support": {
+ "issues": "https://github.com/myclabs/DeepCopy/issues",
+ "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4"
+ },
"funding": [
{
"url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
"type": "tidelift"
}
],
- "time": "2020-11-13T09:40:50+00:00"
+ "time": "2025-08-01T08:46:24+00:00"
},
{
"name": "nikic/php-parser",
- "version": "v4.10.4",
+ "version": "v5.7.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e"
+ "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/c6d052fc58cb876152f89f532b95a8d7907e7f0e",
- "reference": "c6d052fc58cb876152f89f532b95a8d7907e7f0e",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82",
+ "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82",
"shasum": ""
},
"require": {
+ "ext-ctype": "*",
+ "ext-json": "*",
"ext-tokenizer": "*",
- "php": ">=7.0"
+ "php": ">=7.4"
},
"require-dev": {
"ircmaxell/php-yacc": "^0.0.7",
- "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
+ "phpunit/phpunit": "^9.0"
},
"bin": [
"bin/php-parse"
@@ -154,7 +295,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.9-dev"
+ "dev-master": "5.x-dev"
}
},
"autoload": {
@@ -176,24 +317,92 @@
"parser",
"php"
],
- "time": "2020-12-20T10:01:03+00:00"
+ "support": {
+ "issues": "https://github.com/nikic/PHP-Parser/issues",
+ "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0"
+ },
+ "time": "2025-12-06T11:56:16+00:00"
+ },
+ {
+ "name": "pdepend/pdepend",
+ "version": "2.16.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/pdepend/pdepend.git",
+ "reference": "f942b208dc2a0868454d01b29f0c75bbcfc6ed58"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/pdepend/pdepend/zipball/f942b208dc2a0868454d01b29f0c75bbcfc6ed58",
+ "reference": "f942b208dc2a0868454d01b29f0c75bbcfc6ed58",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.7",
+ "symfony/config": "^2.3.0|^3|^4|^5|^6.0|^7.0",
+ "symfony/dependency-injection": "^2.3.0|^3|^4|^5|^6.0|^7.0",
+ "symfony/filesystem": "^2.3.0|^3|^4|^5|^6.0|^7.0",
+ "symfony/polyfill-mbstring": "^1.19"
+ },
+ "require-dev": {
+ "easy-doc/easy-doc": "0.0.0|^1.2.3",
+ "gregwar/rst": "^1.0",
+ "squizlabs/php_codesniffer": "^2.0.0"
+ },
+ "bin": [
+ "src/bin/pdepend"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "PDepend\\": "src/main/php/PDepend"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "description": "Official version of pdepend to be handled with Composer",
+ "keywords": [
+ "PHP Depend",
+ "PHP_Depend",
+ "dev",
+ "pdepend"
+ ],
+ "support": {
+ "issues": "https://github.com/pdepend/pdepend/issues",
+ "source": "https://github.com/pdepend/pdepend/tree/2.16.2"
+ },
+ "funding": [
+ {
+ "url": "https://tidelift.com/funding/github/packagist/pdepend/pdepend",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-12-17T18:09:59+00:00"
},
{
"name": "phar-io/manifest",
- "version": "2.0.1",
+ "version": "2.0.4",
"source": {
"type": "git",
"url": "https://github.com/phar-io/manifest.git",
- "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133"
+ "reference": "54750ef60c58e43759730615a392c31c80e23176"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phar-io/manifest/zipball/85265efd3af7ba3ca4b2a2c34dbfc5788dd29133",
- "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133",
+ "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",
@@ -232,20 +441,30 @@
}
],
"description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
- "time": "2020-06-27T14:33:11+00:00"
+ "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.1.0",
+ "version": "3.2.1",
"source": {
"type": "git",
"url": "https://github.com/phar-io/version.git",
- "reference": "bae7c545bef187884426f042434e561ab1ddb182"
+ "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phar-io/version/zipball/bae7c545bef187884426f042434e561ab1ddb182",
- "reference": "bae7c545bef187884426f042434e561ab1ddb182",
+ "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
+ "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
"shasum": ""
},
"require": {
@@ -279,313 +498,315 @@
}
],
"description": "Library for handling version information and constraints",
- "time": "2021-02-23T14:00:09+00:00"
+ "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": "phpdocumentor/reflection-common",
- "version": "2.2.0",
+ "name": "phpmd/phpmd",
+ "version": "2.15.0",
"source": {
"type": "git",
- "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
- "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b"
+ "url": "https://github.com/phpmd/phpmd.git",
+ "reference": "74a1f56e33afad4128b886e334093e98e1b5e7c0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b",
- "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b",
+ "url": "https://api.github.com/repos/phpmd/phpmd/zipball/74a1f56e33afad4128b886e334093e98e1b5e7c0",
+ "reference": "74a1f56e33afad4128b886e334093e98e1b5e7c0",
"shasum": ""
},
"require": {
- "php": "^7.2 || ^8.0"
+ "composer/xdebug-handler": "^1.0 || ^2.0 || ^3.0",
+ "ext-xml": "*",
+ "pdepend/pdepend": "^2.16.1",
+ "php": ">=5.3.9"
},
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-2.x": "2.x-dev"
- }
+ "require-dev": {
+ "easy-doc/easy-doc": "0.0.0 || ^1.3.2",
+ "ext-json": "*",
+ "ext-simplexml": "*",
+ "gregwar/rst": "^1.0",
+ "mikey179/vfsstream": "^1.6.8",
+ "squizlabs/php_codesniffer": "^2.9.2 || ^3.7.2"
},
+ "bin": [
+ "src/bin/phpmd"
+ ],
+ "type": "library",
"autoload": {
- "psr-4": {
- "phpDocumentor\\Reflection\\": "src/"
+ "psr-0": {
+ "PHPMD\\": "src/main/php"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "MIT"
+ "BSD-3-Clause"
],
"authors": [
{
- "name": "Jaap van Otterdijk",
- "email": "opensource@ijaap.nl"
+ "name": "Manuel Pichler",
+ "email": "github@manuel-pichler.de",
+ "homepage": "https://github.com/manuelpichler",
+ "role": "Project Founder"
+ },
+ {
+ "name": "Marc Würth",
+ "email": "ravage@bluewin.ch",
+ "homepage": "https://github.com/ravage84",
+ "role": "Project Maintainer"
+ },
+ {
+ "name": "Other contributors",
+ "homepage": "https://github.com/phpmd/phpmd/graphs/contributors",
+ "role": "Contributors"
}
],
- "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
- "homepage": "http://www.phpdoc.org",
+ "description": "PHPMD is a spin-off project of PHP Depend and aims to be a PHP equivalent of the well known Java tool PMD.",
+ "homepage": "https://phpmd.org/",
"keywords": [
- "FQSEN",
- "phpDocumentor",
- "phpdoc",
- "reflection",
- "static analysis"
+ "dev",
+ "mess detection",
+ "mess detector",
+ "pdepend",
+ "phpmd",
+ "pmd"
+ ],
+ "support": {
+ "irc": "irc://irc.freenode.org/phpmd",
+ "issues": "https://github.com/phpmd/phpmd/issues",
+ "source": "https://github.com/phpmd/phpmd/tree/2.15.0"
+ },
+ "funding": [
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpmd/phpmd",
+ "type": "tidelift"
+ }
],
- "time": "2020-06-27T09:03:43+00:00"
+ "time": "2023-12-11T08:22:20+00:00"
},
{
- "name": "phpdocumentor/reflection-docblock",
- "version": "5.2.2",
- "source": {
- "type": "git",
- "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
- "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556"
- },
+ "name": "phpstan/phpstan",
+ "version": "2.1.51",
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/069a785b2141f5bcf49f3e353548dc1cce6df556",
- "reference": "069a785b2141f5bcf49f3e353548dc1cce6df556",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/dc3b523c45e714c70de2ac5113b958223b55dc59",
+ "reference": "dc3b523c45e714c70de2ac5113b958223b55dc59",
"shasum": ""
},
"require": {
- "ext-filter": "*",
- "php": "^7.2 || ^8.0",
- "phpdocumentor/reflection-common": "^2.2",
- "phpdocumentor/type-resolver": "^1.3",
- "webmozart/assert": "^1.9.1"
+ "php": "^7.4|^8.0"
},
- "require-dev": {
- "mockery/mockery": "~1.3.2"
+ "conflict": {
+ "phpstan/phpstan-shim": "*"
},
+ "bin": [
+ "phpstan",
+ "phpstan.phar"
+ ],
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "5.x-dev"
- }
- },
"autoload": {
- "psr-4": {
- "phpDocumentor\\Reflection\\": "src"
- }
+ "files": [
+ "bootstrap.php"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
- "authors": [
+ "description": "PHPStan - PHP Static Analysis Tool",
+ "keywords": [
+ "dev",
+ "static analysis"
+ ],
+ "support": {
+ "docs": "https://phpstan.org/user-guide/getting-started",
+ "forum": "https://github.com/phpstan/phpstan/discussions",
+ "issues": "https://github.com/phpstan/phpstan/issues",
+ "security": "https://github.com/phpstan/phpstan/security/policy",
+ "source": "https://github.com/phpstan/phpstan-src"
+ },
+ "funding": [
{
- "name": "Mike van Riel",
- "email": "me@mikevanriel.com"
+ "url": "https://github.com/ondrejmirtes",
+ "type": "github"
},
{
- "name": "Jaap van Otterdijk",
- "email": "account@ijaap.nl"
+ "url": "https://github.com/phpstan",
+ "type": "github"
}
],
- "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
- "time": "2020-09-03T19:13:55+00:00"
+ "time": "2026-04-21T18:22:01+00:00"
},
{
- "name": "phpdocumentor/type-resolver",
- "version": "1.4.0",
+ "name": "phpunit/php-code-coverage",
+ "version": "10.1.16",
"source": {
"type": "git",
- "url": "https://github.com/phpDocumentor/TypeResolver.git",
- "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0"
+ "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
+ "reference": "7e308268858ed6baedc8704a304727d20bc07c77"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0",
- "reference": "6a467b8989322d92aa1c8bf2bebcc6e5c2ba55c0",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77",
+ "reference": "7e308268858ed6baedc8704a304727d20bc07c77",
"shasum": ""
},
"require": {
- "php": "^7.2 || ^8.0",
- "phpdocumentor/reflection-common": "^2.0"
+ "ext-dom": "*",
+ "ext-libxml": "*",
+ "ext-xmlwriter": "*",
+ "nikic/php-parser": "^4.19.1 || ^5.1.0",
+ "php": ">=8.1",
+ "phpunit/php-file-iterator": "^4.1.0",
+ "phpunit/php-text-template": "^3.0.1",
+ "sebastian/code-unit-reverse-lookup": "^3.0.0",
+ "sebastian/complexity": "^3.2.0",
+ "sebastian/environment": "^6.1.0",
+ "sebastian/lines-of-code": "^2.0.2",
+ "sebastian/version": "^4.0.1",
+ "theseer/tokenizer": "^1.2.3"
},
"require-dev": {
- "ext-tokenizer": "*"
+ "phpunit/phpunit": "^10.1"
+ },
+ "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-1.x": "1.x-dev"
+ "dev-main": "10.1.x-dev"
}
},
"autoload": {
- "psr-4": {
- "phpDocumentor\\Reflection\\": "src"
- }
+ "classmap": [
+ "src/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "MIT"
+ "BSD-3-Clause"
],
"authors": [
{
- "name": "Mike van Riel",
- "email": "me@mikevanriel.com"
+ "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/10.1.16"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
}
],
- "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
- "time": "2020-09-17T18:55:26+00:00"
+ "time": "2024-08-22T04:31:57+00:00"
},
{
- "name": "phpspec/prophecy",
- "version": "1.13.0",
+ "name": "phpunit/php-file-iterator",
+ "version": "4.1.0",
"source": {
"type": "git",
- "url": "https://github.com/phpspec/prophecy.git",
- "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea"
+ "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
+ "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpspec/prophecy/zipball/be1996ed8adc35c3fd795488a653f4b518be70ea",
- "reference": "be1996ed8adc35c3fd795488a653f4b518be70ea",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c",
+ "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c",
"shasum": ""
},
"require": {
- "doctrine/instantiator": "^1.2",
- "php": "^7.2 || ~8.0, <8.1",
- "phpdocumentor/reflection-docblock": "^5.2",
- "sebastian/comparator": "^3.0 || ^4.0",
- "sebastian/recursion-context": "^3.0 || ^4.0"
+ "php": ">=8.1"
},
"require-dev": {
- "phpspec/phpspec": "^6.0",
- "phpunit/phpunit": "^8.0 || ^9.0"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.11.x-dev"
+ "dev-main": "4.0-dev"
}
},
"autoload": {
- "psr-4": {
- "Prophecy\\": "src/Prophecy"
- }
+ "classmap": [
+ "src/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "MIT"
+ "BSD-3-Clause"
],
"authors": [
{
- "name": "Konstantin Kudryashov",
- "email": "ever.zet@gmail.com",
- "homepage": "http://everzet.com"
- },
- {
- "name": "Marcello Duarte",
- "email": "marcello.duarte@gmail.com"
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
}
],
- "description": "Highly opinionated mocking framework for PHP 5.3+",
- "homepage": "https://github.com/phpspec/prophecy",
+ "description": "FilterIterator implementation that filters files based on a list of suffixes.",
+ "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
"keywords": [
- "Double",
- "Dummy",
- "fake",
- "mock",
- "spy",
- "stub"
- ],
- "time": "2021-03-17T13:42:18+00:00"
- },
- {
- "name": "phpstan/phpstan",
- "version": "0.12.84",
- "source": {
- "type": "git",
- "url": "https://github.com/phpstan/phpstan.git",
- "reference": "9c43f15da8798c8f30a4b099e6a94530a558cfd5"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9c43f15da8798c8f30a4b099e6a94530a558cfd5",
- "reference": "9c43f15da8798c8f30a4b099e6a94530a558cfd5",
- "shasum": ""
- },
- "require": {
- "php": "^7.1|^8.0"
- },
- "conflict": {
- "phpstan/phpstan-shim": "*"
- },
- "bin": [
- "phpstan",
- "phpstan.phar"
+ "filesystem",
+ "iterator"
],
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "0.12-dev"
- }
- },
- "autoload": {
- "files": [
- "bootstrap.php"
- ]
+ "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/4.1.0"
},
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "description": "PHPStan - PHP Static Analysis Tool",
"funding": [
{
- "url": "https://github.com/ondrejmirtes",
+ "url": "https://github.com/sebastianbergmann",
"type": "github"
- },
- {
- "url": "https://www.patreon.com/phpstan",
- "type": "patreon"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan",
- "type": "tidelift"
}
],
- "time": "2021-04-19T17:10:54+00:00"
+ "time": "2023-08-31T06:24:48+00:00"
},
{
- "name": "phpunit/php-code-coverage",
- "version": "9.2.5",
+ "name": "phpunit/php-invoker",
+ "version": "4.0.0",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1"
+ "url": "https://github.com/sebastianbergmann/php-invoker.git",
+ "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f3e026641cc91909d421802dd3ac7827ebfd97e1",
- "reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7",
+ "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7",
"shasum": ""
},
"require": {
- "ext-dom": "*",
- "ext-libxml": "*",
- "ext-xmlwriter": "*",
- "nikic/php-parser": "^4.10.2",
- "php": ">=7.3",
- "phpunit/php-file-iterator": "^3.0.3",
- "phpunit/php-text-template": "^2.0.2",
- "sebastian/code-unit-reverse-lookup": "^2.0.2",
- "sebastian/complexity": "^2.0",
- "sebastian/environment": "^5.1.2",
- "sebastian/lines-of-code": "^1.0.3",
- "sebastian/version": "^3.0.1",
- "theseer/tokenizer": "^1.2.0"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "ext-pcntl": "*",
+ "phpunit/phpunit": "^10.0"
},
"suggest": {
- "ext-pcov": "*",
- "ext-xdebug": "*"
+ "ext-pcntl": "*"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "9.2-dev"
+ "dev-main": "4.0-dev"
}
},
"autoload": {
@@ -604,45 +825,47 @@
"role": "lead"
}
],
- "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
- "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
+ "description": "Invoke callables with a timeout",
+ "homepage": "https://github.com/sebastianbergmann/php-invoker/",
"keywords": [
- "coverage",
- "testing",
- "xunit"
+ "process"
],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-invoker/issues",
+ "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0"
+ },
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
- "time": "2020-11-28T06:44:49+00:00"
+ "time": "2023-02-03T06:56:09+00:00"
},
{
- "name": "phpunit/php-file-iterator",
- "version": "3.0.5",
+ "name": "phpunit/php-text-template",
+ "version": "3.0.1",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
- "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8"
+ "url": "https://github.com/sebastianbergmann/php-text-template.git",
+ "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/aa4be8575f26070b100fccb67faabb28f21f66f8",
- "reference": "aa4be8575f26070b100fccb67faabb28f21f66f8",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748",
+ "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.0-dev"
+ "dev-main": "3.0-dev"
}
},
"autoload": {
@@ -661,48 +884,48 @@
"role": "lead"
}
],
- "description": "FilterIterator implementation that filters files based on a list of suffixes.",
- "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
+ "description": "Simple template engine.",
+ "homepage": "https://github.com/sebastianbergmann/php-text-template/",
"keywords": [
- "filesystem",
- "iterator"
+ "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/3.0.1"
+ },
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
- "time": "2020-09-28T05:57:25+00:00"
+ "time": "2023-08-31T14:07:24+00:00"
},
{
- "name": "phpunit/php-invoker",
- "version": "3.1.1",
+ "name": "phpunit/php-timer",
+ "version": "6.0.0",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/php-invoker.git",
- "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
+ "url": "https://github.com/sebastianbergmann/php-timer.git",
+ "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
- "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d",
+ "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "ext-pcntl": "*",
- "phpunit/phpunit": "^9.3"
- },
- "suggest": {
- "ext-pcntl": "*"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.1-dev"
+ "dev-main": "6.0-dev"
}
},
"autoload": {
@@ -721,46 +944,81 @@
"role": "lead"
}
],
- "description": "Invoke callables with a timeout",
- "homepage": "https://github.com/sebastianbergmann/php-invoker/",
+ "description": "Utility class for timing",
+ "homepage": "https://github.com/sebastianbergmann/php-timer/",
"keywords": [
- "process"
+ "timer"
],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-timer/issues",
+ "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0"
+ },
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
- "time": "2020-09-28T05:58:55+00:00"
+ "time": "2023-02-03T06:57:52+00:00"
},
{
- "name": "phpunit/php-text-template",
- "version": "2.0.4",
+ "name": "phpunit/phpunit",
+ "version": "10.5.63",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/php-text-template.git",
- "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28"
+ "url": "https://github.com/sebastianbergmann/phpunit.git",
+ "reference": "33198268dad71e926626b618f3ec3966661e4d90"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
- "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/33198268dad71e926626b618f3ec3966661e4d90",
+ "reference": "33198268dad71e926626b618f3ec3966661e4d90",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "ext-dom": "*",
+ "ext-json": "*",
+ "ext-libxml": "*",
+ "ext-mbstring": "*",
+ "ext-xml": "*",
+ "ext-xmlwriter": "*",
+ "myclabs/deep-copy": "^1.13.4",
+ "phar-io/manifest": "^2.0.4",
+ "phar-io/version": "^3.2.1",
+ "php": ">=8.1",
+ "phpunit/php-code-coverage": "^10.1.16",
+ "phpunit/php-file-iterator": "^4.1.0",
+ "phpunit/php-invoker": "^4.0.0",
+ "phpunit/php-text-template": "^3.0.1",
+ "phpunit/php-timer": "^6.0.0",
+ "sebastian/cli-parser": "^2.0.1",
+ "sebastian/code-unit": "^2.0.0",
+ "sebastian/comparator": "^5.0.5",
+ "sebastian/diff": "^5.1.1",
+ "sebastian/environment": "^6.1.0",
+ "sebastian/exporter": "^5.1.4",
+ "sebastian/global-state": "^6.0.2",
+ "sebastian/object-enumerator": "^5.0.0",
+ "sebastian/recursion-context": "^5.0.1",
+ "sebastian/type": "^4.0.0",
+ "sebastian/version": "^4.0.1"
},
- "require-dev": {
- "phpunit/phpunit": "^9.3"
+ "suggest": {
+ "ext-soap": "To be able to generate mocks based on WSDL files"
},
+ "bin": [
+ "phpunit"
+ ],
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.0-dev"
+ "dev-main": "10.5-dev"
}
},
"autoload": {
+ "files": [
+ "src/Framework/Assert/Functions.php"
+ ],
"classmap": [
"src/"
]
@@ -776,197 +1034,169 @@
"role": "lead"
}
],
- "description": "Simple template engine.",
- "homepage": "https://github.com/sebastianbergmann/php-text-template/",
+ "description": "The PHP Unit Testing framework.",
+ "homepage": "https://phpunit.de/",
"keywords": [
- "template"
+ "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/10.5.63"
+ },
"funding": [
+ {
+ "url": "https://phpunit.de/sponsors.html",
+ "type": "custom"
+ },
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
+ "type": "tidelift"
}
],
- "time": "2020-10-26T05:33:50+00:00"
+ "time": "2026-01-27T05:48:37+00:00"
},
{
- "name": "phpunit/php-timer",
- "version": "5.0.3",
+ "name": "psr/container",
+ "version": "2.0.2",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/php-timer.git",
- "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2"
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
- "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
"shasum": ""
},
"require": {
- "php": ">=7.3"
- },
- "require-dev": {
- "phpunit/phpunit": "^9.3"
+ "php": ">=7.4.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.0-dev"
+ "dev-master": "2.0.x-dev"
}
},
"autoload": {
- "classmap": [
- "src/"
- ]
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
}
],
- "description": "Utility class for timing",
- "homepage": "https://github.com/sebastianbergmann/php-timer/",
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
"keywords": [
- "timer"
- ],
- "funding": [
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- }
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
],
- "time": "2020-10-26T13:16:10+00:00"
+ "support": {
+ "issues": "https://github.com/php-fig/container/issues",
+ "source": "https://github.com/php-fig/container/tree/2.0.2"
+ },
+ "time": "2021-11-05T16:47:00+00:00"
},
{
- "name": "phpunit/phpunit",
- "version": "9.5.4",
+ "name": "psr/log",
+ "version": "3.0.2",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "c73c6737305e779771147af66c96ca6a7ed8a741"
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c73c6737305e779771147af66c96ca6a7ed8a741",
- "reference": "c73c6737305e779771147af66c96ca6a7ed8a741",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
+ "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
"shasum": ""
},
"require": {
- "doctrine/instantiator": "^1.3.1",
- "ext-dom": "*",
- "ext-json": "*",
- "ext-libxml": "*",
- "ext-mbstring": "*",
- "ext-xml": "*",
- "ext-xmlwriter": "*",
- "myclabs/deep-copy": "^1.10.1",
- "phar-io/manifest": "^2.0.1",
- "phar-io/version": "^3.0.2",
- "php": ">=7.3",
- "phpspec/prophecy": "^1.12.1",
- "phpunit/php-code-coverage": "^9.2.3",
- "phpunit/php-file-iterator": "^3.0.5",
- "phpunit/php-invoker": "^3.1.1",
- "phpunit/php-text-template": "^2.0.3",
- "phpunit/php-timer": "^5.0.2",
- "sebastian/cli-parser": "^1.0.1",
- "sebastian/code-unit": "^1.0.6",
- "sebastian/comparator": "^4.0.5",
- "sebastian/diff": "^4.0.3",
- "sebastian/environment": "^5.1.3",
- "sebastian/exporter": "^4.0.3",
- "sebastian/global-state": "^5.0.1",
- "sebastian/object-enumerator": "^4.0.3",
- "sebastian/resource-operations": "^3.0.3",
- "sebastian/type": "^2.3",
- "sebastian/version": "^3.0.2"
- },
- "require-dev": {
- "ext-pdo": "*",
- "phpspec/prophecy-phpunit": "^2.0.1"
- },
- "suggest": {
- "ext-soap": "*",
- "ext-xdebug": "*"
+ "php": ">=8.0.0"
},
- "bin": [
- "phpunit"
- ],
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "9.5-dev"
+ "dev-master": "3.x-dev"
}
},
"autoload": {
- "classmap": [
- "src/"
- ],
- "files": [
- "src/Framework/Assert/Functions.php"
- ]
+ "psr-4": {
+ "Psr\\Log\\": "src"
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
}
],
- "description": "The PHP Unit Testing framework.",
- "homepage": "https://phpunit.de/",
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
"keywords": [
- "phpunit",
- "testing",
- "xunit"
- ],
- "funding": [
- {
- "url": "https://phpunit.de/donate.html",
- "type": "custom"
- },
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- }
+ "log",
+ "psr",
+ "psr-3"
],
- "time": "2021-03-23T07:16:29+00:00"
+ "support": {
+ "source": "https://github.com/php-fig/log/tree/3.0.2"
+ },
+ "time": "2024-09-11T13:17:53+00:00"
},
{
"name": "sebastian/cli-parser",
- "version": "1.0.1",
+ "version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/cli-parser.git",
- "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
+ "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
- "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
+ "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084",
+ "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.0-dev"
+ "dev-main": "2.0-dev"
}
},
"autoload": {
@@ -987,38 +1217,43 @@
],
"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/2.0.1"
+ },
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
- "time": "2020-09-28T06:08:49+00:00"
+ "time": "2024-03-02T07:12:49+00:00"
},
{
"name": "sebastian/code-unit",
- "version": "1.0.8",
+ "version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit.git",
- "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120"
+ "reference": "a81fee9eef0b7a76af11d121767abc44c104e503"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120",
- "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503",
+ "reference": "a81fee9eef0b7a76af11d121767abc44c104e503",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.0-dev"
+ "dev-main": "2.0-dev"
}
},
"autoload": {
@@ -1039,38 +1274,42 @@
],
"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",
+ "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0"
+ },
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
- "time": "2020-10-26T13:08:54+00:00"
+ "time": "2023-02-03T06:58:43+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
- "version": "2.0.3",
+ "version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
- "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
+ "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
- "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d",
+ "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.0-dev"
+ "dev-main": "3.0-dev"
}
},
"autoload": {
@@ -1090,40 +1329,46 @@
],
"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",
+ "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0"
+ },
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
- "time": "2020-09-28T05:30:19+00:00"
+ "time": "2023-02-03T06:59:15+00:00"
},
{
"name": "sebastian/comparator",
- "version": "4.0.6",
+ "version": "5.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
- "reference": "55f4261989e546dc112258c7a75935a81a7ce382"
+ "reference": "55dfef806eb7dfeb6e7a6935601fef866f8ca48d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382",
- "reference": "55f4261989e546dc112258c7a75935a81a7ce382",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55dfef806eb7dfeb6e7a6935601fef866f8ca48d",
+ "reference": "55dfef806eb7dfeb6e7a6935601fef866f8ca48d",
"shasum": ""
},
"require": {
- "php": ">=7.3",
- "sebastian/diff": "^4.0",
- "sebastian/exporter": "^4.0"
+ "ext-dom": "*",
+ "ext-mbstring": "*",
+ "php": ">=8.1",
+ "sebastian/diff": "^5.0",
+ "sebastian/exporter": "^5.0"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.5"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.0-dev"
+ "dev-main": "5.0-dev"
}
},
"autoload": {
@@ -1160,39 +1405,56 @@
"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/5.0.5"
+ },
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator",
+ "type": "tidelift"
}
],
- "time": "2020-10-26T15:49:45+00:00"
+ "time": "2026-01-24T09:25:16+00:00"
},
{
"name": "sebastian/complexity",
- "version": "2.0.2",
+ "version": "3.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/complexity.git",
- "reference": "739b35e53379900cc9ac327b2147867b8b6efd88"
+ "reference": "68ff824baeae169ec9f2137158ee529584553799"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88",
- "reference": "739b35e53379900cc9ac327b2147867b8b6efd88",
+ "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799",
+ "reference": "68ff824baeae169ec9f2137158ee529584553799",
"shasum": ""
},
"require": {
- "nikic/php-parser": "^4.7",
- "php": ">=7.3"
+ "nikic/php-parser": "^4.18 || ^5.0",
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.0-dev"
+ "dev-main": "3.2-dev"
}
},
"autoload": {
@@ -1213,39 +1475,44 @@
],
"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/3.2.0"
+ },
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
- "time": "2020-10-26T15:52:27+00:00"
+ "time": "2023-12-21T08:37:17+00:00"
},
{
"name": "sebastian/diff",
- "version": "4.0.4",
+ "version": "5.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
- "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d"
+ "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d",
- "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e",
+ "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3",
- "symfony/process": "^4.2 || ^5"
+ "phpunit/phpunit": "^10.0",
+ "symfony/process": "^6.4"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.0-dev"
+ "dev-main": "5.1-dev"
}
},
"autoload": {
@@ -1275,33 +1542,38 @@
"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/5.1.1"
+ },
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
- "time": "2020-10-26T13:10:38+00:00"
+ "time": "2024-03-02T07:15:17+00:00"
},
{
"name": "sebastian/environment",
- "version": "5.1.3",
+ "version": "6.1.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
- "reference": "388b6ced16caa751030f6a69e588299fa09200ac"
+ "reference": "8074dbcd93529b357029f5cc5058fd3e43666984"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/388b6ced16caa751030f6a69e588299fa09200ac",
- "reference": "388b6ced16caa751030f6a69e588299fa09200ac",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984",
+ "reference": "8074dbcd93529b357029f5cc5058fd3e43666984",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"suggest": {
"ext-posix": "*"
@@ -1309,7 +1581,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.1-dev"
+ "dev-main": "6.1-dev"
}
},
"autoload": {
@@ -1328,46 +1600,51 @@
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
- "homepage": "http://www.github.com/sebastianbergmann/environment",
+ "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/6.1.0"
+ },
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
- "time": "2020-09-28T05:52:38+00:00"
+ "time": "2024-03-23T08:47:14+00:00"
},
{
"name": "sebastian/exporter",
- "version": "4.0.3",
+ "version": "5.1.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
- "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65"
+ "reference": "0735b90f4da94969541dac1da743446e276defa6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/d89cc98761b8cb5a1a235a6b703ae50d34080e65",
- "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/0735b90f4da94969541dac1da743446e276defa6",
+ "reference": "0735b90f4da94969541dac1da743446e276defa6",
"shasum": ""
},
"require": {
- "php": ">=7.3",
- "sebastian/recursion-context": "^4.0"
+ "ext-mbstring": "*",
+ "php": ">=8.1",
+ "sebastian/recursion-context": "^5.0"
},
"require-dev": {
- "ext-mbstring": "*",
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.5"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.0-dev"
+ "dev-main": "5.1-dev"
}
},
"autoload": {
@@ -1402,49 +1679,63 @@
}
],
"description": "Provides the functionality to export PHP variables for visualization",
- "homepage": "http://www.github.com/sebastianbergmann/exporter",
+ "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/5.1.4"
+ },
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter",
+ "type": "tidelift"
}
],
- "time": "2020-09-28T05:24:23+00:00"
+ "time": "2025-09-24T06:09:11+00:00"
},
{
"name": "sebastian/global-state",
- "version": "5.0.2",
+ "version": "6.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
- "reference": "a90ccbddffa067b51f574dea6eb25d5680839455"
+ "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/a90ccbddffa067b51f574dea6eb25d5680839455",
- "reference": "a90ccbddffa067b51f574dea6eb25d5680839455",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9",
+ "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9",
"shasum": ""
},
"require": {
- "php": ">=7.3",
- "sebastian/object-reflector": "^2.0",
- "sebastian/recursion-context": "^4.0"
+ "php": ">=8.1",
+ "sebastian/object-reflector": "^3.0",
+ "sebastian/recursion-context": "^5.0"
},
"require-dev": {
"ext-dom": "*",
- "phpunit/phpunit": "^9.3"
- },
- "suggest": {
- "ext-uopz": "*"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.0-dev"
+ "dev-main": "6.0-dev"
}
},
"autoload": {
@@ -1463,43 +1754,48 @@
}
],
"description": "Snapshotting of global state",
- "homepage": "http://www.github.com/sebastianbergmann/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/6.0.2"
+ },
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
- "time": "2020-10-26T15:55:19+00:00"
+ "time": "2024-03-02T07:19:19+00:00"
},
{
"name": "sebastian/lines-of-code",
- "version": "1.0.3",
+ "version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
- "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc"
+ "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc",
- "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc",
+ "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0",
+ "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0",
"shasum": ""
},
"require": {
- "nikic/php-parser": "^4.6",
- "php": ">=7.3"
+ "nikic/php-parser": "^4.18 || ^5.0",
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.0-dev"
+ "dev-main": "2.0-dev"
}
},
"autoload": {
@@ -1520,40 +1816,45 @@
],
"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/2.0.2"
+ },
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
- "time": "2020-11-28T06:42:11+00:00"
+ "time": "2023-12-21T08:38:20+00:00"
},
{
"name": "sebastian/object-enumerator",
- "version": "4.0.4",
+ "version": "5.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-enumerator.git",
- "reference": "5c9eeac41b290a3712d88851518825ad78f45c71"
+ "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71",
- "reference": "5c9eeac41b290a3712d88851518825ad78f45c71",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906",
+ "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906",
"shasum": ""
},
"require": {
- "php": ">=7.3",
- "sebastian/object-reflector": "^2.0",
- "sebastian/recursion-context": "^4.0"
+ "php": ">=8.1",
+ "sebastian/object-reflector": "^3.0",
+ "sebastian/recursion-context": "^5.0"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.0-dev"
+ "dev-main": "5.0-dev"
}
},
"autoload": {
@@ -1573,38 +1874,42 @@
],
"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",
+ "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0"
+ },
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
- "time": "2020-10-26T13:12:34+00:00"
+ "time": "2023-02-03T07:08:32+00:00"
},
{
"name": "sebastian/object-reflector",
- "version": "2.0.4",
+ "version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-reflector.git",
- "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7"
+ "reference": "24ed13d98130f0e7122df55d06c5c4942a577957"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
- "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957",
+ "reference": "24ed13d98130f0e7122df55d06c5c4942a577957",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.0-dev"
+ "dev-main": "3.0-dev"
}
},
"autoload": {
@@ -1624,38 +1929,42 @@
],
"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",
+ "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0"
+ },
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
- "time": "2020-10-26T13:14:26+00:00"
+ "time": "2023-02-03T07:06:18+00:00"
},
{
"name": "sebastian/recursion-context",
- "version": "4.0.4",
+ "version": "5.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
- "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172"
+ "reference": "47e34210757a2f37a97dcd207d032e1b01e64c7a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172",
- "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172",
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/47e34210757a2f37a97dcd207d032e1b01e64c7a",
+ "reference": "47e34210757a2f37a97dcd207d032e1b01e64c7a",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.5"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.0-dev"
+ "dev-main": "5.0-dev"
}
},
"autoload": {
@@ -1682,39 +1991,56 @@
}
],
"description": "Provides functionality to recursively process PHP variables",
- "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
+ "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/5.0.1"
+ },
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
+ },
+ {
+ "url": "https://liberapay.com/sebastianbergmann",
+ "type": "liberapay"
+ },
+ {
+ "url": "https://thanks.dev/u/gh/sebastianbergmann",
+ "type": "thanks_dev"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context",
+ "type": "tidelift"
}
],
- "time": "2020-10-26T13:17:30+00:00"
+ "time": "2025-08-10T07:50:56+00:00"
},
{
- "name": "sebastian/resource-operations",
- "version": "3.0.3",
+ "name": "sebastian/type",
+ "version": "4.0.0",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/resource-operations.git",
- "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
+ "url": "https://github.com/sebastianbergmann/type.git",
+ "reference": "462699a16464c3944eefc02ebdd77882bd3925bf"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
- "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
+ "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf",
+ "reference": "462699a16464c3944eefc02ebdd77882bd3925bf",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.0"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.0-dev"
+ "dev-main": "4.0-dev"
}
},
"autoload": {
@@ -1729,43 +2055,45 @@
"authors": [
{
"name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
}
],
- "description": "Provides a list of PHP built-in functions that operate on resources",
- "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
+ "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",
+ "source": "https://github.com/sebastianbergmann/type/tree/4.0.0"
+ },
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
- "time": "2020-09-28T06:45:17+00:00"
+ "time": "2023-02-03T07:10:45+00:00"
},
{
- "name": "sebastian/type",
- "version": "2.3.1",
+ "name": "sebastian/version",
+ "version": "4.0.1",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/type.git",
- "reference": "81cd61ab7bbf2de744aba0ea61fae32f721df3d2"
+ "url": "https://github.com/sebastianbergmann/version.git",
+ "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/81cd61ab7bbf2de744aba0ea61fae32f721df3d2",
- "reference": "81cd61ab7bbf2de744aba0ea61fae32f721df3d2",
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17",
+ "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17",
"shasum": ""
},
"require": {
- "php": ">=7.3"
- },
- "require-dev": {
- "phpunit/phpunit": "^9.3"
+ "php": ">=8.1"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.3-dev"
+ "dev-main": "4.0-dev"
}
},
"autoload": {
@@ -1784,102 +2112,436 @@
"role": "lead"
}
],
- "description": "Collection of value objects that represent the types of the PHP type system",
- "homepage": "https://github.com/sebastianbergmann/type",
+ "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",
+ "source": "https://github.com/sebastianbergmann/version/tree/4.0.1"
+ },
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
- "time": "2020-10-26T13:18:59+00:00"
+ "time": "2023-02-07T11:34:05+00:00"
},
{
- "name": "sebastian/version",
- "version": "3.0.2",
+ "name": "squizlabs/php_codesniffer",
+ "version": "3.13.5",
"source": {
"type": "git",
- "url": "https://github.com/sebastianbergmann/version.git",
- "reference": "c6c1022351a901512170118436c764e473f6de8c"
+ "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
+ "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
- "reference": "c6c1022351a901512170118436c764e473f6de8c",
+ "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0ca86845ce43291e8f5692c7356fccf3bcf02bf4",
+ "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4",
"shasum": ""
},
"require": {
- "php": ">=7.3"
- },
+ "ext-simplexml": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlwriter": "*",
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4"
+ },
+ "bin": [
+ "bin/phpcbf",
+ "bin/phpcs"
+ ],
+ "type": "library",
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Greg Sherwood",
+ "role": "Former lead"
+ },
+ {
+ "name": "Juliette Reinders Folmer",
+ "role": "Current lead"
+ },
+ {
+ "name": "Contributors",
+ "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors"
+ }
+ ],
+ "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
+ "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
+ "keywords": [
+ "phpcs",
+ "standards",
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues",
+ "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy",
+ "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
+ "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki"
+ },
+ "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-11-04T16:30:35+00:00"
+ },
+ {
+ "name": "symfony/config",
+ "version": "v7.4.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/config.git",
+ "reference": "2d19dde43fa2ff720b9a40763ace7226594f503b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/config/zipball/2d19dde43fa2ff720b9a40763ace7226594f503b",
+ "reference": "2d19dde43fa2ff720b9a40763ace7226594f503b",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/filesystem": "^7.1|^8.0",
+ "symfony/polyfill-ctype": "~1.8"
+ },
+ "conflict": {
+ "symfony/finder": "<6.4",
+ "symfony/service-contracts": "<2.5"
+ },
+ "require-dev": {
+ "symfony/event-dispatcher": "^6.4|^7.0|^8.0",
+ "symfony/finder": "^6.4|^7.0|^8.0",
+ "symfony/messenger": "^6.4|^7.0|^8.0",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/yaml": "^6.4|^7.0|^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Config\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/config/tree/v7.4.8"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-03-24T13:12:05+00:00"
+ },
+ {
+ "name": "symfony/dependency-injection",
+ "version": "v7.4.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/dependency-injection.git",
+ "reference": "f7025fd7b687c240426562f86ada06a93b1e771d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f7025fd7b687c240426562f86ada06a93b1e771d",
+ "reference": "f7025fd7b687c240426562f86ada06a93b1e771d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "psr/container": "^1.1|^2.0",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/service-contracts": "^3.6",
+ "symfony/var-exporter": "^6.4.20|^7.2.5|^8.0"
+ },
+ "conflict": {
+ "ext-psr": "<1.1|>=2",
+ "symfony/config": "<6.4",
+ "symfony/finder": "<6.4",
+ "symfony/yaml": "<6.4"
+ },
+ "provide": {
+ "psr/container-implementation": "1.1|2.0",
+ "symfony/service-implementation": "1.1|2.0|3.0"
+ },
+ "require-dev": {
+ "symfony/config": "^6.4|^7.0|^8.0",
+ "symfony/expression-language": "^6.4|^7.0|^8.0",
+ "symfony/yaml": "^6.4|^7.0|^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\DependencyInjection\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Allows you to standardize and centralize the way objects are constructed in your application",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/dependency-injection/tree/v7.4.8"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-03-31T06:50:29+00:00"
+ },
+ {
+ "name": "symfony/deprecation-contracts",
+ "version": "v3.6.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/deprecation-contracts.git",
+ "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62",
+ "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
"type": "library",
"extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
"branch-alias": {
- "dev-master": "3.0-dev"
+ "dev-main": "3.6-dev"
}
},
"autoload": {
- "classmap": [
- "src/"
+ "files": [
+ "function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de",
- "role": "lead"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Library that helps with managing the version number of Git-hosted PHP projects",
- "homepage": "https://github.com/sebastianbergmann/version",
+ "description": "A generic function and convention to trigger deprecation notices",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0"
+ },
"funding": [
{
- "url": "https://github.com/sebastianbergmann",
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
"type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
}
],
- "time": "2020-09-28T06:39:44+00:00"
+ "time": "2024-09-25T14:21:43+00:00"
+ },
+ {
+ "name": "symfony/filesystem",
+ "version": "v7.4.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/filesystem.git",
+ "reference": "58b9790d12f9670b7f53a1c1738febd3108970a5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/58b9790d12f9670b7f53a1c1738febd3108970a5",
+ "reference": "58b9790d12f9670b7f53a1c1738febd3108970a5",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-mbstring": "~1.8"
+ },
+ "require-dev": {
+ "symfony/process": "^6.4|^7.0|^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Filesystem\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides basic utilities for the filesystem",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/filesystem/tree/v7.4.8"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-03-24T13:12:05+00:00"
},
{
"name": "symfony/polyfill-ctype",
- "version": "v1.22.1",
+ "version": "v1.36.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
- "reference": "c6c942b1ac76c82448322025e084cadc56048b4e"
+ "reference": "141046a8f9477948ff284fa65be2095baafb94f2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e",
- "reference": "c6c942b1ac76c82448322025e084cadc56048b4e",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2",
+ "reference": "141046a8f9477948ff284fa65be2095baafb94f2",
"shasum": ""
},
"require": {
- "php": ">=7.1"
+ "php": ">=7.2"
+ },
+ "provide": {
+ "ext-ctype": "*"
},
"suggest": {
"ext-ctype": "For best performance"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-main": "1.22-dev"
- },
"thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
- "psr-4": {
- "Symfony\\Polyfill\\Ctype\\": ""
- },
"files": [
"bootstrap.php"
- ]
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Ctype\\": ""
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -1903,6 +2565,9 @@
"polyfill",
"portable"
],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.36.0"
+ },
"funding": [
{
"url": "https://symfony.com/sponsor",
@@ -1912,94 +2577,220 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2021-01-07T16:49:33+00:00"
+ "time": "2026-04-10T16:19:22+00:00"
},
{
- "name": "theseer/tokenizer",
- "version": "1.2.0",
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.36.0",
"source": {
"type": "git",
- "url": "https://github.com/theseer/tokenizer.git",
- "reference": "75a63c33a8577608444246075ea0af0d052e452a"
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/theseer/tokenizer/zipball/75a63c33a8577608444246075ea0af0d052e452a",
- "reference": "75a63c33a8577608444246075ea0af0d052e452a",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6a21eb99c6973357967f6ce3708cd55a6bec6315",
+ "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315",
"shasum": ""
},
"require": {
- "ext-dom": "*",
- "ext-tokenizer": "*",
- "ext-xmlwriter": "*",
- "php": "^7.2 || ^8.0"
+ "ext-iconv": "*",
+ "php": ">=7.2"
+ },
+ "provide": {
+ "ext-mbstring": "*"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
},
"type": "library",
+ "extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
+ }
+ },
"autoload": {
- "classmap": [
- "src/"
- ]
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-3-Clause"
+ "MIT"
],
"authors": [
{
- "name": "Arne Blankerts",
- "email": "arne@blankerts.de",
- "role": "Developer"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.36.0"
+ },
"funding": [
{
- "url": "https://github.com/theseer",
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
"type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
}
],
- "time": "2020-07-12T23:59:07+00:00"
+ "time": "2026-04-10T17:25:58+00:00"
},
{
- "name": "webmozart/assert",
- "version": "1.10.0",
+ "name": "symfony/service-contracts",
+ "version": "v3.6.1",
"source": {
"type": "git",
- "url": "https://github.com/webmozarts/assert.git",
- "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25"
+ "url": "https://github.com/symfony/service-contracts.git",
+ "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25",
- "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43",
+ "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43",
"shasum": ""
},
"require": {
- "php": "^7.2 || ^8.0",
- "symfony/polyfill-ctype": "^1.8"
+ "php": ">=8.1",
+ "psr/container": "^1.1|^2.0",
+ "symfony/deprecation-contracts": "^2.5|^3"
},
"conflict": {
- "phpstan/phpstan": "<0.12.20",
- "vimeo/psalm": "<4.6.1 || 4.6.2"
- },
- "require-dev": {
- "phpunit/phpunit": "^8.5.13"
+ "ext-psr": "<1.1|>=2"
},
"type": "library",
"extra": {
+ "thanks": {
+ "url": "https://github.com/symfony/contracts",
+ "name": "symfony/contracts"
+ },
"branch-alias": {
- "dev-master": "1.10-dev"
+ "dev-main": "3.6-dev"
}
},
"autoload": {
"psr-4": {
- "Webmozart\\Assert\\": "src/"
+ "Symfony\\Contracts\\Service\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Test/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Generic abstractions related to writing services",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/service-contracts/tree/v3.6.1"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
}
+ ],
+ "time": "2025-07-15T11:30:57+00:00"
+ },
+ {
+ "name": "symfony/var-exporter",
+ "version": "v7.4.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/var-exporter.git",
+ "reference": "398907e89a2a56fe426f7955c6fa943ec0c77225"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/var-exporter/zipball/398907e89a2a56fe426f7955c6fa943ec0c77225",
+ "reference": "398907e89a2a56fe426f7955c6fa943ec0c77225",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3"
+ },
+ "require-dev": {
+ "symfony/property-access": "^6.4|^7.0|^8.0",
+ "symfony/serializer": "^6.4|^7.0|^8.0",
+ "symfony/var-dumper": "^6.4|^7.0|^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\VarExporter\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -2007,27 +2798,108 @@
],
"authors": [
{
- "name": "Bernhard Schussek",
- "email": "bschussek@gmail.com"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Assertions to validate method input/output with nice error messages.",
+ "description": "Allows exporting any serializable PHP data structure to plain PHP code",
+ "homepage": "https://symfony.com",
"keywords": [
- "assert",
- "check",
- "validate"
+ "clone",
+ "construct",
+ "export",
+ "hydrate",
+ "instantiate",
+ "lazy-loading",
+ "proxy",
+ "serialize"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/var-exporter/tree/v7.4.8"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-03-24T13:12:05+00:00"
+ },
+ {
+ "name": "theseer/tokenizer",
+ "version": "1.3.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/theseer/tokenizer.git",
+ "reference": "b7489ce515e168639d17feec34b8847c326b0b3c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c",
+ "reference": "b7489ce515e168639d17feec34b8847c326b0b3c",
+ "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.3.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/theseer",
+ "type": "github"
+ }
],
- "time": "2021-03-09T10:59:23+00:00"
+ "time": "2025-11-17T20:03:58+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
- "stability-flags": [],
+ "stability-flags": {},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
- "php": ">=7.2"
+ "php": ">=8.2"
},
- "platform-dev": [],
- "plugin-api-version": "1.1.0"
+ "platform-dev": {},
+ "plugin-api-version": "2.9.0"
}
diff --git a/phpcs.xml b/phpcs.xml
new file mode 100644
index 0000000..2d2aff4
--- /dev/null
+++ b/phpcs.xml
@@ -0,0 +1,64 @@
+
+
+ Created from PHP.Gt/Styleguide
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/phpmd.xml b/phpmd.xml
new file mode 100644
index 0000000..d125c4d
--- /dev/null
+++ b/phpmd.xml
@@ -0,0 +1,50 @@
+
+
+ Custom ruleset
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..5e1b5d9
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+ ./test/phpunit/
+
+
+
+
+
+
+
+
+
+ src/
+
+
+
+
diff --git a/src/FileHandler.php b/src/FileHandler.php
index fce69be..71f82c1 100644
--- a/src/FileHandler.php
+++ b/src/FileHandler.php
@@ -1,28 +1,30 @@
$cache */
+ protected array $cache;
/**
* @link http://php.net/manual/en/sessionhandlerinterface.open.php
- * @param string $save_path The path where to store/retrieve the session.
+ * @param string $savePath The path where to store/retrieve the session.
* @param string $name The session name.
*/
- public function open($save_path, $name):bool {
+ public function open(string $savePath, string $name):bool {
$success = true;
- $save_path = str_replace(
+ $savePath = str_replace(
["/", "\\"],
DIRECTORY_SEPARATOR,
- $save_path
+ $savePath
);
$this->path = implode(DIRECTORY_SEPARATOR, [
- $save_path,
+ $savePath,
$name,
]);
@@ -33,48 +35,40 @@ public function open($save_path, $name):bool {
return $success;
}
- /**
- * @link http://php.net/manual/en/sessionhandlerinterface.close.php
- */
+ /** @link http://php.net/manual/en/sessionhandlerinterface.close.php */
public function close():bool {
return true;
}
- /**
- * @link http://php.net/manual/en/sessionhandlerinterface.read.php
- * @param string $session_id
- */
- public function read($session_id):string {
- if(isset($this->cache[$session_id])) {
- return $this->cache[$session_id];
+ /** @link http://php.net/manual/en/sessionhandlerinterface.read.php */
+ public function read(string $sessionId):string {
+ if(isset($this->cache[$sessionId])) {
+ return $this->cache[$sessionId];
}
- $filePath = $this->getFilePath($session_id);
+ $filePath = $this->getFilePath($sessionId);
if(!file_exists($filePath)) {
return "";
}
- $this->cache[$session_id] = file_get_contents($filePath);
- return $this->cache[$session_id];
+ $this->cache[$sessionId] = file_get_contents($filePath) ?: "";
+ return $this->cache[$sessionId];
}
- /**
- * @link http://php.net/manual/en/sessionhandlerinterface.write.php
- * @param string $session_id
- * @param string $session_data
- */
- public function write($session_id, $session_data):bool {
- $filePath = $this->getFilePath($session_id);
- return file_put_contents($filePath, $session_data) > 0;
+ /** @link http://php.net/manual/en/sessionhandlerinterface.write.php */
+ public function write(string $sessionId, string $sessionData):bool {
+ if($sessionData === self::EMPTY_PHP_ARRAY) {
+ return true;
+ }
+ $filePath = $this->getFilePath($sessionId);
+ $bytesWritten = file_put_contents($filePath, $sessionData);
+ return $bytesWritten !== false;
}
- /**
- * @link http://php.net/manual/en/sessionhandlerinterface.destroy.php
- * @param string $session_id
- */
- public function destroy($session_id):bool {
- $filePath = $this->getFilePath($session_id);
+ /** @link http://php.net/manual/en/sessionhandlerinterface.destroy.php */
+ public function destroy(string $id = ""):bool {
+ $filePath = $this->getFilePath($id);
if(file_exists($filePath)) {
return unlink($filePath);
@@ -83,13 +77,11 @@ public function destroy($session_id):bool {
return true;
}
- /**
- * @link http://php.net/manual/en/sessionhandlerinterface.gc.php
- * @param int $maxlifetime
- */
- public function gc($maxlifetime):bool {
+ /** @link http://php.net/manual/en/sessionhandlerinterface.gc.php */
+ public function gc(int $maxLifeTime):int|false {
$now = time();
- $expired = $now - $maxlifetime;
+ $expired = $now - $maxLifeTime;
+ $num = 0;
foreach(new DirectoryIterator($this->path) as $fileInfo) {
if(!$fileInfo->isFile()) {
@@ -101,10 +93,11 @@ public function gc($maxlifetime):bool {
if(!unlink($fileInfo->getPathname())) {
return false;
}
+ $num++;
}
}
- return true;
+ return $num;
}
protected function getFilePath(string $id):string {
@@ -113,4 +106,4 @@ protected function getFilePath(string $id):string {
$id,
]);
}
-}
\ No newline at end of file
+}
diff --git a/src/Flash.php b/src/Flash.php
new file mode 100644
index 0000000..34b9aa8
--- /dev/null
+++ b/src/Flash.php
@@ -0,0 +1,32 @@
+session->get("queue.$name");
+ if(!$queue) {
+ $queue = new SplQueue();
+ $this->session->set("queue.$name", $queue);
+ }
+
+ $queue->enqueue(new FlashMessage($name, $message));
+ }
+
+ public function consume(string $name):?FlashMessage {
+ /** @var null|SplQueue $queue */
+ $queue = $this->session->get("queue.$name");
+ try {
+ return $queue->dequeue();
+ }
+ catch(RuntimeException $e) {
+ $this->session->remove("queue.$name");
+ return null;
+ }
+ }
+
+}
diff --git a/src/FlashMessage.php b/src/FlashMessage.php
new file mode 100644
index 0000000..a3a3394
--- /dev/null
+++ b/src/FlashMessage.php
@@ -0,0 +1,9 @@
+parseSavePath($savePath, $name);
+ $this->config = $config;
+ return $this->connect($config);
+ }
+
+ /** @param array{
+ * host:string,
+ * port:int,
+ * timeout:float,
+ * readTimeout:float,
+ * persistentId:?string,
+ * prefix:string,
+ * ttl:int,
+ * database:int,
+ * auth:array{string,string}|string|null,
+ * context:array{stream:array{verify_peer:bool,verify_peer_name:bool}}|null
+ * } $config
+ */
+ private function connect(array $config):bool {
+ $client = $this->createClient();
+
+ $connected = $client->connect(
+ $config["host"],
+ $config["port"],
+ $config["timeout"],
+ $config["persistentId"],
+ 0,
+ $config["readTimeout"],
+ $config["context"],
+ );
+
+ if(!$connected) {
+ return false;
+ }
+
+ if($config["auth"] !== null && !$client->auth($config["auth"])) {
+ return false;
+ }
+
+ if($config["database"] > 0 && !$client->select($config["database"])) {
+ return false;
+ }
+
+ $this->client = $client;
+ $this->prefix = $config["prefix"];
+ $this->ttl = $config["ttl"];
+ return true;
+ }
+
+ public function close():bool {
+ if(is_null($this->client)) {
+ return true;
+ }
+
+ try {
+ return $this->client->close();
+ }
+ catch(Throwable) {
+ return true;
+ }
+ finally {
+ $this->client = null;
+ }
+ }
+
+ public function read(string $sessionId):string {
+ $value = $this->retryOnce(
+ fn() => $this->requireClient()->get($this->getKey($sessionId))
+ );
+ return is_string($value) ? $value : "";
+ }
+
+ public function write(string $sessionId, string $sessionData):bool {
+ if($sessionData === self::EMPTY_PHP_ARRAY) {
+ return true;
+ }
+
+ $key = $this->getKey($sessionId);
+
+ if($this->ttl > 0) {
+ return $this->retryOnce(
+ fn() => $this->requireClient()->setEx($key, $this->ttl, $sessionData)
+ );
+ }
+
+ return $this->retryOnce(
+ fn() => $this->requireClient()->set($key, $sessionData)
+ );
+ }
+
+ public function destroy(string $id = ""):bool {
+ return $this->retryOnce(
+ fn() => $this->requireClient()->del($this->getKey($id))
+ ) >= 0;
+ }
+
+ // phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
+ public function gc(int $maxLifeTime):int|false {
+ return 0;
+ }
+ // phpcs:enable
+
+ /**
+ * @return array{
+ * host:string,
+ * port:int,
+ * timeout:float,
+ * readTimeout:float,
+ * persistentId:?string,
+ * prefix:string,
+ * ttl:int,
+ * database:int,
+ * auth:array{string,string}|string|null,
+ * context:array{stream:array{verify_peer:bool,verify_peer_name:bool}}|null
+ * }
+ */
+ private function parseSavePath(string $savePath, string $name):array {
+ $parts = parse_url($savePath);
+ if($parts === false || !isset($parts["host"])) {
+ throw new RuntimeException("Invalid Redis save_path DSN.");
+ }
+
+ parse_str($parts["query"] ?? "", $query);
+
+ [$host, $context] = $this->parseHostAndContext($parts, $query);
+
+ return [
+ "host" => $host,
+ "port" => (int)($parts["port"] ?? self::DEFAULT_PORT),
+ "timeout" => (float)($query["timeout"] ?? 0),
+ "readTimeout" => (float)($query["read_timeout"] ?? 0),
+ "persistentId" => $this->parsePersistentId($query),
+ "prefix" => $this->parsePrefix($query, $name),
+ "ttl" => (int)($query["ttl"] ?? ini_get("session.gc_maxlifetime")),
+ "database" => $this->parseDatabase($parts),
+ "auth" => $this->parseAuth($parts),
+ "context" => $context,
+ ];
+ }
+
+ /**
+ * @param array $parts
+ * @param array $query
+ * @return array{
+ * 0:string,
+ * 1:array{stream:array{verify_peer:bool,verify_peer_name:bool}}|null
+ * }
+ */
+ private function parseHostAndContext(array $parts, array $query):array {
+ $scheme = strtolower($parts["scheme"] ?? "redis");
+ $host = $parts["host"];
+
+ if(!in_array($scheme, ["rediss", "tls"], true)) {
+ return [$host, null];
+ }
+
+ return [
+ "tls://$host",
+ [
+ "stream" => [
+ "verify_peer" => filter_var(
+ $query["verify_peer"] ?? true,
+ FILTER_VALIDATE_BOOL
+ ),
+ "verify_peer_name" => filter_var(
+ $query["verify_peer_name"] ?? true,
+ FILTER_VALIDATE_BOOL
+ ),
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * @param array $parts
+ * @return array{string,string}|string|null
+ */
+ private function parseAuth(array $parts):array|string|null {
+ if(isset($parts["user"]) && $parts["user"] !== "" && isset($parts["pass"])) {
+ return [rawurldecode($parts["user"]), rawurldecode($parts["pass"])];
+ }
+
+ if(isset($parts["pass"])) {
+ return rawurldecode($parts["pass"]);
+ }
+
+ return null;
+ }
+
+ /**
+ * @param array $query
+ */
+ private function parsePersistentId(array $query):?string {
+ if(
+ !isset($query["persistent"])
+ || !filter_var($query["persistent"], FILTER_VALIDATE_BOOL)
+ ) {
+ return null;
+ }
+
+ return is_string($query["persistent_id"] ?? null)
+ ? $query["persistent_id"]
+ : "phpgt-session";
+ }
+
+ /**
+ * @param array $query
+ */
+ private function parsePrefix(array $query, string $name):string {
+ return is_string($query["prefix"] ?? null)
+ ? $query["prefix"]
+ : $name . self::DEFAULT_PREFIX_SEPARATOR;
+ }
+
+ /**
+ * @param array $parts
+ */
+ private function parseDatabase(array $parts):int {
+ return isset($parts["path"])
+ ? (int)trim($parts["path"], "/")
+ : 0;
+ }
+
+ private function getKey(string $sessionId):string {
+ return $this->prefix . $sessionId;
+ }
+
+ protected function createClient():Redis {
+ if(!class_exists(Redis::class)) {
+ throw new RuntimeException(
+ "The phpredis extension is required to use GT\\Session\\RedisHandler."
+ );
+ }
+
+ return new Redis();
+ }
+
+ private function requireClient():Redis {
+ if(is_null($this->client)) {
+ throw new RuntimeException("RedisHandler::open() must be called before use.");
+ }
+
+ return $this->client;
+ }
+
+ private function reconnect():void {
+ if(is_null($this->config)) {
+ throw new RuntimeException("RedisHandler::open() must be called before reconnect.");
+ }
+
+ $this->close();
+ $this->connect($this->config);
+ }
+
+ /**
+ * @template T
+ * @param callable():T $callback
+ * @return T
+ */
+ private function retryOnce(callable $callback):mixed {
+ try {
+ return $callback();
+ }
+ catch(Throwable) {
+ $this->reconnect();
+ return $callback();
+ }
+ }
+}
diff --git a/src/Session.php b/src/Session.php
index 5289b05..eab4aa7 100644
--- a/src/Session.php
+++ b/src/Session.php
@@ -1,63 +1,64 @@
*/
+ protected array $config;
+ /** @param iterable $config */
public function __construct(
SessionHandlerInterface $sessionHandler,
iterable $config = [],
- string $id = null
+ ?string $id = null,
) {
$this->sessionHandler = $sessionHandler;
+ if(!is_array($config)) {
+ $config = iterator_to_array($config);
+ }
+ /** @var array $config */
+ $this->config = $config;
+
if(is_null($id)) {
$id = $this->getId();
}
$this->id = $id;
- $sessionPath = $this->getAbsolutePath(
+ $sessionPath = $this->normaliseSavePath(
$config["save_path"] ?? self::DEFAULT_SESSION_PATH
);
$sessionName = $config["name"] ?? self::DEFAULT_SESSION_NAME;
- $sessionStartAttempts = 0;
-
- do {
- $success = @session_start([
- "save_path" => $sessionPath,
- "name" => $sessionName,
- "cookie_lifetime" => $config["cookie_lifetime"] ?? self::DEFAULT_SESSION_LIFETIME,
- "cookie_path" => $config["cookie_path"] ?? self::DEFAULT_COOKIE_PATH,
- "cookie_domain" => $config["cookie_domain"] ?? self::DEFAULT_SESSION_DOMAIN,
- "cookie_secure" => $config["cookie_secure"] ?? self::DEFAULT_SESSION_SECURE,
- "cookie_httponly" => $config["cookie_httponly"] ?? self::DEFAULT_SESSION_HTTPONLY,
- ]);
-
- if(!$success) {
- $sessionStartAttempts++;
- @session_destroy();
- }
- }
- while(!$success && $sessionStartAttempts <= 1);
+ $this->attemptStart($sessionPath, $sessionName, $config);
$this->sessionHandler->open($sessionPath, $sessionName);
- $this->store = $this->readSessionData() ?: null;
+ $this->store = $this->readSessionData();
if(is_null($this->store)) {
$this->store = new SessionStore(__NAMESPACE__, $this);
}
@@ -67,7 +68,7 @@ public function kill():void {
$this->sessionHandler->destroy($this->getId());
$params = session_get_cookie_params();
setcookie(
- session_name(),
+ session_name() ?: "",
"",
-1,
$params["path"],
@@ -80,18 +81,18 @@ public function kill():void {
public function getStore(
string $namespace,
bool $createIfNotExists = false
- ):?SessionStore {
+ ):?SessionStoreInterface {
return $this->store->getStore(
$namespace,
$createIfNotExists
);
}
- public function get(string $key) {
+ public function get(string $key):mixed {
return $this->store->get($key);
}
- public function set(string $key, $value):void {
+ public function set(string $key, mixed $value):void {
$this->store->set($key, $value);
}
@@ -109,10 +110,14 @@ public function getId():string {
session_id($this->createNewId());
}
- return session_id();
+ return session_id() ?: "";
}
- protected function getAbsolutePath(string $path):string {
+ protected function normaliseSavePath(string $path):string {
+ if($this->isDsn($path)) {
+ return $path;
+ }
+
$path = str_replace(
["/", "\\"],
DIRECTORY_SEPARATOR,
@@ -129,18 +134,132 @@ protected function getAbsolutePath(string $path):string {
return $path;
}
+ protected function isDsn(string $path):bool {
+ return (bool)preg_match('/^[a-z][a-z0-9+.-]*:\/\//i', $path);
+ }
+
+ /** @SuppressWarnings("PHPMD.Superglobals") */
protected function createNewId():string {
- return session_create_id();
+ if(($this->config["use_trans_sid"] ?? null)
+ && !$this->config["use_cookies"]) {
+ return $_GET[$this->config["name"]] ?? session_create_id();
+ }
+ return session_create_id() ?: "";
}
- protected function readSessionData() {
- return unserialize($this->sessionHandler->read($this->id));
+ /** @SuppressWarnings("PHPMD.EmptyCatchBlock") */
+ protected function readSessionData():?SessionStore {
+ try {
+ $data = $this->sessionHandler->read($this->id) ?: "";
+ $store = unserialize($data);
+ if ($store instanceof SessionStore) {
+ return $store;
+ }
+ }
+ // PHPCS:ignore
+ catch (Throwable) {}
+
+ return null;
}
- public function write() {
- $this->sessionHandler->write(
+
+ public function write():bool {
+ return $this->sessionHandler->write(
$this->id,
serialize($this->store)
);
}
-}
\ No newline at end of file
+
+ /**
+ * @param string $sessionPath
+ * @param string $sessionName
+ * @param array $config
+ * @SuppressWarnings("PHPMD.UnusedFormalParameter")
+ * @return void
+ */
+ // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInImplementedInterfaceAfterLastUsed
+ private function attemptStart(
+ string $sessionPath,
+ string $sessionName,
+ array $config,
+ ?string $unusedContext = null,
+ ):void {
+ $sessionOptions = $this->getSessionOptions(
+ $sessionPath,
+ $sessionName,
+ $config,
+ );
+ $this->tryStartSession($sessionOptions);
+ }
+
+ /**
+ * @param array $config
+ * @return array
+ */
+ private function getSessionOptions(
+ string $sessionPath,
+ string $sessionName,
+ array $config
+ ):array {
+ $defaultConfig = [
+ "use_only_cookies" => true,
+ "use_cookies" => true,
+ "use_trans_sid" => false,
+ "cookie_lifetime" => self::DEFAULT_SESSION_LIFETIME,
+ "cookie_path" => self::DEFAULT_COOKIE_PATH,
+ "cookie_domain" => self::DEFAULT_SESSION_DOMAIN,
+ "cookie_secure" => self::DEFAULT_SESSION_SECURE,
+ "cookie_httponly" => self::DEFAULT_SESSION_HTTPONLY,
+ "cookie_samesite" => self::DEFAULT_COOKIE_SAMESITE,
+ "use_strict_mode" => self::DEFAULT_STRICT_MODE,
+ ];
+
+ $config = array_merge($defaultConfig, $config);
+
+ return [
+ "save_path" => $sessionPath,
+ "name" => $sessionName,
+ "serialize_handler" => "php_serialize",
+ "use_only_cookies" => $config["use_only_cookies"],
+ "use_cookies" => $config["use_cookies"],
+ "use_trans_sid" => $config["use_trans_sid"] ?? false,
+ "cookie_lifetime" => $config["cookie_lifetime"],
+ "cookie_path" => $config["cookie_path"],
+ "cookie_domain" => $config["cookie_domain"],
+ "cookie_secure" => $config["cookie_secure"],
+ "cookie_httponly" => $config["cookie_httponly"],
+ "cookie_samesite" => $config["cookie_samesite"],
+ "use_strict_mode" => $config["use_strict_mode"],
+ ];
+ }
+
+ /**
+ * @param array $sessionOptions
+ * @SuppressWarnings("PHPMD.EmptyCatchBlock")
+ */
+ private function tryStartSession(array $sessionOptions):void {
+ $startAttempts = 0;
+ do {
+ $success = false;
+
+ try {
+ if(session_status() !== PHP_SESSION_ACTIVE) {
+ $success = session_start($sessionOptions);
+ }
+ }
+ // PHPCS:ignore
+ catch(Throwable) {}
+
+ if(!$success) {
+ if(session_status() === PHP_SESSION_ACTIVE) {
+ session_destroy();
+ }
+ if(session_id()) {
+ session_regenerate_id(true);
+ }
+ }
+ $startAttempts++;
+ }
+ while(!$success && $startAttempts <= 1);
+ }
+}
diff --git a/src/SessionArrayWrapper.php b/src/SessionArrayWrapper.php
index 7d808fc..ed2ab60 100644
--- a/src/SessionArrayWrapper.php
+++ b/src/SessionArrayWrapper.php
@@ -1,18 +1,20 @@
*/
+ private array $sourceArray;
+ /** @param array &$sourceArray */
public function __construct(array &$sourceArray) {
$this->sourceArray = &$sourceArray;
}
- public function get(string $key) {
+ public function get(string $key):mixed {
return $this->sourceArray[$key] ?? null;
}
- public function set(string $key, $value) {
+ public function set(string $key, mixed $value):void {
$this->sourceArray[$key] = $value;
}
@@ -27,4 +29,4 @@ public function remove(string $key):void {
unset($this->sourceArray[$key]);
}
-}
\ No newline at end of file
+}
diff --git a/src/SessionContainer.php b/src/SessionContainer.php
index 6b4e385..68d121c 100644
--- a/src/SessionContainer.php
+++ b/src/SessionContainer.php
@@ -1,9 +1,9 @@
+ * @SuppressWarnings("PHPMD.TooManyPublicMethods")
+ */
+class SessionStore extends ArrayIterator implements SessionStoreInterface {
+ use NullableTypeSafeGetter;
+
+ protected string $name;
+ protected Session $session;
+ /** @var array */
+ protected array $stores;
+ protected ?SessionStore $parentStore;
public function __construct(
string $name,
Session $session,
- self $parentStore = null
+ ?self $parentStore = null
) {
$this->name = $name;
$this->session = $session;
$this->parentStore = $parentStore;
$this->stores = [];
- $this->data = [];
+ parent::__construct();
}
- public function setData(string $key, $value):void {
- $this->data[$key] = $value;
+ public function setData(string $key, mixed $value):void {
+ $this->offsetSet($key, $value);
}
- public function getData(string $key) {
- return $this->data[$key] ?? null;
+ public function getData(string $key):mixed {
+ if(!$this->offsetExists($key)) {
+ return null;
+ }
+
+ return $this->offsetGet($key);
}
public function containsData(string $key):bool {
- return isset($this->data[$key]);
+ return $this->offsetExists($key);
}
public function containsStore(string $key):bool {
@@ -42,7 +52,7 @@ public function containsStore(string $key):bool {
}
public function removeData(string $key):void {
- unset($this->data[$key]);
+ $this->offsetUnset($key);
}
public function removeStore(string $key):void {
@@ -69,16 +79,12 @@ public function getStore(
$namespaceParts = explode(".", $namespace);
$topLevelStoreName = array_shift($namespaceParts);
- /** @var SessionStore $store */
$store = $this->stores[$topLevelStoreName] ?? null;
if(is_null($store)) {
if($createIfNotExists) {
- $store = $this->createStore($namespace);
- return $store;
- }
- else {
- return null;
+ return $this->createStore($namespace);
}
+ return null;
}
if(empty($namespaceParts)) {
@@ -117,27 +123,13 @@ public function createStore(string $namespace):SessionStore {
return $this->getStore($namespace);
}
- public function get(string $key) {
- $store = $this;
- $lastDotPosition = strrpos($key, ".");
-
- if ($lastDotPosition !== false) {
- $namespace = $this->getNamespaceFromKey($key);
- $store = $this->getStore($namespace);
- }
-
- if (is_null($store)) {
- return null;
- }
-
- if ($lastDotPosition !== false) {
- $key = substr($key, $lastDotPosition + 1);
- }
-
- return $store->getData($key);
+ public function get(string $key):mixed {
+ $store = $this->getStoreFromKey($key);
+ $key = $this->normaliseKey($key);
+ return $store?->getData($key);
}
- public function set(string $key, $value):void {
+ public function set(string $key, mixed $value):void {
$store = $this;
$lastDotPosition = strrpos($key, ".");
@@ -159,6 +151,12 @@ public function set(string $key, $value):void {
}
public function contains(string $key):bool {
+ $store = $this->getStoreFromKey($key);
+ $key = $this->normaliseKey($key);
+ return $store?->containsData($key) ?? false;
+ }
+
+ private function getStoreFromKey(string $key):?SessionStore {
$store = $this;
$lastDotPosition = strrpos($key, ".");
@@ -168,19 +166,24 @@ public function contains(string $key):bool {
}
if (is_null($store)) {
- return false;
+ return null;
}
- if ($lastDotPosition !== false) {
+ return $store;
+ }
+
+ private function normaliseKey(string $key):string {
+ $lastDotPosition = strrpos($key, ".");
+ if($lastDotPosition !== false) {
$key = substr($key, $lastDotPosition + 1);
}
- return $store->containsData($key);
+ return $key;
}
- public function remove(string $key = null):void {
+ public function remove(?string $key = null):void {
if(is_null($key)) {
- foreach($this->stores as $i => $childStore) {
+ foreach(array_keys($this->stores) as $i) {
unset($this->stores[$i]);
}
@@ -191,16 +194,16 @@ public function remove(string $key = null):void {
$store = $this;
$lastDotPosition = strrpos($key, ".");
- if ($lastDotPosition !== false) {
+ if($lastDotPosition !== false) {
$namespace = $this->getNamespaceFromKey($key);
$store = $this->getStore($namespace);
}
- if (is_null($store)) {
+ if(is_null($store)) {
return;
}
- if ($lastDotPosition !== false) {
+ if($lastDotPosition !== false) {
$key = substr($key, $lastDotPosition + 1);
}
@@ -213,11 +216,11 @@ protected function getSession():Session {
}
protected function getNamespaceFromKey(string $key):?string {
- $lastDotPostition = strrpos($key, ".");
- if ($lastDotPostition === false) {
+ $lastDotPosition = strrpos($key, ".");
+ if ($lastDotPosition === false) {
return null;
}
- return substr($key, 0, $lastDotPostition);
+ return substr($key, 0, $lastDotPosition);
}
-}
\ No newline at end of file
+}
diff --git a/src/SessionStoreFactory.php b/src/SessionStoreFactory.php
index 10bdae1..2bf6d5b 100644
--- a/src/SessionStoreFactory.php
+++ b/src/SessionStoreFactory.php
@@ -1,8 +1,11 @@
expects(self::once())
+ ->method("get")
+ ->with("queue.test")
+ ->willReturn(null);
+ $sessionStore->expects(self::once())
+ ->method("set")
+ ->with(
+ self::equalTo("queue.test"),
+ self::isInstanceOf(SplQueue::class)
+ );
+
+ $sut = new Flash($sessionStore);
+ $sut->put("test", "Test message");
+ }
+
+ public function testConsume_none():void {
+ $queue = self::createMock(SplQueue::class);
+ $queue->expects(self::once())
+ ->method("dequeue")
+ ->willThrowException(new RuntimeException("Can't shift from an empty datastructure"));
+ $sessionStore = self::createMock(SessionStoreInterface::class);
+ $sessionStore->expects(self::once())
+ ->method("get")
+ ->with("queue.test")
+ ->willReturn($queue);
+ $sut = new Flash($sessionStore);
+ $flashMessage = $sut->consume("test");
+ self::assertNull($flashMessage);
+ }
+
+ public function testConsume():void {
+ $fm1 = new FlashMessage("test", "First");
+ $fm2 = new FlashMessage("test", "Second");
+
+ $queue = self::createMock(SplQueue::class);
+ $queue->expects(self::exactly(3))
+ ->method("dequeue")
+ ->willReturnOnConsecutiveCalls($fm1, $fm2);
+
+ $sessionStore = self::createMock(SessionStoreInterface::class);
+ $sessionStore->expects(self::exactly(3))
+ ->method("get")
+ ->with("queue.test")
+ ->willReturn($queue);
+ $sessionStore->expects(self::once())
+ ->method("remove")
+ ->with("queue.test");
+ $sut = new Flash($sessionStore);
+
+ $flashMessage = $sut->consume("test");
+ self::assertInstanceOf(FlashMessage::class, $flashMessage);
+ self::assertSame("First", $flashMessage->message);
+ $flashMessage = $sut->consume("test");
+ self::assertInstanceOf(FlashMessage::class, $flashMessage);
+ self::assertSame("Second", $flashMessage->message);
+ $flashMessage = $sut->consume("test");
+ self::assertNull($flashMessage);
+ }
+}
diff --git a/test/phpunit/Helper/DataProvider/ConfigProvider.php b/test/phpunit/Helper/DataProvider/ConfigProvider.php
index 541d7c1..1f6d440 100644
--- a/test/phpunit/Helper/DataProvider/ConfigProvider.php
+++ b/test/phpunit/Helper/DataProvider/ConfigProvider.php
@@ -1,5 +1,7 @@
client;
+ }
+ };
+
+ $sut->open(
+ "redis://default:secret@example.internal:25061/2?prefix=prod:session:&ttl=1800&timeout=1.5&read_timeout=2.5&persistent=1&persistent_id=pool-a",
+ "GT",
+ );
+
+ self::assertSame("example.internal", $client->connectParameters["host"]);
+ self::assertSame(25061, $client->connectParameters["port"]);
+ self::assertSame(1.5, $client->connectParameters["timeout"]);
+ self::assertSame(2.5, $client->connectParameters["readTimeout"]);
+ self::assertSame("pool-a", $client->connectParameters["persistentId"]);
+ self::assertSame([["default", "secret"]], $client->authCalls);
+ self::assertSame([2], $client->selectCalls);
+
+ $sut->write("abc123", "payload");
+ self::assertSame("payload", $sut->read("abc123"));
+ self::assertSame(
+ [
+ "key" => "prod:session:abc123",
+ "ttl" => 1800,
+ "value" => "payload",
+ ],
+ $client->setExCalls[0],
+ );
+ }
+
+ public function testOpenParsesTlsDsn():void {
+ $client = new TestRedisClient();
+ $sut = new class($client) extends RedisHandler {
+ public function __construct(private readonly TestRedisClient $client) {}
+
+ protected function createClient():Redis {
+ /** @phpstan-ignore-next-line */
+ return $this->client;
+ }
+ };
+
+ $sut->open(
+ "rediss://:secret@example.internal?verify_peer=0&verify_peer_name=0",
+ "GT",
+ );
+ $sut->write("abc123", "payload");
+
+ self::assertSame("tls://example.internal", $client->connectParameters["host"]);
+ self::assertSame(
+ [
+ "stream" => [
+ "verify_peer" => false,
+ "verify_peer_name" => false,
+ ],
+ ],
+ $client->connectParameters["context"],
+ );
+ self::assertSame(["secret"], $client->authCalls);
+ self::assertSame("payload", $client->data["GT:abc123"]);
+ }
+
+ public function testDestroyAndClose():void {
+ $client = new TestRedisClient();
+ $sut = new class($client) extends RedisHandler {
+ public function __construct(private readonly TestRedisClient $client) {}
+
+ protected function createClient():Redis {
+ /** @phpstan-ignore-next-line */
+ return $this->client;
+ }
+ };
+ $sut->open("redis://cache.internal", "GT");
+ $sut->write("abc123", "payload");
+
+ self::assertTrue($sut->destroy("abc123"));
+ self::assertSame("", $sut->read("abc123"));
+ self::assertTrue($sut->close());
+ self::assertTrue($client->closed);
+ }
+
+ public function testEmptyNativePhpSessionWriteDoesNotOverwriteStoredSession():void {
+ $client = new TestRedisClient();
+ $sut = new class($client) extends RedisHandler {
+ public function __construct(private readonly TestRedisClient $client) {}
+
+ protected function createClient():Redis {
+ /** @phpstan-ignore-next-line */
+ return $this->client;
+ }
+ };
+ $sut->open("redis://cache.internal", "GT");
+ $sut->write("abc123", "stored-session");
+ $sut->write("abc123", "a:0:{}");
+
+ self::assertSame("stored-session", $sut->read("abc123"));
+ }
+
+ public function testCommandRetriesAfterDisconnectedClient():void {
+ $client = new TestRedisClient();
+ $sut = new class($client) extends RedisHandler {
+ public function __construct(private readonly TestRedisClient $client) {}
+
+ protected function createClient():Redis {
+ /** @phpstan-ignore-next-line */
+ return $this->client;
+ }
+ };
+ $sut->open("redis://cache.internal", "GT");
+ $client->failNextSetEx = true;
+
+ self::assertTrue($sut->write("abc123", "payload"));
+ self::assertSame("payload", $sut->read("abc123"));
+ self::assertSame(2, $client->connectCount);
+ }
+}
+
+class TestRedisClient extends Redis {
+ /** @var array */
+ public array $connectParameters = [];
+ /** @var array */
+ public array $setExCalls = [];
+ /** @var array */
+ public array $setCalls = [];
+ /** @var array */
+ public array $authCalls = [];
+ /** @var array */
+ public array $selectCalls = [];
+ /** @var array */
+ public array $data = [];
+ public int $deleted = 0;
+ public int $connectCount = 0;
+ public bool $failNextSetEx = false;
+ public bool $closed = false;
+
+ /**
+ * @param array{auth?:array{0:string|false|null,1?:string},stream?:array}|null $context
+ */
+ public function connect(
+ string $host,
+ int $port = 6379,
+ float $timeout = 0,
+ ?string $persistent_id = null,
+ int $retry_interval = 0,
+ float $read_timeout = 0,
+ ?array $context = null,
+ ):bool {
+ $this->connectCount++;
+ $this->connectParameters = [
+ "host" => $host,
+ "port" => $port,
+ "timeout" => $timeout,
+ "persistentId" => $persistent_id,
+ "retryInterval" => $retry_interval,
+ "readTimeout" => $read_timeout,
+ "context" => $context,
+ ];
+ return true;
+ }
+
+ /**
+ * @param array{string,string}|string $credentials
+ */
+ public function auth(mixed $credentials):Redis|bool {
+ $this->authCalls []= $credentials;
+ return true;
+ }
+
+ public function select(int $database):Redis|bool {
+ $this->selectCalls []= $database;
+ return true;
+ }
+
+ public function get(string $key):string|false {
+ return $this->data[$key] ?? false;
+ }
+
+ public function set(string $key, mixed $value, mixed $options = null):Redis|string|bool {
+ $this->setCalls []= $key;
+ $this->data[$key] = (string)$value;
+ return true;
+ }
+
+ public function setEx(string $key, int $ttl, mixed $value) {
+ if($this->failNextSetEx) {
+ $this->failNextSetEx = false;
+ throw new \RedisException("Redis server went away");
+ }
+
+ $this->setExCalls []= [
+ "key" => $key,
+ "ttl" => $ttl,
+ "value" => (string)$value,
+ ];
+ $this->data[$key] = (string)$value;
+ return true;
+ }
+
+ public function del(array|string $key, string ...$otherKeys):Redis|int|false {
+ if(is_array($key)) {
+ $key = reset($key);
+ }
+
+ unset($this->data[$key]);
+ return ++$this->deleted;
+ }
+
+ public function close():bool {
+ $this->closed = true;
+ return true;
+ }
+}
diff --git a/test/phpunit/SessionArrayWrapperTest.php b/test/phpunit/SessionArrayWrapperTest.php
index e74aff5..5ca7b31 100644
--- a/test/phpunit/SessionArrayWrapperTest.php
+++ b/test/phpunit/SessionArrayWrapperTest.php
@@ -1,7 +1,7 @@
getMockBuilder(Handler::class)
- ->getMock();
+ protected static function createStaticMock(string $className):MockObject {
+ $tc = new SessionStoreTest("");
+ return $tc->createMock($className);
+ }
+
+ /** @dataProvider data_randomKeyValuePairs */
+ public static function testGetSetDotNotation(array $keyValuePairs, Handler $handler):void {
$session = new Session($handler);
$sessionNamespace = "gt.test.session";
@@ -81,4 +83,100 @@ public function testGetCreatesNonExistantStore() {
self::assertNotNull($leafStore);
}
-}
\ No newline at end of file
+
+ public function testGetString():void {
+ $session = $this->createMock(Session::class);
+ $sut = new SessionStore("test", $session);
+
+ $numericValue = rand(1000, 9999);
+ $sut->set("test.value", $numericValue);
+
+ self::assertSame((string)$numericValue, $sut->getString("test.value"));
+ }
+
+ public function testGetInt():void {
+ $session = $this->createMock(Session::class);
+ $sut = new SessionStore("test", $session);
+
+ $numericStringValue = (string)rand(1000, 9999);
+ $sut->set("test.value", $numericStringValue);
+
+ self::assertSame((int)$numericStringValue, $sut->getInt("test.value"));
+ }
+
+ public function testGetFloat():void {
+ $session = $this->createMock(Session::class);
+ $sut = new SessionStore("test", $session);
+
+ $numericStringValue = (string)(rand(1000, 9999) - 0.105);
+ $sut->set("test.value", $numericStringValue);
+
+ self::assertSame((float)$numericStringValue, $sut->getFloat("test.value"));
+ }
+
+ public function testGetBool():void {
+ $session = $this->createMock(Session::class);
+ $sut = new SessionStore("test", $session);
+
+ $numericValue = rand(0, 1);
+ $sut->set("test.value", $numericValue);
+
+ self::assertSame((bool)$numericValue, $sut->getBool("test.value"));
+ }
+
+ public function testGetDateTime():void {
+ $session = $this->createMock(Session::class);
+ $sut = new SessionStore("test", $session);
+
+ $numericValue = time();
+ $sut->set("test.value", $numericValue);
+
+ $dateTime = new DateTime();
+ $dateTime->setTimestamp($numericValue);
+ self::assertEquals($dateTime, $sut->getDateTime("test.value"));
+ }
+
+ public function testCount():void {
+ $session = $this->createMock(Session::class);
+ $sut = new SessionStore("test", $session);
+
+ $rawData = [
+ "one" => "first",
+ "two" => "second",
+ "three" => "third",
+ ];
+
+ foreach($rawData as $key => $value) {
+ $sut->set($key, $value);
+ }
+
+ self::assertCount(3, $sut);
+ }
+
+
+ public function testSessionStoreIsIterable():void {
+ $session = $this->createMock(Session::class);
+ $sut = new SessionStore("test", $session);
+
+ $rawData = [
+ "key1" => "value1",
+ "key2" => "value2",
+ "key3" => "value3",
+ ];
+
+ foreach($rawData as $key => $value) {
+ $sut->set($key, $value);
+ }
+
+ foreach($sut as $key => $value) {
+ self::assertArrayHasKey($key, $rawData);
+ self::assertSame($rawData[$key], $value);
+ }
+ }
+
+ public function testSessionStoreImplementsInterface():void {
+ $session = $this->createMock(Session::class);
+ $sut = new SessionStore("test", $session);
+ self::assertInstanceOf(SessionStoreInterface::class, $sut);
+ }
+}
diff --git a/test/phpunit/SessionTest.php b/test/phpunit/SessionTest.php
index 59e5814..bb4ec01 100644
--- a/test/phpunit/SessionTest.php
+++ b/test/phpunit/SessionTest.php
@@ -1,12 +1,13 @@
getMockBuilder(Handler::class)
- ->getMock();
+ protected static function createStaticMock(string $className):MockObject {
+ $tc = new SessionStoreTest("");
+ return $tc->createMock($className);
+ }
+ public function testSessionStarts():void {
self::assertEmpty(FunctionMocker::$mockCalls["session_start"]);
+ $handler = self::createMock(Handler::class);
new Session($handler);
self::assertCount(
1,
@@ -34,15 +37,83 @@ public function testSessionStarts():void {
);
}
- /**
- * @dataProvider data_randomConfig
- */
- public function testSessionStartsWithConfig(array $config):void {
- /** @var Handler|MockObject $handler */
- $handler = $this->getMockBuilder(Handler::class)
- ->getMock();
+ public function testSessionStartPreservesDsnSavePath():void {
+ $handler = self::createMock(Handler::class);
+ $savePath = "valkey://cache.internal:6379/0?ttl=1440";
+
+ new Session($handler, [
+ "save_path" => $savePath,
+ ]);
- new Session($handler ,$config);
+ $sessionStartParameter = FunctionMocker::$mockCalls["session_start"][0][0];
+ self::assertSame($savePath, $sessionStartParameter["save_path"]);
+ }
+
+ public function testWriteSessionDataCalled() {
+ $handler = self::createMock(Handler::class);
+ $handler->expects($this->exactly(2))
+ ->method("write");
+ $session = new Session($handler);
+
+ $session->set("test-key", "test-value");
+ $session->remove("test-key");
+ }
+
+ public function testGetString():void {
+ $handler = self::createMock(Handler::class);
+ $sut = new Session($handler);
+
+ $numericValue = rand(1000, 9999);
+ $sut->set("test.value", $numericValue);
+
+ self::assertSame((string)$numericValue, $sut->getString("test.value"));
+ }
+
+ public function testGetInt():void {
+ $handler = self::createMock(Handler::class);
+ $sut = new Session($handler);
+
+ $numericStringValue = (string)rand(1000, 9999);
+ $sut->set("test.value", $numericStringValue);
+
+ self::assertSame((int)$numericStringValue, $sut->getInt("test.value"));
+ }
+
+ public function testGetFloat():void {
+ $handler = self::createMock(Handler::class);
+ $sut = new Session($handler);
+
+ $numericStringValue = (string)(rand(1000, 9999) - 0.105);
+ $sut->set("test.value", $numericStringValue);
+
+ self::assertSame((float)$numericStringValue, $sut->getFloat("test.value"));
+ }
+
+ public function testGetBool():void {
+ $handler = self::createMock(Handler::class);
+ $sut = new Session($handler);
+
+ $numericValue = rand(0, 1);
+ $sut->set("test.value", $numericValue);
+
+ self::assertSame((bool)$numericValue, $sut->getBool("test.value"));
+ }
+
+ public function testGetDateTime():void {
+ $handler = self::createMock(Handler::class);
+ $sut = new Session($handler);
+
+ $numericValue = time();
+ $sut->set("test.value", $numericValue);
+
+ $dateTime = new DateTime();
+ $dateTime->setTimestamp($numericValue);
+ self::assertEquals($dateTime, $sut->getDateTime("test.value"));
+ }
+
+ /** @dataProvider data_randomConfig */
+ private static function testSessionStartsWithConfig(array $config, Handler $handler):void {
+ new Session($handler, $config);
$sessionStartParameter = FunctionMocker::$mockCalls["session_start"][0][0];
foreach($config as $key => $value) {
@@ -55,46 +126,20 @@ public function testSessionStartsWithConfig(array $config):void {
}
/** @dataProvider data_randomConfig */
- public function testSessionStartDestroysFailedSession(array $config):void {
- /** @var Handler|MockObject $handler */
- $handler = $this->getMockBuilder(Handler::class)
- ->getMock();
-
+ private static function testSessionStartDestroysFailedSession(array $config, Handler $handler):void {
FunctionMocker::$callState["session_start__fail"] = true;
new Session($handler, $config);
self::assertCount(1, FunctionMocker::$mockCalls["session_destroy"]);
}
- public function testWriteSessionDataCalled() {
- /** @var Handler|MockObject $handler */
- $handler = $this->getMockBuilder(Handler::class)
- ->getMock();
- $handler->expects($this->exactly(2))
- ->method("write");
- $session = new Session($handler);
-
- $session->set("test-key", "test-value");
- $session->remove("test-key");
- }
-
- /**
- * @dataProvider data_randomString
- */
- public function testGetReturnsNull(string $randomString):void {
- /** @var Handler|MockObject $handler */
- $handler = $this->getMockBuilder(Handler::class)
- ->getMock();
+ /** @dataProvider data_randomString */
+ private static function testGetReturnsNull(string $randomString, Handler $handler):void {
$session = new Session($handler);
self::assertNull($session->get($randomString));
}
- /**
- * @@dataProvider data_randomKeyValuePairs
- */
- public function testSetGet(array $keyValuePairs):void {
- /** @var Handler|MockObject $handler */
- $handler = $this->getMockBuilder(Handler::class)
- ->getMock();
+ /** @dataProvider data_randomKeyValuePairs */
+ private static function testSetGet(array $keyValuePairs, Handler $handler):void {
$session = new Session($handler);
foreach($keyValuePairs as $key => $value) {
@@ -106,13 +151,8 @@ public function testSetGet(array $keyValuePairs):void {
}
}
- /**
- * @dataProvider data_randomKeyValuePairs
- */
- public function testSetGetNamespaced(array $keyValuePairs):void {
- /** @var Handler|MockObject $handler */
- $handler = $this->getMockBuilder(Handler::class)
- ->getMock();
+ /** @dataProvider data_randomKeyValuePairs */
+ private static function testSetGetNamespaced(array $keyValuePairs, Handler $handler):void {
$session = new Session($handler);
foreach($keyValuePairs as $key => $value) {
@@ -134,45 +174,35 @@ public function testSetGetNamespaced(array $keyValuePairs):void {
}
}
- /**
- * @dataProvider data_randomKeyValuePairs
- */
- public function testSetGetNamespacedSameParentNamespace(array $keyValuePairs):void {
- /** @var Handler|MockObject $handler */
- $handler = $this->getMockBuilder(Handler::class)
- ->getMock();
- $session = new Session($handler);
-
- $parentNamespace = implode(".", [
- uniqid("namespace1-"),
- uniqid("namespace2-"),
- ]);
-
- foreach($keyValuePairs as $key => $value) {
- $newKey = implode(".", [
- $parentNamespace,
- $key,
- ]);
- $keyValuePairs[$newKey] = $value;
- unset($keyValuePairs[$key]);
- }
-
- foreach($keyValuePairs as $key => $value) {
- $session->set($key, $value);
- }
-
- foreach($keyValuePairs as $key => $value) {
- self::assertEquals($value, $session->get($key));
- }
- }
-
- /**
- * @@dataProvider data_randomKeyValuePairs
- */
- public function testSetGetNotExistsOtherKey(array $keyValuePairs):void {
- /** @var Handler|MockObject $handler */
- $handler = $this->getMockBuilder(Handler::class)
- ->getMock();
+ /** @dataProvider data_randomKeyValuePairs */
+ private static function testSetGetNamespacedSameParentNamespace(array $keyValuePairs, Handler $handler):void {
+ $session = new Session($handler);
+
+ $parentNamespace = implode(".", [
+ uniqid("namespace1-"),
+ uniqid("namespace2-"),
+ ]);
+
+ foreach($keyValuePairs as $key => $value) {
+ $newKey = implode(".", [
+ $parentNamespace,
+ $key,
+ ]);
+ $keyValuePairs[$newKey] = $value;
+ unset($keyValuePairs[$key]);
+ }
+
+ foreach($keyValuePairs as $key => $value) {
+ $session->set($key, $value);
+ }
+
+ foreach($keyValuePairs as $key => $value) {
+ self::assertEquals($value, $session->get($key));
+ }
+ }
+
+ /** @dataProvider data_randomKeyValuePairs */
+ private static function testSetGetNotExistsOtherKey(array $keyValuePairs, Handler $handler):void {
$session = new Session($handler);
foreach($keyValuePairs as $key => $value) {
@@ -197,13 +227,8 @@ public function testSetGetNotExistsOtherKey(array $keyValuePairs):void {
}
}
- /**
- * @dataProvider data_randomKeyValuePairs
- */
- public function testContains(array $keyValuePairs):void {
- /** @var Handler|MockObject $handler */
- $handler = $this->getMockBuilder(Handler::class)
- ->getMock();
+ /** @dataProvider data_randomKeyValuePairs */
+ private static function testContains(array $keyValuePairs, Handler $handler):void {
$session = new Session($handler);
foreach($keyValuePairs as $key => $value) {
@@ -215,13 +240,8 @@ public function testContains(array $keyValuePairs):void {
}
}
- /**
- * @dataProvider data_randomKeyValuePairs
- */
- public function testNotContains(array $keyValuePairs):void {
- /** @var Handler|MockObject $handler */
- $handler = $this->getMockBuilder(Handler::class)
- ->getMock();
+ /** @dataProvider data_randomKeyValuePairs */
+ private static function testNotContains(array $keyValuePairs, Handler $handler):void {
$session = new Session($handler);
foreach($keyValuePairs as $key => $value) {
@@ -233,20 +253,15 @@ public function testNotContains(array $keyValuePairs):void {
}
}
- /**
- * @dataProvider data_randomKeyValuePairs
- */
- public function testRemove(array $keyValuePairs):void {
- /** @var Handler|MockObject $handler */
- $handler = $this->getMockBuilder(Handler::class)
- ->getMock();
+ /** @dataProvider data_randomKeyValuePairs */
+ private static function testRemove(array $keyValuePairs, Handler $handler):void {
$session = new Session($handler);
foreach($keyValuePairs as $key => $value) {
$session->set($key, $value);
}
- uasort($keyValuePairs, function () {
+ uasort($keyValuePairs, function() {
return rand(-1, 1);
});
@@ -257,57 +272,47 @@ public function testRemove(array $keyValuePairs):void {
}
}
- /**
- * @dataProvider data_randomKeyValuePairs
- */
- public function testNamespaceKeyIsRemovedFromSession(array $keyValuePairs):void {
- /** @var Handler|MockObject $handler */
- $handler = $this->getMockBuilder(Handler::class)
- ->getMock();
- $session = new Session($handler);
-
- $parentNamespace = implode(".", [
- uniqid("namespace1-"),
- uniqid("namespace2-"),
+ /** @dataProvider data_randomKeyValuePairs */
+ private static function testNamespaceKeyIsRemovedFromSession(array $keyValuePairs, Handler $handler):void {
+ $session = new Session($handler);
+
+ $parentNamespace = implode(".", [
+ uniqid("namespace1-"),
+ uniqid("namespace2-"),
]);
- foreach($keyValuePairs as $key => $value) {
- $fullKey = implode(".", [
- $parentNamespace,
+ foreach($keyValuePairs as $key => $value) {
+ $fullKey = implode(".", [
+ $parentNamespace,
$key,
]);
- $session->set($fullKey, $value);
+ $session->set($fullKey, $value);
}
$keyToRemove = array_rand($keyValuePairs);
- $fullKeyToRemove = implode(".", [
- $parentNamespace,
+ $fullKeyToRemove = implode(".", [
+ $parentNamespace,
$keyToRemove,
]);
- $store = $session->getStore($parentNamespace);
- $store->remove($keyToRemove);
- unset($keyValuePairs[$keyToRemove]);
+ $store = $session->getStore($parentNamespace);
+ $store->remove($keyToRemove);
+ unset($keyValuePairs[$keyToRemove]);
- foreach($keyValuePairs as $key => $value) {
- $fullKey = implode(".", [
- $parentNamespace,
+ foreach($keyValuePairs as $key => $value) {
+ $fullKey = implode(".", [
+ $parentNamespace,
$key,
]);
- self::assertTrue($session->contains($fullKey));
+ self::assertTrue($session->contains($fullKey));
}
self::assertFalse($session->contains($fullKeyToRemove));
}
- /**
- * @dataProvider data_randomKeyValuePairs
- */
- public function testNamespaceKeyIsRemovedFromStore(array $keyValuePairs): void {
- /** @var Handler|MockObject $handler */
- $handler = $this->getMockBuilder(Handler::class)
- ->getMock();
+ /** @dataProvider data_randomKeyValuePairs */
+ private static function testNamespaceKeyIsRemovedFromStore(array $keyValuePairs, Handler $handler): void {
$session = new Session($handler);
$parentNamespace = implode(".", [
@@ -336,13 +341,8 @@ public function testNamespaceKeyIsRemovedFromStore(array $keyValuePairs): void {
self::assertFalse($store->contains($keyToRemove));
}
- /**
- * @dataProvider data_randomKeyValuePairs
- */
- public function testRemoveNamespace(array $keyValuePairs) {
- /** @var Handler|MockObject $handler */
- $handler = $this->getMockBuilder(Handler::class)
- ->getMock();
+ /** @dataProvider data_randomKeyValuePairs */
+ private static function testRemoveNamespace(array $keyValuePairs, Handler $handler) {
$session = new Session($handler);
$namespace1 = uniqid("namespace1-");
@@ -379,13 +379,8 @@ public function testRemoveNamespace(array $keyValuePairs) {
self::assertFalse($session->contains($parentNamespace));
}
- /**
- * @dataProvider data_randomKeyValuePairs
- */
- public function testRemoveSiblingNamespace(array $keyValuePairs) {
- /** @var Handler|MockObject $handler */
- $handler = $this->getMockBuilder(Handler::class)
- ->getMock();
+ /** @dataProvider data_randomKeyValuePairs */
+ private static function testRemoveSiblingNamespace(array $keyValuePairs, Handler $handler) {
$session = new Session($handler);
$namespace0 = uniqid("namespace0-");
@@ -464,4 +459,4 @@ public function testRemoveSiblingNamespace(array $keyValuePairs) {
);
}
}
-}
\ No newline at end of file
+}
diff --git a/test/phpunit/phpunit.xml b/test/phpunit/phpunit.xml
deleted file mode 100644
index cf95bea..0000000
--- a/test/phpunit/phpunit.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
- ../../src
-
-
-
-
-
-
-
-
- .
-
-
-
-
\ No newline at end of file