From 30227b112851629f9b564e2fc299459104c1e5a4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 17:29:41 +0100
Subject: [PATCH 01/32] ci: remove travis file
---
.travis.yml | 13 -------------
1 file changed, 13 deletions(-)
delete mode 100644 .travis.yml
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 1f33380..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-language: php
-
-sudo: false
-
-php:
- - 5.6
- - 7.0
- - 7.1
- - 7.2
-
-before_script:
- - if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]; then echo "extension = redis.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; fi
- - composer install --dev
From 33883c9f84f56324f7d94034b69f2897421a1dce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 17:29:51 +0100
Subject: [PATCH 02/32] composer: remove branch alias
---
composer.json | 5 -----
1 file changed, 5 deletions(-)
diff --git a/composer.json b/composer.json
index 7679a40..9b102cc 100644
--- a/composer.json
+++ b/composer.json
@@ -39,10 +39,5 @@
"Beberlei\\Metrics\\": "src/Beberlei/Metrics",
"Beberlei\\Bundle\\MetricsBundle\\": "src/Beberlei/Bundle/MetricsBundle"
}
- },
- "extra": {
- "branch-alias": {
- "dev-master": "2.x-dev"
- }
}
}
From 6940144b53a0f4738c5569d7432577146117518e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 17:39:04 +0100
Subject: [PATCH 03/32] composer: re-organise it a bit
---
composer.json | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/composer.json b/composer.json
index 9b102cc..c60f8b8 100644
--- a/composer.json
+++ b/composer.json
@@ -2,6 +2,7 @@
"name": "beberlei/metrics",
"description": "Simple library to talk to metrics collector services.",
"keywords": ["metrics", "logging"],
+ "license": "MIT",
"authors": [
{
"name": "Benjamin Eberlei",
@@ -14,13 +15,6 @@
"role": "Lead Developer"
}
],
- "license": "MIT",
- "suggest": {
- "corley/influxdb-sdk": "For InfluxDB integration",
- "okitsu/zabbix-sender": "For zabbix integration",
- "kriswallsmith/buzz": "For Librato integration",
- "jimdo/prometheus_client_php": "For Prometheus integration"
- },
"require": {
"psr/log": "^1.0 || ^2.0 || ^3.0"
},
@@ -39,5 +33,14 @@
"Beberlei\\Metrics\\": "src/Beberlei/Metrics",
"Beberlei\\Bundle\\MetricsBundle\\": "src/Beberlei/Bundle/MetricsBundle"
}
+ },
+ "suggest": {
+ "corley/influxdb-sdk": "For InfluxDB integration",
+ "okitsu/zabbix-sender": "For zabbix integration",
+ "kriswallsmith/buzz": "For Librato integration",
+ "jimdo/prometheus_client_php": "For Prometheus integration"
+ },
+ "config": {
+ "sort-packages": true
}
}
From 7276758190863a37ffee07ba9cef5ae0fd556424 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 17:40:53 +0100
Subject: [PATCH 04/32] composer: simplify autoloader
---
composer.json | 4 ++--
src/{Beberlei => }/Metrics/Collector/Collector.php | 0
src/{Beberlei => }/Metrics/Collector/DoctrineDBAL.php | 0
src/{Beberlei => }/Metrics/Collector/DogStatsD.php | 0
src/{Beberlei => }/Metrics/Collector/GaugeableCollector.php | 0
src/{Beberlei => }/Metrics/Collector/Graphite.php | 0
src/{Beberlei => }/Metrics/Collector/InMemory.php | 0
src/{Beberlei => }/Metrics/Collector/InfluxDB.php | 0
.../Metrics/Collector/InlineTaggableGaugeableCollector.php | 0
.../Collector/InlineTaggableGaugeableNullCollector.php | 0
src/{Beberlei => }/Metrics/Collector/Librato.php | 0
src/{Beberlei => }/Metrics/Collector/Logger.php | 0
src/{Beberlei => }/Metrics/Collector/Null.php | 0
src/{Beberlei => }/Metrics/Collector/NullCollector.php | 0
src/{Beberlei => }/Metrics/Collector/Prometheus.php | 0
src/{Beberlei => }/Metrics/Collector/StatsD.php | 0
src/{Beberlei => }/Metrics/Collector/TaggableCollector.php | 0
src/{Beberlei => }/Metrics/Collector/Telegraf.php | 0
src/{Beberlei => }/Metrics/Collector/Zabbix.php | 0
src/{Beberlei => }/Metrics/Factory.php | 0
src/{Beberlei => }/Metrics/MetricsException.php | 0
src/{Beberlei => }/Metrics/Tests/Collector/InMemoryTest.php | 0
src/{Beberlei => }/Metrics/Tests/Collector/InfluxDBTest.php | 0
src/{Beberlei => }/Metrics/Tests/Collector/PrometheusTest.php | 0
src/{Beberlei => }/Metrics/Tests/FactoryTest.php | 0
.../Bundle => }/MetricsBundle/BeberleiMetricsBundle.php | 0
.../DependencyInjection/BeberleiMetricsExtension.php | 0
.../MetricsBundle/DependencyInjection/Configuration.php | 0
.../Bundle => }/MetricsBundle/Resources/config/metrics.xml | 0
.../DependencyInjection/BeberleiMetricsExtensionTest.php | 0
30 files changed, 2 insertions(+), 2 deletions(-)
rename src/{Beberlei => }/Metrics/Collector/Collector.php (100%)
rename src/{Beberlei => }/Metrics/Collector/DoctrineDBAL.php (100%)
rename src/{Beberlei => }/Metrics/Collector/DogStatsD.php (100%)
rename src/{Beberlei => }/Metrics/Collector/GaugeableCollector.php (100%)
rename src/{Beberlei => }/Metrics/Collector/Graphite.php (100%)
rename src/{Beberlei => }/Metrics/Collector/InMemory.php (100%)
rename src/{Beberlei => }/Metrics/Collector/InfluxDB.php (100%)
rename src/{Beberlei => }/Metrics/Collector/InlineTaggableGaugeableCollector.php (100%)
rename src/{Beberlei => }/Metrics/Collector/InlineTaggableGaugeableNullCollector.php (100%)
rename src/{Beberlei => }/Metrics/Collector/Librato.php (100%)
rename src/{Beberlei => }/Metrics/Collector/Logger.php (100%)
rename src/{Beberlei => }/Metrics/Collector/Null.php (100%)
rename src/{Beberlei => }/Metrics/Collector/NullCollector.php (100%)
rename src/{Beberlei => }/Metrics/Collector/Prometheus.php (100%)
rename src/{Beberlei => }/Metrics/Collector/StatsD.php (100%)
rename src/{Beberlei => }/Metrics/Collector/TaggableCollector.php (100%)
rename src/{Beberlei => }/Metrics/Collector/Telegraf.php (100%)
rename src/{Beberlei => }/Metrics/Collector/Zabbix.php (100%)
rename src/{Beberlei => }/Metrics/Factory.php (100%)
rename src/{Beberlei => }/Metrics/MetricsException.php (100%)
rename src/{Beberlei => }/Metrics/Tests/Collector/InMemoryTest.php (100%)
rename src/{Beberlei => }/Metrics/Tests/Collector/InfluxDBTest.php (100%)
rename src/{Beberlei => }/Metrics/Tests/Collector/PrometheusTest.php (100%)
rename src/{Beberlei => }/Metrics/Tests/FactoryTest.php (100%)
rename src/{Beberlei/Bundle => }/MetricsBundle/BeberleiMetricsBundle.php (100%)
rename src/{Beberlei/Bundle => }/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php (100%)
rename src/{Beberlei/Bundle => }/MetricsBundle/DependencyInjection/Configuration.php (100%)
rename src/{Beberlei/Bundle => }/MetricsBundle/Resources/config/metrics.xml (100%)
rename src/{Beberlei/Bundle => }/MetricsBundle/Tests/DependencyInjection/BeberleiMetricsExtensionTest.php (100%)
diff --git a/composer.json b/composer.json
index c60f8b8..04f2e12 100644
--- a/composer.json
+++ b/composer.json
@@ -30,8 +30,8 @@
},
"autoload": {
"psr-4": {
- "Beberlei\\Metrics\\": "src/Beberlei/Metrics",
- "Beberlei\\Bundle\\MetricsBundle\\": "src/Beberlei/Bundle/MetricsBundle"
+ "Beberlei\\Metrics\\": "src/Metrics",
+ "Beberlei\\Bundle\\MetricsBundle\\": "src/MetricsBundle"
}
},
"suggest": {
diff --git a/src/Beberlei/Metrics/Collector/Collector.php b/src/Metrics/Collector/Collector.php
similarity index 100%
rename from src/Beberlei/Metrics/Collector/Collector.php
rename to src/Metrics/Collector/Collector.php
diff --git a/src/Beberlei/Metrics/Collector/DoctrineDBAL.php b/src/Metrics/Collector/DoctrineDBAL.php
similarity index 100%
rename from src/Beberlei/Metrics/Collector/DoctrineDBAL.php
rename to src/Metrics/Collector/DoctrineDBAL.php
diff --git a/src/Beberlei/Metrics/Collector/DogStatsD.php b/src/Metrics/Collector/DogStatsD.php
similarity index 100%
rename from src/Beberlei/Metrics/Collector/DogStatsD.php
rename to src/Metrics/Collector/DogStatsD.php
diff --git a/src/Beberlei/Metrics/Collector/GaugeableCollector.php b/src/Metrics/Collector/GaugeableCollector.php
similarity index 100%
rename from src/Beberlei/Metrics/Collector/GaugeableCollector.php
rename to src/Metrics/Collector/GaugeableCollector.php
diff --git a/src/Beberlei/Metrics/Collector/Graphite.php b/src/Metrics/Collector/Graphite.php
similarity index 100%
rename from src/Beberlei/Metrics/Collector/Graphite.php
rename to src/Metrics/Collector/Graphite.php
diff --git a/src/Beberlei/Metrics/Collector/InMemory.php b/src/Metrics/Collector/InMemory.php
similarity index 100%
rename from src/Beberlei/Metrics/Collector/InMemory.php
rename to src/Metrics/Collector/InMemory.php
diff --git a/src/Beberlei/Metrics/Collector/InfluxDB.php b/src/Metrics/Collector/InfluxDB.php
similarity index 100%
rename from src/Beberlei/Metrics/Collector/InfluxDB.php
rename to src/Metrics/Collector/InfluxDB.php
diff --git a/src/Beberlei/Metrics/Collector/InlineTaggableGaugeableCollector.php b/src/Metrics/Collector/InlineTaggableGaugeableCollector.php
similarity index 100%
rename from src/Beberlei/Metrics/Collector/InlineTaggableGaugeableCollector.php
rename to src/Metrics/Collector/InlineTaggableGaugeableCollector.php
diff --git a/src/Beberlei/Metrics/Collector/InlineTaggableGaugeableNullCollector.php b/src/Metrics/Collector/InlineTaggableGaugeableNullCollector.php
similarity index 100%
rename from src/Beberlei/Metrics/Collector/InlineTaggableGaugeableNullCollector.php
rename to src/Metrics/Collector/InlineTaggableGaugeableNullCollector.php
diff --git a/src/Beberlei/Metrics/Collector/Librato.php b/src/Metrics/Collector/Librato.php
similarity index 100%
rename from src/Beberlei/Metrics/Collector/Librato.php
rename to src/Metrics/Collector/Librato.php
diff --git a/src/Beberlei/Metrics/Collector/Logger.php b/src/Metrics/Collector/Logger.php
similarity index 100%
rename from src/Beberlei/Metrics/Collector/Logger.php
rename to src/Metrics/Collector/Logger.php
diff --git a/src/Beberlei/Metrics/Collector/Null.php b/src/Metrics/Collector/Null.php
similarity index 100%
rename from src/Beberlei/Metrics/Collector/Null.php
rename to src/Metrics/Collector/Null.php
diff --git a/src/Beberlei/Metrics/Collector/NullCollector.php b/src/Metrics/Collector/NullCollector.php
similarity index 100%
rename from src/Beberlei/Metrics/Collector/NullCollector.php
rename to src/Metrics/Collector/NullCollector.php
diff --git a/src/Beberlei/Metrics/Collector/Prometheus.php b/src/Metrics/Collector/Prometheus.php
similarity index 100%
rename from src/Beberlei/Metrics/Collector/Prometheus.php
rename to src/Metrics/Collector/Prometheus.php
diff --git a/src/Beberlei/Metrics/Collector/StatsD.php b/src/Metrics/Collector/StatsD.php
similarity index 100%
rename from src/Beberlei/Metrics/Collector/StatsD.php
rename to src/Metrics/Collector/StatsD.php
diff --git a/src/Beberlei/Metrics/Collector/TaggableCollector.php b/src/Metrics/Collector/TaggableCollector.php
similarity index 100%
rename from src/Beberlei/Metrics/Collector/TaggableCollector.php
rename to src/Metrics/Collector/TaggableCollector.php
diff --git a/src/Beberlei/Metrics/Collector/Telegraf.php b/src/Metrics/Collector/Telegraf.php
similarity index 100%
rename from src/Beberlei/Metrics/Collector/Telegraf.php
rename to src/Metrics/Collector/Telegraf.php
diff --git a/src/Beberlei/Metrics/Collector/Zabbix.php b/src/Metrics/Collector/Zabbix.php
similarity index 100%
rename from src/Beberlei/Metrics/Collector/Zabbix.php
rename to src/Metrics/Collector/Zabbix.php
diff --git a/src/Beberlei/Metrics/Factory.php b/src/Metrics/Factory.php
similarity index 100%
rename from src/Beberlei/Metrics/Factory.php
rename to src/Metrics/Factory.php
diff --git a/src/Beberlei/Metrics/MetricsException.php b/src/Metrics/MetricsException.php
similarity index 100%
rename from src/Beberlei/Metrics/MetricsException.php
rename to src/Metrics/MetricsException.php
diff --git a/src/Beberlei/Metrics/Tests/Collector/InMemoryTest.php b/src/Metrics/Tests/Collector/InMemoryTest.php
similarity index 100%
rename from src/Beberlei/Metrics/Tests/Collector/InMemoryTest.php
rename to src/Metrics/Tests/Collector/InMemoryTest.php
diff --git a/src/Beberlei/Metrics/Tests/Collector/InfluxDBTest.php b/src/Metrics/Tests/Collector/InfluxDBTest.php
similarity index 100%
rename from src/Beberlei/Metrics/Tests/Collector/InfluxDBTest.php
rename to src/Metrics/Tests/Collector/InfluxDBTest.php
diff --git a/src/Beberlei/Metrics/Tests/Collector/PrometheusTest.php b/src/Metrics/Tests/Collector/PrometheusTest.php
similarity index 100%
rename from src/Beberlei/Metrics/Tests/Collector/PrometheusTest.php
rename to src/Metrics/Tests/Collector/PrometheusTest.php
diff --git a/src/Beberlei/Metrics/Tests/FactoryTest.php b/src/Metrics/Tests/FactoryTest.php
similarity index 100%
rename from src/Beberlei/Metrics/Tests/FactoryTest.php
rename to src/Metrics/Tests/FactoryTest.php
diff --git a/src/Beberlei/Bundle/MetricsBundle/BeberleiMetricsBundle.php b/src/MetricsBundle/BeberleiMetricsBundle.php
similarity index 100%
rename from src/Beberlei/Bundle/MetricsBundle/BeberleiMetricsBundle.php
rename to src/MetricsBundle/BeberleiMetricsBundle.php
diff --git a/src/Beberlei/Bundle/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
similarity index 100%
rename from src/Beberlei/Bundle/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
rename to src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
diff --git a/src/Beberlei/Bundle/MetricsBundle/DependencyInjection/Configuration.php b/src/MetricsBundle/DependencyInjection/Configuration.php
similarity index 100%
rename from src/Beberlei/Bundle/MetricsBundle/DependencyInjection/Configuration.php
rename to src/MetricsBundle/DependencyInjection/Configuration.php
diff --git a/src/Beberlei/Bundle/MetricsBundle/Resources/config/metrics.xml b/src/MetricsBundle/Resources/config/metrics.xml
similarity index 100%
rename from src/Beberlei/Bundle/MetricsBundle/Resources/config/metrics.xml
rename to src/MetricsBundle/Resources/config/metrics.xml
diff --git a/src/Beberlei/Bundle/MetricsBundle/Tests/DependencyInjection/BeberleiMetricsExtensionTest.php b/src/MetricsBundle/Tests/DependencyInjection/BeberleiMetricsExtensionTest.php
similarity index 100%
rename from src/Beberlei/Bundle/MetricsBundle/Tests/DependencyInjection/BeberleiMetricsExtensionTest.php
rename to src/MetricsBundle/Tests/DependencyInjection/BeberleiMetricsExtensionTest.php
From ba19a515245796c90bf067c840e6b70fda01832b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 17:42:45 +0100
Subject: [PATCH 05/32] composer: move tests to it's own folder
---
composer.json | 5 +++++
.../Tests => tests/Metrics}/Collector/InMemoryTest.php | 0
.../Tests => tests/Metrics}/Collector/InfluxDBTest.php | 0
.../Tests => tests/Metrics}/Collector/PrometheusTest.php | 0
{src/Metrics/Tests => tests/Metrics}/FactoryTest.php | 0
.../DependencyInjection/BeberleiMetricsExtensionTest.php | 0
6 files changed, 5 insertions(+)
rename {src/Metrics/Tests => tests/Metrics}/Collector/InMemoryTest.php (100%)
rename {src/Metrics/Tests => tests/Metrics}/Collector/InfluxDBTest.php (100%)
rename {src/Metrics/Tests => tests/Metrics}/Collector/PrometheusTest.php (100%)
rename {src/Metrics/Tests => tests/Metrics}/FactoryTest.php (100%)
rename {src/MetricsBundle/Tests => tests/MetricsBundle}/DependencyInjection/BeberleiMetricsExtensionTest.php (100%)
diff --git a/composer.json b/composer.json
index 04f2e12..95ceaea 100644
--- a/composer.json
+++ b/composer.json
@@ -34,6 +34,11 @@
"Beberlei\\Bundle\\MetricsBundle\\": "src/MetricsBundle"
}
},
+ "autoload-dev": {
+ "psr-4": {
+ "Beberlei\\Bundle\\MetricsBundle\\": "src/MetricsBundle"
+ }
+ },
"suggest": {
"corley/influxdb-sdk": "For InfluxDB integration",
"okitsu/zabbix-sender": "For zabbix integration",
diff --git a/src/Metrics/Tests/Collector/InMemoryTest.php b/tests/Metrics/Collector/InMemoryTest.php
similarity index 100%
rename from src/Metrics/Tests/Collector/InMemoryTest.php
rename to tests/Metrics/Collector/InMemoryTest.php
diff --git a/src/Metrics/Tests/Collector/InfluxDBTest.php b/tests/Metrics/Collector/InfluxDBTest.php
similarity index 100%
rename from src/Metrics/Tests/Collector/InfluxDBTest.php
rename to tests/Metrics/Collector/InfluxDBTest.php
diff --git a/src/Metrics/Tests/Collector/PrometheusTest.php b/tests/Metrics/Collector/PrometheusTest.php
similarity index 100%
rename from src/Metrics/Tests/Collector/PrometheusTest.php
rename to tests/Metrics/Collector/PrometheusTest.php
diff --git a/src/Metrics/Tests/FactoryTest.php b/tests/Metrics/FactoryTest.php
similarity index 100%
rename from src/Metrics/Tests/FactoryTest.php
rename to tests/Metrics/FactoryTest.php
diff --git a/src/MetricsBundle/Tests/DependencyInjection/BeberleiMetricsExtensionTest.php b/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
similarity index 100%
rename from src/MetricsBundle/Tests/DependencyInjection/BeberleiMetricsExtensionTest.php
rename to tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
From 733f06e2caeb058d34c224113e18d294d1b66c7a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 17:46:41 +0100
Subject: [PATCH 06/32] phpunit: use symfony/phpunit-bridge
---
.gitignore | 1 +
composer.json | 3 ++-
phpunit.xml | 27 ++++++++++++++++++++
phpunit.xml.dist | 29 ----------------------
tests/Metrics/Collector/InMemoryTest.php | 2 +-
tests/Metrics/Collector/InfluxDBTest.php | 2 +-
tests/Metrics/Collector/PrometheusTest.php | 2 +-
7 files changed, 33 insertions(+), 33 deletions(-)
create mode 100644 phpunit.xml
delete mode 100644 phpunit.xml.dist
diff --git a/.gitignore b/.gitignore
index c8153b5..50b0964 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
/composer.lock
/vendor/
+/.phpunit.cache/
diff --git a/composer.json b/composer.json
index 95ceaea..1f6860f 100644
--- a/composer.json
+++ b/composer.json
@@ -26,7 +26,8 @@
"okitsu/zabbix-sender": "*@dev",
"symfony/config": "~3.3 || ~4.0",
"symfony/dependency-injection": "~3.3 || ~4.0",
- "symfony/http-kernel": "~3.3 || ~4.0"
+ "symfony/http-kernel": "~3.3 || ~4.0",
+ "symfony/phpunit-bridge": "^7.0"
},
"autoload": {
"psr-4": {
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 0000000..5d58267
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,27 @@
+
+
+
+
+ tests
+
+
+
+
+
+ src
+
+
+
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
deleted file mode 100644
index 2023ce8..0000000
--- a/phpunit.xml.dist
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
- ./src/Beberlei/Bundle/MetricsBundle/Tests
- ./src/Beberlei/Metrics/Tests/
-
-
-
-
-
- ./src
-
- ./src/Beberlei/Bundle/MetricsBundle/Tests
- ./src/Beberlei/Metrics/Tests/
-
-
-
-
diff --git a/tests/Metrics/Collector/InMemoryTest.php b/tests/Metrics/Collector/InMemoryTest.php
index 66e1c3f..96116cc 100644
--- a/tests/Metrics/Collector/InMemoryTest.php
+++ b/tests/Metrics/Collector/InMemoryTest.php
@@ -24,7 +24,7 @@ class InMemoryTest extends TestCase
/** @var InMemory */
private $collector;
- public function setUp()
+ protected function setUp(): void
{
$this->collector = new InMemory();
}
diff --git a/tests/Metrics/Collector/InfluxDBTest.php b/tests/Metrics/Collector/InfluxDBTest.php
index e5c0f40..7efc63d 100644
--- a/tests/Metrics/Collector/InfluxDBTest.php
+++ b/tests/Metrics/Collector/InfluxDBTest.php
@@ -29,7 +29,7 @@ class InfluxDBTest extends TestCase
*/
private $collector;
- protected function setUp()
+ protected function setUp(): void
{
$this->client = $this->getMockBuilder('\\InfluxDB\\Client')
->disableOriginalConstructor()
diff --git a/tests/Metrics/Collector/PrometheusTest.php b/tests/Metrics/Collector/PrometheusTest.php
index f42f3ab..94a25fa 100644
--- a/tests/Metrics/Collector/PrometheusTest.php
+++ b/tests/Metrics/Collector/PrometheusTest.php
@@ -32,7 +32,7 @@ class PrometheusTest extends TestCase
*/
private $collector;
- protected function setUp()
+ protected function setUp(): void
{
$this->collectorRegistryMock = $this->getMockBuilder('\\Prometheus\\CollectorRegistry')
->disableOriginalConstructor()
From 4d33fa1cba688b3f8b939d302496b4d08f6d9eb8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 18:30:20 +0100
Subject: [PATCH 07/32] zabbix: Remove collector
---
README.md | 21 -----
composer.json | 2 -
src/Metrics/Collector/Zabbix.php | 78 -------------------
src/Metrics/Factory.php | 30 -------
.../BeberleiMetricsExtension.php | 15 ----
.../Resources/config/metrics.xml | 4 -
tests/Metrics/FactoryTest.php | 7 --
.../BeberleiMetricsExtensionTest.php | 49 ------------
8 files changed, 206 deletions(-)
delete mode 100644 src/Metrics/Collector/Zabbix.php
diff --git a/README.md b/README.md
index abbee4a..27e3b03 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,6 @@ Currently supported backends:
* Null (Dummy that does nothing)
* Prometheus
* StatsD
-* Zabbix
* DogStatsD
## Installation
@@ -71,17 +70,6 @@ $collector->flush();
'foo.beberlei.de',
- 'server' => 'localhost',
- 'port' => 10051,
-));
-
-$zabbixConfig = \Beberlei\Metrics\Factory::create('zabbix_file', array(
- 'hostname' => 'foo.beberlei.de',
- 'file' => '/etc/zabbix/zabbix_agentd.conf'
-));
-
$librato = \Beberlei\Metrics\Factory::create('librato', array(
'hostname' => 'foo.beberlei.de',
'username' => 'foo',
@@ -118,15 +106,6 @@ beberlei_metrics:
collectors:
foo:
type: statsd
- bar:
- type: zabbix
- prefix: foo.beberlei.de
- host: localhost
- port: 10051
- baz:
- type: zabbix_file
- prefix: foo.beberlei.de
- file: /etc/zabbix/zabbix_agentd.conf
librato:
type: librato
username: foo
diff --git a/composer.json b/composer.json
index 1f6860f..cab3003 100644
--- a/composer.json
+++ b/composer.json
@@ -23,7 +23,6 @@
"doctrine/dbal": "~2.0",
"jimdo/prometheus_client_php": "^0.5",
"kriswallsmith/buzz": "*",
- "okitsu/zabbix-sender": "*@dev",
"symfony/config": "~3.3 || ~4.0",
"symfony/dependency-injection": "~3.3 || ~4.0",
"symfony/http-kernel": "~3.3 || ~4.0",
@@ -42,7 +41,6 @@
},
"suggest": {
"corley/influxdb-sdk": "For InfluxDB integration",
- "okitsu/zabbix-sender": "For zabbix integration",
"kriswallsmith/buzz": "For Librato integration",
"jimdo/prometheus_client_php": "For Prometheus integration"
},
diff --git a/src/Metrics/Collector/Zabbix.php b/src/Metrics/Collector/Zabbix.php
deleted file mode 100644
index 214e064..0000000
--- a/src/Metrics/Collector/Zabbix.php
+++ /dev/null
@@ -1,78 +0,0 @@
-sender = $sender;
- $this->prefix = $prefix ?: gethostname();
- }
-
- /**
- * {@inheritdoc}
- */
- public function increment($variable)
- {
- $this->sender->addData($this->prefix, $variable, '1');
- }
-
- /**
- * {@inheritdoc}
- */
- public function decrement($variable)
- {
- $this->sender->addData($this->prefix, $variable, '-1');
- }
-
- /**
- * {@inheritdoc}
- */
- public function timing($variable, $time)
- {
- $this->sender->addData($this->prefix, $variable, $time);
- }
-
- /**
- * {@inheritdoc}
- */
- public function measure($variable, $value)
- {
- $this->sender->addData($this->prefix, $variable, $value);
- }
-
- /**
- * {@inheritdoc}
- */
- public function flush()
- {
- $this->sender->send();
- }
-}
diff --git a/src/Metrics/Factory.php b/src/Metrics/Factory.php
index 0e6ba73..8a3704b 100644
--- a/src/Metrics/Factory.php
+++ b/src/Metrics/Factory.php
@@ -13,8 +13,6 @@
namespace Beberlei\Metrics;
-use Net\Zabbix\Sender;
-use Net\Zabbix\Agent\Config;
use Buzz\Browser;
use Buzz\Client\Curl;
@@ -108,34 +106,6 @@ public static function create($type, array $options = array())
return new Collector\Graphite($options['host'], $options['port']);
- case 'zabbix':
- if (!isset($options['hostname'])) {
- throw new MetricsException('Hostname is required for zabbix collector.');
- }
-
- if (!isset($options['server']) && !isset($options['port'])) {
- $sender = new Sender();
- } elseif (isset($options['server']) && !isset($options['port'])) {
- $sender = new Sender($options['server']);
- } elseif (!isset($options['server']) && isset($options['port'])) {
- throw new MetricsException('You should specified a server if you specified a port.');
- } else {
- $sender = new Sender($options['server'], $options['port']);
- }
-
- return new Collector\Zabbix($sender, $options['hostname']);
-
- case 'zabbix_file':
- if (!isset($options['hostname'])) {
- throw new MetricsException('Hostname is required for zabbix collector.');
- }
-
- $file = isset($options['file']) ? $options['file'] : null;
- $sender = new Sender();
- $sender->importAgentConfig(new Config($file));
-
- return new Collector\Zabbix($sender, $options['hostname']);
-
case 'librato':
if (!isset($options['hostname'])) {
throw new MetricsException('Hostname is required for librato collector.');
diff --git a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
index 3da3fe1..f943c17 100644
--- a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
+++ b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
@@ -102,21 +102,6 @@ private function createCollector($type, $config)
$definition->replaceArgument(1, $config['port'] ?: 8125);
$definition->replaceArgument(2, (string) $config['prefix']);
- return $definition;
- case 'zabbix':
- $sender = new Definition('Net\Zabbix\Sender');
- if ($config['file']) {
- $senderConfig = new Definition('Net\Zabbix\Agent\Config');
- $senderConfig->addArgument($config['file']);
- $sender->addMethodCall('importAgentConfig', array($senderConfig));
- } else {
- $sender->addArgument($config['host'] ?: 'localhost');
- $sender->addArgument((int) $config['port'] ?: 10051);
- }
-
- $definition->replaceArgument(0, $sender);
- $definition->replaceArgument(1, $config['prefix']);
-
return $definition;
default:
throw new \InvalidArgumentException(sprintf('The type "%s" is not supported', $type));
diff --git a/src/MetricsBundle/Resources/config/metrics.xml b/src/MetricsBundle/Resources/config/metrics.xml
index 128fd63..5cae232 100644
--- a/src/MetricsBundle/Resources/config/metrics.xml
+++ b/src/MetricsBundle/Resources/config/metrics.xml
@@ -56,10 +56,6 @@
-
-
-
-
diff --git a/tests/Metrics/FactoryTest.php b/tests/Metrics/FactoryTest.php
index fa7cd1a..4fa931c 100644
--- a/tests/Metrics/FactoryTest.php
+++ b/tests/Metrics/FactoryTest.php
@@ -21,9 +21,6 @@ public function getCreateValidMetricTests()
array('Beberlei\Metrics\Collector\DogStatsD', 'dogstatsd', array('host' => 'localhost')),
array('Beberlei\Metrics\Collector\Graphite', 'graphite'),
array('Beberlei\Metrics\Collector\Graphite', 'graphite', array('host' => 'localhost', 'port' => 1234)),
- array('Beberlei\Metrics\Collector\Zabbix', 'zabbix', array('hostname' => 'foobar.com', 'server' => 'localhost', 'port' => 1234)),
- array('Beberlei\Metrics\Collector\Zabbix', 'zabbix_file', array('hostname' => 'foobar.com')),
- array('Beberlei\Metrics\Collector\Zabbix', 'zabbix_file', array('hostname' => 'foobar.com', 'file' => '/tmp/foobar')),
array('Beberlei\Metrics\Collector\Librato', 'librato', array('hostname' => 'foobar.com', 'username' => 'username', 'password' => 'password')),
array('Beberlei\Metrics\Collector\DoctrineDBAL', 'doctrine_dbal', array('connection' => $this->getMockBuilder('Doctrine\DBAL\Connection')->disableOriginalConstructor()->getMock())),
array('Beberlei\Metrics\Collector\Logger', 'logger', array('logger' => new NullLogger())),
@@ -55,10 +52,6 @@ public function getCreateThrowExceptionIfOptionsAreInvalidTests()
array('You should specified a host and a port if you specified a prefix.', 'dogstatsd', array('port' => '1234', 'prefix' => 'prefix')),
array('You should specified a host and a port if you specified a prefix.', 'dogstatsd', array('hostname' => 'foobar.com', 'prefix' => 'prefix')),
array('You should specified a host if you specified a port.', 'graphite', array('port' => '1234')),
- array('Hostname is required for zabbix collector.', 'zabbix'),
- array('Hostname is required for zabbix collector.', 'zabbix', array('hostname', 'foobar.com')),
- array('You should specified a server if you specified a port.', 'zabbix', array('hostname' => 'foobar.com', 'port' => '1234')),
- array('Hostname is required for zabbix collector.', 'zabbix_file'),
array('Hostname is required for librato collector.', 'librato'),
array('No username given for librato collector.', 'librato', array('hostname' => 'foobar.com')),
array('No password given for librato collector.', 'librato', array('hostname' => 'foobar.com', 'username' => 'username')),
diff --git a/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php b/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
index 5fdee8d..a301784 100644
--- a/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
+++ b/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
@@ -223,55 +223,6 @@ public function testWithTelegraf()
$this->assertEquals(',string_tag=first_value,int_tag=123', $this->getProperty($collector, 'tags'));
}
- public function testWithZabbix()
- {
- $container = $this->createContainer(array(
- 'default' => 'simple',
- 'collectors' => array(
- 'simple' => array(
- 'type' => 'zabbix',
- ),
- 'full' => array(
- 'type' => 'zabbix',
- 'prefix' => 'foo.beberlei.de',
- 'host' => 'zabbix.localhost',
- 'port' => 1234,
- ),
- 'file' => array(
- 'type' => 'zabbix',
- 'prefix' => 'foo.beberlei.de',
- 'file' => '/etc/zabbix/zabbix_agentd.conf',
- ),
- ),
- ), array(
- 'beberlei_metrics.collector.simple',
- 'beberlei_metrics.collector.full',
- 'beberlei_metrics.collector.file'
- ));
-
- $collector = $container->get('beberlei_metrics.collector.simple');
- $this->assertInstanceOf('Beberlei\Metrics\Collector\Zabbix', $collector);
- $this->assertSame(gethostname(), $this->getProperty($collector, 'prefix'));
- $sender = $this->getProperty($collector, 'sender');
- $this->assertInstanceOf('Net\Zabbix\Sender', $sender);
- $this->assertSame('localhost', $this->getProperty($sender, '_servername'));
- $this->assertSame(10051, $this->getProperty($sender, '_serverport'));
-
- $collector = $container->get('beberlei_metrics.collector.full');
- $this->assertInstanceOf('Beberlei\Metrics\Collector\Zabbix', $collector);
- $this->assertSame('foo.beberlei.de', $this->getProperty($collector, 'prefix'));
- $sender = $this->getProperty($collector, 'sender');
- $this->assertInstanceOf('Net\Zabbix\Sender', $sender);
- $this->assertSame('zabbix.localhost', $this->getProperty($sender, '_servername'));
- $this->assertSame(1234, $this->getProperty($sender, '_serverport'));
-
- $collector = $container->get('beberlei_metrics.collector.file');
- $this->assertInstanceOf('Beberlei\Metrics\Collector\Zabbix', $collector);
- $this->assertSame('foo.beberlei.de', $this->getProperty($collector, 'prefix'));
- $sender = $this->getProperty($collector, 'sender');
- $this->assertInstanceOf('Net\Zabbix\Sender', $sender);
- }
-
public function testWithInfluxDB()
{
$influxDBClientMock = $this->getMockBuilder('InfluxDB\Client')
From 1cdf63d03b1661a1fbd29cb5c7333ebfbf09d8b9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 18:32:20 +0100
Subject: [PATCH 08/32] composer: bump requirements to PHP 8.1+
---
composer.json | 1 +
1 file changed, 1 insertion(+)
diff --git a/composer.json b/composer.json
index cab3003..b26f381 100644
--- a/composer.json
+++ b/composer.json
@@ -19,6 +19,7 @@
"psr/log": "^1.0 || ^2.0 || ^3.0"
},
"require-dev": {
+ "php": ">=8.1",
"corley/influxdb-sdk": "^0.5.1",
"doctrine/dbal": "~2.0",
"jimdo/prometheus_client_php": "^0.5",
From 5457cf6dcb70c5d0350d8d8df01e6621b5e74149 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 18:34:49 +0100
Subject: [PATCH 09/32] composer: drop support for Symfony < 5.4
---
composer.json | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/composer.json b/composer.json
index b26f381..b361c37 100644
--- a/composer.json
+++ b/composer.json
@@ -24,10 +24,15 @@
"doctrine/dbal": "~2.0",
"jimdo/prometheus_client_php": "^0.5",
"kriswallsmith/buzz": "*",
- "symfony/config": "~3.3 || ~4.0",
- "symfony/dependency-injection": "~3.3 || ~4.0",
- "symfony/http-kernel": "~3.3 || ~4.0",
- "symfony/phpunit-bridge": "^7.0"
+ "symfony/config": "^5.4 || ^6.4 || ^7.0",
+ "symfony/dependency-injection": "^5.4 || ^6.4 || ^7.0",
+ "symfony/http-kernel": "^5.4 || ^6.4 || ^7.0",
+ "symfony/phpunit-bridge": "^6.4 || ^7.0"
+ },
+ "conflict": {
+ "symfony/config": "<5.4",
+ "symfony/dependency-injection": "<5.4",
+ "symfony/http-kernel": "<5.4"
},
"autoload": {
"psr-4": {
From b5ac1c9ad8ec526074d2a3f956c5d1c360cc2e37 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 18:41:55 +0100
Subject: [PATCH 10/32] composer: switch to symfony http-client instead of buzz
---
composer.json | 3 ++-
src/Metrics/Collector/Librato.php | 21 +++++++++----------
src/Metrics/Factory.php | 17 +++++----------
.../Resources/config/metrics.xml | 9 +++-----
4 files changed, 20 insertions(+), 30 deletions(-)
diff --git a/composer.json b/composer.json
index b361c37..83e700f 100644
--- a/composer.json
+++ b/composer.json
@@ -23,15 +23,16 @@
"corley/influxdb-sdk": "^0.5.1",
"doctrine/dbal": "~2.0",
"jimdo/prometheus_client_php": "^0.5",
- "kriswallsmith/buzz": "*",
"symfony/config": "^5.4 || ^6.4 || ^7.0",
"symfony/dependency-injection": "^5.4 || ^6.4 || ^7.0",
+ "symfony/http-client": "^5.4 || ^6.4 || ^7.0",
"symfony/http-kernel": "^5.4 || ^6.4 || ^7.0",
"symfony/phpunit-bridge": "^6.4 || ^7.0"
},
"conflict": {
"symfony/config": "<5.4",
"symfony/dependency-injection": "<5.4",
+ "symfony/http-client": "<5.4",
"symfony/http-kernel": "<5.4"
},
"autoload": {
diff --git a/src/Metrics/Collector/Librato.php b/src/Metrics/Collector/Librato.php
index 9bbd96d..b53c9e5 100644
--- a/src/Metrics/Collector/Librato.php
+++ b/src/Metrics/Collector/Librato.php
@@ -13,12 +13,12 @@
namespace Beberlei\Metrics\Collector;
-use Buzz\Browser;
+use Symfony\Contracts\HttpClient\Exception\ExceptionInterface;
+use Symfony\Contracts\HttpClient\HttpClientInterface;
class Librato implements Collector
{
- /** @var \Buzz\Browser */
- private $browser;
+ private HttpClientInterface $httpClient;
/** @var string */
private $source;
@@ -36,14 +36,13 @@ class Librato implements Collector
);
/**
- * @param \Buzz\Browser $browser
* @param string $source
* @param string $username
* @param string $password
*/
- public function __construct(Browser $browser, $source, $username, $password)
+ public function __construct(HttpClientInterface $httpClient, $source, $username, $password)
{
- $this->browser = $browser;
+ $this->httpClient = $httpClient;
$this->source = $source;
$this->username = $username;
$this->password = $password;
@@ -107,12 +106,12 @@ public function flush()
}
try {
- $this->browser->post('https://metrics-api.librato.com/v1/metrics', array(
- 'Authorization: Basic '.base64_encode($this->username.':'.$this->password),
- 'Content-Type: application/json',
- ), json_encode($this->data));
+ $this->httpClient->request('POST', 'https://metrics-api.librato.com/v1/metrics', [
+ 'auth_basic' => [$this->username, $this->password],
+ 'json' => $this->data,
+ ]);
$this->data = array('gauges' => array(), 'counters' => array());
- } catch (\Exception $e) {
+ } catch (ExceptionInterface) {
}
}
}
diff --git a/src/Metrics/Factory.php b/src/Metrics/Factory.php
index 8a3704b..01ab153 100644
--- a/src/Metrics/Factory.php
+++ b/src/Metrics/Factory.php
@@ -13,18 +13,15 @@
namespace Beberlei\Metrics;
-use Buzz\Browser;
-use Buzz\Client\Curl;
+use Symfony\Component\HttpClient\HttpClient;
+use Symfony\Contracts\HttpClient\HttpClientInterface;
/**
* Static factory for Metrics Collectors.
*/
abstract class Factory
{
- /**
- * @var Buzz\Browser
- */
- private static $httpClient;
+ private static HttpClientInterface $httpClient;
/**
* Create Metrics Collector Instance.
@@ -162,12 +159,8 @@ public static function create($type, array $options = array())
}
}
- private static function getHttpClient()
+ private static function getHttpClient(): HttpClientInterface
{
- if (self::$httpClient === null) {
- self::$httpClient = new Browser(new Curl());
- }
-
- return self::$httpClient;
+ return self::$httpClient ??= HttpClient::create();
}
}
diff --git a/src/MetricsBundle/Resources/config/metrics.xml b/src/MetricsBundle/Resources/config/metrics.xml
index 5cae232..0d53ed4 100644
--- a/src/MetricsBundle/Resources/config/metrics.xml
+++ b/src/MetricsBundle/Resources/config/metrics.xml
@@ -6,11 +6,8 @@
-
-
-
-
-
+
+
@@ -26,7 +23,7 @@
-
+
From 11f8e4a0c79dd7132c33e1f21e95ab91d985a7d7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 18:48:49 +0100
Subject: [PATCH 11/32] chore: modernise PHP code
---
.../{Collector.php => CollectorInterface.php} | 23 +-
src/Metrics/Collector/DoctrineDBAL.php | 56 +---
src/Metrics/Collector/DogStatsD.php | 71 +---
...or.php => GaugeableCollectorInterface.php} | 7 +-
src/Metrics/Collector/Graphite.php | 69 ++--
src/Metrics/Collector/InMemory.php | 119 ++-----
src/Metrics/Collector/InfluxDB.php | 71 ++--
.../InlineTaggableGaugeableCollector.php | 65 ----
.../InlineTaggableGaugeableNullCollector.php | 64 ----
src/Metrics/Collector/Librato.php | 87 ++---
src/Metrics/Collector/Logger.php | 48 +--
src/Metrics/Collector/NullCollector.php | 36 +--
src/Metrics/Collector/Prometheus.php | 95 ++----
src/Metrics/Collector/StatsD.php | 63 +---
src/Metrics/Collector/TaggableCollector.php | 27 --
...ull.php => TaggableCollectorInterface.php} | 6 +-
src/Metrics/Collector/Telegraf.php | 94 ++----
src/Metrics/Factory.php | 76 +++--
.../BeberleiMetricsExtension.php | 21 +-
.../DependencyInjection/Configuration.php | 18 +-
tests/Metrics/Collector/InMemoryTest.php | 26 +-
tests/Metrics/Collector/InfluxDBTest.php | 75 +----
tests/Metrics/Collector/PrometheusTest.php | 103 +++---
tests/Metrics/FactoryTest.php | 68 ++--
.../BeberleiMetricsExtensionTest.php | 304 +++++-------------
25 files changed, 440 insertions(+), 1252 deletions(-)
rename src/Metrics/Collector/{Collector.php => CollectorInterface.php} (61%)
rename src/Metrics/Collector/{GaugeableCollector.php => GaugeableCollectorInterface.php} (76%)
delete mode 100644 src/Metrics/Collector/InlineTaggableGaugeableCollector.php
delete mode 100644 src/Metrics/Collector/InlineTaggableGaugeableNullCollector.php
delete mode 100644 src/Metrics/Collector/TaggableCollector.php
rename src/Metrics/Collector/{Null.php => TaggableCollectorInterface.php} (79%)
diff --git a/src/Metrics/Collector/Collector.php b/src/Metrics/Collector/CollectorInterface.php
similarity index 61%
rename from src/Metrics/Collector/Collector.php
rename to src/Metrics/Collector/CollectorInterface.php
index 51d44a0..5431a87 100644
--- a/src/Metrics/Collector/Collector.php
+++ b/src/Metrics/Collector/CollectorInterface.php
@@ -13,43 +13,32 @@
namespace Beberlei\Metrics\Collector;
-/**
- * Collector interface.
- */
-interface Collector
+interface CollectorInterface
{
/**
* Updates a counter by some arbitrary amount.
- *
- * @param string $variable
- * @param int $value The amount to increment the counter by
*/
- public function measure($variable, $value);
+ public function measure(string $variable, int $value, array $tags = []): void;
/**
* Increments a counter.
- *
- * @param string $variable
*/
- public function increment($variable);
+ public function increment(string $variable, array $tags = []): void;
/**
* Decrements a counter.
- *
- * @param string $variable
*/
- public function decrement($variable);
+ public function decrement(string $variable, array $tags = []): void;
/**
* Records a timing.
*
- * @param string $variable
* @param int $time The duration of the timing in milliseconds
*/
- public function timing($variable, $time);
+ public function timing(string $variable, int $time, array $tags = []): void;
/**
* Sends the metrics to the adapter backend.
*/
- public function flush();
+ public function flush(): void;
}
diff --git a/src/Metrics/Collector/DoctrineDBAL.php b/src/Metrics/Collector/DoctrineDBAL.php
index 33ac0f6..caf1b47 100644
--- a/src/Metrics/Collector/DoctrineDBAL.php
+++ b/src/Metrics/Collector/DoctrineDBAL.php
@@ -29,58 +29,36 @@
* The Primary key can either be a surrogate (id) or
* has to span all 3 columns.
*/
-class DoctrineDBAL implements Collector
+class DoctrineDBAL implements CollectorInterface
{
- /** @var \Doctrine\DBAL\Connection */
- private $conn;
+ private array $data = [];
- /** @var array */
- private $data;
-
- /**
- * @param \Doctrine\DBAL\Connection $conn
- */
- public function __construct(Connection $conn)
- {
- $this->conn = $conn;
+ public function __construct(
+ private readonly Connection $conn
+ ) {
}
- /**
- * {@inheritdoc}
- */
- public function timing($stat, $time)
+ public function measure(string $variable, int $value, array $tags = []): void
{
- $this->data[] = array($stat, $time, date('Y-m-d'));
+ $this->data[] = [$variable, $value, date('Y-m-d')];
}
- /**
- * {@inheritdoc}
- */
- public function increment($stats)
+ public function increment(string $variable, array $tags = []): void
{
- $this->data[] = array($stats, 1, date('Y-m-d'));
+ $this->data[] = [$variable, 1, date('Y-m-d')];
}
- /**
- * {@inheritdoc}
- */
- public function decrement($stats)
+ public function decrement(string $variable, array $tags = []): void
{
- $this->data[] = array($stats, -1, date('Y-m-d'));
+ $this->data[] = [$variable, -1, date('Y-m-d')];
}
- /**
- * {@inheritdoc}
- */
- public function measure($variable, $value)
+ public function timing(string $variable, int $time, array $tags = []): void
{
- $this->data[] = array($variable, $value, date('Y-m-d'));
+ $this->data[] = [$variable, $time, date('Y-m-d')];
}
- /**
- * {@inheritdoc}
- */
- public function flush()
+ public function flush(): void
{
if (!$this->data) {
return;
@@ -95,14 +73,14 @@ public function flush()
$stmt->bindParam(1, $measurement[0]);
$stmt->bindParam(2, $measurement[1]);
$stmt->bindParam(3, $measurement[2]);
- $stmt->execute();
+ $stmt->executeStatement();
}
$this->conn->commit();
- } catch (Exception $e) {
+ } catch (Exception) {
$this->conn->rollback();
}
- $this->data = array();
+ $this->data = [];
}
}
diff --git a/src/Metrics/Collector/DogStatsD.php b/src/Metrics/Collector/DogStatsD.php
index 7f9a82d..9fdbbdd 100644
--- a/src/Metrics/Collector/DogStatsD.php
+++ b/src/Metrics/Collector/DogStatsD.php
@@ -13,77 +13,43 @@
namespace Beberlei\Metrics\Collector;
-class DogStatsD implements Collector, InlineTaggableGaugeableCollector
+class DogStatsD implements CollectorInterface, GaugeableCollectorInterface
{
- /** @var string */
- private $host;
+ private array $data = [];
- /** @var string */
- private $port;
-
- /** @var string */
- private $prefix;
-
- /** @var array */
- private $data;
-
- /**
- * @param string $host
- * @param string $port
- * @param string $prefix
- */
- public function __construct($host = 'localhost', $port = '8125', $prefix = '')
- {
- $this->host = $host;
- $this->port = $port;
- $this->prefix = $prefix;
- $this->data = array();
+ public function __construct(
+ private readonly string $host = 'localhost',
+ private readonly int $port = 8125,
+ private readonly string $prefix = '',
+ ) {
}
- /**
- * {@inheritdoc}
- */
- public function measure($variable, $value, $tags = array())
+ public function measure(string $variable, int $value, array $tags = []): void
{
$this->data[] = sprintf('%s:%s|c%s', $variable, $value, $this->buildTagString($tags));
}
- /**
- * {@inheritdoc}
- */
- public function increment($variable, $tags = array())
+ public function increment(string $variable, array $tags = []): void
{
$this->data[] = $variable.':1|c'.$this->buildTagString($tags);
}
- /**
- * {@inheritdoc}
- */
- public function decrement($variable, $tags = array())
+ public function decrement(string $variable, array $tags = []): void
{
$this->data[] = $variable.':-1|c'.$this->buildTagString($tags);
}
- /**
- * {@inheritdoc}
- */
- public function timing($variable, $time, $tags = array())
+ public function timing(string $variable, int $time, array $tags = []): void
{
$this->data[] = sprintf('%s:%s|ms%s', $variable, $time, $this->buildTagString($tags));
}
- /**
- * {@inheritdoc}
- */
- public function gauge($variable, $value, $tags = array())
+ public function gauge(string $variable, int $value, array $tags = []): void
{
$this->data[] = sprintf('%s:%s|g%s', $variable, $value, $this->buildTagString($tags));
}
- /**
- * {@inheritdoc}
- */
- public function flush()
+ public function flush(): void
{
if (!$this->data) {
return;
@@ -99,24 +65,21 @@ public function flush()
foreach ($this->data as $line) {
fwrite($fp, $this->prefix.$line);
}
+
error_reporting($level);
fclose($fp);
- $this->data = array();
+ $this->data = [];
}
/**
* Given a key/value map of metric tags, builds them into a
* DogStatsD tag string and returns the string.
- *
- * @param $tags array
- *
- * @return string
*/
- private function buildTagString($tags)
+ private function buildTagString(array $tags): string
{
- $results = array();
+ $results = [];
foreach ($tags as $key => $value) {
$results[] = sprintf('%s:%s', $key, $value);
diff --git a/src/Metrics/Collector/GaugeableCollector.php b/src/Metrics/Collector/GaugeableCollectorInterface.php
similarity index 76%
rename from src/Metrics/Collector/GaugeableCollector.php
rename to src/Metrics/Collector/GaugeableCollectorInterface.php
index ffeb98f..56938f9 100644
--- a/src/Metrics/Collector/GaugeableCollector.php
+++ b/src/Metrics/Collector/GaugeableCollectorInterface.php
@@ -13,13 +13,10 @@
namespace Beberlei\Metrics\Collector;
-interface GaugeableCollector
+interface GaugeableCollectorInterface
{
/**
* Updates a gauge by an arbitrary amount.
- *
- * @param string $variable
- * @param int $value
*/
- public function gauge($variable, $value);
+ public function gauge(string $variable, int $value, array $tags = []): void;
}
diff --git a/src/Metrics/Collector/Graphite.php b/src/Metrics/Collector/Graphite.php
index e052565..bdd9b4a 100644
--- a/src/Metrics/Collector/Graphite.php
+++ b/src/Metrics/Collector/Graphite.php
@@ -18,68 +18,39 @@
/**
* Sends statistics to the stats daemon over UDP or TCP.
*/
-class Graphite implements Collector
+class Graphite implements CollectorInterface
{
- /** @var string */
- private $protocol;
+ private array $data = [];
- /** @var string */
- private $host;
-
- /** @var int */
- private $port;
-
- /** @var array */
- private $data = array();
-
- /**
- * @param string $host
- * @param int $port
- * @param string $protocol
- */
- public function __construct($host = 'localhost', $port = 2003, $protocol = 'tcp')
- {
- $this->host = $host;
- $this->port = $port;
- $this->protocol = $protocol;
+ public function __construct(
+ private readonly string $host = 'localhost',
+ private readonly int $port = 2003,
+ private readonly string $protocol = 'tcp'
+ ) {
}
- /**
- * {@inheritdoc}
- */
- public function timing($variable, $time)
+ public function measure(string $variable, int $value, array $tags = []): void
{
- $this->push($variable, $time);
+ $this->push($variable, $value);
}
- /**
- * {@inheritdoc}
- */
- public function increment($variable)
+
+ public function increment(string $variable, array $tags = []): void
{
$this->push($variable, 1);
}
- /**
- * {@inheritdoc}
- */
- public function decrement($variable)
+ public function decrement(string $variable, array $tags = []): void
{
$this->push($variable, -1);
}
- /**
- * {@inheritdoc}
- */
- public function measure($variable, $value)
+ public function timing(string $variable, int $time, array $tags = []): void
{
- $this->push($variable, $value);
+ $this->push($variable, $time);
}
- /**
- * {@inheritdoc}
- */
- public function flush()
+ public function flush(): void
{
if (!$this->data) {
return;
@@ -93,21 +64,21 @@ public function flush()
}
foreach ($this->data as $line) {
- fwrite($fp, $line);
+ fwrite($fp, (string) $line);
}
fclose($fp);
- } catch (Exception $e) {
+ } catch (Exception) {
}
- $this->data = array();
+ $this->data = [];
}
- public function push($stat, $value, $time = null)
+ public function push(string $variable, int|float $value, ?int $time = null): void
{
$this->data[] = sprintf(
is_float($value) ? "%s %.18f %d\n" : "%s %d %d\n",
- $stat,
+ $variable,
$value,
$time ?: time()
);
diff --git a/src/Metrics/Collector/InMemory.php b/src/Metrics/Collector/InMemory.php
index 95df43b..bae39f3 100644
--- a/src/Metrics/Collector/InMemory.php
+++ b/src/Metrics/Collector/InMemory.php
@@ -17,138 +17,67 @@
* Stores metrics in memory.
* Useful for testing and with any custom persistence mechanisms.
*/
-class InMemory implements Collector, GaugeableCollector
+class InMemory implements CollectorInterface, GaugeableCollectorInterface
{
/** @var int[] */
- private $incrementData = [];
+ private array $incrementData = [];
+
/** @var int[] */
- private $gaugeData = [];
+ private array $gaugeData = [];
+
/** @var int[] */
- private $timingData = [];
+ private array $timingData = [];
- /**
- * Updates a counter by some arbitrary amount.
- *
- * @param string $variable
- * @param int $value The amount to increment the counter by
- */
- public function measure($variable, $value)
+ public function measure(string $variable, int $value, array $tags = []): void
{
- if (!isset($this->incrementData[$variable])) {
- $this->incrementData[$variable] = 0;
- }
+ $this->incrementData[$variable] ??= 0;
$this->incrementData[$variable] += $value;
}
- /**
- * Increments a counter.
- *
- * @param string $variable
- */
- public function increment($variable)
+ public function increment(string $variable, array $tags = []): void
{
$this->measure($variable, 1);
}
- /**
- * Decrements a counter.
- *
- * @param string $variable
- */
- public function decrement($variable)
+ public function decrement(string $variable, array $tags = []): void
{
$this->measure($variable, -1);
}
- /**
- * Records a timing.
- *
- * @param string $variable
- * @param int $time The duration of the timing in milliseconds
- */
- public function timing($variable, $time)
+ public function timing(string $variable, int $time, array $tags = []): void
{
if (!isset($this->timingData[$variable])) {
$this->timingData[$variable] = 0;
}
- $this->timingData[$variable] = $time;
- }
- /**
- * Sends the metrics to the adapter backend.
- */
- public function flush()
- {
- $this->timingData = [];
- $this->gaugeData = [];
- $this->incrementData = [];
+ $this->timingData[$variable] = $time;
}
- /**
- * Updates a gauge by an arbitrary amount.
- *
- * @param string $variable
- * @param int $value
- */
- public function gauge($variable, $value)
+ public function gauge(string $variable, int $value, array $tags = []): void
{
- $sign = substr($value, 0, 1);
-
- if (in_array($sign, ['-', '+'])) {
- $this->gaugeIncrement($variable, (int) $value);
-
- return;
- }
-
$this->gaugeData[$variable] = $value;
}
- /**
- * Returns current value of incremented/decremented/measured variable.
- *
- * @param string $variable
- *
- * @return int
- */
- public function getMeasure($variable)
+ public function flush(): void
{
- return isset($this->incrementData[$variable]) ? $this->incrementData[$variable] : 0;
+ $this->timingData = [];
+ $this->gaugeData = [];
+ $this->incrementData = [];
}
- /**
- * Returns current value of gauged variable.
- *
- * @param string $variable
- *
- * @return int
- */
- public function getGauge($variable)
+
+ public function getMeasure(string $variable): int
{
- return isset($this->gaugeData[$variable]) ? $this->gaugeData[$variable] : 0;
+ return $this->incrementData[$variable] ?? 0;
}
- /**
- * Returns current value of timed variable.
- *
- * @param string $variable
- *
- * @return int
- */
- public function getTiming($variable)
+ public function getGauge(string $variable): int
{
- return isset($this->timingData[$variable]) ? $this->timingData[$variable] : 0;
+ return $this->gaugeData[$variable] ?? 0;
}
- /**
- * @param string $variable
- * @param int $value
- */
- private function gaugeIncrement($variable, $value)
+ public function getTiming(string $variable): int
{
- if (!isset($this->gaugeData[$variable])) {
- $this->gaugeData[$variable] = 0;
- }
-
- $this->gaugeData[$variable] += $value;
+ return $this->timingData[$variable] ?? 0;
}
}
diff --git a/src/Metrics/Collector/InfluxDB.php b/src/Metrics/Collector/InfluxDB.php
index ae657b8..e995972 100644
--- a/src/Metrics/Collector/InfluxDB.php
+++ b/src/Metrics/Collector/InfluxDB.php
@@ -15,81 +15,46 @@
use InfluxDB\Client;
-class InfluxDB implements Collector, TaggableCollector
+class InfluxDB implements CollectorInterface, TaggableCollectorInterface
{
- /** @var \InfluxDB\Client */
- private $client;
+ private array $data = [];
- /** @var array */
- private $data = array();
-
- /** @var array */
- private $tags = array();
-
- /**
- * @param Client $client
- */
- public function __construct(Client $client)
- {
- $this->client = $client;
+ public function __construct(
+ private readonly Client $client,
+ private array $tags = [],
+ ) {
}
- /**
- * {@inheritdoc}
- */
- public function increment($variable)
+ public function measure(string $variable, int $value, array $tags = []): void
{
- $this->data[] = array($variable, 1);
+ $this->data[] = [$variable, $value, $tags];
}
- /**
- * {@inheritdoc}
- */
- public function decrement($variable)
+ public function increment(string $variable, array $tags = []): void
{
- $this->data[] = array($variable, -1);
+ $this->data[] = [$variable, 1, $tags];
}
- /**
- * {@inheritdoc}
- */
- public function timing($variable, $time)
+ public function decrement(string $variable, array $tags = []): void
{
- $this->data[] = array($variable, $time);
+ $this->data[] = [$variable, -1, $tags];
}
- /**
- * {@inheritdoc}
- */
- public function measure($variable, $value)
+ public function timing(string $variable, int $time, array $tags = []): void
{
- $this->data[] = array($variable, $value);
+ $this->data[] = [$variable, $time, $tags];
}
- /**
- * {@inheritdoc}
- */
- public function flush()
+ public function flush(): void
{
foreach ($this->data as $data) {
- $this->client->mark(array(
- 'points' => array(
- array(
- 'measurement' => $data[0],
- 'fields' => array('value' => $data[1]),
- ),
- ),
- 'tags' => $this->tags,
- ));
+ $this->client->mark(['points' => [['measurement' => $data[0], 'fields' => ['value' => $data[1]]]], 'tags' => $data[2] + $this->tags]);
}
- $this->data = array();
+ $this->data = [];
}
- /**
- * {@inheritdoc}
- */
- public function setTags($tags)
+ public function setTags(array $tags): void
{
$this->tags = $tags;
}
diff --git a/src/Metrics/Collector/InlineTaggableGaugeableCollector.php b/src/Metrics/Collector/InlineTaggableGaugeableCollector.php
deleted file mode 100644
index 1fdebb1..0000000
--- a/src/Metrics/Collector/InlineTaggableGaugeableCollector.php
+++ /dev/null
@@ -1,65 +0,0 @@
- [], 'gauges' => []];
- /** @var string */
- private $source;
-
- /** @var string */
- private $username;
-
- /** @var string */
- private $password;
-
- /** @var array */
- private $data = array(
- 'counters' => array(),
- 'gauges' => array(),
- );
-
- /**
- * @param string $source
- * @param string $username
- * @param string $password
- */
- public function __construct(HttpClientInterface $httpClient, $source, $username, $password)
- {
- $this->httpClient = $httpClient;
- $this->source = $source;
- $this->username = $username;
- $this->password = $password;
+ public function __construct(
+ private readonly HttpClientInterface $httpClient,
+ private readonly string $source,
+ private readonly string $username,
+ private readonly string $password
+ ) {
}
- /**
- * {@inheritdoc}
- */
- public function increment($variable)
+ public function measure(string $variable, int $value, array $tags = []): void
{
- $this->data['counters'][] = array(
- 'source' => $this->source,
- 'name' => $variable,
- 'value' => 1,
- );
+ $this->data['gauges'][] = ['source' => $this->source, 'name' => $variable, 'value' => $value];
}
- /**
- * {@inheritdoc}
- */
- public function decrement($variable)
+ public function increment(string $variable, array $tags = []): void
{
- $this->data['counters'][] = array(
- 'source' => $this->source,
- 'name' => $variable,
- 'value' => -1,
- );
+ $this->data['counters'][] = ['source' => $this->source, 'name' => $variable, 'value' => 1];
}
- /**
- * {@inheritdoc}
- */
- public function timing($variable, $time)
+ public function decrement(string $variable, array $tags = []): void
{
- $this->data['gauges'][] = array(
- 'source' => $this->source,
- 'name' => $variable,
- 'value' => $time,
- );
+ $this->data['counters'][] = ['source' => $this->source, 'name' => $variable, 'value' => -1];
}
- /**
- * {@inheritdoc}
- */
- public function measure($variable, $value)
+ public function timing(string $variable, int $time, array $tags = []): void
{
- $this->data['gauges'][] = array(
- 'source' => $this->source,
- 'name' => $variable,
- 'value' => $value,
- );
+ $this->data['gauges'][] = ['source' => $this->source, 'name' => $variable, 'value' => $time];
}
- /**
- * {@inheritdoc}
- */
- public function flush()
+ public function flush(): void
{
if (!$this->data['gauges'] && !$this->data['counters']) {
return;
@@ -110,7 +59,7 @@ public function flush()
'auth_basic' => [$this->username, $this->password],
'json' => $this->data,
]);
- $this->data = array('gauges' => array(), 'counters' => array());
+ $this->data = ['gauges' => [], 'counters' => []];
} catch (ExceptionInterface) {
}
}
diff --git a/src/Metrics/Collector/Logger.php b/src/Metrics/Collector/Logger.php
index c501981..0a294d8 100644
--- a/src/Metrics/Collector/Logger.php
+++ b/src/Metrics/Collector/Logger.php
@@ -15,63 +15,39 @@
use Psr\Log\LoggerInterface;
-class Logger implements Collector, GaugeableCollector
+class Logger implements CollectorInterface, GaugeableCollectorInterface
{
- /** @var \Psr\Log\LoggerInterface */
- private $logger;
+ public function __construct(
+ private readonly LoggerInterface $logger,
+ ) {
+ }
- /**
- * @param \Psr\Log\LoggerInterface $logger
- */
- public function __construct(LoggerInterface $logger)
+ public function measure(string $variable, int $value, array $tags = []): void
{
- $this->logger = $logger;
+ $this->logger->debug(sprintf('measure:%s:%s', $variable, $value));
}
- /**
- * {@inheritdoc}
- */
- public function increment($variable)
+ public function increment(string $variable, array $tags = []): void
{
$this->logger->debug('increment:'.$variable);
}
- /**
- * {@inheritdoc}
- */
- public function decrement($variable)
+ public function decrement(string $variable, array $tags = []): void
{
$this->logger->debug('decrement:'.$variable);
}
- /**
- * {@inheritdoc}
- */
- public function timing($variable, $time)
+ public function timing(string $variable, int $time, array $tags = []): void
{
$this->logger->debug(sprintf('timing:%s:%s', $variable, $time));
}
- /**
- * {@inheritdoc}
- */
- public function measure($variable, $value)
- {
- $this->logger->debug(sprintf('measure:%s:%s', $variable, $value));
- }
-
- /**
- * {@inheritdoc}
- */
- public function gauge($variable, $value)
+ public function gauge(string $variable, int $value, array $tags = []): void
{
$this->logger->debug(sprintf('gauge:%s:%s', $variable, $value));
}
- /**
- * {@inheritdoc}
- */
- public function flush()
+ public function flush(): void
{
$this->logger->debug('flush');
}
diff --git a/src/Metrics/Collector/NullCollector.php b/src/Metrics/Collector/NullCollector.php
index acb543b..38f05c1 100644
--- a/src/Metrics/Collector/NullCollector.php
+++ b/src/Metrics/Collector/NullCollector.php
@@ -13,47 +13,33 @@
namespace Beberlei\Metrics\Collector;
-class NullCollector implements Collector, GaugeableCollector
+class NullCollector implements CollectorInterface, GaugeableCollectorInterface, TaggableCollectorInterface
{
- /**
- * {@inheritdoc}
- */
- public function increment($variable)
+ public function increment(string $variable, array $tags = []): void
{
}
- /**
- * {@inheritdoc}
- */
- public function decrement($variable)
+ public function decrement(string $variable, array $tags = []): void
{
}
- /**
- * {@inheritdoc}
- */
- public function timing($variable, $time)
+ public function timing(string $variable, int $time, array $tags = []): void
{
}
- /**
- * {@inheritdoc}
- */
- public function measure($variable, $value)
+ public function measure(string $variable, int $value, array $tags = []): void
{
}
- /**
- * {@inheritdoc}
- */
- public function gauge($variable, $value)
+ public function gauge(string $variable, int $value, array $tags = []): void
{
}
- /**
- * {@inheritdoc}
- */
- public function flush()
+ public function flush(): void
+ {
+ }
+
+ public function setTags(array $tags): void
{
}
}
diff --git a/src/Metrics/Collector/Prometheus.php b/src/Metrics/Collector/Prometheus.php
index ced78e2..6945adf 100644
--- a/src/Metrics/Collector/Prometheus.php
+++ b/src/Metrics/Collector/Prometheus.php
@@ -13,87 +13,42 @@
namespace Beberlei\Metrics\Collector;
+use Prometheus\Gauge;
use Prometheus\CollectorRegistry;
use Prometheus\Exception\MetricNotFoundException;
-class Prometheus implements Collector, TaggableCollector
+class Prometheus implements CollectorInterface, TaggableCollectorInterface
{
- /**
- * @var CollectorRegistry
- */
- private $collectorRegistry;
-
- /**
- * @var string
- */
- private $namespace = '';
-
- /** @var array */
- private $data = array(
- 'counters' => array(),
- 'gauges' => array(),
- );
-
- /**
- * @var array
- */
- private $tags = array();
-
- /**
- * @param CollectorRegistry $collectorRegistry
- * @param string $namespace
- */
- public function __construct(CollectorRegistry $collectorRegistry, $namespace = '')
- {
- $this->collectorRegistry = $collectorRegistry;
- $this->namespace = $namespace;
+ private array $data = ['counters' => [], 'gauges' => []];
+
+ public function __construct(
+ private readonly CollectorRegistry $collectorRegistry,
+ private readonly string $namespace = '',
+ private array $tags = [],
+ ) {
}
- /**
- * {@inheritdoc}
- */
- public function measure($variable, $value)
+ public function measure(string $variable, int $value, array $tags = []): void
{
- $this->data['gauges'][] = array(
- 'name' => $variable,
- 'value' => $value,
- );
+ $this->data['gauges'][] = ['name' => $variable, 'value' => $value];
}
- /**
- * {@inheritdoc}
- */
- public function increment($variable)
+ public function increment(string $variable, array $tags = []): void
{
- $this->data['counters'][] = array(
- 'name' => $variable,
- 'value' => 1,
- );
+ $this->data['counters'][] = ['name' => $variable, 'value' => 1];
}
- /**
- * {@inheritdoc}
- */
- public function decrement($variable)
+ public function decrement(string $variable, array $tags = []): void
{
- $this->data['counters'][] = array(
- 'name' => $variable,
- 'value' => -1,
- );
+ $this->data['counters'][] = ['name' => $variable, 'value' => -1];
}
- /**
- * {@inheritdoc}
- */
- public function timing($variable, $time)
+ public function timing(string $variable, int $time, array $tags = []): void
{
$this->measure($variable, $time);
}
- /**
- * {@inheritdoc}
- */
- public function flush()
+ public function flush(): void
{
if (!$this->data['gauges'] && !$this->data['counters']) {
return;
@@ -117,27 +72,19 @@ public function flush()
$gauge->set($gaugeData['value'], $tagsValues);
}
- $this->data = array('counters' => array(), 'gauges' => array());
+ $this->data = ['counters' => [], 'gauges' => []];
}
- /**
- * {@inheritdoc}
- */
- public function setTags($tags)
+ public function setTags(array $tags): void
{
$this->tags = $tags;
}
- /**
- * @param string $variable
- *
- * @return \Prometheus\Gauge
- */
- private function getOrRegisterGaugeForVariable($variable)
+ private function getOrRegisterGaugeForVariable(string $variable): Gauge
{
try {
$gauge = $this->collectorRegistry->getGauge($this->namespace, $variable);
- } catch (MetricNotFoundException $e) {
+ } catch (MetricNotFoundException) {
$gauge = $this->collectorRegistry->registerGauge(
$this->namespace,
$variable,
diff --git a/src/Metrics/Collector/StatsD.php b/src/Metrics/Collector/StatsD.php
index e6c92fc..4ae2fc8 100644
--- a/src/Metrics/Collector/StatsD.php
+++ b/src/Metrics/Collector/StatsD.php
@@ -16,77 +16,43 @@
/**
* Sends statistics to the stats daemon over UDP.
*/
-class StatsD implements Collector, GaugeableCollector
+class StatsD implements CollectorInterface, GaugeableCollectorInterface
{
- /** @var string */
- private $host;
+ private array $data = [];
- /** @var string */
- private $port;
-
- /** @var string */
- private $prefix;
-
- /** @var array */
- private $data;
-
- /**
- * @param string $host
- * @param string $port
- * @param string $prefix
- */
- public function __construct($host = 'localhost', $port = '8125', $prefix = '')
- {
- $this->host = $host;
- $this->port = $port;
- $this->prefix = $prefix;
- $this->data = array();
+ public function __construct(
+ private readonly string $host = 'localhost',
+ private readonly int $port = 8125,
+ private readonly string $prefix = '',
+ ) {
}
- /**
- * {@inheritdoc}
- */
- public function timing($variable, $time)
+ public function timing(string $variable, int $time, array $tags = []): void
{
$this->data[] = sprintf('%s:%s|ms', $variable, $time);
}
- /**
- * {@inheritdoc}
- */
- public function increment($variable)
+ public function increment(string $variable, array $tags = []): void
{
$this->data[] = $variable.':1|c';
}
- /**
- * {@inheritdoc}
- */
- public function decrement($variable)
+ public function decrement(string $variable, array $tags = []): void
{
$this->data[] = $variable.':-1|c';
}
- /**
- * {@inheritdoc}
- */
- public function measure($variable, $value)
+ public function measure(string $variable, int $value, array $tags = []): void
{
$this->data[] = sprintf('%s:%s|c', $variable, $value);
}
- /**
- * {@inheritdoc}
- */
- public function gauge($variable, $value)
+ public function gauge(string $variable, int $value, array $tags = []): void
{
$this->data[] = sprintf('%s:%s|g', $variable, $value);
}
- /**
- * {@inheritdoc}
- */
- public function flush()
+ public function flush(): void
{
if (!$this->data) {
return;
@@ -102,10 +68,11 @@ public function flush()
foreach ($this->data as $line) {
fwrite($fp, $this->prefix.$line);
}
+
error_reporting($level);
fclose($fp);
- $this->data = array();
+ $this->data = [];
}
}
diff --git a/src/Metrics/Collector/TaggableCollector.php b/src/Metrics/Collector/TaggableCollector.php
deleted file mode 100644
index 2e9cda0..0000000
--- a/src/Metrics/Collector/TaggableCollector.php
+++ /dev/null
@@ -1,27 +0,0 @@
-host = $host;
- $this->port = $port;
- $this->prefix = $prefix;
- $this->data = array();
- }
-
- /**
- * {@inheritdoc}
- */
- public function setTags($tags)
- {
- $this->tags = http_build_query($tags, '', ',');
- $this->tags = (strlen($this->tags) > 0 ? ','.$this->tags : $this->tags);
+ private array $data = [];
+
+ public function __construct(
+ private readonly string $host = 'localhost',
+ private readonly int $port = 8125,
+ private readonly string $prefix = '',
+ private string $tags = '',
+ ) {
}
- /**
- * {@inheritdoc}
- */
- public function timing($variable, $time)
+ public function measure(string $variable, int $value, array $tags = []): void
{
- $this->data[] = sprintf('%s%s:%s|ms', $variable, $this->tags, $time);
+ $this->data[] = sprintf('%s%s:%s|c', $variable, $this->tags, $value);
}
- /**
- * {@inheritdoc}
- */
- public function increment($variable)
+ public function increment(string $variable, array $tags = []): void
{
$this->data[] = $variable.$this->tags.':1|c';
}
- /**
- * {@inheritdoc}
- */
- public function decrement($variable)
+ public function decrement(string $variable, array $tags = []): void
{
$this->data[] = $variable.$this->tags.':-1|c';
}
- /**
- * {@inheritdoc}
- */
- public function measure($variable, $value)
+ public function timing(string $variable, int $time, array $tags = []): void
{
- $this->data[] = sprintf('%s%s:%s|c', $variable, $this->tags, $value);
+ $this->data[] = sprintf('%s%s:%s|ms', $variable, $this->tags, $time);
}
- /**
- * {@inheritdoc}
- */
- public function gauge($variable, $value)
+ public function gauge(string $variable, int $value, array $tags = []): void
{
$this->data[] = sprintf('%s%s:%s|g', $variable, $this->tags, $value);
}
- /**
- * @param $variable
- * @param $value
- */
- public function set($variable, $value)
+ public function set(string $variable, string $value): void
{
$this->data[] = sprintf('%s%s:%s|s', $variable, $this->tags, $value);
}
- /**
- * {@inheritdoc}
- */
- public function flush()
+ public function flush(): void
{
if (!$this->data) {
return;
@@ -125,10 +76,17 @@ public function flush()
foreach ($this->data as $line) {
fwrite($fp, $this->prefix.$line);
}
+
error_reporting($level);
fclose($fp);
- $this->data = array();
+ $this->data = [];
+ }
+
+ public function setTags(array $tags): void
+ {
+ $this->tags = http_build_query($tags, '', ',');
+ $this->tags = strlen($this->tags) > 0 ? ','.$this->tags : $this->tags;
}
}
diff --git a/src/Metrics/Factory.php b/src/Metrics/Factory.php
index 01ab153..3d2a012 100644
--- a/src/Metrics/Factory.php
+++ b/src/Metrics/Factory.php
@@ -13,6 +13,17 @@
namespace Beberlei\Metrics;
+use Beberlei\Metrics\Collector\StatsD;
+use Beberlei\Metrics\Collector\DogStatsD;
+use Beberlei\Metrics\Collector\Telegraf;
+use Beberlei\Metrics\Collector\Graphite;
+use Beberlei\Metrics\Collector\Librato;
+use Beberlei\Metrics\Collector\DoctrineDBAL;
+use Beberlei\Metrics\Collector\Logger;
+use Beberlei\Metrics\Collector\InfluxDB;
+use Beberlei\Metrics\Collector\NullCollector;
+use Beberlei\Metrics\Collector\InlineTaggableGaugeableNullCollector;
+use Beberlei\Metrics\Collector\Prometheus;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Contracts\HttpClient\HttpClientInterface;
@@ -27,81 +38,90 @@ abstract class Factory
* Create Metrics Collector Instance.
*
* @param string $type
- * @param array $options
*
* @throws MetricsException
- *
* @return Collector\Collector
*/
- public static function create($type, array $options = array())
+ public static function create($type, array $options = [])
{
switch ($type) {
case 'statsd':
if ((!isset($options['host']) || !isset($options['port'])) && isset($options['prefix'])) {
throw new MetricsException('You should specified a host and a port if you specified a prefix.');
}
+
if (!isset($options['host']) && !isset($options['port'])) {
- return new Collector\StatsD();
+ return new StatsD();
}
+
if (isset($options['host']) && !isset($options['port'])) {
- return new Collector\StatsD($options['host']);
+ return new StatsD($options['host']);
}
+
if (!isset($options['host']) && isset($options['port'])) {
throw new MetricsException('You should specified a host if you specified a port.');
}
- $prefix = isset($options['prefix']) ? $options['prefix'] : '';
+ $prefix = $options['prefix'] ?? '';
- return new Collector\StatsD($options['host'], $options['port'], $prefix);
+ return new StatsD($options['host'], $options['port'], $prefix);
case 'dogstatsd':
if ((!isset($options['host']) || !isset($options['port'])) && isset($options['prefix'])) {
throw new MetricsException('You should specified a host and a port if you specified a prefix.');
}
+
if (!isset($options['host']) && !isset($options['port'])) {
- return new Collector\DogStatsD();
+ return new DogStatsD();
}
+
if (isset($options['host']) && !isset($options['port'])) {
- return new Collector\DogStatsD($options['host']);
+ return new DogStatsD($options['host']);
}
+
if (!isset($options['host']) && isset($options['port'])) {
throw new MetricsException('You should specified a host if you specified a port.');
}
- $prefix = isset($options['prefix']) ? $options['prefix'] : '';
+ $prefix = $options['prefix'] ?? '';
- return new Collector\DogStatsD($options['host'], $options['port'], $prefix);
+ return new DogStatsD($options['host'], $options['port'], $prefix);
case 'telegraf':
if ((!isset($options['host']) || !isset($options['port'])) && isset($options['prefix'])) {
throw new MetricsException('You should specified a host and a port if you specified a prefix.');
}
+
if (!isset($options['host']) && !isset($options['port'])) {
- return new Collector\Telegraf();
+ return new Telegraf();
}
+
if (isset($options['host']) && !isset($options['port'])) {
- return new Collector\Telegraf($options['host']);
+ return new Telegraf($options['host']);
}
+
if (!isset($options['host']) && isset($options['port'])) {
throw new MetricsException('You should specified a host if you specified a port.');
}
- $prefix = isset($options['prefix']) ? $options['prefix'] : '';
+ $prefix = $options['prefix'] ?? '';
- return new Collector\Telegraf($options['host'], $options['port'], $prefix);
+ return new Telegraf($options['host'], $options['port'], $prefix);
case 'graphite':
if (!isset($options['host']) && !isset($options['port'])) {
- return new Collector\Graphite();
+ return new Graphite();
}
+
if (isset($options['host']) && !isset($options['port'])) {
- return new Collector\Graphite($options['host']);
+ return new Graphite($options['host']);
}
+
if (!isset($options['host']) && isset($options['port'])) {
throw new MetricsException('You should specified a host if you specified a port.');
}
- return new Collector\Graphite($options['host'], $options['port']);
+ return new Graphite($options['host'], $options['port']);
case 'librato':
if (!isset($options['hostname'])) {
@@ -116,43 +136,43 @@ public static function create($type, array $options = array())
throw new MetricsException('No password given for librato collector.');
}
- return new Collector\Librato(self::getHttpClient(), $options['hostname'], $options['username'], $options['password']);
+ return new Librato(self::getHttpClient(), $options['hostname'], $options['username'], $options['password']);
case 'doctrine_dbal':
if (!isset($options['connection'])) {
throw new MetricsException('connection is required for Doctrine DBAL collector.');
}
- return new Collector\DoctrineDBAL($options['connection']);
+ return new DoctrineDBAL($options['connection']);
case 'logger':
if (!isset($options['logger'])) {
throw new MetricsException("Missing 'logger' key with logger service.");
}
- return new Collector\Logger($options['logger']);
+ return new Logger($options['logger']);
case 'influxdb':
if (!isset($options['client'])) {
- throw new MetricsException('Missing \'client\' key for InfluxDB collector.');
+ throw new MetricsException("Missing 'client' key for InfluxDB collector.");
}
- return new Collector\InfluxDB($options['client']);
+ return new InfluxDB($options['client']);
case 'null':
- return new Collector\NullCollector();
+ return new NullCollector();
case 'null_inlinetaggable':
- return new Collector\InlineTaggableGaugeableNullCollector();
+ return new InlineTaggableGaugeableNullCollector();
case 'prometheus':
if (!isset($options['collector_registry'])) {
- throw new MetricsException('Missing \'collector_registry\' key for Prometheus collector.');
+ throw new MetricsException("Missing 'collector_registry' key for Prometheus collector.");
}
- $namespace = isset($options['namespace']) ? $options['namespace'] : '';
+ $namespace = $options['namespace'] ?? '';
- return new Collector\Prometheus($options['collector_registry'], $namespace);
+ return new Prometheus($options['collector_registry'], $namespace);
default:
throw new MetricsException(sprintf('Unknown metrics collector given (%s).', $type));
diff --git a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
index f943c17..5d8c51f 100644
--- a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
+++ b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
@@ -13,10 +13,7 @@
class BeberleiMetricsExtension extends Extension
{
- /**
- * @return void
- */
- public function load(array $configs, ContainerBuilder $container)
+ public function load(array $configs, ContainerBuilder $container): void
{
$configuration = $this->getConfiguration($configs, $container);
$config = $this->processConfiguration($configuration, $configs);
@@ -39,24 +36,16 @@ public function load(array $configs, ContainerBuilder $container)
$container->setAlias(Collector::class, 'beberlei_metrics.collector');
}
- private function createCollector($type, $config)
+ private function createCollector($type, array $config)
{
$definition = new ChildDefinition('beberlei_metrics.collector_proto.'.$config['type']);
// Theses listeners should be as late as possible
- $definition->addTag('kernel.event_listener', array(
- 'method' => 'flush',
- 'priority' => -1024,
- 'event' => 'kernel.terminate',
- ));
- $definition->addTag('kernel.event_listener', array(
- 'method' => 'flush',
- 'priority' => -1024,
- 'event' => 'console.terminate',
- ));
+ $definition->addTag('kernel.event_listener', ['method' => 'flush', 'priority' => -1024, 'event' => 'kernel.terminate']);
+ $definition->addTag('kernel.event_listener', ['method' => 'flush', 'priority' => -1024, 'event' => 'console.terminate']);
if (count($config['tags']) > 0) {
- $definition->addMethodCall('setTags', array($config['tags']));
+ $definition->addMethodCall('setTags', [$config['tags']]);
}
switch ($type) {
diff --git a/src/MetricsBundle/DependencyInjection/Configuration.php b/src/MetricsBundle/DependencyInjection/Configuration.php
index 3fee12e..4eb62cd 100644
--- a/src/MetricsBundle/DependencyInjection/Configuration.php
+++ b/src/MetricsBundle/DependencyInjection/Configuration.php
@@ -45,32 +45,24 @@ public function getConfigTreeBuilder(): TreeBuilder
->scalarNode('prometheus_collector_registry')->defaultNull()->info('It must to contain service id for Prometheus\\CollectorRegistry class instance.')->end()
->scalarNode('namespace')->defaultValue('')->end()
->arrayNode('tags')
- ->defaultValue(array())
+ ->defaultValue([])
->prototype('scalar')->end()
->end()
->end()
->validate()
- ->ifTrue(function ($v) {
- return 'librato' === $v['type'] && empty($v['source']);
- })
+ ->ifTrue(static fn($v): bool => 'librato' === $v['type'] && empty($v['source']))
->thenInvalid('The source has to be specified to use a Librato')
->end()
->validate()
- ->ifTrue(function ($v) {
- return 'librato' === $v['type'] && empty($v['username']);
- })
+ ->ifTrue(static fn($v): bool => 'librato' === $v['type'] && empty($v['username']))
->thenInvalid('The username has to be specified to use a Librato')
->end()
->validate()
- ->ifTrue(function ($v) {
- return 'librato' === $v['type'] && empty($v['password']);
- })
+ ->ifTrue(static fn($v): bool => 'librato' === $v['type'] && empty($v['password']))
->thenInvalid('The password has to be specified to use a Librato')
->end()
->validate()
- ->ifTrue(function ($v) {
- return 'prometheus' === $v['type'] && empty($v['prometheus_collector_registry']);
- })
+ ->ifTrue(static fn($v): bool => 'prometheus' === $v['type'] && empty($v['prometheus_collector_registry']))
->thenInvalid('The prometheus_collector_registry has to be specified to use a Prometheus')
->end()
->end()
diff --git a/tests/Metrics/Collector/InMemoryTest.php b/tests/Metrics/Collector/InMemoryTest.php
index 96116cc..259b8b0 100644
--- a/tests/Metrics/Collector/InMemoryTest.php
+++ b/tests/Metrics/Collector/InMemoryTest.php
@@ -18,18 +18,18 @@
class InMemoryTest extends TestCase
{
- const VARIABLE_A = 'variable_a';
- const VARIABLE_B = 'variable_b';
+ public const VARIABLE_A = 'variable_a';
- /** @var InMemory */
- private $collector;
+ public const VARIABLE_B = 'variable_b';
+
+ private InMemory $collector;
protected function setUp(): void
{
$this->collector = new InMemory();
}
- public function testIncrement()
+ public function testIncrement(): void
{
$this->collector->increment(self::VARIABLE_A);
$this->collector->increment(self::VARIABLE_A);
@@ -40,7 +40,7 @@ public function testIncrement()
$this->assertEquals(1, $this->collector->getMeasure(self::VARIABLE_B));
}
- public function testDecrement()
+ public function testDecrement(): void
{
$this->collector->increment(self::VARIABLE_A);
$this->collector->increment(self::VARIABLE_A);
@@ -53,7 +53,7 @@ public function testDecrement()
$this->assertEquals(-2, $this->collector->getMeasure(self::VARIABLE_B));
}
- public function testTiming()
+ public function testTiming(): void
{
$this->collector->timing(self::VARIABLE_A, 123);
@@ -64,7 +64,7 @@ public function testTiming()
$this->assertEquals(112, $this->collector->getTiming(self::VARIABLE_B));
}
- public function testMeasure()
+ public function testMeasure(): void
{
$this->collector->measure(self::VARIABLE_A, 2);
$this->collector->measure(self::VARIABLE_A, -5);
@@ -76,7 +76,7 @@ public function testMeasure()
$this->assertEquals(123, $this->collector->getMeasure(self::VARIABLE_B));
}
- public function testSettingGauge()
+ public function testSettingGauge(): void
{
$this->collector->gauge(self::VARIABLE_A, 2);
$this->collector->gauge(self::VARIABLE_A, 5);
@@ -88,7 +88,7 @@ public function testSettingGauge()
$this->assertEquals(0, $this->collector->getGauge(self::VARIABLE_B));
}
- public function testIncrementingGauge()
+ public function testIncrementingGauge(): void
{
$this->collector->gauge(self::VARIABLE_A, '10');
$this->collector->gauge(self::VARIABLE_A, '+2');
@@ -97,7 +97,7 @@ public function testIncrementingGauge()
$this->assertEquals(9, $this->collector->getGauge(self::VARIABLE_A));
}
- public function testSettingGaugeToNegativeValue()
+ public function testSettingGaugeToNegativeValue(): void
{
$this->collector->gauge(self::VARIABLE_A, 1); //sets to 1
$this->collector->gauge(self::VARIABLE_A, 2); //sets to 2
@@ -109,7 +109,7 @@ public function testSettingGaugeToNegativeValue()
$this->assertEquals(-5, $this->collector->getGauge(self::VARIABLE_A));
}
- public function testTypesOfMetricsAreSeparate()
+ public function testTypesOfMetricsAreSeparate(): void
{
$this->collector->increment(self::VARIABLE_A);
$this->collector->gauge(self::VARIABLE_A, 2);
@@ -120,7 +120,7 @@ public function testTypesOfMetricsAreSeparate()
$this->assertEquals(3, $this->collector->getTiming(self::VARIABLE_A));
}
- public function testFlushClearsData()
+ public function testFlushClearsData(): void
{
$this->collector->increment(self::VARIABLE_A);
$this->collector->gauge(self::VARIABLE_A, 2);
diff --git a/tests/Metrics/Collector/InfluxDBTest.php b/tests/Metrics/Collector/InfluxDBTest.php
index 7efc63d..f976324 100644
--- a/tests/Metrics/Collector/InfluxDBTest.php
+++ b/tests/Metrics/Collector/InfluxDBTest.php
@@ -13,6 +13,7 @@
namespace Beberlei\Metrics\Tests\Collector;
+use InfluxDB\Client;
use PHPUnit\Framework\TestCase;
use PHPUnit_Framework_MockObject_MockObject;
use Beberlei\Metrics\Collector\InfluxDB;
@@ -24,30 +25,19 @@ class InfluxDBTest extends TestCase
*/
private $client;
- /**
- * @var InfluxDB
- */
- private $collector;
+ private InfluxDB $collector;
protected function setUp(): void
{
- $this->client = $this->getMockBuilder('\\InfluxDB\\Client')
+ $this->client = $this->getMockBuilder(Client::class)
->disableOriginalConstructor()
->getMock();
$this->collector = new InfluxDB($this->client);
}
- public function testCollectIncrement()
+ public function testCollectIncrement(): void
{
- $expectedArgs = array(
- 'points' => array(
- array(
- 'measurement' => 'series-name',
- 'fields' => array('value' => 1),
- ),
- ),
- 'tags' => array(),
- );
+ $expectedArgs = ['points' => [['measurement' => 'series-name', 'fields' => ['value' => 1]]], 'tags' => []];
$this->client->expects($this->once())
->method('mark')
@@ -57,17 +47,9 @@ public function testCollectIncrement()
$this->collector->flush();
}
- public function testCollectDecrement()
+ public function testCollectDecrement(): void
{
- $expectedArgs = array(
- 'points' => array(
- array(
- 'measurement' => 'series-name',
- 'fields' => array('value' => -1),
- ),
- ),
- 'tags' => array(),
- );
+ $expectedArgs = ['points' => [['measurement' => 'series-name', 'fields' => ['value' => -1]]], 'tags' => []];
$this->client->expects($this->once())
->method('mark')
@@ -77,17 +59,9 @@ public function testCollectDecrement()
$this->collector->flush();
}
- public function testCollectTiming()
+ public function testCollectTiming(): void
{
- $expectedArgs = array(
- 'points' => array(
- array(
- 'measurement' => 'series-name',
- 'fields' => array('value' => 47.11),
- ),
- ),
- 'tags' => array(),
- );
+ $expectedArgs = ['points' => [['measurement' => 'series-name', 'fields' => ['value' => 47.11]]], 'tags' => []];
$this->client->expects($this->once())
->method('mark')
@@ -97,17 +71,9 @@ public function testCollectTiming()
$this->collector->flush();
}
- public function testCollectMeasure()
+ public function testCollectMeasure(): void
{
- $expectedArgs = array(
- 'points' => array(
- array(
- 'measurement' => 'series-name',
- 'fields' => array('value' => 47.11),
- ),
- ),
- 'tags' => array(),
- );
+ $expectedArgs = ['points' => [['measurement' => 'series-name', 'fields' => ['value' => 47.11]]], 'tags' => []];
$this->client->expects($this->once())
->method('mark')
@@ -117,22 +83,11 @@ public function testCollectMeasure()
$this->collector->flush();
}
- public function testCollectMeasureWithTags()
+ public function testCollectMeasureWithTags(): void
{
- $expectedTags = array(
- 'dc' => 'west',
- 'node' => 'nemesis101',
- );
-
- $expectedArgs = array(
- 'points' => array(
- array(
- 'measurement' => 'series-name',
- 'fields' => array('value' => 47.11),
- ),
- ),
- 'tags' => $expectedTags,
- );
+ $expectedTags = ['dc' => 'west', 'node' => 'nemesis101'];
+
+ $expectedArgs = ['points' => [['measurement' => 'series-name', 'fields' => ['value' => 47.11]]], 'tags' => $expectedTags];
$this->client->expects($this->once())
->method('mark')
diff --git a/tests/Metrics/Collector/PrometheusTest.php b/tests/Metrics/Collector/PrometheusTest.php
index 94a25fa..895c258 100644
--- a/tests/Metrics/Collector/PrometheusTest.php
+++ b/tests/Metrics/Collector/PrometheusTest.php
@@ -13,28 +13,28 @@
namespace Beberlei\Metrics\Tests\Collector;
+use Prometheus\CollectorRegistry;
+use Prometheus\Gauge;
use Beberlei\Metrics\Collector\Prometheus;
use PHPUnit\Framework\TestCase;
use Prometheus\Exception\MetricNotFoundException;
class PrometheusTest extends TestCase
{
- const TEST_NAMESPACE = 'some_metric_namespace';
- const TEST_VARIABLE_NAME = 'some_variable_name';
+ public const TEST_NAMESPACE = 'some_metric_namespace';
+
+ public const TEST_VARIABLE_NAME = 'some_variable_name';
/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
private $collectorRegistryMock;
- /**
- * @var Prometheus
- */
- private $collector;
+ private Prometheus $collector;
protected function setUp(): void
{
- $this->collectorRegistryMock = $this->getMockBuilder('\\Prometheus\\CollectorRegistry')
+ $this->collectorRegistryMock = $this->getMockBuilder(CollectorRegistry::class)
->disableOriginalConstructor()
->getMock()
;
@@ -42,18 +42,18 @@ protected function setUp(): void
$this->collector = new Prometheus($this->collectorRegistryMock, self::TEST_NAMESPACE);
}
- public function testMeasure()
+ public function testMeasure(): void
{
$expectedVariableValue = 123;
- $gaugeMock = $this->getMockBuilder('\\Prometheus\\Gauge')
+ $gaugeMock = $this->getMockBuilder(Gauge::class)
->disableOriginalConstructor()
->getMock()
;
$gaugeMock
->expects($this->once())
->method('set')
- ->with($expectedVariableValue, array())
+ ->with($expectedVariableValue, [])
;
$this->collectorRegistryMock
@@ -67,12 +67,12 @@ public function testMeasure()
$this->collector->flush();
}
- public function testMeasureWithTags()
+ public function testMeasureWithTags(): void
{
$expectedVariableValue = 123;
- $expectedTagsValues = array('value1', 'value2');
+ $expectedTagsValues = ['value1', 'value2'];
- $gaugeMock = $this->getMockBuilder('\\Prometheus\\Gauge')
+ $gaugeMock = $this->getMockBuilder(Gauge::class)
->disableOriginalConstructor()
->getMock()
;
@@ -89,25 +89,22 @@ public function testMeasureWithTags()
->willReturn($gaugeMock)
;
- $this->collector->setTags(array(
- 'tag1' => 'value1',
- 'tag2' => 'value2',
- ));
+ $this->collector->setTags(['tag1' => 'value1', 'tag2' => 'value2']);
$this->collector->measure(self::TEST_VARIABLE_NAME, $expectedVariableValue);
$this->collector->flush();
}
- public function testIncrement()
+ public function testIncrement(): void
{
- $gaugeMock = $this->getMockBuilder('\\Prometheus\\Gauge')
+ $gaugeMock = $this->getMockBuilder(Gauge::class)
->disableOriginalConstructor()
->getMock()
;
$gaugeMock
->expects($this->once())
->method('inc')
- ->with(array())
+ ->with([])
;
$this->collectorRegistryMock
@@ -121,11 +118,11 @@ public function testIncrement()
$this->collector->flush();
}
- public function testIncrementWithTags()
+ public function testIncrementWithTags(): void
{
- $expectedTagsValues = array('value1', 'value2');
+ $expectedTagsValues = ['value1', 'value2'];
- $gaugeMock = $this->getMockBuilder('\\Prometheus\\Gauge')
+ $gaugeMock = $this->getMockBuilder(Gauge::class)
->disableOriginalConstructor()
->getMock()
;
@@ -142,25 +139,22 @@ public function testIncrementWithTags()
->willReturn($gaugeMock)
;
- $this->collector->setTags(array(
- 'tag1' => 'value1',
- 'tag2' => 'value2',
- ));
+ $this->collector->setTags(['tag1' => 'value1', 'tag2' => 'value2']);
$this->collector->increment(self::TEST_VARIABLE_NAME);
$this->collector->flush();
}
- public function testDecrement()
+ public function testDecrement(): void
{
- $gaugeMock = $this->getMockBuilder('\\Prometheus\\Gauge')
+ $gaugeMock = $this->getMockBuilder(Gauge::class)
->disableOriginalConstructor()
->getMock()
;
$gaugeMock
->expects($this->once())
->method('dec')
- ->with(array())
+ ->with([])
;
$this->collectorRegistryMock
@@ -174,11 +168,11 @@ public function testDecrement()
$this->collector->flush();
}
- public function testDecrementWithTags()
+ public function testDecrementWithTags(): void
{
- $expectedTagsValues = array('value1', 'value2');
+ $expectedTagsValues = ['value1', 'value2'];
- $gaugeMock = $this->getMockBuilder('\\Prometheus\\Gauge')
+ $gaugeMock = $this->getMockBuilder(Gauge::class)
->disableOriginalConstructor()
->getMock()
;
@@ -195,27 +189,24 @@ public function testDecrementWithTags()
->willReturn($gaugeMock)
;
- $this->collector->setTags(array(
- 'tag1' => 'value1',
- 'tag2' => 'value2',
- ));
+ $this->collector->setTags(['tag1' => 'value1', 'tag2' => 'value2']);
$this->collector->decrement(self::TEST_VARIABLE_NAME);
$this->collector->flush();
}
- public function testTiming()
+ public function testTiming(): void
{
$expectedVariableValue = 123;
- $gaugeMock = $this->getMockBuilder('\\Prometheus\\Gauge')
+ $gaugeMock = $this->getMockBuilder(Gauge::class)
->disableOriginalConstructor()
->getMock()
;
$gaugeMock
->expects($this->once())
->method('set')
- ->with($expectedVariableValue, array())
+ ->with($expectedVariableValue, [])
;
$this->collectorRegistryMock
@@ -229,12 +220,12 @@ public function testTiming()
$this->collector->flush();
}
- public function testTimingWithTags()
+ public function testTimingWithTags(): void
{
$expectedVariableValue = 123;
- $expectedTagsValues = array('value1', 'value2');
+ $expectedTagsValues = ['value1', 'value2'];
- $gaugeMock = $this->getMockBuilder('\\Prometheus\\Gauge')
+ $gaugeMock = $this->getMockBuilder(Gauge::class)
->disableOriginalConstructor()
->getMock()
;
@@ -251,22 +242,19 @@ public function testTimingWithTags()
->willReturn($gaugeMock)
;
- $this->collector->setTags(array(
- 'tag1' => 'value1',
- 'tag2' => 'value2',
- ));
+ $this->collector->setTags(['tag1' => 'value1', 'tag2' => 'value2']);
$this->collector->timing(self::TEST_VARIABLE_NAME, $expectedVariableValue);
$this->collector->flush();
}
- public function testMeasureWhenSetNewVariableWithTags()
+ public function testMeasureWhenSetNewVariableWithTags(): void
{
$expectedVariableValue = 123;
- $expectedTagsNames = array('tag1', 'tag2');
- $expectedTagsValues = array('value1', 'value2');
+ $expectedTagsNames = ['tag1', 'tag2'];
+ $expectedTagsValues = ['value1', 'value2'];
- $gaugeMock = $this->getMockBuilder('\\Prometheus\\Gauge')
+ $gaugeMock = $this->getMockBuilder(Gauge::class)
->disableOriginalConstructor()
->getMock()
;
@@ -289,10 +277,7 @@ public function testMeasureWhenSetNewVariableWithTags()
->willReturn($gaugeMock)
;
- $this->collector->setTags(array(
- 'tag1' => 'value1',
- 'tag2' => 'value2',
- ));
+ $this->collector->setTags(['tag1' => 'value1', 'tag2' => 'value2']);
$this->collector->measure(self::TEST_VARIABLE_NAME, $expectedVariableValue);
$this->collector->flush();
@@ -301,24 +286,24 @@ public function testMeasureWhenSetNewVariableWithTags()
/**
* Method flush must to reset value of field `data`.
*/
- public function testFlushWhenCallsTwiceWithDifferentData()
+ public function testFlushWhenCallsTwiceWithDifferentData(): void
{
$firstExpectedVariableValue = 123;
$secondExpectedVariableValue = 321;
- $gaugeMock = $this->getMockBuilder('\\Prometheus\\Gauge')
+ $gaugeMock = $this->getMockBuilder(Gauge::class)
->disableOriginalConstructor()
->getMock()
;
$gaugeMock
->expects($this->at(0))
->method('set')
- ->with($firstExpectedVariableValue, array())
+ ->with($firstExpectedVariableValue, [])
;
$gaugeMock
->expects($this->at(1))
->method('set')
- ->with($secondExpectedVariableValue, array())
+ ->with($secondExpectedVariableValue, [])
;
$this->collectorRegistryMock
diff --git a/tests/Metrics/FactoryTest.php b/tests/Metrics/FactoryTest.php
index 4fa931c..a1581a4 100644
--- a/tests/Metrics/FactoryTest.php
+++ b/tests/Metrics/FactoryTest.php
@@ -2,78 +2,56 @@
namespace Beberlei\Metrics\Tests;
+use Beberlei\Metrics\Collector\StatsD;
+use Beberlei\Metrics\Collector\DogStatsD;
+use Beberlei\Metrics\Collector\Graphite;
+use Beberlei\Metrics\Collector\Librato;
+use Beberlei\Metrics\Collector\DoctrineDBAL;
+use Doctrine\DBAL\Connection;
+use Beberlei\Metrics\Collector\Logger;
+use Beberlei\Metrics\Collector\NullCollector;
+use Beberlei\Metrics\Collector\InlineTaggableGaugeableNullCollector;
+use Beberlei\Metrics\Collector\InfluxDB;
+use InfluxDB\Client;
+use Beberlei\Metrics\Collector\Prometheus;
+use Prometheus\CollectorRegistry;
+use Beberlei\Metrics\MetricsException;
use Beberlei\Metrics\Factory;
use PHPUnit\Framework\TestCase;
use Psr\Log\NullLogger;
class FactoryTest extends TestCase
{
- public function getCreateValidMetricTests()
+ public function getCreateValidMetricTests(): array
{
- return array(
- array('Beberlei\Metrics\Collector\StatsD', 'statsd'),
- array('Beberlei\Metrics\Collector\StatsD', 'statsd', array('host' => 'localhost', 'port' => 1234, 'prefix' => 'prefix')),
- array('Beberlei\Metrics\Collector\StatsD', 'statsd', array('host' => 'localhost', 'port' => 1234)),
- array('Beberlei\Metrics\Collector\StatsD', 'statsd', array('host' => 'localhost')),
- array('Beberlei\Metrics\Collector\DogStatsD', 'dogstatsd'),
- array('Beberlei\Metrics\Collector\DogStatsD', 'dogstatsd', array('host' => 'localhost', 'port' => 1234, 'prefix' => 'prefix')),
- array('Beberlei\Metrics\Collector\DogStatsD', 'dogstatsd', array('host' => 'localhost', 'port' => 1234)),
- array('Beberlei\Metrics\Collector\DogStatsD', 'dogstatsd', array('host' => 'localhost')),
- array('Beberlei\Metrics\Collector\Graphite', 'graphite'),
- array('Beberlei\Metrics\Collector\Graphite', 'graphite', array('host' => 'localhost', 'port' => 1234)),
- array('Beberlei\Metrics\Collector\Librato', 'librato', array('hostname' => 'foobar.com', 'username' => 'username', 'password' => 'password')),
- array('Beberlei\Metrics\Collector\DoctrineDBAL', 'doctrine_dbal', array('connection' => $this->getMockBuilder('Doctrine\DBAL\Connection')->disableOriginalConstructor()->getMock())),
- array('Beberlei\Metrics\Collector\Logger', 'logger', array('logger' => new NullLogger())),
- array('Beberlei\Metrics\Collector\NullCollector', 'null'),
- array('Beberlei\Metrics\Collector\InlineTaggableGaugeableNullCollector', 'null_inlinetaggable'),
- array('Beberlei\Metrics\Collector\InfluxDB', 'influxdb', array('client' => $this->getMockBuilder('\\InfluxDB\\Client')->disableOriginalConstructor()->getMock())),
- array('Beberlei\Metrics\Collector\Prometheus', 'prometheus', array('collector_registry' => $this->getMockBuilder('\\Prometheus\\CollectorRegistry')->disableOriginalConstructor()->getMock())),
- array('Beberlei\Metrics\Collector\Prometheus', 'prometheus', array('collector_registry' => $this->getMockBuilder('\\Prometheus\\CollectorRegistry')->disableOriginalConstructor()->getMock(), 'namespace' => 'some_namespace')),
- );
+ return [[StatsD::class, 'statsd'], [StatsD::class, 'statsd', ['host' => 'localhost', 'port' => 1234, 'prefix' => 'prefix']], [StatsD::class, 'statsd', ['host' => 'localhost', 'port' => 1234]], [StatsD::class, 'statsd', ['host' => 'localhost']], [DogStatsD::class, 'dogstatsd'], [DogStatsD::class, 'dogstatsd', ['host' => 'localhost', 'port' => 1234, 'prefix' => 'prefix']], [DogStatsD::class, 'dogstatsd', ['host' => 'localhost', 'port' => 1234]], [DogStatsD::class, 'dogstatsd', ['host' => 'localhost']], [Graphite::class, 'graphite'], [Graphite::class, 'graphite', ['host' => 'localhost', 'port' => 1234]], [Librato::class, 'librato', ['hostname' => 'foobar.com', 'username' => 'username', 'password' => 'password']], [DoctrineDBAL::class, 'doctrine_dbal', ['connection' => $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock()]], [Logger::class, 'logger', ['logger' => new NullLogger()]], [NullCollector::class, 'null'], [InlineTaggableGaugeableNullCollector::class, 'null_inlinetaggable'], [InfluxDB::class, 'influxdb', ['client' => $this->getMockBuilder(Client::class)->disableOriginalConstructor()->getMock()]], [Prometheus::class, 'prometheus', ['collector_registry' => $this->getMockBuilder(CollectorRegistry::class)->disableOriginalConstructor()->getMock()]], [Prometheus::class, 'prometheus', ['collector_registry' => $this->getMockBuilder(CollectorRegistry::class)->disableOriginalConstructor()->getMock(), 'namespace' => 'some_namespace']]];
}
/**
* @dataProvider getCreateValidMetricTests
*/
- public function testCreateValidMetric($expectedClass, $type, $options = array())
+ public function testCreateValidMetric(string $expectedClass, string $type, array $options = []): void
{
$this->assertInstanceOf($expectedClass, Factory::create($type, $options));
}
- public function getCreateThrowExceptionIfOptionsAreInvalidTests()
+ public function getCreateThrowExceptionIfOptionsAreInvalidTests(): array
{
- return array(
- array('You should specified a host if you specified a port.', 'statsd', array('port' => '1234')),
- array('You should specified a host and a port if you specified a prefix.', 'statsd', array('prefix' => 'prefix')),
- array('You should specified a host and a port if you specified a prefix.', 'statsd', array('port' => '1234', 'prefix' => 'prefix')),
- array('You should specified a host and a port if you specified a prefix.', 'statsd', array('hostname' => 'foobar.com', 'prefix' => 'prefix')),
- array('You should specified a host if you specified a port.', 'dogstatsd', array('port' => '1234')),
- array('You should specified a host and a port if you specified a prefix.', 'dogstatsd', array('prefix' => 'prefix')),
- array('You should specified a host and a port if you specified a prefix.', 'dogstatsd', array('port' => '1234', 'prefix' => 'prefix')),
- array('You should specified a host and a port if you specified a prefix.', 'dogstatsd', array('hostname' => 'foobar.com', 'prefix' => 'prefix')),
- array('You should specified a host if you specified a port.', 'graphite', array('port' => '1234')),
- array('Hostname is required for librato collector.', 'librato'),
- array('No username given for librato collector.', 'librato', array('hostname' => 'foobar.com')),
- array('No password given for librato collector.', 'librato', array('hostname' => 'foobar.com', 'username' => 'username')),
- array('connection is required for Doctrine DBAL collector.', 'doctrine_dbal'),
- array('Missing \'logger\' key with logger service.', 'logger'),
- array('Missing \'client\' key for InfluxDB collector.', 'influxdb'),
- array('Missing \'collector_registry\' key for Prometheus collector.', 'prometheus'),
- );
+ return [['You should specified a host if you specified a port.', 'statsd', ['port' => '1234']], ['You should specified a host and a port if you specified a prefix.', 'statsd', ['prefix' => 'prefix']], ['You should specified a host and a port if you specified a prefix.', 'statsd', ['port' => '1234', 'prefix' => 'prefix']], ['You should specified a host and a port if you specified a prefix.', 'statsd', ['hostname' => 'foobar.com', 'prefix' => 'prefix']], ['You should specified a host if you specified a port.', 'dogstatsd', ['port' => '1234']], ['You should specified a host and a port if you specified a prefix.', 'dogstatsd', ['prefix' => 'prefix']], ['You should specified a host and a port if you specified a prefix.', 'dogstatsd', ['port' => '1234', 'prefix' => 'prefix']], ['You should specified a host and a port if you specified a prefix.', 'dogstatsd', ['hostname' => 'foobar.com', 'prefix' => 'prefix']], ['You should specified a host if you specified a port.', 'graphite', ['port' => '1234']], ['Hostname is required for librato collector.', 'librato'], ['No username given for librato collector.', 'librato', ['hostname' => 'foobar.com']], ['No password given for librato collector.', 'librato', ['hostname' => 'foobar.com', 'username' => 'username']], ['connection is required for Doctrine DBAL collector.', 'doctrine_dbal'], ["Missing 'logger' key with logger service.", 'logger'], ["Missing 'client' key for InfluxDB collector.", 'influxdb'], ["Missing 'collector_registry' key for Prometheus collector.", 'prometheus']];
}
/**
* @dataProvider getCreateThrowExceptionIfOptionsAreInvalidTests
*/
- public function testCreateThrowExceptionIfOptionsAreInvalid($expectedMessage, $type, $options = array())
+ public function testCreateThrowExceptionIfOptionsAreInvalid(string $expectedMessage, string $type, array $options = []): void
{
try {
Factory::create($type, $options);
$this->fail('An expected exception (MetricsException) has not been raised.');
- } catch (\Exception $e) {
- $this->assertInstanceOf('Beberlei\Metrics\MetricsException', $e);
- $this->assertSame($expectedMessage, $e->getMessage());
+ } catch (\Exception $exception) {
+ $this->assertInstanceOf(MetricsException::class, $exception);
+ $this->assertSame($expectedMessage, $exception->getMessage());
}
}
}
diff --git a/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php b/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
index a301784..c739b54 100644
--- a/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
+++ b/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
@@ -13,6 +13,19 @@
namespace Beberlei\Bundle\MetricsBundle\Tests\DependencyInjection;
+use Beberlei\Metrics\Collector\Graphite;
+use Beberlei\Metrics\Collector\Librato;
+use Beberlei\Metrics\Collector\Logger;
+use Beberlei\Metrics\Collector\NullCollector;
+use Beberlei\Metrics\Collector\StatsD;
+use Beberlei\Metrics\Collector\DogStatsD;
+use Beberlei\Metrics\Collector\Telegraf;
+use InfluxDB\Client;
+use Beberlei\Metrics\Collector\InfluxDB;
+use Prometheus\CollectorRegistry;
+use Beberlei\Metrics\Collector\Prometheus;
+use Beberlei\Metrics\Collector\InMemory;
+use Psr\Log\NullLogger;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
@@ -20,34 +33,18 @@
class BeberleiMetricsExtensionTest extends TestCase
{
- public function testWithGraphite()
+ public function testWithGraphite(): void
{
- $container = $this->createContainer(array(
- 'default' => 'simple',
- 'collectors' => array(
- 'simple' => array(
- 'type' => 'graphite',
- ),
- 'full' => array(
- 'type' => 'graphite',
- 'host' => 'graphite.localhost',
- 'port' => 1234,
- 'protocol' => 'udp',
- ),
- ),
- ), array(
- 'beberlei_metrics.collector.simple',
- 'beberlei_metrics.collector.full'
- ));
+ $container = $this->createContainer(['default' => 'simple', 'collectors' => ['simple' => ['type' => 'graphite'], 'full' => ['type' => 'graphite', 'host' => 'graphite.localhost', 'port' => 1234, 'protocol' => 'udp']]], ['beberlei_metrics.collector.simple', 'beberlei_metrics.collector.full']);
$collector = $container->get('beberlei_metrics.collector.simple');
- $this->assertInstanceOf('Beberlei\Metrics\Collector\Graphite', $collector);
+ $this->assertInstanceOf(Graphite::class, $collector);
$this->assertSame('tcp', $this->getProperty($collector, 'protocol'));
$this->assertSame('localhost', $this->getProperty($collector, 'host'));
$this->assertSame(2003, $this->getProperty($collector, 'port'));
$collector = $container->get('beberlei_metrics.collector.full');
- $this->assertInstanceOf('Beberlei\Metrics\Collector\Graphite', $collector);
+ $this->assertInstanceOf(Graphite::class, $collector);
$this->assertSame('udp', $this->getProperty($collector, 'protocol'));
$this->assertSame('graphite.localhost', $this->getProperty($collector, 'host'));
$this->assertSame(1234, $this->getProperty($collector, 'port'));
@@ -57,165 +54,86 @@ public function testWithGraphite()
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
* The source has to be specified to use a Librato
*/
- public function testWithLibratoAndInvalidConfiguration()
+ public function testWithLibratoAndInvalidConfiguration(): void
{
- $container = $this->createContainer(array(
- 'collectors' => array(
- 'simple' => array(
- 'type' => 'librato',
- ),
- ),
- ), array('beberlei_metrics.collector.librato'));
-
- $this->assertInstanceOf('Beberlei\Metrics\Collector\Librato', $container->get('beberlei_metrics.collector.librato'));
+ $container = $this->createContainer(['collectors' => ['simple' => ['type' => 'librato']]], ['beberlei_metrics.collector.librato']);
+
+ $this->assertInstanceOf(Librato::class, $container->get('beberlei_metrics.collector.librato'));
}
- public function testWithLibrato()
+ public function testWithLibrato(): void
{
- $container = $this->createContainer(array(
- 'collectors' => array(
- 'full' => array(
- 'type' => 'librato',
- 'source' => 'foo.beberlei.de',
- 'username' => 'foo',
- 'password' => 'bar',
- ),
- ),
- ), array('beberlei_metrics.collector.full'));
+ $container = $this->createContainer(['collectors' => ['full' => ['type' => 'librato', 'source' => 'foo.beberlei.de', 'username' => 'foo', 'password' => 'bar']]], ['beberlei_metrics.collector.full']);
$collector = $container->get('beberlei_metrics.collector.full');
- $this->assertInstanceOf('Beberlei\Metrics\Collector\Librato', $collector);
+ $this->assertInstanceOf(Librato::class, $collector);
$this->assertSame('foo.beberlei.de', $this->getProperty($collector, 'source'));
$this->assertSame('foo', $this->getProperty($collector, 'username'));
$this->assertSame('bar', $this->getProperty($collector, 'password'));
}
- public function testWithLogger()
+ public function testWithLogger(): void
{
- $container = $this->createContainer(array(
- 'collectors' => array(
- 'logger' => array(
- 'type' => 'logger',
- ),
- ),
- ), array('beberlei_metrics.collector.logger'));
-
- $this->assertInstanceOf('Beberlei\Metrics\Collector\Logger', $container->get('beberlei_metrics.collector.logger'));
+ $container = $this->createContainer(['collectors' => ['logger' => ['type' => 'logger']]], ['beberlei_metrics.collector.logger']);
+
+ $this->assertInstanceOf(Logger::class, $container->get('beberlei_metrics.collector.logger'));
}
- public function testWithNullCollector()
+ public function testWithNullCollector(): void
{
- $container = $this->createContainer(array(
- 'collectors' => array(
- 'null' => array(
- 'type' => 'null',
- ),
- ),
- ), array('beberlei_metrics.collector.null'));
-
- $this->assertInstanceOf('Beberlei\Metrics\Collector\NullCollector', $container->get('beberlei_metrics.collector.null'));
+ $container = $this->createContainer(['collectors' => ['null' => ['type' => 'null']]], ['beberlei_metrics.collector.null']);
+
+ $this->assertInstanceOf(NullCollector::class, $container->get('beberlei_metrics.collector.null'));
}
- public function testWithStatsD()
+ public function testWithStatsD(): void
{
- $container = $this->createContainer(array(
- 'default' => 'simple',
- 'collectors' => array(
- 'simple' => array(
- 'type' => 'statsd',
- ),
- 'full' => array(
- 'type' => 'statsd',
- 'host' => 'statsd.localhost',
- 'port' => 1234,
- 'prefix' => 'application.com.symfony.',
- ),
- ),
- ), array(
- 'beberlei_metrics.collector.simple',
- 'beberlei_metrics.collector.full'
- ));
+ $container = $this->createContainer(['default' => 'simple', 'collectors' => ['simple' => ['type' => 'statsd'], 'full' => ['type' => 'statsd', 'host' => 'statsd.localhost', 'port' => 1234, 'prefix' => 'application.com.symfony.']]], ['beberlei_metrics.collector.simple', 'beberlei_metrics.collector.full']);
$collector = $container->get('beberlei_metrics.collector.simple');
- $this->assertInstanceOf('Beberlei\Metrics\Collector\StatsD', $collector);
+ $this->assertInstanceOf(StatsD::class, $collector);
$this->assertSame('localhost', $this->getProperty($collector, 'host'));
$this->assertSame(8125, $this->getProperty($collector, 'port'));
$this->assertSame('', $this->getProperty($collector, 'prefix'));
$collector = $container->get('beberlei_metrics.collector.full');
- $this->assertInstanceOf('Beberlei\Metrics\Collector\StatsD', $collector);
+ $this->assertInstanceOf(StatsD::class, $collector);
$this->assertSame('statsd.localhost', $this->getProperty($collector, 'host'));
$this->assertSame(1234, $this->getProperty($collector, 'port'));
$this->assertSame('application.com.symfony.', $this->getProperty($collector, 'prefix'));
}
- public function testWithDogStatsD()
+ public function testWithDogStatsD(): void
{
- $container = $this->createContainer(array(
- 'default' => 'simple',
- 'collectors' => array(
- 'simple' => array(
- 'type' => 'dogstatsd',
- ),
- 'full' => array(
- 'type' => 'dogstatsd',
- 'host' => 'dogstatsd.localhost',
- 'port' => 1234,
- 'prefix' => 'application.com.symfony.',
- ),
- ),
- ), array(
- 'beberlei_metrics.collector.simple',
- 'beberlei_metrics.collector.full'
- ));
+ $container = $this->createContainer(['default' => 'simple', 'collectors' => ['simple' => ['type' => 'dogstatsd'], 'full' => ['type' => 'dogstatsd', 'host' => 'dogstatsd.localhost', 'port' => 1234, 'prefix' => 'application.com.symfony.']]], ['beberlei_metrics.collector.simple', 'beberlei_metrics.collector.full']);
$collector = $container->get('beberlei_metrics.collector.simple');
- $this->assertInstanceOf('Beberlei\Metrics\Collector\DogStatsD', $collector);
+ $this->assertInstanceOf(DogStatsD::class, $collector);
$this->assertSame('localhost', $this->getProperty($collector, 'host'));
$this->assertSame(8125, $this->getProperty($collector, 'port'));
$this->assertSame('', $this->getProperty($collector, 'prefix'));
$collector = $container->get('beberlei_metrics.collector.full');
- $this->assertInstanceOf('Beberlei\Metrics\Collector\DogStatsD', $collector);
+ $this->assertInstanceOf(DogStatsD::class, $collector);
$this->assertSame('dogstatsd.localhost', $this->getProperty($collector, 'host'));
$this->assertSame(1234, $this->getProperty($collector, 'port'));
$this->assertSame('application.com.symfony.', $this->getProperty($collector, 'prefix'));
}
- public function testWithTelegraf()
+ public function testWithTelegraf(): void
{
- $expectedTags = array(
- 'string_tag' => 'first_value',
- 'int_tag' => 123,
- );
-
- $container = $this->createContainer(array(
- 'default' => 'simple',
- 'collectors' => array(
- 'simple' => array(
- 'type' => 'telegraf',
- ),
- 'full' => array(
- 'type' => 'telegraf',
- 'host' => 'telegraf.localhost',
- 'port' => 1234,
- 'prefix' => 'application.com.symfony.',
- 'tags' => $expectedTags,
- ),
- ),
- ), array(
- 'beberlei_metrics.collector.simple',
- 'beberlei_metrics.collector.full'
- ));
+ $expectedTags = ['string_tag' => 'first_value', 'int_tag' => 123];
+
+ $container = $this->createContainer(['default' => 'simple', 'collectors' => ['simple' => ['type' => 'telegraf'], 'full' => ['type' => 'telegraf', 'host' => 'telegraf.localhost', 'port' => 1234, 'prefix' => 'application.com.symfony.', 'tags' => $expectedTags]]], ['beberlei_metrics.collector.simple', 'beberlei_metrics.collector.full']);
$collector = $container->get('beberlei_metrics.collector.simple');
- $this->assertInstanceOf('Beberlei\Metrics\Collector\Telegraf', $collector);
+ $this->assertInstanceOf(Telegraf::class, $collector);
$this->assertSame('localhost', $this->getProperty($collector, 'host'));
$this->assertSame(8125, $this->getProperty($collector, 'port'));
$this->assertSame('', $this->getProperty($collector, 'prefix'));
$collector = $container->get('beberlei_metrics.collector.full');
- $this->assertInstanceOf('Beberlei\Metrics\Collector\Telegraf', $collector);
+ $this->assertInstanceOf(Telegraf::class, $collector);
$this->assertSame('telegraf.localhost', $this->getProperty($collector, 'host'));
$this->assertSame(1234, $this->getProperty($collector, 'port'));
$this->assertSame('application.com.symfony.', $this->getProperty($collector, 'prefix'));
@@ -223,148 +141,88 @@ public function testWithTelegraf()
$this->assertEquals(',string_tag=first_value,int_tag=123', $this->getProperty($collector, 'tags'));
}
- public function testWithInfluxDB()
+ public function testWithInfluxDB(): void
{
- $influxDBClientMock = $this->getMockBuilder('InfluxDB\Client')
+ $influxDBClientMock = $this->getMockBuilder(Client::class)
->disableOriginalConstructor()
->getMock()
;
- $container = $this->createContainer(array(
- 'collectors' => array(
- 'influxdb' => array(
- 'type' => 'influxdb',
- 'influxdb_client' => 'influxdb_client_mock',
- ),
- ),
- ), array('beberlei_metrics.collector.influxdb'), array(
- 'influxdb_client_mock' => $influxDBClientMock,
- ));
+ $container = $this->createContainer(['collectors' => ['influxdb' => ['type' => 'influxdb', 'influxdb_client' => 'influxdb_client_mock']]], ['beberlei_metrics.collector.influxdb'], ['influxdb_client_mock' => $influxDBClientMock]);
$collector = $container->get('beberlei_metrics.collector.influxdb');
- $this->assertInstanceOf('Beberlei\Metrics\Collector\InfluxDB', $collector);
+ $this->assertInstanceOf(InfluxDB::class, $collector);
$this->assertSame($influxDBClientMock, $this->getProperty($collector, 'client'));
}
- public function testWithInfluxDBAndWithTags()
+ public function testWithInfluxDBAndWithTags(): void
{
- $expectedTags = array(
- 'string_tag' => 'first_value',
- 'int_tag' => 123,
- );
+ $expectedTags = ['string_tag' => 'first_value', 'int_tag' => 123];
- $influxDBClientMock = $this->getMockBuilder('InfluxDB\Client')
+ $influxDBClientMock = $this->getMockBuilder(Client::class)
->disableOriginalConstructor()
->getMock()
;
- $container = $this->createContainer(array(
- 'collectors' => array(
- 'influxdb' => array(
- 'type' => 'influxdb',
- 'influxdb_client' => 'influxdb_client_mock',
- 'tags' => $expectedTags,
- ),
- ),
- ), array('beberlei_metrics.collector.influxdb'), array(
- 'influxdb_client_mock' => $influxDBClientMock,
- ));
+ $container = $this->createContainer(['collectors' => ['influxdb' => ['type' => 'influxdb', 'influxdb_client' => 'influxdb_client_mock', 'tags' => $expectedTags]]], ['beberlei_metrics.collector.influxdb'], ['influxdb_client_mock' => $influxDBClientMock]);
$collector = $container->get('beberlei_metrics.collector.influxdb');
- $this->assertInstanceOf('Beberlei\Metrics\Collector\InfluxDB', $collector);
+ $this->assertInstanceOf(InfluxDB::class, $collector);
$this->assertEquals($expectedTags, $this->getProperty($collector, 'tags'));
}
- public function testWithPrometheus()
+ public function testWithPrometheus(): void
{
- $prometheusCollectorRegistryMock = $this->getMockBuilder('\\Prometheus\\CollectorRegistry')
+ $prometheusCollectorRegistryMock = $this->getMockBuilder(CollectorRegistry::class)
->disableOriginalConstructor()
->getMock()
;
- $container = $this->createContainer(array(
- 'collectors' => array(
- 'prometheus' => array(
- 'type' => 'prometheus',
- 'prometheus_collector_registry' => 'prometheus_collector_registry_mock',
- ),
- ),
- ), array('beberlei_metrics.collector.prometheus'), array(
- 'prometheus_collector_registry_mock' => $prometheusCollectorRegistryMock,
- ));
+ $container = $this->createContainer(['collectors' => ['prometheus' => ['type' => 'prometheus', 'prometheus_collector_registry' => 'prometheus_collector_registry_mock']]], ['beberlei_metrics.collector.prometheus'], ['prometheus_collector_registry_mock' => $prometheusCollectorRegistryMock]);
$collector = $container->get('beberlei_metrics.collector.prometheus');
- $this->assertInstanceOf('Beberlei\Metrics\Collector\Prometheus', $collector);
+ $this->assertInstanceOf(Prometheus::class, $collector);
$this->assertSame($prometheusCollectorRegistryMock, $this->getProperty($collector, 'collectorRegistry'));
$this->assertSame('', $this->getProperty($collector, 'namespace'));
}
- public function testWithInMemory()
+ public function testWithInMemory(): void
{
- $container = $this->createContainer(array(
- 'collectors' => array(
- 'memory' => array(
- 'type' => 'memory',
- ),
- ),
- ), array('beberlei_metrics.collector.memory'));
+ $container = $this->createContainer(['collectors' => ['memory' => ['type' => 'memory']]], ['beberlei_metrics.collector.memory']);
$collector = $container->get('beberlei_metrics.collector.memory');
- $this->assertInstanceOf('Beberlei\Metrics\Collector\InMemory', $collector);
+ $this->assertInstanceOf(InMemory::class, $collector);
}
- public function testWithPrometheusAndWithNamespace()
+ public function testWithPrometheusAndWithNamespace(): void
{
$expectedNamespace = 'some_namespace';
- $prometheusCollectorRegistryMock = $this->getMockBuilder('\\Prometheus\\CollectorRegistry')
+ $prometheusCollectorRegistryMock = $this->getMockBuilder(CollectorRegistry::class)
->disableOriginalConstructor()
->getMock()
;
- $container = $this->createContainer(array(
- 'collectors' => array(
- 'prometheus' => array(
- 'type' => 'prometheus',
- 'prometheus_collector_registry' => 'prometheus_collector_registry_mock',
- 'namespace' => $expectedNamespace,
- ),
- ),
- ), array('beberlei_metrics.collector.prometheus'), array(
- 'prometheus_collector_registry_mock' => $prometheusCollectorRegistryMock,
- ));
+ $container = $this->createContainer(['collectors' => ['prometheus' => ['type' => 'prometheus', 'prometheus_collector_registry' => 'prometheus_collector_registry_mock', 'namespace' => $expectedNamespace]]], ['beberlei_metrics.collector.prometheus'], ['prometheus_collector_registry_mock' => $prometheusCollectorRegistryMock]);
$collector = $container->get('beberlei_metrics.collector.prometheus');
- $this->assertInstanceOf('Beberlei\Metrics\Collector\Prometheus', $collector);
+ $this->assertInstanceOf(Prometheus::class, $collector);
$this->assertSame($prometheusCollectorRegistryMock, $this->getProperty($collector, 'collectorRegistry'));
$this->assertSame($expectedNamespace, $this->getProperty($collector, 'namespace'));
}
- public function testWithPrometheusAndWithTags()
+ public function testWithPrometheusAndWithTags(): void
{
- $expectedTags = array(
- 'string_tag' => 'first_value',
- 'int_tag' => 123,
- );
+ $expectedTags = ['string_tag' => 'first_value', 'int_tag' => 123];
- $prometheusCollectorRegistryMock = $this->getMockBuilder('\\Prometheus\\CollectorRegistry')
+ $prometheusCollectorRegistryMock = $this->getMockBuilder(CollectorRegistry::class)
->disableOriginalConstructor()
->getMock()
;
- $container = $this->createContainer(array(
- 'collectors' => array(
- 'prometheus' => array(
- 'type' => 'prometheus',
- 'prometheus_collector_registry' => 'prometheus_collector_registry_mock',
- 'tags' => $expectedTags,
- ),
- ),
- ), array('beberlei_metrics.collector.prometheus'), array(
- 'prometheus_collector_registry_mock' => $prometheusCollectorRegistryMock,
- ));
+ $container = $this->createContainer(['collectors' => ['prometheus' => ['type' => 'prometheus', 'prometheus_collector_registry' => 'prometheus_collector_registry_mock', 'tags' => $expectedTags]]], ['beberlei_metrics.collector.prometheus'], ['prometheus_collector_registry_mock' => $prometheusCollectorRegistryMock]);
$collector = $container->get('beberlei_metrics.collector.prometheus');
- $this->assertInstanceOf('Beberlei\Metrics\Collector\Prometheus', $collector);
+ $this->assertInstanceOf(Prometheus::class, $collector);
$this->assertEquals($expectedTags, $this->getProperty($collector, 'tags'));
}
@@ -372,25 +230,19 @@ public function testWithPrometheusAndWithTags()
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
* @expectedExceptionMessage The prometheus_collector_registry has to be specified to use a Prometheus
*/
- public function testValidationWhenTypeIsPrometheusAndPrometheusCollectorRegistryIsNotSpecified()
+ public function testValidationWhenTypeIsPrometheusAndPrometheusCollectorRegistryIsNotSpecified(): void
{
- $this->createContainer(array(
- 'collectors' => array(
- 'prometheus' => array(
- 'type' => 'prometheus',
- ),
- ),
- ));
+ $this->createContainer(['collectors' => ['prometheus' => ['type' => 'prometheus']]]);
}
- private function createContainer($configs, $publicServices = array(), $additionalServices = array())
+ private function createContainer($configs, array $publicServices = [], array $additionalServices = []): ContainerBuilder
{
$container = new ContainerBuilder();
$extension = new BeberleiMetricsExtension();
- $extension->load(array($configs), $container);
+ $extension->load([$configs], $container);
// Needed for logger collector
- $container->setDefinition('logger', new Definition('Psr\Log\NullLogger'));
+ $container->setDefinition('logger', new Definition(NullLogger::class));
foreach ($additionalServices as $serviceId => $additionalService) {
$container->set($serviceId, $additionalService);
@@ -405,9 +257,9 @@ private function createContainer($configs, $publicServices = array(), $additiona
return $container;
}
- private function getProperty($object, $property)
+ private function getProperty(?object $object, string $property)
{
- $reflectionProperty = new \ReflectionProperty(get_class($object), $property);
+ $reflectionProperty = new \ReflectionProperty($object::class, $property);
$reflectionProperty->setAccessible(true);
return $reflectionProperty->getValue($object);
From 871a1faf839baa1dddceb2bb7dbdba4033e4834b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 19:42:33 +0100
Subject: [PATCH 12/32] chore: add php-cs-fixer
---
.php-cs-fixer.php | 30 +
example/statsd.php | 4 +-
src/Metrics/Collector/CollectorInterface.php | 2 +-
src/Metrics/Collector/DoctrineDBAL.php | 3 +-
src/Metrics/Collector/DogStatsD.php | 10 +-
src/Metrics/Collector/Graphite.php | 9 +-
src/Metrics/Collector/InMemory.php | 1 -
src/Metrics/Collector/Logger.php | 4 +-
src/Metrics/Collector/Prometheus.php | 2 +-
src/Metrics/Collector/StatsD.php | 8 +-
src/Metrics/Collector/Telegraf.php | 10 +-
src/Metrics/Factory.php | 13 +-
.../BeberleiMetricsExtension.php | 15 +-
.../DependencyInjection/Configuration.php | 8 +-
tests/Metrics/Collector/InMemoryTest.php | 6 +-
tests/Metrics/Collector/InfluxDBTest.php | 23 +-
tests/Metrics/Collector/PrometheusTest.php | 4 +-
tests/Metrics/FactoryTest.php | 16 +-
.../BeberleiMetricsExtensionTest.php | 15 +-
tools/php-cs-fixer/.gitignore | 1 +
tools/php-cs-fixer/composer.json | 5 +
tools/php-cs-fixer/composer.lock | 1823 +++++++++++++++++
22 files changed, 1936 insertions(+), 76 deletions(-)
create mode 100644 .php-cs-fixer.php
create mode 100644 tools/php-cs-fixer/.gitignore
create mode 100644 tools/php-cs-fixer/composer.json
create mode 100644 tools/php-cs-fixer/composer.lock
diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php
new file mode 100644
index 0000000..312ddf8
--- /dev/null
+++ b/.php-cs-fixer.php
@@ -0,0 +1,30 @@
+ignoreVCSIgnored(true)
+ ->in(__DIR__)
+ ->append([
+ __FILE__,
+ ])
+;
+
+return (new PhpCsFixer\Config())
+ ->setRiskyAllowed(true)
+ ->setRules([
+ '@PHP81Migration' => true,
+ '@PhpCsFixer' => true,
+ '@Symfony' => true,
+ '@Symfony:risky' => true,
+ 'heredoc_indentation' => false,
+ 'single_line_empty_body' => false,
+ 'ordered_types' => false, // From @PhpCsFixer but we don't want it
+ 'php_unit_internal_class' => false, // From @PhpCsFixer but we don't want it
+ 'php_unit_test_class_requires_covers' => false, // From @PhpCsFixer but we don't want it
+ 'phpdoc_add_missing_param_annotation' => false, // From @PhpCsFixer but we don't want it
+ 'concat_space' => ['spacing' => 'one'],
+ 'ordered_class_elements' => true, // Symfony(PSR12) override the default value, but we don't want
+ 'blank_line_before_statement' => true, // Symfony(PSR12) override the default value, but we don't want
+ 'method_chaining_indentation' => false, // Do not work well with Tree builder
+ ])
+ ->setFinder($finder)
+;
diff --git a/example/statsd.php b/example/statsd.php
index 2fb3b68..8ce6cc5 100644
--- a/example/statsd.php
+++ b/example/statsd.php
@@ -1,8 +1,8 @@
increment('foo.bar');
diff --git a/src/Metrics/Collector/CollectorInterface.php b/src/Metrics/Collector/CollectorInterface.php
index 5431a87..0844c26 100644
--- a/src/Metrics/Collector/CollectorInterface.php
+++ b/src/Metrics/Collector/CollectorInterface.php
@@ -33,7 +33,7 @@ public function decrement(string $variable, array $tags = []): void;
/**
* Records a timing.
*
- * @param int $time The duration of the timing in milliseconds
+ * @param int $time The duration of the timing in milliseconds
*/
public function timing(string $variable, int $time, array $tags = []): void;
diff --git a/src/Metrics/Collector/DoctrineDBAL.php b/src/Metrics/Collector/DoctrineDBAL.php
index caf1b47..875072b 100644
--- a/src/Metrics/Collector/DoctrineDBAL.php
+++ b/src/Metrics/Collector/DoctrineDBAL.php
@@ -14,7 +14,6 @@
namespace Beberlei\Metrics\Collector;
use Doctrine\DBAL\Connection;
-use Exception;
/**
* Sends statistics to a relational database.
@@ -77,7 +76,7 @@ public function flush(): void
}
$this->conn->commit();
- } catch (Exception) {
+ } catch (\Exception) {
$this->conn->rollback();
}
diff --git a/src/Metrics/Collector/DogStatsD.php b/src/Metrics/Collector/DogStatsD.php
index 9fdbbdd..bfc167d 100644
--- a/src/Metrics/Collector/DogStatsD.php
+++ b/src/Metrics/Collector/DogStatsD.php
@@ -31,12 +31,12 @@ public function measure(string $variable, int $value, array $tags = []): void
public function increment(string $variable, array $tags = []): void
{
- $this->data[] = $variable.':1|c'.$this->buildTagString($tags);
+ $this->data[] = $variable . ':1|c' . $this->buildTagString($tags);
}
public function decrement(string $variable, array $tags = []): void
{
- $this->data[] = $variable.':-1|c'.$this->buildTagString($tags);
+ $this->data[] = $variable . ':-1|c' . $this->buildTagString($tags);
}
public function timing(string $variable, int $time, array $tags = []): void
@@ -55,7 +55,7 @@ public function flush(): void
return;
}
- $fp = fsockopen('udp://'.$this->host, $this->port, $errno, $errstr, 1.0);
+ $fp = fsockopen('udp://' . $this->host, $this->port, $errno, $errstr, 1.0);
if (!$fp) {
return;
@@ -63,7 +63,7 @@ public function flush(): void
$level = error_reporting(0);
foreach ($this->data as $line) {
- fwrite($fp, $this->prefix.$line);
+ fwrite($fp, $this->prefix . $line);
}
error_reporting($level);
@@ -87,7 +87,7 @@ private function buildTagString(array $tags): string
$tagString = implode(',', $results);
- if (strlen($tagString)) {
+ if (\strlen($tagString)) {
$tagString = sprintf('|#%s', $tagString);
}
diff --git a/src/Metrics/Collector/Graphite.php b/src/Metrics/Collector/Graphite.php
index bdd9b4a..1bc7711 100644
--- a/src/Metrics/Collector/Graphite.php
+++ b/src/Metrics/Collector/Graphite.php
@@ -13,8 +13,6 @@
namespace Beberlei\Metrics\Collector;
-use Exception;
-
/**
* Sends statistics to the stats daemon over UDP or TCP.
*/
@@ -34,7 +32,6 @@ public function measure(string $variable, int $value, array $tags = []): void
$this->push($variable, $value);
}
-
public function increment(string $variable, array $tags = []): void
{
$this->push($variable, 1);
@@ -57,7 +54,7 @@ public function flush(): void
}
try {
- $fp = fsockopen($this->protocol.'://'.$this->host, $this->port);
+ $fp = fsockopen($this->protocol . '://' . $this->host, $this->port);
if (!$fp) {
return;
@@ -68,7 +65,7 @@ public function flush(): void
}
fclose($fp);
- } catch (Exception) {
+ } catch (\Exception) {
}
$this->data = [];
@@ -77,7 +74,7 @@ public function flush(): void
public function push(string $variable, int|float $value, ?int $time = null): void
{
$this->data[] = sprintf(
- is_float($value) ? "%s %.18f %d\n" : "%s %d %d\n",
+ \is_float($value) ? "%s %.18f %d\n" : "%s %d %d\n",
$variable,
$value,
$time ?: time()
diff --git a/src/Metrics/Collector/InMemory.php b/src/Metrics/Collector/InMemory.php
index bae39f3..3b63564 100644
--- a/src/Metrics/Collector/InMemory.php
+++ b/src/Metrics/Collector/InMemory.php
@@ -65,7 +65,6 @@ public function flush(): void
$this->incrementData = [];
}
-
public function getMeasure(string $variable): int
{
return $this->incrementData[$variable] ?? 0;
diff --git a/src/Metrics/Collector/Logger.php b/src/Metrics/Collector/Logger.php
index 0a294d8..04593be 100644
--- a/src/Metrics/Collector/Logger.php
+++ b/src/Metrics/Collector/Logger.php
@@ -29,12 +29,12 @@ public function measure(string $variable, int $value, array $tags = []): void
public function increment(string $variable, array $tags = []): void
{
- $this->logger->debug('increment:'.$variable);
+ $this->logger->debug('increment:' . $variable);
}
public function decrement(string $variable, array $tags = []): void
{
- $this->logger->debug('decrement:'.$variable);
+ $this->logger->debug('decrement:' . $variable);
}
public function timing(string $variable, int $time, array $tags = []): void
diff --git a/src/Metrics/Collector/Prometheus.php b/src/Metrics/Collector/Prometheus.php
index 6945adf..4c18439 100644
--- a/src/Metrics/Collector/Prometheus.php
+++ b/src/Metrics/Collector/Prometheus.php
@@ -13,9 +13,9 @@
namespace Beberlei\Metrics\Collector;
-use Prometheus\Gauge;
use Prometheus\CollectorRegistry;
use Prometheus\Exception\MetricNotFoundException;
+use Prometheus\Gauge;
class Prometheus implements CollectorInterface, TaggableCollectorInterface
{
diff --git a/src/Metrics/Collector/StatsD.php b/src/Metrics/Collector/StatsD.php
index 4ae2fc8..5fc901f 100644
--- a/src/Metrics/Collector/StatsD.php
+++ b/src/Metrics/Collector/StatsD.php
@@ -34,12 +34,12 @@ public function timing(string $variable, int $time, array $tags = []): void
public function increment(string $variable, array $tags = []): void
{
- $this->data[] = $variable.':1|c';
+ $this->data[] = $variable . ':1|c';
}
public function decrement(string $variable, array $tags = []): void
{
- $this->data[] = $variable.':-1|c';
+ $this->data[] = $variable . ':-1|c';
}
public function measure(string $variable, int $value, array $tags = []): void
@@ -58,7 +58,7 @@ public function flush(): void
return;
}
- $fp = fsockopen('udp://'.$this->host, $this->port, $errno, $errstr, 1.0);
+ $fp = fsockopen('udp://' . $this->host, $this->port, $errno, $errstr, 1.0);
if (!$fp) {
return;
@@ -66,7 +66,7 @@ public function flush(): void
$level = error_reporting(0);
foreach ($this->data as $line) {
- fwrite($fp, $this->prefix.$line);
+ fwrite($fp, $this->prefix . $line);
}
error_reporting($level);
diff --git a/src/Metrics/Collector/Telegraf.php b/src/Metrics/Collector/Telegraf.php
index 01be2bc..ab3cdde 100644
--- a/src/Metrics/Collector/Telegraf.php
+++ b/src/Metrics/Collector/Telegraf.php
@@ -37,12 +37,12 @@ public function measure(string $variable, int $value, array $tags = []): void
public function increment(string $variable, array $tags = []): void
{
- $this->data[] = $variable.$this->tags.':1|c';
+ $this->data[] = $variable . $this->tags . ':1|c';
}
public function decrement(string $variable, array $tags = []): void
{
- $this->data[] = $variable.$this->tags.':-1|c';
+ $this->data[] = $variable . $this->tags . ':-1|c';
}
public function timing(string $variable, int $time, array $tags = []): void
@@ -66,7 +66,7 @@ public function flush(): void
return;
}
- $fp = fsockopen('udp://'.$this->host, $this->port, $errno, $errstr, 1.0);
+ $fp = fsockopen('udp://' . $this->host, $this->port, $errno, $errstr, 1.0);
if (!$fp) {
return;
@@ -74,7 +74,7 @@ public function flush(): void
$level = error_reporting(0);
foreach ($this->data as $line) {
- fwrite($fp, $this->prefix.$line);
+ fwrite($fp, $this->prefix . $line);
}
error_reporting($level);
@@ -87,6 +87,6 @@ public function flush(): void
public function setTags(array $tags): void
{
$this->tags = http_build_query($tags, '', ',');
- $this->tags = strlen($this->tags) > 0 ? ','.$this->tags : $this->tags;
+ $this->tags = \strlen($this->tags) > 0 ? ',' . $this->tags : $this->tags;
}
}
diff --git a/src/Metrics/Factory.php b/src/Metrics/Factory.php
index 3d2a012..ac83675 100644
--- a/src/Metrics/Factory.php
+++ b/src/Metrics/Factory.php
@@ -13,17 +13,17 @@
namespace Beberlei\Metrics;
-use Beberlei\Metrics\Collector\StatsD;
+use Beberlei\Metrics\Collector\DoctrineDBAL;
use Beberlei\Metrics\Collector\DogStatsD;
-use Beberlei\Metrics\Collector\Telegraf;
use Beberlei\Metrics\Collector\Graphite;
+use Beberlei\Metrics\Collector\InfluxDB;
+use Beberlei\Metrics\Collector\InlineTaggableGaugeableNullCollector;
use Beberlei\Metrics\Collector\Librato;
-use Beberlei\Metrics\Collector\DoctrineDBAL;
use Beberlei\Metrics\Collector\Logger;
-use Beberlei\Metrics\Collector\InfluxDB;
use Beberlei\Metrics\Collector\NullCollector;
-use Beberlei\Metrics\Collector\InlineTaggableGaugeableNullCollector;
use Beberlei\Metrics\Collector\Prometheus;
+use Beberlei\Metrics\Collector\StatsD;
+use Beberlei\Metrics\Collector\Telegraf;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Contracts\HttpClient\HttpClientInterface;
@@ -39,8 +39,9 @@ abstract class Factory
*
* @param string $type
*
- * @throws MetricsException
* @return Collector\Collector
+ *
+ * @throws MetricsException
*/
public static function create($type, array $options = [])
{
diff --git a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
index 5d8c51f..63cd6d4 100644
--- a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
+++ b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
@@ -6,7 +6,6 @@
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
@@ -18,33 +17,33 @@ public function load(array $configs, ContainerBuilder $container): void
$configuration = $this->getConfiguration($configs, $container);
$config = $this->processConfiguration($configuration, $configs);
- $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
+ $loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
$loader->load('metrics.xml');
foreach ($config['collectors'] as $name => $colConfig) {
$definition = $this->createCollector($colConfig['type'], $colConfig);
- $container->setDefinition('beberlei_metrics.collector.'.$name, $definition);
+ $container->setDefinition('beberlei_metrics.collector.' . $name, $definition);
}
- if ($config['default'] && $container->hasDefinition('beberlei_metrics.collector.'.$config['default'])) {
+ if ($config['default'] && $container->hasDefinition('beberlei_metrics.collector.' . $config['default'])) {
$name = $config['default'];
- } elseif (1 !== count($config['collectors'])) {
+ } elseif (1 !== \count($config['collectors'])) {
throw new \LogicException('You should select a default collector');
}
- $container->setAlias('beberlei_metrics.collector', 'beberlei_metrics.collector.'.$name);
+ $container->setAlias('beberlei_metrics.collector', 'beberlei_metrics.collector.' . $name);
$container->setAlias(Collector::class, 'beberlei_metrics.collector');
}
private function createCollector($type, array $config)
{
- $definition = new ChildDefinition('beberlei_metrics.collector_proto.'.$config['type']);
+ $definition = new ChildDefinition('beberlei_metrics.collector_proto.' . $config['type']);
// Theses listeners should be as late as possible
$definition->addTag('kernel.event_listener', ['method' => 'flush', 'priority' => -1024, 'event' => 'kernel.terminate']);
$definition->addTag('kernel.event_listener', ['method' => 'flush', 'priority' => -1024, 'event' => 'console.terminate']);
- if (count($config['tags']) > 0) {
+ if (\count($config['tags']) > 0) {
$definition->addMethodCall('setTags', [$config['tags']]);
}
diff --git a/src/MetricsBundle/DependencyInjection/Configuration.php b/src/MetricsBundle/DependencyInjection/Configuration.php
index 4eb62cd..dba61d0 100644
--- a/src/MetricsBundle/DependencyInjection/Configuration.php
+++ b/src/MetricsBundle/DependencyInjection/Configuration.php
@@ -50,19 +50,19 @@ public function getConfigTreeBuilder(): TreeBuilder
->end()
->end()
->validate()
- ->ifTrue(static fn($v): bool => 'librato' === $v['type'] && empty($v['source']))
+ ->ifTrue(static fn ($v): bool => 'librato' === $v['type'] && empty($v['source']))
->thenInvalid('The source has to be specified to use a Librato')
->end()
->validate()
- ->ifTrue(static fn($v): bool => 'librato' === $v['type'] && empty($v['username']))
+ ->ifTrue(static fn ($v): bool => 'librato' === $v['type'] && empty($v['username']))
->thenInvalid('The username has to be specified to use a Librato')
->end()
->validate()
- ->ifTrue(static fn($v): bool => 'librato' === $v['type'] && empty($v['password']))
+ ->ifTrue(static fn ($v): bool => 'librato' === $v['type'] && empty($v['password']))
->thenInvalid('The password has to be specified to use a Librato')
->end()
->validate()
- ->ifTrue(static fn($v): bool => 'prometheus' === $v['type'] && empty($v['prometheus_collector_registry']))
+ ->ifTrue(static fn ($v): bool => 'prometheus' === $v['type'] && empty($v['prometheus_collector_registry']))
->thenInvalid('The prometheus_collector_registry has to be specified to use a Prometheus')
->end()
->end()
diff --git a/tests/Metrics/Collector/InMemoryTest.php b/tests/Metrics/Collector/InMemoryTest.php
index 259b8b0..8a04290 100644
--- a/tests/Metrics/Collector/InMemoryTest.php
+++ b/tests/Metrics/Collector/InMemoryTest.php
@@ -99,9 +99,9 @@ public function testIncrementingGauge(): void
public function testSettingGaugeToNegativeValue(): void
{
- $this->collector->gauge(self::VARIABLE_A, 1); //sets to 1
- $this->collector->gauge(self::VARIABLE_A, 2); //sets to 2
- $this->collector->gauge(self::VARIABLE_A, -5); //decreases by 5
+ $this->collector->gauge(self::VARIABLE_A, 1); // sets to 1
+ $this->collector->gauge(self::VARIABLE_A, 2); // sets to 2
+ $this->collector->gauge(self::VARIABLE_A, -5); // decreases by 5
$this->assertEquals(-3, $this->collector->getGauge(self::VARIABLE_A));
$this->collector->gauge(self::VARIABLE_A, 0);
diff --git a/tests/Metrics/Collector/InfluxDBTest.php b/tests/Metrics/Collector/InfluxDBTest.php
index f976324..b05a6ab 100644
--- a/tests/Metrics/Collector/InfluxDBTest.php
+++ b/tests/Metrics/Collector/InfluxDBTest.php
@@ -13,15 +13,14 @@
namespace Beberlei\Metrics\Tests\Collector;
+use Beberlei\Metrics\Collector\InfluxDB;
use InfluxDB\Client;
use PHPUnit\Framework\TestCase;
-use PHPUnit_Framework_MockObject_MockObject;
-use Beberlei\Metrics\Collector\InfluxDB;
class InfluxDBTest extends TestCase
{
/**
- * @var PHPUnit_Framework_MockObject_MockObject
+ * @var \PHPUnit_Framework_MockObject_MockObject
*/
private $client;
@@ -31,7 +30,8 @@ protected function setUp(): void
{
$this->client = $this->getMockBuilder(Client::class)
->disableOriginalConstructor()
- ->getMock();
+ ->getMock()
+ ;
$this->collector = new InfluxDB($this->client);
}
@@ -41,7 +41,8 @@ public function testCollectIncrement(): void
$this->client->expects($this->once())
->method('mark')
- ->with($expectedArgs);
+ ->with($expectedArgs)
+ ;
$this->collector->increment('series-name');
$this->collector->flush();
@@ -53,7 +54,8 @@ public function testCollectDecrement(): void
$this->client->expects($this->once())
->method('mark')
- ->with($expectedArgs);
+ ->with($expectedArgs)
+ ;
$this->collector->decrement('series-name');
$this->collector->flush();
@@ -65,7 +67,8 @@ public function testCollectTiming(): void
$this->client->expects($this->once())
->method('mark')
- ->with($expectedArgs);
+ ->with($expectedArgs)
+ ;
$this->collector->timing('series-name', 47.11);
$this->collector->flush();
@@ -77,7 +80,8 @@ public function testCollectMeasure(): void
$this->client->expects($this->once())
->method('mark')
- ->with($expectedArgs);
+ ->with($expectedArgs)
+ ;
$this->collector->measure('series-name', 47.11);
$this->collector->flush();
@@ -91,7 +95,8 @@ public function testCollectMeasureWithTags(): void
$this->client->expects($this->once())
->method('mark')
- ->with($expectedArgs);
+ ->with($expectedArgs)
+ ;
$this->collector->setTags($expectedTags);
$this->collector->measure('series-name', 47.11);
diff --git a/tests/Metrics/Collector/PrometheusTest.php b/tests/Metrics/Collector/PrometheusTest.php
index 895c258..8fd13e8 100644
--- a/tests/Metrics/Collector/PrometheusTest.php
+++ b/tests/Metrics/Collector/PrometheusTest.php
@@ -13,11 +13,11 @@
namespace Beberlei\Metrics\Tests\Collector;
-use Prometheus\CollectorRegistry;
-use Prometheus\Gauge;
use Beberlei\Metrics\Collector\Prometheus;
use PHPUnit\Framework\TestCase;
+use Prometheus\CollectorRegistry;
use Prometheus\Exception\MetricNotFoundException;
+use Prometheus\Gauge;
class PrometheusTest extends TestCase
{
diff --git a/tests/Metrics/FactoryTest.php b/tests/Metrics/FactoryTest.php
index a1581a4..8eb27b4 100644
--- a/tests/Metrics/FactoryTest.php
+++ b/tests/Metrics/FactoryTest.php
@@ -2,22 +2,22 @@
namespace Beberlei\Metrics\Tests;
-use Beberlei\Metrics\Collector\StatsD;
+use Beberlei\Metrics\Collector\DoctrineDBAL;
use Beberlei\Metrics\Collector\DogStatsD;
use Beberlei\Metrics\Collector\Graphite;
+use Beberlei\Metrics\Collector\InfluxDB;
+use Beberlei\Metrics\Collector\InlineTaggableGaugeableNullCollector;
use Beberlei\Metrics\Collector\Librato;
-use Beberlei\Metrics\Collector\DoctrineDBAL;
-use Doctrine\DBAL\Connection;
use Beberlei\Metrics\Collector\Logger;
use Beberlei\Metrics\Collector\NullCollector;
-use Beberlei\Metrics\Collector\InlineTaggableGaugeableNullCollector;
-use Beberlei\Metrics\Collector\InfluxDB;
-use InfluxDB\Client;
use Beberlei\Metrics\Collector\Prometheus;
-use Prometheus\CollectorRegistry;
-use Beberlei\Metrics\MetricsException;
+use Beberlei\Metrics\Collector\StatsD;
use Beberlei\Metrics\Factory;
+use Beberlei\Metrics\MetricsException;
+use Doctrine\DBAL\Connection;
+use InfluxDB\Client;
use PHPUnit\Framework\TestCase;
+use Prometheus\CollectorRegistry;
use Psr\Log\NullLogger;
class FactoryTest extends TestCase
diff --git a/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php b/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
index c739b54..05e2bc8 100644
--- a/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
+++ b/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
@@ -13,23 +13,23 @@
namespace Beberlei\Bundle\MetricsBundle\Tests\DependencyInjection;
+use Beberlei\Bundle\MetricsBundle\DependencyInjection\BeberleiMetricsExtension;
+use Beberlei\Metrics\Collector\DogStatsD;
use Beberlei\Metrics\Collector\Graphite;
+use Beberlei\Metrics\Collector\InfluxDB;
+use Beberlei\Metrics\Collector\InMemory;
use Beberlei\Metrics\Collector\Librato;
use Beberlei\Metrics\Collector\Logger;
use Beberlei\Metrics\Collector\NullCollector;
+use Beberlei\Metrics\Collector\Prometheus;
use Beberlei\Metrics\Collector\StatsD;
-use Beberlei\Metrics\Collector\DogStatsD;
use Beberlei\Metrics\Collector\Telegraf;
use InfluxDB\Client;
-use Beberlei\Metrics\Collector\InfluxDB;
+use PHPUnit\Framework\TestCase;
use Prometheus\CollectorRegistry;
-use Beberlei\Metrics\Collector\Prometheus;
-use Beberlei\Metrics\Collector\InMemory;
use Psr\Log\NullLogger;
-use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
-use Beberlei\Bundle\MetricsBundle\DependencyInjection\BeberleiMetricsExtension;
class BeberleiMetricsExtensionTest extends TestCase
{
@@ -228,6 +228,7 @@ public function testWithPrometheusAndWithTags(): void
/**
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
+ *
* @expectedExceptionMessage The prometheus_collector_registry has to be specified to use a Prometheus
*/
public function testValidationWhenTypeIsPrometheusAndPrometheusCollectorRegistryIsNotSpecified(): void
@@ -248,7 +249,7 @@ private function createContainer($configs, array $publicServices = [], array $ad
$container->set($serviceId, $additionalService);
}
- foreach($publicServices as $serviceId) {
+ foreach ($publicServices as $serviceId) {
$container->getDefinition($serviceId)->setPublic(true);
}
diff --git a/tools/php-cs-fixer/.gitignore b/tools/php-cs-fixer/.gitignore
new file mode 100644
index 0000000..57872d0
--- /dev/null
+++ b/tools/php-cs-fixer/.gitignore
@@ -0,0 +1 @@
+/vendor/
diff --git a/tools/php-cs-fixer/composer.json b/tools/php-cs-fixer/composer.json
new file mode 100644
index 0000000..b0ac7ff
--- /dev/null
+++ b/tools/php-cs-fixer/composer.json
@@ -0,0 +1,5 @@
+{
+ "require": {
+ "friendsofphp/php-cs-fixer": "^3.46"
+ }
+}
diff --git a/tools/php-cs-fixer/composer.lock b/tools/php-cs-fixer/composer.lock
new file mode 100644
index 0000000..811d41a
--- /dev/null
+++ b/tools/php-cs-fixer/composer.lock
@@ -0,0 +1,1823 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+ "This file is @generated automatically"
+ ],
+ "content-hash": "df2cc2d63945b734c8edd007837e47ad",
+ "packages": [
+ {
+ "name": "composer/pcre",
+ "version": "3.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/pcre.git",
+ "reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/pcre/zipball/00104306927c7a0919b4ced2aaa6782c1e61a3c9",
+ "reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.3",
+ "phpstan/phpstan-strict-rules": "^1.1",
+ "symfony/phpunit-bridge": "^5"
+ },
+ "type": "library",
+ "extra": {
+ "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.1.1"
+ },
+ "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": "2023-10-11T07:11:09+00:00"
+ },
+ {
+ "name": "composer/semver",
+ "version": "3.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/semver.git",
+ "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32",
+ "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3.2 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.4",
+ "symfony/phpunit-bridge": "^4.2 || ^5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\Semver\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nils Adermann",
+ "email": "naderman@naderman.de",
+ "homepage": "http://www.naderman.de"
+ },
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ },
+ {
+ "name": "Rob Bast",
+ "email": "rob.bast@gmail.com",
+ "homepage": "http://robbast.nl"
+ }
+ ],
+ "description": "Semver library that offers utilities, version constraint parsing and validation.",
+ "keywords": [
+ "semantic",
+ "semver",
+ "validation",
+ "versioning"
+ ],
+ "support": {
+ "irc": "ircs://irc.libera.chat:6697/composer",
+ "issues": "https://github.com/composer/semver/issues",
+ "source": "https://github.com/composer/semver/tree/3.4.0"
+ },
+ "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": "2023-08-31T09:50:34+00:00"
+ },
+ {
+ "name": "composer/xdebug-handler",
+ "version": "3.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/xdebug-handler.git",
+ "reference": "ced299686f41dce890debac69273b47ffe98a40c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c",
+ "reference": "ced299686f41dce890debac69273b47ffe98a40c",
+ "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",
+ "symfony/phpunit-bridge": "^6.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Composer\\XdebugHandler\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "John Stevenson",
+ "email": "john-stevenson@blueyonder.co.uk"
+ }
+ ],
+ "description": "Restarts a process without Xdebug.",
+ "keywords": [
+ "Xdebug",
+ "performance"
+ ],
+ "support": {
+ "irc": "irc://irc.freenode.org/composer",
+ "issues": "https://github.com/composer/xdebug-handler/issues",
+ "source": "https://github.com/composer/xdebug-handler/tree/3.0.3"
+ },
+ "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": "2022-02-25T21:32:43+00:00"
+ },
+ {
+ "name": "friendsofphp/php-cs-fixer",
+ "version": "v3.49.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
+ "reference": "8742f7aa6f72a399688b65e4f58992c2d4681fc2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/8742f7aa6f72a399688b65e4f58992c2d4681fc2",
+ "reference": "8742f7aa6f72a399688b65e4f58992c2d4681fc2",
+ "shasum": ""
+ },
+ "require": {
+ "composer/semver": "^3.4",
+ "composer/xdebug-handler": "^3.0.3",
+ "ext-filter": "*",
+ "ext-json": "*",
+ "ext-tokenizer": "*",
+ "php": "^7.4 || ^8.0",
+ "sebastian/diff": "^4.0 || ^5.0",
+ "symfony/console": "^5.4 || ^6.0 || ^7.0",
+ "symfony/event-dispatcher": "^5.4 || ^6.0 || ^7.0",
+ "symfony/filesystem": "^5.4 || ^6.0 || ^7.0",
+ "symfony/finder": "^5.4 || ^6.0 || ^7.0",
+ "symfony/options-resolver": "^5.4 || ^6.0 || ^7.0",
+ "symfony/polyfill-mbstring": "^1.28",
+ "symfony/polyfill-php80": "^1.28",
+ "symfony/polyfill-php81": "^1.28",
+ "symfony/process": "^5.4 || ^6.0 || ^7.0",
+ "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0"
+ },
+ "require-dev": {
+ "facile-it/paraunit": "^1.3 || ^2.0",
+ "justinrainbow/json-schema": "^5.2",
+ "keradus/cli-executor": "^2.1",
+ "mikey179/vfsstream": "^1.6.11",
+ "php-coveralls/php-coveralls": "^2.7",
+ "php-cs-fixer/accessible-object": "^1.1",
+ "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.4",
+ "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.4",
+ "phpunit/phpunit": "^9.6 || ^10.5.5",
+ "symfony/yaml": "^5.4 || ^6.0 || ^7.0"
+ },
+ "suggest": {
+ "ext-dom": "For handling output formats in XML",
+ "ext-mbstring": "For handling non-UTF8 characters."
+ },
+ "bin": [
+ "php-cs-fixer"
+ ],
+ "type": "application",
+ "autoload": {
+ "psr-4": {
+ "PhpCsFixer\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Dariusz Rumiński",
+ "email": "dariusz.ruminski@gmail.com"
+ }
+ ],
+ "description": "A tool to automatically fix PHP code style",
+ "keywords": [
+ "Static code analysis",
+ "fixer",
+ "standards",
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
+ "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.49.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/keradus",
+ "type": "github"
+ }
+ ],
+ "time": "2024-02-02T00:41:40+00:00"
+ },
+ {
+ "name": "psr/container",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
+ "keywords": [
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
+ ],
+ "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": "psr/event-dispatcher",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/event-dispatcher.git",
+ "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0",
+ "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\EventDispatcher\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Standard interfaces for event handling.",
+ "keywords": [
+ "events",
+ "psr",
+ "psr-14"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/event-dispatcher/issues",
+ "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0"
+ },
+ "time": "2019-01-08T18:20:26+00:00"
+ },
+ {
+ "name": "psr/log",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
+ "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/log/tree/3.0.0"
+ },
+ "time": "2021-07-14T16:46:02+00:00"
+ },
+ {
+ "name": "sebastian/diff",
+ "version": "5.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/diff.git",
+ "reference": "fbf413a49e54f6b9b17e12d900ac7f6101591b7f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/fbf413a49e54f6b9b17e12d900ac7f6101591b7f",
+ "reference": "fbf413a49e54f6b9b17e12d900ac7f6101591b7f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0",
+ "symfony/process": "^4.2 || ^5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Kore Nordmann",
+ "email": "mail@kore-nordmann.de"
+ }
+ ],
+ "description": "Diff implementation",
+ "homepage": "https://github.com/sebastianbergmann/diff",
+ "keywords": [
+ "diff",
+ "udiff",
+ "unidiff",
+ "unified diff"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/diff/issues",
+ "security": "https://github.com/sebastianbergmann/diff/security/policy",
+ "source": "https://github.com/sebastianbergmann/diff/tree/5.1.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-12-22T10:55:06+00:00"
+ },
+ {
+ "name": "symfony/console",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/console.git",
+ "reference": "c5010d50f1ee4b25cfa0201d9915cf1b14071456"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/console/zipball/c5010d50f1ee4b25cfa0201d9915cf1b14071456",
+ "reference": "c5010d50f1ee4b25cfa0201d9915cf1b14071456",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/string": "^6.4|^7.0"
+ },
+ "conflict": {
+ "symfony/dependency-injection": "<6.4",
+ "symfony/dotenv": "<6.4",
+ "symfony/event-dispatcher": "<6.4",
+ "symfony/lock": "<6.4",
+ "symfony/process": "<6.4"
+ },
+ "provide": {
+ "psr/log-implementation": "1.0|2.0|3.0"
+ },
+ "require-dev": {
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/event-dispatcher": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/lock": "^6.4|^7.0",
+ "symfony/messenger": "^6.4|^7.0",
+ "symfony/process": "^6.4|^7.0",
+ "symfony/stopwatch": "^6.4|^7.0",
+ "symfony/var-dumper": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Console\\": ""
+ },
+ "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": "Eases the creation of beautiful and testable command line interfaces",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "cli",
+ "command-line",
+ "console",
+ "terminal"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/console/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/deprecation-contracts",
+ "version": "v3.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/deprecation-contracts.git",
+ "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf",
+ "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "files": [
+ "function.php"
+ ]
+ },
+ "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": "A generic function and convention to trigger deprecation notices",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0"
+ },
+ "funding": [
+ {
+ "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": "2023-05-23T14:45:45+00:00"
+ },
+ {
+ "name": "symfony/event-dispatcher",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/event-dispatcher.git",
+ "reference": "834c28d533dd0636f910909d01b9ff45cc094b5e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/834c28d533dd0636f910909d01b9ff45cc094b5e",
+ "reference": "834c28d533dd0636f910909d01b9ff45cc094b5e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/event-dispatcher-contracts": "^2.5|^3"
+ },
+ "conflict": {
+ "symfony/dependency-injection": "<6.4",
+ "symfony/service-contracts": "<2.5"
+ },
+ "provide": {
+ "psr/event-dispatcher-implementation": "1.0",
+ "symfony/event-dispatcher-implementation": "2.0|3.0"
+ },
+ "require-dev": {
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/error-handler": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/stopwatch": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\EventDispatcher\\": ""
+ },
+ "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 tools that allow your application components to communicate with each other by dispatching events and listening to them",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/event-dispatcher/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/event-dispatcher-contracts",
+ "version": "v3.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/event-dispatcher-contracts.git",
+ "reference": "a76aed96a42d2b521153fb382d418e30d18b59df"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df",
+ "reference": "a76aed96a42d2b521153fb382d418e30d18b59df",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "psr/event-dispatcher": "^1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\EventDispatcher\\": ""
+ }
+ },
+ "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 dispatching event",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.0"
+ },
+ "funding": [
+ {
+ "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": "2023-05-23T14:45:45+00:00"
+ },
+ {
+ "name": "symfony/filesystem",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/filesystem.git",
+ "reference": "2890e3a825bc0c0558526c04499c13f83e1b6b12"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/2890e3a825bc0c0558526c04499c13f83e1b6b12",
+ "reference": "2890e3a825bc0c0558526c04499c13f83e1b6b12",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-mbstring": "~1.8"
+ },
+ "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.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/finder",
+ "version": "v7.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/finder.git",
+ "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/6e5688d69f7cfc4ed4a511e96007e06c2d34ce56",
+ "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "symfony/filesystem": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Finder\\": ""
+ },
+ "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": "Finds files and directories via an intuitive fluent interface",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/finder/tree/v7.0.0"
+ },
+ "funding": [
+ {
+ "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": "2023-10-31T17:59:56+00:00"
+ },
+ {
+ "name": "symfony/options-resolver",
+ "version": "v7.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/options-resolver.git",
+ "reference": "700ff4096e346f54cb628ea650767c8130f1001f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/options-resolver/zipball/700ff4096e346f54cb628ea650767c8130f1001f",
+ "reference": "700ff4096e346f54cb628ea650767c8130f1001f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\OptionsResolver\\": ""
+ },
+ "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 an improved replacement for the array_replace PHP function",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "config",
+ "configuration",
+ "options"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/options-resolver/tree/v7.0.0"
+ },
+ "funding": [
+ {
+ "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": "2023-08-08T10:20:21+00:00"
+ },
+ {
+ "name": "symfony/polyfill-ctype",
+ "version": "v1.29.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-ctype.git",
+ "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ef4d7e442ca910c4764bce785146269b30cb5fc4",
+ "reference": "ef4d7e442ca910c4764bce785146269b30cb5fc4",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "provide": {
+ "ext-ctype": "*"
+ },
+ "suggest": {
+ "ext-ctype": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Ctype\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Gert de Pagter",
+ "email": "BackEndTea@gmail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for ctype functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "ctype",
+ "polyfill",
+ "portable"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.29.0"
+ },
+ "funding": [
+ {
+ "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": "2024-01-29T20:11:03+00:00"
+ },
+ {
+ "name": "symfony/polyfill-intl-grapheme",
+ "version": "v1.29.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
+ "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f",
+ "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "suggest": {
+ "ext-intl": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
+ }
+ },
+ "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": "Symfony polyfill for intl's grapheme_* functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "grapheme",
+ "intl",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0"
+ },
+ "funding": [
+ {
+ "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": "2024-01-29T20:11:03+00:00"
+ },
+ {
+ "name": "symfony/polyfill-intl-normalizer",
+ "version": "v1.29.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
+ "reference": "bc45c394692b948b4d383a08d7753968bed9a83d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d",
+ "reference": "bc45c394692b948b4d383a08d7753968bed9a83d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "suggest": {
+ "ext-intl": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "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": "Symfony polyfill for intl's Normalizer class and related functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "intl",
+ "normalizer",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0"
+ },
+ "funding": [
+ {
+ "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": "2024-01-29T20:11:03+00:00"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.29.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
+ "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "provide": {
+ "ext-mbstring": "*"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ }
+ },
+ "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": "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.29.0"
+ },
+ "funding": [
+ {
+ "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": "2024-01-29T20:11:03+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php80",
+ "version": "v1.29.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php80.git",
+ "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/87b68208d5c1188808dd7839ee1e6c8ec3b02f1b",
+ "reference": "87b68208d5c1188808dd7839ee1e6c8ec3b02f1b",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php80\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ion Bazan",
+ "email": "ion.bazan@gmail.com"
+ },
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.29.0"
+ },
+ "funding": [
+ {
+ "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": "2024-01-29T20:11:03+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php81",
+ "version": "v1.29.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php81.git",
+ "reference": "c565ad1e63f30e7477fc40738343c62b40bc672d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/c565ad1e63f30e7477fc40738343c62b40bc672d",
+ "reference": "c565ad1e63f30e7477fc40738343c62b40bc672d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php81\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "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": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php81/tree/v1.29.0"
+ },
+ "funding": [
+ {
+ "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": "2024-01-29T20:11:03+00:00"
+ },
+ {
+ "name": "symfony/process",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/process.git",
+ "reference": "937a195147e0c27b2759ade834169ed006d0bc74"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/process/zipball/937a195147e0c27b2759ade834169ed006d0bc74",
+ "reference": "937a195147e0c27b2759ade834169ed006d0bc74",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Process\\": ""
+ },
+ "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": "Executes commands in sub-processes",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/process/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/service-contracts",
+ "version": "v3.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/service-contracts.git",
+ "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0",
+ "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "psr/container": "^1.1|^2.0"
+ },
+ "conflict": {
+ "ext-psr": "<1.1|>=2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "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.4.1"
+ },
+ "funding": [
+ {
+ "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": "2023-12-26T14:02:43+00:00"
+ },
+ {
+ "name": "symfony/stopwatch",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/stopwatch.git",
+ "reference": "983900d6fddf2b0cbaacacbbad07610854bd8112"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/stopwatch/zipball/983900d6fddf2b0cbaacacbbad07610854bd8112",
+ "reference": "983900d6fddf2b0cbaacacbbad07610854bd8112",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/service-contracts": "^2.5|^3"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Stopwatch\\": ""
+ },
+ "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 a way to profile code",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/stopwatch/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/string",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/string.git",
+ "reference": "524aac4a280b90a4420d8d6a040718d0586505ac"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/string/zipball/524aac4a280b90a4420d8d6a040718d0586505ac",
+ "reference": "524aac4a280b90a4420d8d6a040718d0586505ac",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-intl-grapheme": "~1.0",
+ "symfony/polyfill-intl-normalizer": "~1.0",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "conflict": {
+ "symfony/translation-contracts": "<2.5"
+ },
+ "require-dev": {
+ "symfony/error-handler": "^6.4|^7.0",
+ "symfony/http-client": "^6.4|^7.0",
+ "symfony/intl": "^6.4|^7.0",
+ "symfony/translation-contracts": "^2.5|^3.0",
+ "symfony/var-exporter": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "Resources/functions.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\String\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "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": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "grapheme",
+ "i18n",
+ "string",
+ "unicode",
+ "utf-8",
+ "utf8"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/string/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-29T15:41:16+00:00"
+ }
+ ],
+ "packages-dev": [],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": [],
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": [],
+ "platform-dev": [],
+ "plugin-api-version": "2.6.0"
+}
From ef3c16c63d1b1267ec6066720e034c7e75deedf9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 19:52:05 +0100
Subject: [PATCH 13/32] chore: add phpstan
---
phpstan-baseline.neon | 11 +++
phpstan.neon | 14 ++++
src/Metrics/Factory.php | 15 +---
.../BeberleiMetricsExtension.php | 7 +-
.../DependencyInjection/Configuration.php | 12 +--
tools/phpstan/.gitignore | 1 +
tools/phpstan/composer.json | 5 ++
tools/phpstan/composer.lock | 81 +++++++++++++++++++
8 files changed, 120 insertions(+), 26 deletions(-)
create mode 100644 phpstan-baseline.neon
create mode 100644 phpstan.neon
create mode 100644 tools/phpstan/.gitignore
create mode 100644 tools/phpstan/composer.json
create mode 100644 tools/phpstan/composer.lock
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
new file mode 100644
index 0000000..a5dbf7a
--- /dev/null
+++ b/phpstan-baseline.neon
@@ -0,0 +1,11 @@
+parameters:
+ ignoreErrors:
+ -
+ message: "#^Variable \\$name might not be defined\\.$#"
+ count: 1
+ path: src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
+
+ -
+ message: "#^Call to an undefined method Symfony\\\\Component\\\\Config\\\\Definition\\\\Builder\\\\NodeDefinition\\:\\:children\\(\\)\\.$#"
+ count: 1
+ path: src/MetricsBundle/DependencyInjection/Configuration.php
diff --git a/phpstan.neon b/phpstan.neon
new file mode 100644
index 0000000..cdf3e39
--- /dev/null
+++ b/phpstan.neon
@@ -0,0 +1,14 @@
+includes:
+ - phpstan-baseline.neon
+
+parameters:
+ level: 8
+ paths:
+ - src
+ inferPrivatePropertyTypeFromConstructor: true
+ checkGenericClassInNonGenericObjectType: false
+ ignoreErrors:
+ # Issue about array shape
+ - '{Property .* type has no value type specified in iterable type array\.}'
+ - '{Method .* has parameter \$\w+ with no value type specified in iterable type array\.}'
+
diff --git a/src/Metrics/Factory.php b/src/Metrics/Factory.php
index ac83675..81bbf0b 100644
--- a/src/Metrics/Factory.php
+++ b/src/Metrics/Factory.php
@@ -13,6 +13,7 @@
namespace Beberlei\Metrics;
+use Beberlei\Metrics\Collector\CollectorInterface;
use Beberlei\Metrics\Collector\DoctrineDBAL;
use Beberlei\Metrics\Collector\DogStatsD;
use Beberlei\Metrics\Collector\Graphite;
@@ -27,23 +28,14 @@
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Contracts\HttpClient\HttpClientInterface;
-/**
- * Static factory for Metrics Collectors.
- */
abstract class Factory
{
private static HttpClientInterface $httpClient;
/**
- * Create Metrics Collector Instance.
- *
- * @param string $type
- *
- * @return Collector\Collector
- *
* @throws MetricsException
*/
- public static function create($type, array $options = [])
+ public static function create(string $type, array $options = []): CollectorInterface
{
switch ($type) {
case 'statsd':
@@ -163,9 +155,6 @@ public static function create($type, array $options = [])
case 'null':
return new NullCollector();
- case 'null_inlinetaggable':
- return new InlineTaggableGaugeableNullCollector();
-
case 'prometheus':
if (!isset($options['collector_registry'])) {
throw new MetricsException("Missing 'collector_registry' key for Prometheus collector.");
diff --git a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
index 63cd6d4..218ce14 100644
--- a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
+++ b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
@@ -3,6 +3,7 @@
namespace Beberlei\Bundle\MetricsBundle\DependencyInjection;
use Beberlei\Metrics\Collector\Collector;
+use Beberlei\Metrics\Collector\CollectorInterface;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -14,7 +15,7 @@ class BeberleiMetricsExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container): void
{
- $configuration = $this->getConfiguration($configs, $container);
+ $configuration = $this->getConfiguration($configs, $container) ?? throw new \LogicException('Expected configuration to be set');
$config = $this->processConfiguration($configuration, $configs);
$loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
@@ -32,10 +33,10 @@ public function load(array $configs, ContainerBuilder $container): void
}
$container->setAlias('beberlei_metrics.collector', 'beberlei_metrics.collector.' . $name);
- $container->setAlias(Collector::class, 'beberlei_metrics.collector');
+ $container->setAlias(CollectorInterface::class, 'beberlei_metrics.collector');
}
- private function createCollector($type, array $config)
+ private function createCollector(string $type, array $config): ChildDefinition
{
$definition = new ChildDefinition('beberlei_metrics.collector_proto.' . $config['type']);
diff --git a/src/MetricsBundle/DependencyInjection/Configuration.php b/src/MetricsBundle/DependencyInjection/Configuration.php
index dba61d0..079cb25 100644
--- a/src/MetricsBundle/DependencyInjection/Configuration.php
+++ b/src/MetricsBundle/DependencyInjection/Configuration.php
@@ -14,14 +14,8 @@ class Configuration implements ConfigurationInterface
*/
public function getConfigTreeBuilder(): TreeBuilder
{
- $treeBuilder = new TreeBuilder('beberlei_metrics');
- if (method_exists($treeBuilder, 'getRootNode')) {
- $rootNode = $treeBuilder->getRootNode();
- } else {
- $rootNode = $treeBuilder->root('beberlei_metrics');
- }
-
- $rootNode
+ return (new TreeBuilder('beberlei_metrics'))
+ ->getRootNode()
->children()
->scalarNode('default')
->defaultNull()
@@ -69,7 +63,5 @@ public function getConfigTreeBuilder(): TreeBuilder
->end()
->end()
;
-
- return $treeBuilder;
}
}
diff --git a/tools/phpstan/.gitignore b/tools/phpstan/.gitignore
new file mode 100644
index 0000000..57872d0
--- /dev/null
+++ b/tools/phpstan/.gitignore
@@ -0,0 +1 @@
+/vendor/
diff --git a/tools/phpstan/composer.json b/tools/phpstan/composer.json
new file mode 100644
index 0000000..9cb4ed5
--- /dev/null
+++ b/tools/phpstan/composer.json
@@ -0,0 +1,5 @@
+{
+ "require": {
+ "phpstan/phpstan": "^1.10.55"
+ }
+}
diff --git a/tools/phpstan/composer.lock b/tools/phpstan/composer.lock
new file mode 100644
index 0000000..84c7c5f
--- /dev/null
+++ b/tools/phpstan/composer.lock
@@ -0,0 +1,81 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+ "This file is @generated automatically"
+ ],
+ "content-hash": "0df3d24799f35a5d623d94f4e4b6744e",
+ "packages": [
+ {
+ "name": "phpstan/phpstan",
+ "version": "1.10.55",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpstan/phpstan.git",
+ "reference": "9a88f9d18ddf4cf54c922fbeac16c4cb164c5949"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9a88f9d18ddf4cf54c922fbeac16c4cb164c5949",
+ "reference": "9a88f9d18ddf4cf54c922fbeac16c4cb164c5949",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2|^8.0"
+ },
+ "conflict": {
+ "phpstan/phpstan-shim": "*"
+ },
+ "bin": [
+ "phpstan",
+ "phpstan.phar"
+ ],
+ "type": "library",
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "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": [
+ {
+ "url": "https://github.com/ondrejmirtes",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/phpstan",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-01-08T12:32:40+00:00"
+ }
+ ],
+ "packages-dev": [],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": [],
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": [],
+ "platform-dev": [],
+ "plugin-api-version": "2.6.0"
+}
From dcd89cf7374d6579a0a572e3760aa651d8db9f70 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 22:07:54 +0100
Subject: [PATCH 14/32] chore: fixed test
---
src/Metrics/Collector/DogStatsD.php | 2 +-
.../Collector/GaugeableCollectorInterface.php | 2 +-
src/Metrics/Collector/InMemory.php | 20 +++--
src/Metrics/Collector/Logger.php | 2 +-
src/Metrics/Collector/NullCollector.php | 2 +-
src/Metrics/Collector/StatsD.php | 2 +-
src/Metrics/Collector/Telegraf.php | 2 +-
src/Metrics/Factory.php | 1 -
.../BeberleiMetricsExtension.php | 1 -
.../DependencyInjection/Configuration.php | 83 ++++++++++---------
tests/Metrics/Collector/InMemoryTest.php | 6 +-
tests/Metrics/Collector/InfluxDBTest.php | 12 +--
tests/Metrics/Collector/PrometheusTest.php | 20 ++---
tests/Metrics/FactoryTest.php | 40 +++++++--
.../BeberleiMetricsExtensionTest.php | 13 ++-
15 files changed, 121 insertions(+), 87 deletions(-)
diff --git a/src/Metrics/Collector/DogStatsD.php b/src/Metrics/Collector/DogStatsD.php
index bfc167d..7091d5e 100644
--- a/src/Metrics/Collector/DogStatsD.php
+++ b/src/Metrics/Collector/DogStatsD.php
@@ -44,7 +44,7 @@ public function timing(string $variable, int $time, array $tags = []): void
$this->data[] = sprintf('%s:%s|ms%s', $variable, $time, $this->buildTagString($tags));
}
- public function gauge(string $variable, int $value, array $tags = []): void
+ public function gauge(string $variable, string|int $value, array $tags = []): void
{
$this->data[] = sprintf('%s:%s|g%s', $variable, $value, $this->buildTagString($tags));
}
diff --git a/src/Metrics/Collector/GaugeableCollectorInterface.php b/src/Metrics/Collector/GaugeableCollectorInterface.php
index 56938f9..3df4e28 100644
--- a/src/Metrics/Collector/GaugeableCollectorInterface.php
+++ b/src/Metrics/Collector/GaugeableCollectorInterface.php
@@ -18,5 +18,5 @@ interface GaugeableCollectorInterface
/**
* Updates a gauge by an arbitrary amount.
*/
- public function gauge(string $variable, int $value, array $tags = []): void;
+ public function gauge(string $variable, string|int $value, array $tags = []): void;
}
diff --git a/src/Metrics/Collector/InMemory.php b/src/Metrics/Collector/InMemory.php
index 3b63564..c9d1771 100644
--- a/src/Metrics/Collector/InMemory.php
+++ b/src/Metrics/Collector/InMemory.php
@@ -46,16 +46,24 @@ public function decrement(string $variable, array $tags = []): void
public function timing(string $variable, int $time, array $tags = []): void
{
- if (!isset($this->timingData[$variable])) {
- $this->timingData[$variable] = 0;
- }
-
+ $this->timingData[$variable] ??= 0;
$this->timingData[$variable] = $time;
}
- public function gauge(string $variable, int $value, array $tags = []): void
+ public function gauge(string $variable, string|int $value, array $tags = []): void
{
- $this->gaugeData[$variable] = $value;
+ if (\is_int($value)) {
+ $this->gaugeData[$variable] = $value;
+
+ return;
+ }
+
+ $sign = substr($value, 0, 1);
+ if (!\in_array($sign, ['-', '+'], true)) {
+ throw new \InvalidArgumentException('Gauge value must be an integer or a string starting with + or -.');
+ }
+ $this->gaugeData[$variable] ??= 0;
+ $this->gaugeData[$variable] += (int) $value;
}
public function flush(): void
diff --git a/src/Metrics/Collector/Logger.php b/src/Metrics/Collector/Logger.php
index 04593be..64a1159 100644
--- a/src/Metrics/Collector/Logger.php
+++ b/src/Metrics/Collector/Logger.php
@@ -42,7 +42,7 @@ public function timing(string $variable, int $time, array $tags = []): void
$this->logger->debug(sprintf('timing:%s:%s', $variable, $time));
}
- public function gauge(string $variable, int $value, array $tags = []): void
+ public function gauge(string $variable, string|int $value, array $tags = []): void
{
$this->logger->debug(sprintf('gauge:%s:%s', $variable, $value));
}
diff --git a/src/Metrics/Collector/NullCollector.php b/src/Metrics/Collector/NullCollector.php
index 38f05c1..898c010 100644
--- a/src/Metrics/Collector/NullCollector.php
+++ b/src/Metrics/Collector/NullCollector.php
@@ -31,7 +31,7 @@ public function measure(string $variable, int $value, array $tags = []): void
{
}
- public function gauge(string $variable, int $value, array $tags = []): void
+ public function gauge(string $variable, string|int $value, array $tags = []): void
{
}
diff --git a/src/Metrics/Collector/StatsD.php b/src/Metrics/Collector/StatsD.php
index 5fc901f..26898b8 100644
--- a/src/Metrics/Collector/StatsD.php
+++ b/src/Metrics/Collector/StatsD.php
@@ -47,7 +47,7 @@ public function measure(string $variable, int $value, array $tags = []): void
$this->data[] = sprintf('%s:%s|c', $variable, $value);
}
- public function gauge(string $variable, int $value, array $tags = []): void
+ public function gauge(string $variable, string|int $value, array $tags = []): void
{
$this->data[] = sprintf('%s:%s|g', $variable, $value);
}
diff --git a/src/Metrics/Collector/Telegraf.php b/src/Metrics/Collector/Telegraf.php
index ab3cdde..240b18b 100644
--- a/src/Metrics/Collector/Telegraf.php
+++ b/src/Metrics/Collector/Telegraf.php
@@ -50,7 +50,7 @@ public function timing(string $variable, int $time, array $tags = []): void
$this->data[] = sprintf('%s%s:%s|ms', $variable, $this->tags, $time);
}
- public function gauge(string $variable, int $value, array $tags = []): void
+ public function gauge(string $variable, string|int $value, array $tags = []): void
{
$this->data[] = sprintf('%s%s:%s|g', $variable, $this->tags, $value);
}
diff --git a/src/Metrics/Factory.php b/src/Metrics/Factory.php
index 81bbf0b..3016ce3 100644
--- a/src/Metrics/Factory.php
+++ b/src/Metrics/Factory.php
@@ -18,7 +18,6 @@
use Beberlei\Metrics\Collector\DogStatsD;
use Beberlei\Metrics\Collector\Graphite;
use Beberlei\Metrics\Collector\InfluxDB;
-use Beberlei\Metrics\Collector\InlineTaggableGaugeableNullCollector;
use Beberlei\Metrics\Collector\Librato;
use Beberlei\Metrics\Collector\Logger;
use Beberlei\Metrics\Collector\NullCollector;
diff --git a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
index 218ce14..b9a209e 100644
--- a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
+++ b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
@@ -2,7 +2,6 @@
namespace Beberlei\Bundle\MetricsBundle\DependencyInjection;
-use Beberlei\Metrics\Collector\Collector;
use Beberlei\Metrics\Collector\CollectorInterface;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ChildDefinition;
diff --git a/src/MetricsBundle/DependencyInjection/Configuration.php b/src/MetricsBundle/DependencyInjection/Configuration.php
index 079cb25..cbdf163 100644
--- a/src/MetricsBundle/DependencyInjection/Configuration.php
+++ b/src/MetricsBundle/DependencyInjection/Configuration.php
@@ -16,48 +16,49 @@ public function getConfigTreeBuilder(): TreeBuilder
{
return (new TreeBuilder('beberlei_metrics'))
->getRootNode()
- ->children()
- ->scalarNode('default')
- ->defaultNull()
- ->end()
- ->arrayNode('collectors')
- ->isRequired()
- ->useAttributeAsKey('name')
- ->prototype('array')
- ->children()
- ->scalarNode('type')->isRequired()->end()
- ->scalarNode('connection')->defaultNull()->end()
- ->scalarNode('file')->defaultNull()->end()
- ->scalarNode('host')->defaultNull()->end()
- ->scalarNode('password')->defaultNull()->end()
- ->integerNode('port')->defaultNull()->end()
- ->scalarNode('prefix')->defaultNull()->end()
- ->scalarNode('protocol')->defaultNull()->end()
- ->scalarNode('source')->defaultNull()->end()
- ->scalarNode('username')->defaultNull()->end()
- ->scalarNode('influxdb_client')->defaultNull()->end()
- ->scalarNode('prometheus_collector_registry')->defaultNull()->info('It must to contain service id for Prometheus\\CollectorRegistry class instance.')->end()
- ->scalarNode('namespace')->defaultValue('')->end()
- ->arrayNode('tags')
- ->defaultValue([])
- ->prototype('scalar')->end()
+ ->children()
+ ->scalarNode('default')
+ ->defaultNull()
+ ->end()
+ ->arrayNode('collectors')
+ ->isRequired()
+ ->useAttributeAsKey('name')
+ ->prototype('array')
+ ->children()
+ ->scalarNode('type')->isRequired()->end()
+ ->scalarNode('connection')->defaultNull()->end()
+ ->scalarNode('file')->defaultNull()->end()
+ ->scalarNode('host')->defaultNull()->end()
+ ->scalarNode('password')->defaultNull()->end()
+ ->integerNode('port')->defaultNull()->end()
+ ->scalarNode('prefix')->defaultNull()->end()
+ ->scalarNode('protocol')->defaultNull()->end()
+ ->scalarNode('source')->defaultNull()->end()
+ ->scalarNode('username')->defaultNull()->end()
+ ->scalarNode('influxdb_client')->defaultNull()->end()
+ ->scalarNode('prometheus_collector_registry')->defaultNull()->info('It must to contain service id for Prometheus\\CollectorRegistry class instance.')->end()
+ ->scalarNode('namespace')->defaultValue('')->end()
+ ->arrayNode('tags')
+ ->defaultValue([])
+ ->prototype('scalar')->end()
+ ->end()
+ ->end()
+ ->validate()
+ ->ifTrue(static fn ($v): bool => 'librato' === $v['type'] && empty($v['source']))
+ ->thenInvalid('The source has to be specified to use a Librato')
+ ->end()
+ ->validate()
+ ->ifTrue(static fn ($v): bool => 'librato' === $v['type'] && empty($v['username']))
+ ->thenInvalid('The username has to be specified to use a Librato')
+ ->end()
+ ->validate()
+ ->ifTrue(static fn ($v): bool => 'librato' === $v['type'] && empty($v['password']))
+ ->thenInvalid('The password has to be specified to use a Librato')
+ ->end()
+ ->validate()
+ ->ifTrue(static fn ($v): bool => 'prometheus' === $v['type'] && empty($v['prometheus_collector_registry']))
+ ->thenInvalid('The prometheus_collector_registry has to be specified to use a Prometheus')
->end()
- ->end()
- ->validate()
- ->ifTrue(static fn ($v): bool => 'librato' === $v['type'] && empty($v['source']))
- ->thenInvalid('The source has to be specified to use a Librato')
- ->end()
- ->validate()
- ->ifTrue(static fn ($v): bool => 'librato' === $v['type'] && empty($v['username']))
- ->thenInvalid('The username has to be specified to use a Librato')
- ->end()
- ->validate()
- ->ifTrue(static fn ($v): bool => 'librato' === $v['type'] && empty($v['password']))
- ->thenInvalid('The password has to be specified to use a Librato')
- ->end()
- ->validate()
- ->ifTrue(static fn ($v): bool => 'prometheus' === $v['type'] && empty($v['prometheus_collector_registry']))
- ->thenInvalid('The prometheus_collector_registry has to be specified to use a Prometheus')
->end()
->end()
->end()
diff --git a/tests/Metrics/Collector/InMemoryTest.php b/tests/Metrics/Collector/InMemoryTest.php
index 8a04290..d24eb90 100644
--- a/tests/Metrics/Collector/InMemoryTest.php
+++ b/tests/Metrics/Collector/InMemoryTest.php
@@ -90,7 +90,7 @@ public function testSettingGauge(): void
public function testIncrementingGauge(): void
{
- $this->collector->gauge(self::VARIABLE_A, '10');
+ $this->collector->gauge(self::VARIABLE_A, 10);
$this->collector->gauge(self::VARIABLE_A, '+2');
$this->collector->gauge(self::VARIABLE_A, '-3');
@@ -101,11 +101,11 @@ public function testSettingGaugeToNegativeValue(): void
{
$this->collector->gauge(self::VARIABLE_A, 1); // sets to 1
$this->collector->gauge(self::VARIABLE_A, 2); // sets to 2
- $this->collector->gauge(self::VARIABLE_A, -5); // decreases by 5
+ $this->collector->gauge(self::VARIABLE_A, '-5'); // decreases by 5
$this->assertEquals(-3, $this->collector->getGauge(self::VARIABLE_A));
$this->collector->gauge(self::VARIABLE_A, 0);
- $this->collector->gauge(self::VARIABLE_A, -5);
+ $this->collector->gauge(self::VARIABLE_A, '-5');
$this->assertEquals(-5, $this->collector->getGauge(self::VARIABLE_A));
}
diff --git a/tests/Metrics/Collector/InfluxDBTest.php b/tests/Metrics/Collector/InfluxDBTest.php
index b05a6ab..4f38ac8 100644
--- a/tests/Metrics/Collector/InfluxDBTest.php
+++ b/tests/Metrics/Collector/InfluxDBTest.php
@@ -63,27 +63,27 @@ public function testCollectDecrement(): void
public function testCollectTiming(): void
{
- $expectedArgs = ['points' => [['measurement' => 'series-name', 'fields' => ['value' => 47.11]]], 'tags' => []];
+ $expectedArgs = ['points' => [['measurement' => 'series-name', 'fields' => ['value' => 47]]], 'tags' => []];
$this->client->expects($this->once())
->method('mark')
->with($expectedArgs)
;
- $this->collector->timing('series-name', 47.11);
+ $this->collector->timing('series-name', 47);
$this->collector->flush();
}
public function testCollectMeasure(): void
{
- $expectedArgs = ['points' => [['measurement' => 'series-name', 'fields' => ['value' => 47.11]]], 'tags' => []];
+ $expectedArgs = ['points' => [['measurement' => 'series-name', 'fields' => ['value' => 47]]], 'tags' => []];
$this->client->expects($this->once())
->method('mark')
->with($expectedArgs)
;
- $this->collector->measure('series-name', 47.11);
+ $this->collector->measure('series-name', 47);
$this->collector->flush();
}
@@ -91,7 +91,7 @@ public function testCollectMeasureWithTags(): void
{
$expectedTags = ['dc' => 'west', 'node' => 'nemesis101'];
- $expectedArgs = ['points' => [['measurement' => 'series-name', 'fields' => ['value' => 47.11]]], 'tags' => $expectedTags];
+ $expectedArgs = ['points' => [['measurement' => 'series-name', 'fields' => ['value' => 47]]], 'tags' => $expectedTags];
$this->client->expects($this->once())
->method('mark')
@@ -99,7 +99,7 @@ public function testCollectMeasureWithTags(): void
;
$this->collector->setTags($expectedTags);
- $this->collector->measure('series-name', 47.11);
+ $this->collector->measure('series-name', 47);
$this->collector->flush();
}
}
diff --git a/tests/Metrics/Collector/PrometheusTest.php b/tests/Metrics/Collector/PrometheusTest.php
index 8fd13e8..7a3a945 100644
--- a/tests/Metrics/Collector/PrometheusTest.php
+++ b/tests/Metrics/Collector/PrometheusTest.php
@@ -14,6 +14,7 @@
namespace Beberlei\Metrics\Tests\Collector;
use Beberlei\Metrics\Collector\Prometheus;
+use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prometheus\CollectorRegistry;
use Prometheus\Exception\MetricNotFoundException;
@@ -25,10 +26,7 @@ class PrometheusTest extends TestCase
public const TEST_VARIABLE_NAME = 'some_variable_name';
- /**
- * @var \PHPUnit_Framework_MockObject_MockObject
- */
- private $collectorRegistryMock;
+ private MockObject&CollectorRegistry $collectorRegistryMock;
private Prometheus $collector;
@@ -296,14 +294,14 @@ public function testFlushWhenCallsTwiceWithDifferentData(): void
->getMock()
;
$gaugeMock
- ->expects($this->at(0))
- ->method('set')
- ->with($firstExpectedVariableValue, [])
- ;
- $gaugeMock
- ->expects($this->at(1))
+ ->expects($matcher = $this->exactly(2))
->method('set')
- ->with($secondExpectedVariableValue, [])
+ ->willReturnCallback(function ($value) use ($matcher) {
+ match ($matcher->getInvocationCount()) {
+ 1 => $this->assertEquals(123, $value),
+ 2 => $this->assertEquals(321, $value),
+ };
+ })
;
$this->collectorRegistryMock
diff --git a/tests/Metrics/FactoryTest.php b/tests/Metrics/FactoryTest.php
index 8eb27b4..607e16e 100644
--- a/tests/Metrics/FactoryTest.php
+++ b/tests/Metrics/FactoryTest.php
@@ -6,7 +6,6 @@
use Beberlei\Metrics\Collector\DogStatsD;
use Beberlei\Metrics\Collector\Graphite;
use Beberlei\Metrics\Collector\InfluxDB;
-use Beberlei\Metrics\Collector\InlineTaggableGaugeableNullCollector;
use Beberlei\Metrics\Collector\Librato;
use Beberlei\Metrics\Collector\Logger;
use Beberlei\Metrics\Collector\NullCollector;
@@ -22,9 +21,25 @@
class FactoryTest extends TestCase
{
- public function getCreateValidMetricTests(): array
+ public function getCreateValidMetricTests(): iterable
{
- return [[StatsD::class, 'statsd'], [StatsD::class, 'statsd', ['host' => 'localhost', 'port' => 1234, 'prefix' => 'prefix']], [StatsD::class, 'statsd', ['host' => 'localhost', 'port' => 1234]], [StatsD::class, 'statsd', ['host' => 'localhost']], [DogStatsD::class, 'dogstatsd'], [DogStatsD::class, 'dogstatsd', ['host' => 'localhost', 'port' => 1234, 'prefix' => 'prefix']], [DogStatsD::class, 'dogstatsd', ['host' => 'localhost', 'port' => 1234]], [DogStatsD::class, 'dogstatsd', ['host' => 'localhost']], [Graphite::class, 'graphite'], [Graphite::class, 'graphite', ['host' => 'localhost', 'port' => 1234]], [Librato::class, 'librato', ['hostname' => 'foobar.com', 'username' => 'username', 'password' => 'password']], [DoctrineDBAL::class, 'doctrine_dbal', ['connection' => $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock()]], [Logger::class, 'logger', ['logger' => new NullLogger()]], [NullCollector::class, 'null'], [InlineTaggableGaugeableNullCollector::class, 'null_inlinetaggable'], [InfluxDB::class, 'influxdb', ['client' => $this->getMockBuilder(Client::class)->disableOriginalConstructor()->getMock()]], [Prometheus::class, 'prometheus', ['collector_registry' => $this->getMockBuilder(CollectorRegistry::class)->disableOriginalConstructor()->getMock()]], [Prometheus::class, 'prometheus', ['collector_registry' => $this->getMockBuilder(CollectorRegistry::class)->disableOriginalConstructor()->getMock(), 'namespace' => 'some_namespace']]];
+ yield [StatsD::class, 'statsd'];
+ yield [StatsD::class, 'statsd', ['host' => 'localhost', 'port' => 1234, 'prefix' => 'prefix']];
+ yield [StatsD::class, 'statsd', ['host' => 'localhost', 'port' => 1234]];
+ yield [StatsD::class, 'statsd', ['host' => 'localhost']];
+ yield [DogStatsD::class, 'dogstatsd'];
+ yield [DogStatsD::class, 'dogstatsd', ['host' => 'localhost', 'port' => 1234, 'prefix' => 'prefix']];
+ yield [DogStatsD::class, 'dogstatsd', ['host' => 'localhost', 'port' => 1234]];
+ yield [DogStatsD::class, 'dogstatsd', ['host' => 'localhost']];
+ yield [Graphite::class, 'graphite'];
+ yield [Graphite::class, 'graphite', ['host' => 'localhost', 'port' => 1234]];
+ yield [Librato::class, 'librato', ['hostname' => 'foobar.com', 'username' => 'username', 'password' => 'password']];
+ yield [DoctrineDBAL::class, 'doctrine_dbal', ['connection' => $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock()]];
+ yield [Logger::class, 'logger', ['logger' => new NullLogger()]];
+ yield [NullCollector::class, 'null'];
+ yield [InfluxDB::class, 'influxdb', ['client' => $this->getMockBuilder(Client::class)->disableOriginalConstructor()->getMock()]];
+ yield [Prometheus::class, 'prometheus', ['collector_registry' => $this->getMockBuilder(CollectorRegistry::class)->disableOriginalConstructor()->getMock()]];
+ yield [Prometheus::class, 'prometheus', ['collector_registry' => $this->getMockBuilder(CollectorRegistry::class)->disableOriginalConstructor()->getMock(), 'namespace' => 'some_namespace']];
}
/**
@@ -35,9 +50,24 @@ public function testCreateValidMetric(string $expectedClass, string $type, array
$this->assertInstanceOf($expectedClass, Factory::create($type, $options));
}
- public function getCreateThrowExceptionIfOptionsAreInvalidTests(): array
+ public function getCreateThrowExceptionIfOptionsAreInvalidTests(): iterable
{
- return [['You should specified a host if you specified a port.', 'statsd', ['port' => '1234']], ['You should specified a host and a port if you specified a prefix.', 'statsd', ['prefix' => 'prefix']], ['You should specified a host and a port if you specified a prefix.', 'statsd', ['port' => '1234', 'prefix' => 'prefix']], ['You should specified a host and a port if you specified a prefix.', 'statsd', ['hostname' => 'foobar.com', 'prefix' => 'prefix']], ['You should specified a host if you specified a port.', 'dogstatsd', ['port' => '1234']], ['You should specified a host and a port if you specified a prefix.', 'dogstatsd', ['prefix' => 'prefix']], ['You should specified a host and a port if you specified a prefix.', 'dogstatsd', ['port' => '1234', 'prefix' => 'prefix']], ['You should specified a host and a port if you specified a prefix.', 'dogstatsd', ['hostname' => 'foobar.com', 'prefix' => 'prefix']], ['You should specified a host if you specified a port.', 'graphite', ['port' => '1234']], ['Hostname is required for librato collector.', 'librato'], ['No username given for librato collector.', 'librato', ['hostname' => 'foobar.com']], ['No password given for librato collector.', 'librato', ['hostname' => 'foobar.com', 'username' => 'username']], ['connection is required for Doctrine DBAL collector.', 'doctrine_dbal'], ["Missing 'logger' key with logger service.", 'logger'], ["Missing 'client' key for InfluxDB collector.", 'influxdb'], ["Missing 'collector_registry' key for Prometheus collector.", 'prometheus']];
+ yield ['You should specified a host if you specified a port.', 'statsd', ['port' => '1234']];
+ yield ['You should specified a host and a port if you specified a prefix.', 'statsd', ['prefix' => 'prefix']];
+ yield ['You should specified a host and a port if you specified a prefix.', 'statsd', ['port' => '1234', 'prefix' => 'prefix']];
+ yield ['You should specified a host and a port if you specified a prefix.', 'statsd', ['hostname' => 'foobar.com', 'prefix' => 'prefix']];
+ yield ['You should specified a host if you specified a port.', 'dogstatsd', ['port' => '1234']];
+ yield ['You should specified a host and a port if you specified a prefix.', 'dogstatsd', ['prefix' => 'prefix']];
+ yield ['You should specified a host and a port if you specified a prefix.', 'dogstatsd', ['port' => '1234', 'prefix' => 'prefix']];
+ yield ['You should specified a host and a port if you specified a prefix.', 'dogstatsd', ['hostname' => 'foobar.com', 'prefix' => 'prefix']];
+ yield ['You should specified a host if you specified a port.', 'graphite', ['port' => '1234']];
+ yield ['Hostname is required for librato collector.', 'librato'];
+ yield ['No username given for librato collector.', 'librato', ['hostname' => 'foobar.com']];
+ yield ['No password given for librato collector.', 'librato', ['hostname' => 'foobar.com', 'username' => 'username']];
+ yield ['connection is required for Doctrine DBAL collector.', 'doctrine_dbal'];
+ yield ["Missing 'logger' key with logger service.", 'logger'];
+ yield ["Missing 'client' key for InfluxDB collector.", 'influxdb'];
+ yield ["Missing 'collector_registry' key for Prometheus collector.", 'prometheus'];
}
/**
diff --git a/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php b/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
index 05e2bc8..554730d 100644
--- a/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
+++ b/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
@@ -28,6 +28,7 @@
use PHPUnit\Framework\TestCase;
use Prometheus\CollectorRegistry;
use Psr\Log\NullLogger;
+use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
@@ -51,11 +52,12 @@ public function testWithGraphite(): void
}
/**
- * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
- * The source has to be specified to use a Librato
+ * The source has to be specified to use a Librato.
*/
public function testWithLibratoAndInvalidConfiguration(): void
{
+ $this->expectException(InvalidConfigurationException::class);
+
$container = $this->createContainer(['collectors' => ['simple' => ['type' => 'librato']]], ['beberlei_metrics.collector.librato']);
$this->assertInstanceOf(Librato::class, $container->get('beberlei_metrics.collector.librato'));
@@ -226,13 +228,10 @@ public function testWithPrometheusAndWithTags(): void
$this->assertEquals($expectedTags, $this->getProperty($collector, 'tags'));
}
- /**
- * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
- *
- * @expectedExceptionMessage The prometheus_collector_registry has to be specified to use a Prometheus
- */
public function testValidationWhenTypeIsPrometheusAndPrometheusCollectorRegistryIsNotSpecified(): void
{
+ $this->expectException(InvalidConfigurationException::class);
+ $this->expectExceptionMessage('The prometheus_collector_registry has to be specified to use a Prometheus');
$this->createContainer(['collectors' => ['prometheus' => ['type' => 'prometheus']]]);
}
From b0d856d1c6f1573eac523a8064e509e1fab3588e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 22:23:24 +0100
Subject: [PATCH 15/32] composer: fix some constraints
---
composer.json | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/composer.json b/composer.json
index 83e700f..faf7084 100644
--- a/composer.json
+++ b/composer.json
@@ -21,15 +21,17 @@
"require-dev": {
"php": ">=8.1",
"corley/influxdb-sdk": "^0.5.1",
- "doctrine/dbal": "~2.0",
- "jimdo/prometheus_client_php": "^0.5",
+ "doctrine/dbal": "^2.0",
+ "jimdo/prometheus_client_php": "^0.5.1",
"symfony/config": "^5.4 || ^6.4 || ^7.0",
"symfony/dependency-injection": "^5.4 || ^6.4 || ^7.0",
"symfony/http-client": "^5.4 || ^6.4 || ^7.0",
"symfony/http-kernel": "^5.4 || ^6.4 || ^7.0",
- "symfony/phpunit-bridge": "^6.4 || ^7.0"
+ "symfony/phpunit-bridge": "^6.4.4 || ^7.0"
},
"conflict": {
+ "doctrine/dbal": "<2",
+ "jimdo/prometheus_client_php": "<0.5.1",
"symfony/config": "<5.4",
"symfony/dependency-injection": "<5.4",
"symfony/http-client": "<5.4",
From 1ed9ab79de51452296b1f8bc3245227d66da2d84 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 22:13:56 +0100
Subject: [PATCH 16/32] ci: add GHA
---
.github/workflows/ci.yaml | 66 +++++++++++++++++++++++++++++++++++++++
1 file changed, 66 insertions(+)
create mode 100644 .github/workflows/ci.yaml
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
new file mode 100644
index 0000000..22159d7
--- /dev/null
+++ b/.github/workflows/ci.yaml
@@ -0,0 +1,66 @@
+name: CI
+
+on:
+ push:
+ # FIXME: Change the branch name to your main branch
+ branches: [main]
+ pull_request: ~
+
+jobs:
+ cs:
+ name: PHP-CS-Fixer
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: PHP-CS-Fixer
+ uses: docker://oskarstark/php-cs-fixer-ga
+ with:
+ args: --diff --dry-run
+
+ phpstan:
+ name: PHPStan
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Install Composer dependencies
+ run: composer update --prefer-dist --no-interaction
+
+ - name: PHPStan
+ env:
+ CHECK_PLATFORM_REQUIREMENTS: false
+ REQUIRE_DEV: true
+ uses: docker://oskarstark/phpstan-ga
+
+ phpunit:
+ name: PHPUnit on PHP ${{ matrix.php-version }} ${{ matrix.name }}
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ php-version: ["8.2", "8.3"]
+ composer-flags: [""]
+ name: [""]
+ include:
+ - php-version: 8.1
+ composer-flags: "--prefer-lowest"
+ name: "(prefer lowest dependencies)"
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Setup PHP, with composer and extensions
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ matrix.php-version }}
+ extensions: mbstring, xml
+ ini-values: phar.readonly="Off"
+
+ - name: Install Composer dependencies
+ run: composer update --prefer-dist --no-interaction ${{ matrix.composer-flags }}
+
+ - name: Run Tests
+ run: vendor/bin/simple-phpunit
From d59d77b9eb2c33c2a09adf043e25ebc8fd7fc3dd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 22:37:52 +0100
Subject: [PATCH 17/32] chore: ensure Collector cannot raise error or exception
---
src/Metrics/Collector/DogStatsD.php | 10 +++++++---
src/Metrics/Collector/Graphite.php | 24 ++++++++++++++----------
src/Metrics/Collector/InfluxDB.php | 6 +++++-
src/Metrics/Collector/StatsD.php | 10 +++++++---
src/Metrics/Collector/Telegraf.php | 11 ++++++++---
src/Metrics/Utils/Box.php | 19 +++++++++++++++++++
6 files changed, 60 insertions(+), 20 deletions(-)
create mode 100644 src/Metrics/Utils/Box.php
diff --git a/src/Metrics/Collector/DogStatsD.php b/src/Metrics/Collector/DogStatsD.php
index 7091d5e..0604ecf 100644
--- a/src/Metrics/Collector/DogStatsD.php
+++ b/src/Metrics/Collector/DogStatsD.php
@@ -13,6 +13,8 @@
namespace Beberlei\Metrics\Collector;
+use Beberlei\Metrics\Utils\Box;
+
class DogStatsD implements CollectorInterface, GaugeableCollectorInterface
{
private array $data = [];
@@ -54,6 +56,11 @@ public function flush(): void
if (!$this->data) {
return;
}
+ Box::box($this->doFlush(...));
+ }
+
+ private function doFlush(): void
+ {
$fp = fsockopen('udp://' . $this->host, $this->port, $errno, $errstr, 1.0);
@@ -61,13 +68,10 @@ public function flush(): void
return;
}
- $level = error_reporting(0);
foreach ($this->data as $line) {
fwrite($fp, $this->prefix . $line);
}
- error_reporting($level);
-
fclose($fp);
$this->data = [];
diff --git a/src/Metrics/Collector/Graphite.php b/src/Metrics/Collector/Graphite.php
index 1bc7711..9ff5930 100644
--- a/src/Metrics/Collector/Graphite.php
+++ b/src/Metrics/Collector/Graphite.php
@@ -13,6 +13,8 @@
namespace Beberlei\Metrics\Collector;
+use Beberlei\Metrics\Utils\Box;
+
/**
* Sends statistics to the stats daemon over UDP or TCP.
*/
@@ -53,21 +55,23 @@ public function flush(): void
return;
}
- try {
- $fp = fsockopen($this->protocol . '://' . $this->host, $this->port);
+ Box::box($this->doFlush(...));
+ }
- if (!$fp) {
- return;
- }
+ private function doFlush(): void
+ {
+ $fp = fsockopen($this->protocol . '://' . $this->host, $this->port);
- foreach ($this->data as $line) {
- fwrite($fp, (string) $line);
- }
+ if (!$fp) {
+ return;
+ }
- fclose($fp);
- } catch (\Exception) {
+ foreach ($this->data as $line) {
+ fwrite($fp, (string) $line);
}
+ fclose($fp);
+
$this->data = [];
}
diff --git a/src/Metrics/Collector/InfluxDB.php b/src/Metrics/Collector/InfluxDB.php
index e995972..75ba748 100644
--- a/src/Metrics/Collector/InfluxDB.php
+++ b/src/Metrics/Collector/InfluxDB.php
@@ -48,7 +48,11 @@ public function timing(string $variable, int $time, array $tags = []): void
public function flush(): void
{
foreach ($this->data as $data) {
- $this->client->mark(['points' => [['measurement' => $data[0], 'fields' => ['value' => $data[1]]]], 'tags' => $data[2] + $this->tags]);
+ try {
+ $this->client->mark(['points' => [['measurement' => $data[0], 'fields' => ['value' => $data[1]]]], 'tags' => $data[2] + $this->tags]);
+ } catch (\Exception) {
+ continue;
+ }
}
$this->data = [];
diff --git a/src/Metrics/Collector/StatsD.php b/src/Metrics/Collector/StatsD.php
index 26898b8..8e9f5b5 100644
--- a/src/Metrics/Collector/StatsD.php
+++ b/src/Metrics/Collector/StatsD.php
@@ -13,6 +13,8 @@
namespace Beberlei\Metrics\Collector;
+use Beberlei\Metrics\Utils\Box;
+
/**
* Sends statistics to the stats daemon over UDP.
*/
@@ -58,19 +60,21 @@ public function flush(): void
return;
}
+ Box::box($this->doFlush(...));
+ }
+
+ private function doFlush(): void
+ {
$fp = fsockopen('udp://' . $this->host, $this->port, $errno, $errstr, 1.0);
if (!$fp) {
return;
}
- $level = error_reporting(0);
foreach ($this->data as $line) {
fwrite($fp, $this->prefix . $line);
}
- error_reporting($level);
-
fclose($fp);
$this->data = [];
diff --git a/src/Metrics/Collector/Telegraf.php b/src/Metrics/Collector/Telegraf.php
index 240b18b..e2b2905 100644
--- a/src/Metrics/Collector/Telegraf.php
+++ b/src/Metrics/Collector/Telegraf.php
@@ -13,6 +13,8 @@
namespace Beberlei\Metrics\Collector;
+use Beberlei\Metrics\Utils\Box;
+
/**
* Sends statistics to the StatsD daemon over UDP,
* ad hoc implementation for the StatsD - Telegraf integration,
@@ -66,19 +68,22 @@ public function flush(): void
return;
}
+ Box::box($this->doFlush(...));
+ }
+
+ private function doFlush(): void
+ {
+
$fp = fsockopen('udp://' . $this->host, $this->port, $errno, $errstr, 1.0);
if (!$fp) {
return;
}
- $level = error_reporting(0);
foreach ($this->data as $line) {
fwrite($fp, $this->prefix . $line);
}
- error_reporting($level);
-
fclose($fp);
$this->data = [];
diff --git a/src/Metrics/Utils/Box.php b/src/Metrics/Utils/Box.php
new file mode 100644
index 0000000..b191fe5
--- /dev/null
+++ b/src/Metrics/Utils/Box.php
@@ -0,0 +1,19 @@
+ null);
+
+ return $callable();
+ } catch (\Throwable) {
+ // ignore
+ } finally {
+ restore_error_handler();
+ }
+ }
+}
From cc5cc9a1e66308e1ce56f88f33f4ceceb5153ffc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 23:05:51 +0100
Subject: [PATCH 18/32] example: init blank symfony application
---
example/statsd.php | 13 -
examples/.castor/docker.php | 472 +
examples/.castor/qa.php | 51 +
examples/.env | 41 +
examples/.env.test | 6 +
examples/.gitattributes | 2 +
examples/.gitignore | 30 +
examples/.php-cs-fixer.php | 27 +
examples/README.md | 102 +
examples/assets/app.js | 10 +
examples/assets/bootstrap.js | 5 +
examples/assets/controllers.json | 15 +
.../assets/controllers/hello_controller.js | 16 +
examples/assets/styles/app.css | 3 +
examples/bin/console | 17 +
examples/bin/phpunit | 23 +
examples/castor.php | 81 +
examples/composer.json | 108 +
examples/composer.lock | 9702 +++++++++++++++++
examples/config/bundles.php | 16 +
examples/config/packages/asset_mapper.yaml | 5 +
examples/config/packages/cache.yaml | 19 +
examples/config/packages/debug.yaml | 5 +
examples/config/packages/doctrine.yaml | 50 +
.../config/packages/doctrine_migrations.yaml | 6 +
examples/config/packages/framework.yaml | 16 +
examples/config/packages/mailer.yaml | 3 +
examples/config/packages/messenger.yaml | 24 +
examples/config/packages/monolog.yaml | 62 +
examples/config/packages/notifier.yaml | 12 +
examples/config/packages/routing.yaml | 10 +
examples/config/packages/security.yaml | 39 +
examples/config/packages/translation.yaml | 7 +
examples/config/packages/twig.yaml | 6 +
examples/config/packages/validator.yaml | 11 +
examples/config/packages/web_profiler.yaml | 17 +
examples/config/preload.php | 5 +
examples/config/routes.yaml | 5 +
examples/config/routes/framework.yaml | 4 +
examples/config/routes/security.yaml | 3 +
examples/config/routes/web_profiler.yaml | 8 +
examples/config/services.yaml | 24 +
examples/importmap.php | 28 +
.../docker/docker-compose.builder.yml | 25 +
.../docker/docker-compose.docker-for-x.yml | 13 +
.../docker/docker-compose.worker.yml | 20 +
.../infrastructure/docker/docker-compose.yml | 38 +
.../docker/services/php/Dockerfile | 121 +
.../mods-available/app-default.ini | 27 +
.../services/php/builder/etc/sudoers.d/sudo | 1 +
.../mods-available/app-builder.ini | 5 +
.../docker/services/php/entrypoint | 26 +
.../php/frontend/etc/nginx/environments | 0
.../php/frontend/etc/nginx/nginx.conf | 74 +
.../php/frontend/etc/service/nginx/run | 3 +
.../php/frontend/etc/service/php-fpm/run | 3 +
.../php-configuration/fpm/php-fpm.conf | 19 +
.../mods-available/app-fpm.ini | 5 +
.../docker/services/router/Dockerfile | 5 +
.../docker/services/router/certs/.gitkeep | 0
.../docker/services/router/generate-ssl.sh | 16 +
.../docker/services/router/openssl.cnf | 19 +
.../services/router/traefik/dynamic_conf.yaml | 12 +
.../services/router/traefik/traefik.yaml | 28 +
examples/migrations/.gitignore | 0
examples/phpstan.neon | 31 +
examples/phpunit.xml.dist | 38 +
examples/public/index.php | 9 +
examples/src/Controller/.gitignore | 0
.../src/Controller/HomepageController.php | 28 +
examples/src/Entity/.gitignore | 0
examples/src/Kernel.php | 11 +
examples/src/Repository/.gitignore | 0
examples/symfony.lock | 282 +
examples/templates/base.html.twig | 17 +
examples/tests/bootstrap.php | 11 +
examples/tools/bin/php-cs-fixer | 1 +
examples/tools/bin/phpstan | 1 +
examples/tools/php-cs-fixer/.gitignore | 1 +
examples/tools/php-cs-fixer/composer.json | 12 +
examples/tools/php-cs-fixer/composer.lock | 1845 ++++
examples/tools/phpstan/.gitignore | 2 +
examples/tools/phpstan/composer.json | 17 +
examples/tools/phpstan/composer.lock | 200 +
examples/translations/.gitignore | 0
85 files changed, 14062 insertions(+), 13 deletions(-)
delete mode 100644 example/statsd.php
create mode 100644 examples/.castor/docker.php
create mode 100644 examples/.castor/qa.php
create mode 100644 examples/.env
create mode 100644 examples/.env.test
create mode 100644 examples/.gitattributes
create mode 100644 examples/.gitignore
create mode 100644 examples/.php-cs-fixer.php
create mode 100644 examples/README.md
create mode 100644 examples/assets/app.js
create mode 100644 examples/assets/bootstrap.js
create mode 100644 examples/assets/controllers.json
create mode 100644 examples/assets/controllers/hello_controller.js
create mode 100644 examples/assets/styles/app.css
create mode 100755 examples/bin/console
create mode 100755 examples/bin/phpunit
create mode 100644 examples/castor.php
create mode 100644 examples/composer.json
create mode 100644 examples/composer.lock
create mode 100644 examples/config/bundles.php
create mode 100644 examples/config/packages/asset_mapper.yaml
create mode 100644 examples/config/packages/cache.yaml
create mode 100644 examples/config/packages/debug.yaml
create mode 100644 examples/config/packages/doctrine.yaml
create mode 100644 examples/config/packages/doctrine_migrations.yaml
create mode 100644 examples/config/packages/framework.yaml
create mode 100644 examples/config/packages/mailer.yaml
create mode 100644 examples/config/packages/messenger.yaml
create mode 100644 examples/config/packages/monolog.yaml
create mode 100644 examples/config/packages/notifier.yaml
create mode 100644 examples/config/packages/routing.yaml
create mode 100644 examples/config/packages/security.yaml
create mode 100644 examples/config/packages/translation.yaml
create mode 100644 examples/config/packages/twig.yaml
create mode 100644 examples/config/packages/validator.yaml
create mode 100644 examples/config/packages/web_profiler.yaml
create mode 100644 examples/config/preload.php
create mode 100644 examples/config/routes.yaml
create mode 100644 examples/config/routes/framework.yaml
create mode 100644 examples/config/routes/security.yaml
create mode 100644 examples/config/routes/web_profiler.yaml
create mode 100644 examples/config/services.yaml
create mode 100644 examples/importmap.php
create mode 100644 examples/infrastructure/docker/docker-compose.builder.yml
create mode 100644 examples/infrastructure/docker/docker-compose.docker-for-x.yml
create mode 100644 examples/infrastructure/docker/docker-compose.worker.yml
create mode 100644 examples/infrastructure/docker/docker-compose.yml
create mode 100644 examples/infrastructure/docker/services/php/Dockerfile
create mode 100644 examples/infrastructure/docker/services/php/base/php-configuration/mods-available/app-default.ini
create mode 100644 examples/infrastructure/docker/services/php/builder/etc/sudoers.d/sudo
create mode 100644 examples/infrastructure/docker/services/php/builder/php-configuration/mods-available/app-builder.ini
create mode 100755 examples/infrastructure/docker/services/php/entrypoint
create mode 100644 examples/infrastructure/docker/services/php/frontend/etc/nginx/environments
create mode 100644 examples/infrastructure/docker/services/php/frontend/etc/nginx/nginx.conf
create mode 100755 examples/infrastructure/docker/services/php/frontend/etc/service/nginx/run
create mode 100755 examples/infrastructure/docker/services/php/frontend/etc/service/php-fpm/run
create mode 100644 examples/infrastructure/docker/services/php/frontend/php-configuration/fpm/php-fpm.conf
create mode 100644 examples/infrastructure/docker/services/php/frontend/php-configuration/mods-available/app-fpm.ini
create mode 100644 examples/infrastructure/docker/services/router/Dockerfile
create mode 100644 examples/infrastructure/docker/services/router/certs/.gitkeep
create mode 100755 examples/infrastructure/docker/services/router/generate-ssl.sh
create mode 100644 examples/infrastructure/docker/services/router/openssl.cnf
create mode 100644 examples/infrastructure/docker/services/router/traefik/dynamic_conf.yaml
create mode 100644 examples/infrastructure/docker/services/router/traefik/traefik.yaml
create mode 100644 examples/migrations/.gitignore
create mode 100644 examples/phpstan.neon
create mode 100644 examples/phpunit.xml.dist
create mode 100644 examples/public/index.php
create mode 100644 examples/src/Controller/.gitignore
create mode 100644 examples/src/Controller/HomepageController.php
create mode 100644 examples/src/Entity/.gitignore
create mode 100644 examples/src/Kernel.php
create mode 100644 examples/src/Repository/.gitignore
create mode 100644 examples/symfony.lock
create mode 100644 examples/templates/base.html.twig
create mode 100644 examples/tests/bootstrap.php
create mode 120000 examples/tools/bin/php-cs-fixer
create mode 120000 examples/tools/bin/phpstan
create mode 100644 examples/tools/php-cs-fixer/.gitignore
create mode 100644 examples/tools/php-cs-fixer/composer.json
create mode 100644 examples/tools/php-cs-fixer/composer.lock
create mode 100644 examples/tools/phpstan/.gitignore
create mode 100644 examples/tools/phpstan/composer.json
create mode 100644 examples/tools/phpstan/composer.lock
create mode 100644 examples/translations/.gitignore
diff --git a/example/statsd.php b/example/statsd.php
deleted file mode 100644
index 8ce6cc5..0000000
--- a/example/statsd.php
+++ /dev/null
@@ -1,13 +0,0 @@
-increment('foo.bar');
- $metrics->decrement('foo.baz');
- $metrics->measure('foo', rand(1, 10));
- $metrics->flush();
- usleep(500);
-}
diff --git a/examples/.castor/docker.php b/examples/.castor/docker.php
new file mode 100644
index 0000000..3640ec7
--- /dev/null
+++ b/examples/.castor/docker.php
@@ -0,0 +1,472 @@
+title('About this project');
+
+ io()->comment('Run castor to display all available commands.');
+ io()->comment('Run castor about to display this project help.');
+ io()->comment('Run castor help [command] to display Castor help.');
+
+ io()->section('Available URLs for this project:');
+ $urls = [variable('root_domain'), ...variable('extra_domains')];
+
+ $payload = @file_get_contents(sprintf('http://%s:8080/api/http/routers', variable('root_domain')));
+ if ($payload) {
+ $routers = json_decode($payload, true);
+ $projectName = variable('project_name');
+ foreach ($routers as $router) {
+ if (!preg_match("{^{$projectName}-(.*)@docker$}", $router['name'])) {
+ continue;
+ }
+ if ("frontend-{$projectName}" === $router['service']) {
+ continue;
+ }
+ if (!preg_match('{^Host\\(`(?P.*)`\\)$}', $router['rule'], $matches)) {
+ continue;
+ }
+ $hosts = explode('`) || Host(`', $matches['hosts']);
+ $urls = [...$urls, ...$hosts];
+ }
+ }
+ io()->listing(array_map(fn ($url) => "https://{$url}", $urls));
+}
+
+#[AsTask(description: 'Opens the project in your browser', namespace: '')]
+function open(): void
+{
+ run(['open', 'https://' . variable('root_domain')], quiet: true);
+}
+
+#[AsTask(description: 'Builds the infrastructure', aliases: ['build'])]
+function build(): void
+{
+ io()->title('Building infrastructure');
+
+ $userId = variable('user_id');
+ $phpVersion = variable('php_version');
+
+ $command = [
+ 'build',
+ '--build-arg', "USER_ID={$userId}",
+ '--build-arg', "PHP_VERSION={$phpVersion}",
+ ];
+
+ docker_compose($command, withBuilder: true);
+}
+
+#[AsTask(description: 'Builds and starts the infrastructure', aliases: ['up'])]
+function up(): void
+{
+ io()->title('Starting infrastructure');
+
+ try {
+ docker_compose(['up', '--detach', '--no-build']);
+ } catch (ExceptionInterface $e) {
+ io()->error('An error occured while starting the infrastructure.');
+ io()->note('Did you forget to run "castor docker:build"?');
+ io()->note('Or you forget to login to the registry?');
+
+ throw $e;
+ }
+}
+
+#[AsTask(description: 'Stops the infrastructure', aliases: ['stop'])]
+function stop(): void
+{
+ io()->title('Stopping infrastructure');
+
+ docker_compose(['stop']);
+}
+
+#[AsTask(description: 'Opens a shell (bash) into a builder container', aliases: ['builder'])]
+function builder(): void
+{
+ $c = context()
+ ->withTimeout(null)
+ ->withTty()
+ ->withEnvironment($_ENV + $_SERVER)
+ ->withAllowFailure()
+ ;
+ docker_compose_run('bash', c: $c);
+}
+
+#[AsTask(description: 'Displays infrastructure logs', aliases: ['logs'])]
+function logs(): void
+{
+ docker_compose(['logs', '-f', '--tail', '150'], c: context()->withTty());
+}
+
+#[AsTask(description: 'Lists containers status', aliases: ['ps'])]
+function ps(): void
+{
+ docker_compose(['ps'], withBuilder: false);
+}
+
+#[AsTask(description: 'Cleans the infrastructure (remove container, volume, networks)', aliases: ['destroy'])]
+function destroy(
+ #[AsOption(description: 'Force the destruction without confirmation', shortcut: 'f')]
+ bool $force = false,
+): void {
+ io()->title('Destroying infrastructure');
+
+ if (!$force) {
+ io()->warning('This will permanently remove all containers, volumes, networks... created for this project.');
+ io()->note('You can use the --force option to avoid this confirmation.');
+ if (!io()->confirm('Are you sure?', false)) {
+ io()->comment('Aborted.');
+
+ return;
+ }
+ }
+
+ docker_compose(['down', '--remove-orphans', '--volumes', '--rmi=local'], withBuilder: true);
+ $files = finder()
+ ->in(variable('root_dir') . '/infrastructure/docker/services/router/certs/')
+ ->name('*.pem')
+ ->files()
+ ;
+ fs()->remove($files);
+}
+
+#[AsTask(description: 'Generates SSL certificates (with mkcert if available or self-signed if not)', namespace: '')]
+function generate_certificates(
+ #[AsOption(description: 'Force the certificates re-generation without confirmation', shortcut: 'f')]
+ bool $force = false,
+): void {
+ $sslDir = variable('root_dir') . '/infrastructure/docker/services/router/certs';
+
+ if (file_exists("{$sslDir}/cert.pem") && !$force) {
+ io()->comment('SSL certificates already exists.');
+ io()->note('Run "castor docker:generate-certificates --force" to generate new certificates.');
+
+ return;
+ }
+
+ io()->title('Generating SSL certificates');
+
+ if ($force) {
+ if (file_exists($f = "{$sslDir}/cert.pem")) {
+ io()->comment('Removing existing certificates in infrastructure/docker/services/router/certs/*.pem.');
+ unlink($f);
+ }
+
+ if (file_exists($f = "{$sslDir}/key.pem")) {
+ unlink($f);
+ }
+ }
+
+ $finder = new ExecutableFinder();
+ $mkcert = $finder->find('mkcert');
+
+ if ($mkcert) {
+ $pathCaRoot = capture(['mkcert', '-CAROOT']);
+
+ if (!is_dir($pathCaRoot)) {
+ io()->warning('You must have mkcert CA Root installed on your host with "mkcert -install" command.');
+
+ return;
+ }
+
+ $rootDomain = variable('root_domain');
+
+ run([
+ 'mkcert',
+ '-cert-file', "{$sslDir}/cert.pem",
+ '-key-file', "{$sslDir}/key.pem",
+ $rootDomain,
+ "*.{$rootDomain}",
+ ...variable('extra_domains'),
+ ]);
+
+ io()->success('Successfully generated SSL certificates with mkcert.');
+
+ if ($force) {
+ io()->note('Please restart the infrastructure to use the new certificates with "castor up" or "castor start".');
+ }
+
+ return;
+ }
+
+ run(['infrastructure/docker/services/router/generate-ssl.sh'], quiet: true);
+
+ io()->success('Successfully generated self-signed SSL certificates in infrastructure/docker/services/router/certs/*.pem.');
+ io()->comment('Consider installing mkcert to generate locally trusted SSL certificates and run "castor docker:generate-certificates --force".');
+
+ if ($force) {
+ io()->note('Please restart the infrastructure to use the new certificates with "castor up" or "castor start".');
+ }
+}
+
+#[AsTask(description: 'Starts the workers', namespace: 'docker:worker', name: 'start', aliases: ['start-workers'])]
+function workers_start(): void
+{
+ io()->title('Starting workers');
+
+ $workers = get_workers();
+
+ if (!$workers) {
+ return;
+ }
+
+ run([
+ 'docker',
+ 'update',
+ '--restart=unless-stopped',
+ ...$workers,
+ ], quiet: true);
+
+ run([
+ 'docker',
+ 'start',
+ ...$workers,
+ ], quiet: true);
+}
+
+#[AsTask(description: 'Stops the workers', namespace: 'docker:worker', name: 'stop', aliases: ['stop-workers'])]
+function workers_stop(): void
+{
+ io()->title('Stopping workers');
+
+ $workers = get_workers();
+
+ if (!$workers) {
+ return;
+ }
+
+ run([
+ 'docker',
+ 'update',
+ '--restart=no',
+ ...$workers,
+ ]);
+
+ run([
+ 'docker',
+ 'stop',
+ ...$workers,
+ ]);
+}
+
+#[AsContext(default: true)]
+function create_default_context(): Context
+{
+ $data = create_default_variables() + [
+ 'project_name' => 'app',
+ 'root_domain' => 'app.test',
+ 'extra_domains' => [],
+ 'php_version' => '8.3',
+ 'docker_compose_files' => [
+ 'docker-compose.yml',
+ 'docker-compose.worker.yml',
+ ],
+ 'macos' => false,
+ 'power_shell' => false,
+ 'user_id' => posix_geteuid(),
+ 'root_dir' => \dirname(__DIR__),
+ 'env' => $_SERVER['CI'] ?? false ? 'ci' : 'dev',
+ ];
+
+ if (file_exists($data['root_dir'] . '/infrastructure/docker/docker-compose.override.yml')) {
+ $data['docker_compose_files'][] = 'docker-compose.override.yml';
+ }
+
+ // We need an empty context to run command, since the default context has
+ // not been set in castor, since we ARE creating it right now
+ $emptyContext = new Context();
+
+ $data['composer_cache_dir'] = cache('composer_cache_dir', function () use ($emptyContext): string {
+ $composerCacheDir = capture(['composer', 'global', 'config', 'cache-dir', '-q'], onFailure: '', context: $emptyContext);
+ // If PHP is broken, the output will not be a valid path but an error message
+ if (!is_dir($composerCacheDir)) {
+ $composerCacheDir = sys_get_temp_dir() . '/castor/composer';
+ // If the directory does not exist, we create it. Otherwise, docker
+ // will do, as root, and the user will not be able to write in it.
+ if (!is_dir($composerCacheDir)) {
+ mkdir($composerCacheDir, 0777, true);
+ }
+ }
+
+ return $composerCacheDir;
+ });
+
+ $platform = strtolower(php_uname('s'));
+ if (str_contains($platform, 'darwin')) {
+ $data['macos'] = true;
+ $data['docker_compose_files'][] = 'docker-compose.docker-for-x.yml';
+ } elseif (\in_array($platform, ['win32', 'win64'])) {
+ $data['docker_compose_files'][] = 'docker-compose.docker-for-x.yml';
+ $data['power_shell'] = true;
+ }
+
+ if ($data['user_id'] > 256000) {
+ $data['user_id'] = 1000;
+ }
+
+ if (0 === $data['user_id']) {
+ log('Running as root? Fallback to fake user id.', 'warning');
+ $data['user_id'] = 1000;
+ }
+
+ return new Context($data, pty: 'dev' === $data['env']);
+}
+
+/**
+ * @param array $subCommand
+ */
+function docker_compose(array $subCommand, ?Context $c = null, bool $withBuilder = false): Process
+{
+ $c ??= context();
+
+ $domains = [variable('root_domain'), ...variable('extra_domains')];
+ $domains = '`' . implode('`) || Host(`', $domains) . '`';
+
+ $c = $c
+ ->withTimeout(null)
+ ->withEnvironment([
+ 'PROJECT_NAME' => variable('project_name'),
+ 'PROJECT_ROOT_DOMAIN' => variable('root_domain'),
+ 'PROJECT_DOMAINS' => $domains,
+ 'USER_ID' => variable('user_id'),
+ 'COMPOSER_CACHE_DIR' => variable('composer_cache_dir'),
+ 'PHP_VERSION' => variable('php_version'),
+ 'BUILDKIT_PROGRESS' => 'plain',
+ ])
+ ;
+
+ $command = [
+ 'docker',
+ 'compose',
+ '-p', variable('project_name'),
+ ];
+
+ foreach (variable('docker_compose_files') as $file) {
+ $command[] = '-f';
+ $command[] = variable('root_dir') . '/infrastructure/docker/' . $file;
+ }
+
+ if ($withBuilder) {
+ $command[] = '-f';
+ $command[] = variable('root_dir') . '/infrastructure/docker/docker-compose.builder.yml';
+ }
+
+ $command = array_merge($command, $subCommand);
+
+ return run($command, context: $c);
+}
+
+function docker_compose_run(
+ string $runCommand,
+ ?Context $c = null,
+ string $service = 'builder',
+ bool $noDeps = true,
+ ?string $workDir = null,
+ bool $portMapping = false,
+ bool $withBuilder = true,
+): Process {
+ $command = [
+ 'run',
+ '--rm',
+ ];
+
+ if ($noDeps) {
+ $command[] = '--no-deps';
+ }
+
+ if ($portMapping) {
+ $command[] = '--service-ports';
+ }
+
+ if (null !== $workDir) {
+ $command[] = '-w';
+ $command[] = $workDir;
+ }
+
+ $command[] = $service;
+ $command[] = '/bin/sh';
+ $command[] = '-c';
+ $command[] = "exec {$runCommand}";
+
+ return docker_compose($command, c: $c, withBuilder: $withBuilder);
+}
+
+function docker_exit_code(
+ string $runCommand,
+ ?Context $c = null,
+ string $service = 'builder',
+ bool $noDeps = true,
+ ?string $workDir = null,
+ bool $withBuilder = true,
+): int {
+ $c = ($c ?? context())->withAllowFailure();
+
+ $process = docker_compose_run(
+ runCommand: $runCommand,
+ c: $c,
+ service: $service,
+ noDeps: $noDeps,
+ workDir: $workDir,
+ withBuilder: $withBuilder,
+ );
+
+ return $process->getExitCode() ?? 0;
+}
+
+// Mac users have a lot of problems running Yarn / Webpack on the Docker stack
+// so this func allow them to run these tools on their host
+function run_in_docker_or_locally_for_mac(string $command, ?Context $c = null): void
+{
+ $c ??= context();
+
+ if (variable('macos')) {
+ run($command, context: $c->withPath(variable('root_dir')));
+ } else {
+ docker_compose_run($command, c: $c);
+ }
+}
+
+/**
+ * Find worker containers for the current project.
+ *
+ * @return array
+ */
+function get_workers(): array
+{
+ $command = [
+ 'docker',
+ 'ps',
+ '-a',
+ '--filter', 'label=docker-starter.worker.' . variable('project_name'),
+ '--quiet',
+ ];
+ $out = capture($command);
+
+ if (!$out) {
+ return [];
+ }
+
+ $workers = explode("\n", $out);
+
+ return array_map('trim', $workers);
+}
diff --git a/examples/.castor/qa.php b/examples/.castor/qa.php
new file mode 100644
index 0000000..32d5202
--- /dev/null
+++ b/examples/.castor/qa.php
@@ -0,0 +1,51 @@
+title('Installing QA tooling');
+
+ docker_compose_run('composer install -o', workDir: '/var/www/tools/php-cs-fixer');
+ docker_compose_run('composer install -o', workDir: '/var/www/tools/phpstan');
+}
+
+// #[AsTask(description: 'Runs PHPUnit', aliases: ['phpunit'])]
+// function phpunit(): int
+// {
+// return docker_exit_code('phpunit');
+// }
+
+#[AsTask(description: 'Runs PHPStan', aliases: ['phpstan'])]
+function phpstan(): int
+{
+ return docker_exit_code('phpstan', workDir: '/var/www');
+}
+
+#[AsTask(description: 'Fixes Coding Style', aliases: ['cs'])]
+function cs(bool $dryRun = false): int
+{
+ if ($dryRun) {
+ return docker_exit_code('php-cs-fixer fix --dry-run --diff', workDir: '/var/www');
+ }
+
+ return docker_exit_code('php-cs-fixer fix', workDir: '/var/www');
+}
diff --git a/examples/.env b/examples/.env
new file mode 100644
index 0000000..1bb8dab
--- /dev/null
+++ b/examples/.env
@@ -0,0 +1,41 @@
+# In all environments, the following files are loaded if they exist,
+# the latter taking precedence over the former:
+#
+# * .env contains default values for the environment variables needed by the app
+# * .env.local uncommitted file with local overrides
+# * .env.$APP_ENV committed environment-specific defaults
+# * .env.$APP_ENV.local uncommitted environment-specific overrides
+#
+# Real environment variables win over .env files.
+#
+# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
+# https://symfony.com/doc/current/configuration/secrets.html
+#
+# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
+# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration
+
+###> symfony/framework-bundle ###
+APP_ENV=dev
+APP_SECRET=acbff843d79416cbb1432679dc4f3ead
+###< symfony/framework-bundle ###
+
+###> doctrine/doctrine-bundle ###
+# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
+# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
+#
+# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
+# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4"
+# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4"
+DATABASE_URL="postgresql://app:app@postgres:5432/app?serverVersion=16&charset=utf8"
+###< doctrine/doctrine-bundle ###
+
+###> symfony/messenger ###
+# Choose one of the transports below
+# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages
+# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages
+MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0
+###< symfony/messenger ###
+
+###> symfony/mailer ###
+# MAILER_DSN=null://null
+###< symfony/mailer ###
diff --git a/examples/.env.test b/examples/.env.test
new file mode 100644
index 0000000..9e7162f
--- /dev/null
+++ b/examples/.env.test
@@ -0,0 +1,6 @@
+# define your env variables for the test env here
+KERNEL_CLASS='App\Kernel'
+APP_SECRET='$ecretf0rt3st'
+SYMFONY_DEPRECATIONS_HELPER=999999
+PANTHER_APP_ENV=panther
+PANTHER_ERROR_SCREENSHOT_DIR=./var/error-screenshots
diff --git a/examples/.gitattributes b/examples/.gitattributes
new file mode 100644
index 0000000..1823cf6
--- /dev/null
+++ b/examples/.gitattributes
@@ -0,0 +1,2 @@
+# Force LF line ending (mandatory for Windows)
+* text=auto eol=lf
diff --git a/examples/.gitignore b/examples/.gitignore
new file mode 100644
index 0000000..2ea9c84
--- /dev/null
+++ b/examples/.gitignore
@@ -0,0 +1,30 @@
+###> symfony/framework-bundle ###
+/.env.local
+/.env.local.php
+/.env.*.local
+/config/secrets/prod/prod.decrypt.private.php
+/public/bundles/
+/var/
+/vendor/
+###< symfony/framework-bundle ###
+
+# Infra & tooling
+/.castor.stub.php
+/infrastructure/docker/docker-compose.override.yml
+/infrastructure/docker/services/router/certs/*.pem
+.php-cs-fixer.cache
+
+###> phpunit/phpunit ###
+/phpunit.xml
+.phpunit.result.cache
+###< phpunit/phpunit ###
+
+###> symfony/phpunit-bridge ###
+.phpunit.result.cache
+/phpunit.xml
+###< symfony/phpunit-bridge ###
+
+###> symfony/asset-mapper ###
+/public/assets/
+/assets/vendor/
+###< symfony/asset-mapper ###
diff --git a/examples/.php-cs-fixer.php b/examples/.php-cs-fixer.php
new file mode 100644
index 0000000..29a627d
--- /dev/null
+++ b/examples/.php-cs-fixer.php
@@ -0,0 +1,27 @@
+ignoreVCSIgnored(true)
+ ->ignoreDotFiles(false)
+ ->in(__DIR__)
+ ->append([
+ __FILE__,
+ ])
+;
+
+return (new PhpCsFixer\Config())
+ ->setRiskyAllowed(true)
+ ->setRules([
+ '@PHP81Migration' => true,
+ '@PhpCsFixer' => true,
+ '@Symfony' => true,
+ '@Symfony:risky' => true,
+ 'php_unit_internal_class' => false, // From @PhpCsFixer but we don't want it
+ 'php_unit_test_class_requires_covers' => false, // From @PhpCsFixer but we don't want it
+ 'phpdoc_add_missing_param_annotation' => false, // From @PhpCsFixer but we don't want it
+ 'concat_space' => ['spacing' => 'one'],
+ 'ordered_class_elements' => true, // Symfony(PSR12) override the default value, but we don't want
+ 'blank_line_before_statement' => true, // Symfony(PSR12) override the default value, but we don't want
+ ])
+ ->setFinder($finder)
+;
diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 0000000..64af536
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1,102 @@
+# My project
+
+## Running the application locally
+
+### Requirements
+
+A Docker environment is provided and requires you to have these tools available:
+
+ * Docker
+ * Bash
+ * PHP >= 8.1
+ * [Castor](https://github.com/jolicode/castor#installation)
+
+#### Castor
+
+Once castor is installed, in order to improve your usage of castor scripts, you
+can install console autocompletion script.
+
+If you are using bash:
+
+```bash
+castor completion | sudo tee /etc/bash_completion.d/castor
+```
+
+If you are using something else, please refer to your shell documentation. You
+may need to use `castor completion > /to/somewhere`.
+
+Castor supports completion for `bash`, `zsh` & `fish` shells.
+
+### Docker environment
+
+The Docker infrastructure provides a web stack with:
+ - NGINX
+ - PostgreSQL
+ - PHP
+ - Traefik
+ - A container with some tooling:
+ - Composer
+ - Node
+ - Yarn / NPM
+
+### Domain configuration (first time only)
+
+Before running the application for the first time, ensure your domain names
+point the IP of your Docker daemon by editing your `/etc/hosts` file.
+
+This IP is probably `127.0.0.1` unless you run Docker in a special VM (like docker-machine for example).
+
+> [!NOTE]
+> The router binds port 80 and 443, that's why it will work with `127.0.0.1`
+
+```
+echo '127.0.0.1 app.test www.app.test' | sudo tee -a /etc/hosts
+```
+
+### Starting the stack
+
+Launch the stack by running this command:
+
+```bash
+castor start
+```
+
+> [!NOTE]
+> the first start of the stack should take a few minutes.
+
+The site is now accessible at the hostnames your have configured over HTTPS
+(you may need to accept self-signed SSL certificate if you do not have mkcert
+installed on your computer - see below).
+
+### SSL certificates
+
+HTTPS is supported out of the box. SSL certificates are not versioned and will
+be generated the first time you start the infrastructure (`castor start`) or if
+you run `castor infra:generate-certificates`.
+
+If you have `mkcert` installed on your computer, it will be used to generate
+locally trusted certificates. See [`mkcert` documentation](https://github.com/FiloSottile/mkcert#installation)
+to understand how to install it. Do not forget to install CA root from mkcert
+by running `mkcert -install`.
+
+If you don't have `mkcert`, then self-signed certificates will instead be
+generated with openssl. You can configure [infrastructure/docker/services/router/openssl.cnf](infrastructure/docker/services/router/openssl.cnf)
+to tweak certificates.
+
+You can run `castor infra:generate-certificates --force` to recreate new certificates
+if some were already generated. Remember to restart the infrastructure to make
+use of the new certificates with `castor up` or `castor start`.
+
+### Builder
+
+Having some composer, yarn or other modifications to make on the project?
+Start the builder which will give you access to a container with all these
+tools available:
+
+```bash
+castor builder
+```
+
+### Other tasks
+
+Checkout `castor` to have the list of available tasks.
diff --git a/examples/assets/app.js b/examples/assets/app.js
new file mode 100644
index 0000000..8725cc5
--- /dev/null
+++ b/examples/assets/app.js
@@ -0,0 +1,10 @@
+import './bootstrap.js';
+/*
+ * Welcome to your app's main JavaScript file!
+ *
+ * This file will be included onto the page via the importmap() Twig function,
+ * which should already be in your base.html.twig.
+ */
+import './styles/app.css';
+
+console.log('This log comes from assets/app.js - welcome to AssetMapper! 🎉');
diff --git a/examples/assets/bootstrap.js b/examples/assets/bootstrap.js
new file mode 100644
index 0000000..d4e50c9
--- /dev/null
+++ b/examples/assets/bootstrap.js
@@ -0,0 +1,5 @@
+import { startStimulusApp } from '@symfony/stimulus-bundle';
+
+const app = startStimulusApp();
+// register any custom, 3rd party controllers here
+// app.register('some_controller_name', SomeImportedController);
diff --git a/examples/assets/controllers.json b/examples/assets/controllers.json
new file mode 100644
index 0000000..29ea244
--- /dev/null
+++ b/examples/assets/controllers.json
@@ -0,0 +1,15 @@
+{
+ "controllers": {
+ "@symfony/ux-turbo": {
+ "turbo-core": {
+ "enabled": true,
+ "fetch": "eager"
+ },
+ "mercure-turbo-stream": {
+ "enabled": false,
+ "fetch": "eager"
+ }
+ }
+ },
+ "entrypoints": []
+}
diff --git a/examples/assets/controllers/hello_controller.js b/examples/assets/controllers/hello_controller.js
new file mode 100644
index 0000000..e847027
--- /dev/null
+++ b/examples/assets/controllers/hello_controller.js
@@ -0,0 +1,16 @@
+import { Controller } from '@hotwired/stimulus';
+
+/*
+ * This is an example Stimulus controller!
+ *
+ * Any element with a data-controller="hello" attribute will cause
+ * this controller to be executed. The name "hello" comes from the filename:
+ * hello_controller.js -> "hello"
+ *
+ * Delete this file or adapt it for your use!
+ */
+export default class extends Controller {
+ connect() {
+ this.element.textContent = 'Hello Stimulus! Edit me in assets/controllers/hello_controller.js';
+ }
+}
diff --git a/examples/assets/styles/app.css b/examples/assets/styles/app.css
new file mode 100644
index 0000000..dd6181a
--- /dev/null
+++ b/examples/assets/styles/app.css
@@ -0,0 +1,3 @@
+body {
+ background-color: skyblue;
+}
diff --git a/examples/bin/console b/examples/bin/console
new file mode 100755
index 0000000..c933dc5
--- /dev/null
+++ b/examples/bin/console
@@ -0,0 +1,17 @@
+#!/usr/bin/env php
+= 80000) {
+ require dirname(__DIR__).'/vendor/phpunit/phpunit/phpunit';
+ } else {
+ define('PHPUNIT_COMPOSER_INSTALL', dirname(__DIR__).'/vendor/autoload.php');
+ require PHPUNIT_COMPOSER_INSTALL;
+ PHPUnit\TextUI\Command::main();
+ }
+} else {
+ if (!is_file(dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php')) {
+ echo "Unable to find the `simple-phpunit.php` script in `vendor/symfony/phpunit-bridge/bin/`.\n";
+ exit(1);
+ }
+
+ require dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php';
+}
diff --git a/examples/castor.php b/examples/castor.php
new file mode 100644
index 0000000..a07f644
--- /dev/null
+++ b/examples/castor.php
@@ -0,0 +1,81 @@
+
+ */
+function create_default_variables(): array
+{
+ return [
+ 'project_name' => 'symfony-metrics',
+ 'root_domain' => 'symfony-metrics.test',
+ 'extra_domains' => [
+ 'grafana.symfony-metrics.test',
+ ],
+ ];
+}
+
+#[AsTask(description: 'Builds and starts the infrastructure, then install the application (composer, yarn, ...)')]
+function start(): void
+{
+ io()->title('Starting the stack');
+
+ workers_stop();
+ generate_certificates(force: false);
+ build();
+ up();
+ cache_clear();
+ install();
+ migrate();
+ workers_start();
+
+ notify('The stack is now up and running.');
+ io()->success('The stack is now up and running.');
+
+ about();
+}
+
+#[AsTask(description: 'Installs the application (composer, yarn, ...)', namespace: 'app', aliases: ['install'])]
+function install(): void
+{
+ io()->title('Installing the application');
+
+ io()->section('Installing PHP dependencies');
+ docker_compose_run('composer install -n --prefer-dist --optimize-autoloader');
+
+ io()->section('Installing importmap');
+ docker_compose_run('bin/console importmap:install');
+
+ qa\install();
+}
+
+#[AsTask(description: 'Clear the application cache', namespace: 'app', aliases: ['cache-clear'])]
+function cache_clear(): void
+{
+ io()->title('Clearing the application cache');
+
+ docker_compose_run('rm -rf var/cache/ && bin/console cache:warmup');
+}
+
+#[AsTask(description: 'Migrates database schema', namespace: 'app:db', aliases: ['migrate'])]
+function migrate(): void
+{
+ io()->title('Migrating the database schema');
+
+ docker_compose_run('bin/console doctrine:database:create --if-not-exists');
+ docker_compose_run('bin/console doctrine:migration:migrate -n --allow-no-migration');
+}
diff --git a/examples/composer.json b/examples/composer.json
new file mode 100644
index 0000000..8d11ee5
--- /dev/null
+++ b/examples/composer.json
@@ -0,0 +1,108 @@
+{
+ "type": "project",
+ "license": "proprietary",
+ "minimum-stability": "stable",
+ "prefer-stable": true,
+ "require": {
+ "php": ">=8.2",
+ "ext-ctype": "*",
+ "ext-iconv": "*",
+ "doctrine/dbal": "^3",
+ "doctrine/doctrine-bundle": "^2.11",
+ "doctrine/doctrine-migrations-bundle": "^3.3",
+ "doctrine/orm": "^3.0",
+ "phpdocumentor/reflection-docblock": "^5.3",
+ "phpstan/phpdoc-parser": "^1.26",
+ "symfony/asset": "7.0.*",
+ "symfony/asset-mapper": "7.0.*",
+ "symfony/console": "7.0.*",
+ "symfony/doctrine-messenger": "7.0.*",
+ "symfony/dotenv": "7.0.*",
+ "symfony/expression-language": "7.0.*",
+ "symfony/flex": "^2",
+ "symfony/form": "7.0.*",
+ "symfony/framework-bundle": "7.0.*",
+ "symfony/http-client": "7.0.*",
+ "symfony/intl": "7.0.*",
+ "symfony/mailer": "7.0.*",
+ "symfony/mime": "7.0.*",
+ "symfony/monolog-bundle": "^3.0",
+ "symfony/notifier": "7.0.*",
+ "symfony/process": "7.0.*",
+ "symfony/property-access": "7.0.*",
+ "symfony/property-info": "7.0.*",
+ "symfony/runtime": "7.0.*",
+ "symfony/security-bundle": "7.0.*",
+ "symfony/serializer": "7.0.*",
+ "symfony/stimulus-bundle": "^2.16",
+ "symfony/string": "7.0.*",
+ "symfony/translation": "7.0.*",
+ "symfony/twig-bundle": "7.0.*",
+ "symfony/ux-turbo": "^2.16",
+ "symfony/validator": "7.0.*",
+ "symfony/web-link": "7.0.*",
+ "symfony/yaml": "7.0.*",
+ "twig/extra-bundle": "^2.12|^3.0",
+ "twig/twig": "^2.12|^3.0"
+ },
+ "config": {
+ "allow-plugins": {
+ "php-http/discovery": true,
+ "symfony/flex": true,
+ "symfony/runtime": true
+ },
+ "sort-packages": true
+ },
+ "autoload": {
+ "psr-4": {
+ "App\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "App\\Tests\\": "tests/"
+ }
+ },
+ "replace": {
+ "symfony/polyfill-ctype": "*",
+ "symfony/polyfill-iconv": "*",
+ "symfony/polyfill-php72": "*",
+ "symfony/polyfill-php73": "*",
+ "symfony/polyfill-php74": "*",
+ "symfony/polyfill-php80": "*",
+ "symfony/polyfill-php81": "*",
+ "symfony/polyfill-php82": "*"
+ },
+ "scripts": {
+ "auto-scripts": {
+ "cache:clear": "symfony-cmd",
+ "assets:install %PUBLIC_DIR%": "symfony-cmd",
+ "importmap:install": "symfony-cmd"
+ },
+ "post-install-cmd": [
+ "@auto-scripts"
+ ],
+ "post-update-cmd": [
+ "@auto-scripts"
+ ]
+ },
+ "conflict": {
+ "symfony/symfony": "*"
+ },
+ "extra": {
+ "symfony": {
+ "allow-contrib": false,
+ "require": "7.0.*"
+ }
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.5",
+ "symfony/browser-kit": "7.0.*",
+ "symfony/css-selector": "7.0.*",
+ "symfony/debug-bundle": "7.0.*",
+ "symfony/maker-bundle": "^1.0",
+ "symfony/phpunit-bridge": "^7.0",
+ "symfony/stopwatch": "7.0.*",
+ "symfony/web-profiler-bundle": "7.0.*"
+ }
+}
diff --git a/examples/composer.lock b/examples/composer.lock
new file mode 100644
index 0000000..7e98a61
--- /dev/null
+++ b/examples/composer.lock
@@ -0,0 +1,9702 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+ "This file is @generated automatically"
+ ],
+ "content-hash": "a081757e3f87e400b4b604ce219bee18",
+ "packages": [
+ {
+ "name": "composer/semver",
+ "version": "3.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/semver.git",
+ "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32",
+ "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3.2 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.4",
+ "symfony/phpunit-bridge": "^4.2 || ^5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\Semver\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nils Adermann",
+ "email": "naderman@naderman.de",
+ "homepage": "http://www.naderman.de"
+ },
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ },
+ {
+ "name": "Rob Bast",
+ "email": "rob.bast@gmail.com",
+ "homepage": "http://robbast.nl"
+ }
+ ],
+ "description": "Semver library that offers utilities, version constraint parsing and validation.",
+ "keywords": [
+ "semantic",
+ "semver",
+ "validation",
+ "versioning"
+ ],
+ "support": {
+ "irc": "ircs://irc.libera.chat:6697/composer",
+ "issues": "https://github.com/composer/semver/issues",
+ "source": "https://github.com/composer/semver/tree/3.4.0"
+ },
+ "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": "2023-08-31T09:50:34+00:00"
+ },
+ {
+ "name": "doctrine/cache",
+ "version": "2.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/cache.git",
+ "reference": "1ca8f21980e770095a31456042471a57bc4c68fb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/cache/zipball/1ca8f21980e770095a31456042471a57bc4c68fb",
+ "reference": "1ca8f21980e770095a31456042471a57bc4c68fb",
+ "shasum": ""
+ },
+ "require": {
+ "php": "~7.1 || ^8.0"
+ },
+ "conflict": {
+ "doctrine/common": ">2.2,<2.4"
+ },
+ "require-dev": {
+ "cache/integration-tests": "dev-master",
+ "doctrine/coding-standard": "^9",
+ "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
+ "psr/cache": "^1.0 || ^2.0 || ^3.0",
+ "symfony/cache": "^4.4 || ^5.4 || ^6",
+ "symfony/var-exporter": "^4.4 || ^5.4 || ^6"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ }
+ ],
+ "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.",
+ "homepage": "https://www.doctrine-project.org/projects/cache.html",
+ "keywords": [
+ "abstraction",
+ "apcu",
+ "cache",
+ "caching",
+ "couchdb",
+ "memcached",
+ "php",
+ "redis",
+ "xcache"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/cache/issues",
+ "source": "https://github.com/doctrine/cache/tree/2.2.0"
+ },
+ "funding": [
+ {
+ "url": "https://www.doctrine-project.org/sponsorship.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.patreon.com/phpdoctrine",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcache",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-05-20T20:07:39+00:00"
+ },
+ {
+ "name": "doctrine/collections",
+ "version": "2.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/collections.git",
+ "reference": "07e16cd7b80a2cffed99e36b541876af172f0257"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/collections/zipball/07e16cd7b80a2cffed99e36b541876af172f0257",
+ "reference": "07e16cd7b80a2cffed99e36b541876af172f0257",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/deprecations": "^1",
+ "php": "^8.1"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^12",
+ "ext-json": "*",
+ "phpstan/phpstan": "^1.8",
+ "phpstan/phpstan-phpunit": "^1.0",
+ "phpunit/phpunit": "^10.5",
+ "vimeo/psalm": "^5.11"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Common\\Collections\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ }
+ ],
+ "description": "PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.",
+ "homepage": "https://www.doctrine-project.org/projects/collections.html",
+ "keywords": [
+ "array",
+ "collections",
+ "iterators",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/collections/issues",
+ "source": "https://github.com/doctrine/collections/tree/2.2.0"
+ },
+ "funding": [
+ {
+ "url": "https://www.doctrine-project.org/sponsorship.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.patreon.com/phpdoctrine",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcollections",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-02-25T22:55:36+00:00"
+ },
+ {
+ "name": "doctrine/dbal",
+ "version": "3.8.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/dbal.git",
+ "reference": "a19a1d05ca211f41089dffcc387733a6875196cb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/dbal/zipball/a19a1d05ca211f41089dffcc387733a6875196cb",
+ "reference": "a19a1d05ca211f41089dffcc387733a6875196cb",
+ "shasum": ""
+ },
+ "require": {
+ "composer-runtime-api": "^2",
+ "doctrine/cache": "^1.11|^2.0",
+ "doctrine/deprecations": "^0.5.3|^1",
+ "doctrine/event-manager": "^1|^2",
+ "php": "^7.4 || ^8.0",
+ "psr/cache": "^1|^2|^3",
+ "psr/log": "^1|^2|^3"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "12.0.0",
+ "fig/log-test": "^1",
+ "jetbrains/phpstorm-stubs": "2023.1",
+ "phpstan/phpstan": "1.10.57",
+ "phpstan/phpstan-strict-rules": "^1.5",
+ "phpunit/phpunit": "9.6.16",
+ "psalm/plugin-phpunit": "0.18.4",
+ "slevomat/coding-standard": "8.13.1",
+ "squizlabs/php_codesniffer": "3.8.1",
+ "symfony/cache": "^5.4|^6.0|^7.0",
+ "symfony/console": "^4.4|^5.4|^6.0|^7.0",
+ "vimeo/psalm": "4.30.0"
+ },
+ "suggest": {
+ "symfony/console": "For helpful console commands such as SQL execution and import of files."
+ },
+ "bin": [
+ "bin/doctrine-dbal"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\DBAL\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ }
+ ],
+ "description": "Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.",
+ "homepage": "https://www.doctrine-project.org/projects/dbal.html",
+ "keywords": [
+ "abstraction",
+ "database",
+ "db2",
+ "dbal",
+ "mariadb",
+ "mssql",
+ "mysql",
+ "oci8",
+ "oracle",
+ "pdo",
+ "pgsql",
+ "postgresql",
+ "queryobject",
+ "sasql",
+ "sql",
+ "sqlite",
+ "sqlserver",
+ "sqlsrv"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/dbal/issues",
+ "source": "https://github.com/doctrine/dbal/tree/3.8.2"
+ },
+ "funding": [
+ {
+ "url": "https://www.doctrine-project.org/sponsorship.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.patreon.com/phpdoctrine",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdbal",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-02-12T18:36:36+00:00"
+ },
+ {
+ "name": "doctrine/deprecations",
+ "version": "1.1.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/deprecations.git",
+ "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab",
+ "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1 || ^8.0"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^9",
+ "phpstan/phpstan": "1.4.10 || 1.10.15",
+ "phpstan/phpstan-phpunit": "^1.0",
+ "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
+ "psalm/plugin-phpunit": "0.18.4",
+ "psr/log": "^1 || ^2 || ^3",
+ "vimeo/psalm": "4.30.0 || 5.12.0"
+ },
+ "suggest": {
+ "psr/log": "Allows logging deprecations via PSR-3 logger implementation"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.",
+ "homepage": "https://www.doctrine-project.org/",
+ "support": {
+ "issues": "https://github.com/doctrine/deprecations/issues",
+ "source": "https://github.com/doctrine/deprecations/tree/1.1.3"
+ },
+ "time": "2024-01-30T19:34:25+00:00"
+ },
+ {
+ "name": "doctrine/doctrine-bundle",
+ "version": "2.11.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/DoctrineBundle.git",
+ "reference": "492725310ae9a1b5b20d6ae09fb5ae6404616e68"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/492725310ae9a1b5b20d6ae09fb5ae6404616e68",
+ "reference": "492725310ae9a1b5b20d6ae09fb5ae6404616e68",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/cache": "^1.11 || ^2.0",
+ "doctrine/dbal": "^3.7.0 || ^4.0",
+ "doctrine/persistence": "^2.2 || ^3",
+ "doctrine/sql-formatter": "^1.0.1",
+ "php": "^7.4 || ^8.0",
+ "symfony/cache": "^5.4 || ^6.0 || ^7.0",
+ "symfony/config": "^5.4 || ^6.0 || ^7.0",
+ "symfony/console": "^5.4 || ^6.0 || ^7.0",
+ "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0",
+ "symfony/deprecation-contracts": "^2.1 || ^3",
+ "symfony/doctrine-bridge": "^5.4.19 || ^6.0.7 || ^7.0",
+ "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0",
+ "symfony/polyfill-php80": "^1.15",
+ "symfony/service-contracts": "^1.1.1 || ^2.0 || ^3"
+ },
+ "conflict": {
+ "doctrine/annotations": ">=3.0",
+ "doctrine/orm": "<2.17 || >=4.0",
+ "twig/twig": "<1.34 || >=2.0 <2.4"
+ },
+ "require-dev": {
+ "doctrine/annotations": "^1 || ^2",
+ "doctrine/coding-standard": "^12",
+ "doctrine/deprecations": "^1.0",
+ "doctrine/orm": "^2.17 || ^3.0",
+ "friendsofphp/proxy-manager-lts": "^1.0",
+ "phpunit/phpunit": "^9.5.26",
+ "psalm/plugin-phpunit": "^0.18.4",
+ "psalm/plugin-symfony": "^5",
+ "psr/log": "^1.1.4 || ^2.0 || ^3.0",
+ "symfony/phpunit-bridge": "^6.1 || ^7.0",
+ "symfony/property-info": "^5.4 || ^6.0 || ^7.0",
+ "symfony/proxy-manager-bridge": "^5.4 || ^6.0 || ^7.0",
+ "symfony/security-bundle": "^5.4 || ^6.0 || ^7.0",
+ "symfony/string": "^5.4 || ^6.0 || ^7.0",
+ "symfony/twig-bridge": "^5.4 || ^6.0 || ^7.0",
+ "symfony/validator": "^5.4 || ^6.0 || ^7.0",
+ "symfony/var-exporter": "^5.4 || ^6.2 || ^7.0",
+ "symfony/web-profiler-bundle": "^5.4 || ^6.0 || ^7.0",
+ "symfony/yaml": "^5.4 || ^6.0 || ^7.0",
+ "twig/twig": "^1.34 || ^2.12 || ^3.0",
+ "vimeo/psalm": "^5.15"
+ },
+ "suggest": {
+ "doctrine/orm": "The Doctrine ORM integration is optional in the bundle.",
+ "ext-pdo": "*",
+ "symfony/web-profiler-bundle": "To use the data collector."
+ },
+ "type": "symfony-bundle",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Bundle\\DoctrineBundle\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ },
+ {
+ "name": "Doctrine Project",
+ "homepage": "https://www.doctrine-project.org/"
+ }
+ ],
+ "description": "Symfony DoctrineBundle",
+ "homepage": "https://www.doctrine-project.org",
+ "keywords": [
+ "database",
+ "dbal",
+ "orm",
+ "persistence"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/DoctrineBundle/issues",
+ "source": "https://github.com/doctrine/DoctrineBundle/tree/2.11.3"
+ },
+ "funding": [
+ {
+ "url": "https://www.doctrine-project.org/sponsorship.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.patreon.com/phpdoctrine",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdoctrine-bundle",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-02-10T20:56:20+00:00"
+ },
+ {
+ "name": "doctrine/doctrine-migrations-bundle",
+ "version": "3.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/DoctrineMigrationsBundle.git",
+ "reference": "1dd42906a5fb9c5960723e2ebb45c68006493835"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/1dd42906a5fb9c5960723e2ebb45c68006493835",
+ "reference": "1dd42906a5fb9c5960723e2ebb45c68006493835",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/doctrine-bundle": "^2.4",
+ "doctrine/migrations": "^3.2",
+ "php": "^7.2|^8.0",
+ "symfony/deprecation-contracts": "^2.1 || ^3",
+ "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^12",
+ "doctrine/orm": "^2.6 || ^3",
+ "doctrine/persistence": "^2.0 || ^3 ",
+ "phpstan/phpstan": "^1.4",
+ "phpstan/phpstan-deprecation-rules": "^1",
+ "phpstan/phpstan-phpunit": "^1",
+ "phpstan/phpstan-strict-rules": "^1.1",
+ "phpstan/phpstan-symfony": "^1.3",
+ "phpunit/phpunit": "^8.5|^9.5",
+ "psalm/plugin-phpunit": "^0.18.4",
+ "psalm/plugin-symfony": "^3 || ^5",
+ "symfony/phpunit-bridge": "^6.3 || ^7",
+ "symfony/var-exporter": "^5.4 || ^6 || ^7",
+ "vimeo/psalm": "^4.30 || ^5.15"
+ },
+ "type": "symfony-bundle",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Bundle\\MigrationsBundle\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Doctrine Project",
+ "homepage": "https://www.doctrine-project.org"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony DoctrineMigrationsBundle",
+ "homepage": "https://www.doctrine-project.org",
+ "keywords": [
+ "dbal",
+ "migrations",
+ "schema"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/DoctrineMigrationsBundle/issues",
+ "source": "https://github.com/doctrine/DoctrineMigrationsBundle/tree/3.3.0"
+ },
+ "funding": [
+ {
+ "url": "https://www.doctrine-project.org/sponsorship.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.patreon.com/phpdoctrine",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdoctrine-migrations-bundle",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-11-13T19:44:41+00:00"
+ },
+ {
+ "name": "doctrine/event-manager",
+ "version": "2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/event-manager.git",
+ "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/event-manager/zipball/750671534e0241a7c50ea5b43f67e23eb5c96f32",
+ "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.1"
+ },
+ "conflict": {
+ "doctrine/common": "<2.9"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^10",
+ "phpstan/phpstan": "^1.8.8",
+ "phpunit/phpunit": "^9.5",
+ "vimeo/psalm": "^4.28"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Common\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ },
+ {
+ "name": "Marco Pivetta",
+ "email": "ocramius@gmail.com"
+ }
+ ],
+ "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.",
+ "homepage": "https://www.doctrine-project.org/projects/event-manager.html",
+ "keywords": [
+ "event",
+ "event dispatcher",
+ "event manager",
+ "event system",
+ "events"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/event-manager/issues",
+ "source": "https://github.com/doctrine/event-manager/tree/2.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://www.doctrine-project.org/sponsorship.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.patreon.com/phpdoctrine",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fevent-manager",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-10-12T20:59:15+00:00"
+ },
+ {
+ "name": "doctrine/inflector",
+ "version": "2.0.10",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/inflector.git",
+ "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc",
+ "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^11.0",
+ "phpstan/phpstan": "^1.8",
+ "phpstan/phpstan-phpunit": "^1.1",
+ "phpstan/phpstan-strict-rules": "^1.3",
+ "phpunit/phpunit": "^8.5 || ^9.5",
+ "vimeo/psalm": "^4.25 || ^5.4"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Inflector\\": "lib/Doctrine/Inflector"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ }
+ ],
+ "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.",
+ "homepage": "https://www.doctrine-project.org/projects/inflector.html",
+ "keywords": [
+ "inflection",
+ "inflector",
+ "lowercase",
+ "manipulation",
+ "php",
+ "plural",
+ "singular",
+ "strings",
+ "uppercase",
+ "words"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/inflector/issues",
+ "source": "https://github.com/doctrine/inflector/tree/2.0.10"
+ },
+ "funding": [
+ {
+ "url": "https://www.doctrine-project.org/sponsorship.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.patreon.com/phpdoctrine",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-02-18T20:23:39+00:00"
+ },
+ {
+ "name": "doctrine/instantiator",
+ "version": "2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/instantiator.git",
+ "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0",
+ "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.1"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^11",
+ "ext-pdo": "*",
+ "ext-phar": "*",
+ "phpbench/phpbench": "^1.2",
+ "phpstan/phpstan": "^1.9.4",
+ "phpstan/phpstan-phpunit": "^1.3",
+ "phpunit/phpunit": "^9.5.27",
+ "vimeo/psalm": "^5.4"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Marco Pivetta",
+ "email": "ocramius@gmail.com",
+ "homepage": "https://ocramius.github.io/"
+ }
+ ],
+ "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
+ "homepage": "https://www.doctrine-project.org/projects/instantiator.html",
+ "keywords": [
+ "constructor",
+ "instantiate"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/instantiator/issues",
+ "source": "https://github.com/doctrine/instantiator/tree/2.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://www.doctrine-project.org/sponsorship.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.patreon.com/phpdoctrine",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-12-30T00:23:10+00:00"
+ },
+ {
+ "name": "doctrine/lexer",
+ "version": "3.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/lexer.git",
+ "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd",
+ "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.1"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^12",
+ "phpstan/phpstan": "^1.10",
+ "phpunit/phpunit": "^10.5",
+ "psalm/plugin-phpunit": "^0.18.3",
+ "vimeo/psalm": "^5.21"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Common\\Lexer\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ }
+ ],
+ "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.",
+ "homepage": "https://www.doctrine-project.org/projects/lexer.html",
+ "keywords": [
+ "annotations",
+ "docblock",
+ "lexer",
+ "parser",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/lexer/issues",
+ "source": "https://github.com/doctrine/lexer/tree/3.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://www.doctrine-project.org/sponsorship.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.patreon.com/phpdoctrine",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-02-05T11:56:58+00:00"
+ },
+ {
+ "name": "doctrine/migrations",
+ "version": "3.7.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/migrations.git",
+ "reference": "47af29eef49f29ebee545947e8b2a4b3be318c8a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/migrations/zipball/47af29eef49f29ebee545947e8b2a4b3be318c8a",
+ "reference": "47af29eef49f29ebee545947e8b2a4b3be318c8a",
+ "shasum": ""
+ },
+ "require": {
+ "composer-runtime-api": "^2",
+ "doctrine/dbal": "^3.5.1 || ^4",
+ "doctrine/deprecations": "^0.5.3 || ^1",
+ "doctrine/event-manager": "^1.2 || ^2.0",
+ "php": "^8.1",
+ "psr/log": "^1.1.3 || ^2 || ^3",
+ "symfony/console": "^5.4 || ^6.0 || ^7.0",
+ "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0",
+ "symfony/var-exporter": "^6.2 || ^7.0"
+ },
+ "conflict": {
+ "doctrine/orm": "<2.12 || >=4"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^12",
+ "doctrine/orm": "^2.13 || ^3",
+ "doctrine/persistence": "^2 || ^3",
+ "doctrine/sql-formatter": "^1.0",
+ "ext-pdo_sqlite": "*",
+ "phpstan/phpstan": "^1.10",
+ "phpstan/phpstan-deprecation-rules": "^1.1",
+ "phpstan/phpstan-phpunit": "^1.3",
+ "phpstan/phpstan-strict-rules": "^1.4",
+ "phpstan/phpstan-symfony": "^1.3",
+ "phpunit/phpunit": "^10.3",
+ "symfony/cache": "^5.4 || ^6.0 || ^7.0",
+ "symfony/process": "^5.4 || ^6.0 || ^7.0",
+ "symfony/yaml": "^5.4 || ^6.0 || ^7.0"
+ },
+ "suggest": {
+ "doctrine/sql-formatter": "Allows to generate formatted SQL with the diff command.",
+ "symfony/yaml": "Allows the use of yaml for migration configuration files."
+ },
+ "bin": [
+ "bin/doctrine-migrations"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Migrations\\": "lib/Doctrine/Migrations"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Michael Simonson",
+ "email": "contact@mikesimonson.com"
+ }
+ ],
+ "description": "PHP Doctrine Migrations project offer additional functionality on top of the database abstraction layer (DBAL) for versioning your database schema and easily deploying changes to it. It is a very easy to use and a powerful tool.",
+ "homepage": "https://www.doctrine-project.org/projects/migrations.html",
+ "keywords": [
+ "database",
+ "dbal",
+ "migrations"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/migrations/issues",
+ "source": "https://github.com/doctrine/migrations/tree/3.7.2"
+ },
+ "funding": [
+ {
+ "url": "https://www.doctrine-project.org/sponsorship.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.patreon.com/phpdoctrine",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fmigrations",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-12-05T11:35:05+00:00"
+ },
+ {
+ "name": "doctrine/orm",
+ "version": "3.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/orm.git",
+ "reference": "2a250b5814de192a23438c0a43e15da7e77890a7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/orm/zipball/2a250b5814de192a23438c0a43e15da7e77890a7",
+ "reference": "2a250b5814de192a23438c0a43e15da7e77890a7",
+ "shasum": ""
+ },
+ "require": {
+ "composer-runtime-api": "^2",
+ "doctrine/collections": "^2.1",
+ "doctrine/dbal": "^3.8.2 || ^4",
+ "doctrine/deprecations": "^0.5.3 || ^1",
+ "doctrine/event-manager": "^1.2 || ^2",
+ "doctrine/inflector": "^1.4 || ^2.0",
+ "doctrine/instantiator": "^1.3 || ^2",
+ "doctrine/lexer": "^3",
+ "doctrine/persistence": "^3.1.1",
+ "ext-ctype": "*",
+ "php": "^8.1",
+ "psr/cache": "^1 || ^2 || ^3",
+ "symfony/console": "^5.4 || ^6.0 || ^7.0",
+ "symfony/var-exporter": "~6.2.13 || ^6.3.2 || ^7.0"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^12.0",
+ "phpbench/phpbench": "^1.0",
+ "phpstan/phpstan": "1.10.35",
+ "phpunit/phpunit": "^10.4.0",
+ "psr/log": "^1 || ^2 || ^3",
+ "squizlabs/php_codesniffer": "3.7.2",
+ "symfony/cache": "^5.4 || ^6.2 || ^7.0",
+ "vimeo/psalm": "5.16.0"
+ },
+ "suggest": {
+ "ext-dom": "Provides support for XSD validation for XML mapping files",
+ "symfony/cache": "Provides cache support for Setup Tool with doctrine/cache 2.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\ORM\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Marco Pivetta",
+ "email": "ocramius@gmail.com"
+ }
+ ],
+ "description": "Object-Relational-Mapper for PHP",
+ "homepage": "https://www.doctrine-project.org/projects/orm.html",
+ "keywords": [
+ "database",
+ "orm"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/orm/issues",
+ "source": "https://github.com/doctrine/orm/tree/3.0.1"
+ },
+ "time": "2024-02-22T12:23:53+00:00"
+ },
+ {
+ "name": "doctrine/persistence",
+ "version": "3.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/persistence.git",
+ "reference": "63fee8c33bef740db6730eb2a750cd3da6495603"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/persistence/zipball/63fee8c33bef740db6730eb2a750cd3da6495603",
+ "reference": "63fee8c33bef740db6730eb2a750cd3da6495603",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/event-manager": "^1 || ^2",
+ "php": "^7.2 || ^8.0",
+ "psr/cache": "^1.0 || ^2.0 || ^3.0"
+ },
+ "conflict": {
+ "doctrine/common": "<2.10"
+ },
+ "require-dev": {
+ "composer/package-versions-deprecated": "^1.11",
+ "doctrine/coding-standard": "^11",
+ "doctrine/common": "^3.0",
+ "phpstan/phpstan": "1.9.4",
+ "phpstan/phpstan-phpunit": "^1",
+ "phpstan/phpstan-strict-rules": "^1.1",
+ "phpunit/phpunit": "^8.5 || ^9.5",
+ "symfony/cache": "^4.4 || ^5.4 || ^6.0",
+ "vimeo/psalm": "4.30.0 || 5.3.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Persistence\\": "src/Persistence"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Guilherme Blanco",
+ "email": "guilhermeblanco@gmail.com"
+ },
+ {
+ "name": "Roman Borschel",
+ "email": "roman@code-factory.org"
+ },
+ {
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de"
+ },
+ {
+ "name": "Jonathan Wage",
+ "email": "jonwage@gmail.com"
+ },
+ {
+ "name": "Johannes Schmitt",
+ "email": "schmittjoh@gmail.com"
+ },
+ {
+ "name": "Marco Pivetta",
+ "email": "ocramius@gmail.com"
+ }
+ ],
+ "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.",
+ "homepage": "https://www.doctrine-project.org/projects/persistence.html",
+ "keywords": [
+ "mapper",
+ "object",
+ "odm",
+ "orm",
+ "persistence"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/persistence/issues",
+ "source": "https://github.com/doctrine/persistence/tree/3.2.0"
+ },
+ "funding": [
+ {
+ "url": "https://www.doctrine-project.org/sponsorship.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://www.patreon.com/phpdoctrine",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fpersistence",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-05-17T18:32:04+00:00"
+ },
+ {
+ "name": "doctrine/sql-formatter",
+ "version": "1.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/sql-formatter.git",
+ "reference": "a321d114e0a18e6497f8a2cd6f890e000cc17ecc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/a321d114e0a18e6497f8a2cd6f890e000cc17ecc",
+ "reference": "a321d114e0a18e6497f8a2cd6f890e000cc17ecc",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1 || ^8.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.4"
+ },
+ "bin": [
+ "bin/sql-formatter"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\SqlFormatter\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jeremy Dorn",
+ "email": "jeremy@jeremydorn.com",
+ "homepage": "https://jeremydorn.com/"
+ }
+ ],
+ "description": "a PHP SQL highlighting library",
+ "homepage": "https://github.com/doctrine/sql-formatter/",
+ "keywords": [
+ "highlight",
+ "sql"
+ ],
+ "support": {
+ "issues": "https://github.com/doctrine/sql-formatter/issues",
+ "source": "https://github.com/doctrine/sql-formatter/tree/1.2.0"
+ },
+ "time": "2023-08-16T21:49:04+00:00"
+ },
+ {
+ "name": "egulias/email-validator",
+ "version": "4.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/egulias/EmailValidator.git",
+ "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ebaaf5be6c0286928352e054f2d5125608e5405e",
+ "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/lexer": "^2.0 || ^3.0",
+ "php": ">=8.1",
+ "symfony/polyfill-intl-idn": "^1.26"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.2",
+ "vimeo/psalm": "^5.12"
+ },
+ "suggest": {
+ "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Egulias\\EmailValidator\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Eduardo Gulias Davis"
+ }
+ ],
+ "description": "A library for validating emails against several RFCs",
+ "homepage": "https://github.com/egulias/EmailValidator",
+ "keywords": [
+ "email",
+ "emailvalidation",
+ "emailvalidator",
+ "validation",
+ "validator"
+ ],
+ "support": {
+ "issues": "https://github.com/egulias/EmailValidator/issues",
+ "source": "https://github.com/egulias/EmailValidator/tree/4.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/egulias",
+ "type": "github"
+ }
+ ],
+ "time": "2023-10-06T06:47:41+00:00"
+ },
+ {
+ "name": "monolog/monolog",
+ "version": "3.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Seldaek/monolog.git",
+ "reference": "c915e2634718dbc8a4a15c61b0e62e7a44e14448"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Seldaek/monolog/zipball/c915e2634718dbc8a4a15c61b0e62e7a44e14448",
+ "reference": "c915e2634718dbc8a4a15c61b0e62e7a44e14448",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "psr/log": "^2.0 || ^3.0"
+ },
+ "provide": {
+ "psr/log-implementation": "3.0.0"
+ },
+ "require-dev": {
+ "aws/aws-sdk-php": "^3.0",
+ "doctrine/couchdb": "~1.0@dev",
+ "elasticsearch/elasticsearch": "^7 || ^8",
+ "ext-json": "*",
+ "graylog2/gelf-php": "^1.4.2 || ^2.0",
+ "guzzlehttp/guzzle": "^7.4.5",
+ "guzzlehttp/psr7": "^2.2",
+ "mongodb/mongodb": "^1.8",
+ "php-amqplib/php-amqplib": "~2.4 || ^3",
+ "phpstan/phpstan": "^1.9",
+ "phpstan/phpstan-deprecation-rules": "^1.0",
+ "phpstan/phpstan-strict-rules": "^1.4",
+ "phpunit/phpunit": "^10.1",
+ "predis/predis": "^1.1 || ^2",
+ "ruflin/elastica": "^7",
+ "symfony/mailer": "^5.4 || ^6",
+ "symfony/mime": "^5.4 || ^6"
+ },
+ "suggest": {
+ "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
+ "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
+ "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",
+ "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
+ "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler",
+ "ext-mbstring": "Allow to work properly with unicode symbols",
+ "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
+ "ext-openssl": "Required to send log messages using SSL",
+ "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)",
+ "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
+ "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
+ "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
+ "rollbar/rollbar": "Allow sending log messages to Rollbar",
+ "ruflin/elastica": "Allow sending log messages to an Elastic Search server"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Monolog\\": "src/Monolog"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "https://seld.be"
+ }
+ ],
+ "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
+ "homepage": "https://github.com/Seldaek/monolog",
+ "keywords": [
+ "log",
+ "logging",
+ "psr-3"
+ ],
+ "support": {
+ "issues": "https://github.com/Seldaek/monolog/issues",
+ "source": "https://github.com/Seldaek/monolog/tree/3.5.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/Seldaek",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/monolog/monolog",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-10-27T15:32:31+00:00"
+ },
+ {
+ "name": "phpdocumentor/reflection-common",
+ "version": "2.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
+ "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b",
+ "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-2.x": "2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "phpDocumentor\\Reflection\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jaap van Otterdijk",
+ "email": "opensource@ijaap.nl"
+ }
+ ],
+ "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
+ "homepage": "http://www.phpdoc.org",
+ "keywords": [
+ "FQSEN",
+ "phpDocumentor",
+ "phpdoc",
+ "reflection",
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues",
+ "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x"
+ },
+ "time": "2020-06-27T09:03:43+00:00"
+ },
+ {
+ "name": "phpdocumentor/reflection-docblock",
+ "version": "5.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
+ "reference": "622548b623e81ca6d78b721c5e029f4ce664f170"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170",
+ "reference": "622548b623e81ca6d78b721c5e029f4ce664f170",
+ "shasum": ""
+ },
+ "require": {
+ "ext-filter": "*",
+ "php": "^7.2 || ^8.0",
+ "phpdocumentor/reflection-common": "^2.2",
+ "phpdocumentor/type-resolver": "^1.3",
+ "webmozart/assert": "^1.9.1"
+ },
+ "require-dev": {
+ "mockery/mockery": "~1.3.2",
+ "psalm/phar": "^4.8"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "phpDocumentor\\Reflection\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Mike van Riel",
+ "email": "me@mikevanriel.com"
+ },
+ {
+ "name": "Jaap van Otterdijk",
+ "email": "account@ijaap.nl"
+ }
+ ],
+ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
+ "support": {
+ "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
+ "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0"
+ },
+ "time": "2021-10-19T17:43:47+00:00"
+ },
+ {
+ "name": "phpdocumentor/type-resolver",
+ "version": "1.8.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpDocumentor/TypeResolver.git",
+ "reference": "153ae662783729388a584b4361f2545e4d841e3c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c",
+ "reference": "153ae662783729388a584b4361f2545e4d841e3c",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/deprecations": "^1.0",
+ "php": "^7.3 || ^8.0",
+ "phpdocumentor/reflection-common": "^2.0",
+ "phpstan/phpdoc-parser": "^1.13"
+ },
+ "require-dev": {
+ "ext-tokenizer": "*",
+ "phpbench/phpbench": "^1.2",
+ "phpstan/extension-installer": "^1.1",
+ "phpstan/phpstan": "^1.8",
+ "phpstan/phpstan-phpunit": "^1.1",
+ "phpunit/phpunit": "^9.5",
+ "rector/rector": "^0.13.9",
+ "vimeo/psalm": "^4.25"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-1.x": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "phpDocumentor\\Reflection\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Mike van Riel",
+ "email": "me@mikevanriel.com"
+ }
+ ],
+ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
+ "support": {
+ "issues": "https://github.com/phpDocumentor/TypeResolver/issues",
+ "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2"
+ },
+ "time": "2024-02-23T11:10:43+00:00"
+ },
+ {
+ "name": "phpstan/phpdoc-parser",
+ "version": "1.26.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpstan/phpdoc-parser.git",
+ "reference": "231e3186624c03d7e7c890ec662b81e6b0405227"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/231e3186624c03d7e7c890ec662b81e6b0405227",
+ "reference": "231e3186624c03d7e7c890ec662b81e6b0405227",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "require-dev": {
+ "doctrine/annotations": "^2.0",
+ "nikic/php-parser": "^4.15",
+ "php-parallel-lint/php-parallel-lint": "^1.2",
+ "phpstan/extension-installer": "^1.0",
+ "phpstan/phpstan": "^1.5",
+ "phpstan/phpstan-phpunit": "^1.1",
+ "phpstan/phpstan-strict-rules": "^1.0",
+ "phpunit/phpunit": "^9.5",
+ "symfony/process": "^5.2"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "PHPStan\\PhpDocParser\\": [
+ "src/"
+ ]
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "PHPDoc parser with support for nullable, intersection and generic types",
+ "support": {
+ "issues": "https://github.com/phpstan/phpdoc-parser/issues",
+ "source": "https://github.com/phpstan/phpdoc-parser/tree/1.26.0"
+ },
+ "time": "2024-02-23T16:05:55+00:00"
+ },
+ {
+ "name": "psr/cache",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/cache.git",
+ "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
+ "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Cache\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for caching libraries",
+ "keywords": [
+ "cache",
+ "psr",
+ "psr-6"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/cache/tree/3.0.0"
+ },
+ "time": "2021-02-03T23:26:27+00:00"
+ },
+ {
+ "name": "psr/clock",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/clock.git",
+ "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d",
+ "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.0 || ^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Psr\\Clock\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for reading the clock.",
+ "homepage": "https://github.com/php-fig/clock",
+ "keywords": [
+ "clock",
+ "now",
+ "psr",
+ "psr-20",
+ "time"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/clock/issues",
+ "source": "https://github.com/php-fig/clock/tree/1.0.0"
+ },
+ "time": "2022-11-25T14:36:26+00:00"
+ },
+ {
+ "name": "psr/container",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
+ "keywords": [
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
+ ],
+ "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": "psr/event-dispatcher",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/event-dispatcher.git",
+ "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0",
+ "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\EventDispatcher\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Standard interfaces for event handling.",
+ "keywords": [
+ "events",
+ "psr",
+ "psr-14"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/event-dispatcher/issues",
+ "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0"
+ },
+ "time": "2019-01-08T18:20:26+00:00"
+ },
+ {
+ "name": "psr/link",
+ "version": "2.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/link.git",
+ "reference": "84b159194ecfd7eaa472280213976e96415433f7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/link/zipball/84b159194ecfd7eaa472280213976e96415433f7",
+ "reference": "84b159194ecfd7eaa472280213976e96415433f7",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "suggest": {
+ "fig/link-util": "Provides some useful PSR-13 utilities"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Link\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interfaces for HTTP links",
+ "homepage": "https://github.com/php-fig/link",
+ "keywords": [
+ "http",
+ "http-link",
+ "link",
+ "psr",
+ "psr-13",
+ "rest"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/link/tree/2.0.1"
+ },
+ "time": "2021-03-11T23:00:27+00:00"
+ },
+ {
+ "name": "psr/log",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
+ "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/log/tree/3.0.0"
+ },
+ "time": "2021-07-14T16:46:02+00:00"
+ },
+ {
+ "name": "symfony/asset",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/asset.git",
+ "reference": "3ae493792fc17cc31b84e231f30f2d154575f171"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/asset/zipball/3ae493792fc17cc31b84e231f30f2d154575f171",
+ "reference": "3ae493792fc17cc31b84e231f30f2d154575f171",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "conflict": {
+ "symfony/http-foundation": "<6.4"
+ },
+ "require-dev": {
+ "symfony/http-client": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Asset\\": ""
+ },
+ "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": "Manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/asset/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/asset-mapper",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/asset-mapper.git",
+ "reference": "7cd421551f53849f641a1a3499392ed5c81598a8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/asset-mapper/zipball/7cd421551f53849f641a1a3499392ed5c81598a8",
+ "reference": "7cd421551f53849f641a1a3499392ed5c81598a8",
+ "shasum": ""
+ },
+ "require": {
+ "composer/semver": "^3.0",
+ "php": ">=8.2",
+ "symfony/filesystem": "^6.4|^7.0",
+ "symfony/http-client": "^6.4|^7.0"
+ },
+ "conflict": {
+ "symfony/framework-bundle": "<6.4"
+ },
+ "require-dev": {
+ "symfony/asset": "^6.4|^7.0",
+ "symfony/browser-kit": "^6.4|^7.0",
+ "symfony/console": "^6.4|^7.0",
+ "symfony/event-dispatcher-contracts": "^3.0",
+ "symfony/finder": "^6.4|^7.0",
+ "symfony/framework-bundle": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/web-link": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\AssetMapper\\": ""
+ },
+ "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": "Maps directories of assets & makes them available in a public directory with versioned filenames.",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/asset-mapper/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-22T20:27:20+00:00"
+ },
+ {
+ "name": "symfony/cache",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/cache.git",
+ "reference": "fc822951dd360a593224bb2cef90a087d0dff60f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/cache/zipball/fc822951dd360a593224bb2cef90a087d0dff60f",
+ "reference": "fc822951dd360a593224bb2cef90a087d0dff60f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "psr/cache": "^2.0|^3.0",
+ "psr/log": "^1.1|^2|^3",
+ "symfony/cache-contracts": "^2.5|^3",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/var-exporter": "^6.4|^7.0"
+ },
+ "conflict": {
+ "doctrine/dbal": "<3.6",
+ "symfony/dependency-injection": "<6.4",
+ "symfony/http-kernel": "<6.4",
+ "symfony/var-dumper": "<6.4"
+ },
+ "provide": {
+ "psr/cache-implementation": "2.0|3.0",
+ "psr/simple-cache-implementation": "1.0|2.0|3.0",
+ "symfony/cache-implementation": "1.1|2.0|3.0"
+ },
+ "require-dev": {
+ "cache/integration-tests": "dev-master",
+ "doctrine/dbal": "^3.6|^4",
+ "predis/predis": "^1.1|^2.0",
+ "psr/simple-cache": "^1.0|^2.0|^3.0",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/filesystem": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/messenger": "^6.4|^7.0",
+ "symfony/var-dumper": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Cache\\": ""
+ },
+ "classmap": [
+ "Traits/ValueWrapper.php"
+ ],
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "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": "Provides extended PSR-6, PSR-16 (and tags) implementations",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "caching",
+ "psr6"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/cache/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-22T20:27:20+00:00"
+ },
+ {
+ "name": "symfony/cache-contracts",
+ "version": "v3.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/cache-contracts.git",
+ "reference": "1d74b127da04ffa87aa940abe15446fa89653778"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/1d74b127da04ffa87aa940abe15446fa89653778",
+ "reference": "1d74b127da04ffa87aa940abe15446fa89653778",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "psr/cache": "^3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\Cache\\": ""
+ }
+ },
+ "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 caching",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/cache-contracts/tree/v3.4.0"
+ },
+ "funding": [
+ {
+ "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": "2023-09-25T12:52:38+00:00"
+ },
+ {
+ "name": "symfony/clock",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/clock.git",
+ "reference": "1c680e565dc0044d8ed3baeb57835fcacd9c6aed"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/clock/zipball/1c680e565dc0044d8ed3baeb57835fcacd9c6aed",
+ "reference": "1c680e565dc0044d8ed3baeb57835fcacd9c6aed",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "psr/clock": "^1.0",
+ "symfony/polyfill-php83": "^1.28"
+ },
+ "provide": {
+ "psr/clock-implementation": "1.0"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "Resources/now.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\Clock\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "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": "Decouples applications from the system clock",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "clock",
+ "psr20",
+ "time"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/clock/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/config",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/config.git",
+ "reference": "44deeba7233f08f383185ffa37dace3b3bc87364"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/config/zipball/44deeba7233f08f383185ffa37dace3b3bc87364",
+ "reference": "44deeba7233f08f383185ffa37dace3b3bc87364",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/filesystem": "^6.4|^7.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",
+ "symfony/finder": "^6.4|^7.0",
+ "symfony/messenger": "^6.4|^7.0",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/yaml": "^6.4|^7.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.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-26T07:52:39+00:00"
+ },
+ {
+ "name": "symfony/console",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/console.git",
+ "reference": "6b099f3306f7c9c2d2786ed736d0026b2903205f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/console/zipball/6b099f3306f7c9c2d2786ed736d0026b2903205f",
+ "reference": "6b099f3306f7c9c2d2786ed736d0026b2903205f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/string": "^6.4|^7.0"
+ },
+ "conflict": {
+ "symfony/dependency-injection": "<6.4",
+ "symfony/dotenv": "<6.4",
+ "symfony/event-dispatcher": "<6.4",
+ "symfony/lock": "<6.4",
+ "symfony/process": "<6.4"
+ },
+ "provide": {
+ "psr/log-implementation": "1.0|2.0|3.0"
+ },
+ "require-dev": {
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/event-dispatcher": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/lock": "^6.4|^7.0",
+ "symfony/messenger": "^6.4|^7.0",
+ "symfony/process": "^6.4|^7.0",
+ "symfony/stopwatch": "^6.4|^7.0",
+ "symfony/var-dumper": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Console\\": ""
+ },
+ "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": "Eases the creation of beautiful and testable command line interfaces",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "cli",
+ "command-line",
+ "console",
+ "terminal"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/console/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-22T20:27:20+00:00"
+ },
+ {
+ "name": "symfony/dependency-injection",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/dependency-injection.git",
+ "reference": "47f37af245df8457ea63409fc242b3cc825ce5eb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/47f37af245df8457ea63409fc242b3cc825ce5eb",
+ "reference": "47f37af245df8457ea63409fc242b3cc825ce5eb",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "psr/container": "^1.1|^2.0",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/service-contracts": "^3.3",
+ "symfony/var-exporter": "^6.4|^7.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",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/yaml": "^6.4|^7.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.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-22T20:27:20+00:00"
+ },
+ {
+ "name": "symfony/deprecation-contracts",
+ "version": "v3.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/deprecation-contracts.git",
+ "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf",
+ "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "files": [
+ "function.php"
+ ]
+ },
+ "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": "A generic function and convention to trigger deprecation notices",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0"
+ },
+ "funding": [
+ {
+ "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": "2023-05-23T14:45:45+00:00"
+ },
+ {
+ "name": "symfony/doctrine-bridge",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/doctrine-bridge.git",
+ "reference": "aded7ef586f9c75a04627326a5748f29ceba3506"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/aded7ef586f9c75a04627326a5748f29ceba3506",
+ "reference": "aded7ef586f9c75a04627326a5748f29ceba3506",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/event-manager": "^2",
+ "doctrine/persistence": "^3.1",
+ "php": ">=8.2",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/service-contracts": "^2.5|^3"
+ },
+ "conflict": {
+ "doctrine/dbal": "<3.6",
+ "doctrine/lexer": "<1.1",
+ "doctrine/orm": "<2.15",
+ "symfony/cache": "<6.4",
+ "symfony/dependency-injection": "<6.4",
+ "symfony/form": "<6.4",
+ "symfony/http-foundation": "<6.4",
+ "symfony/http-kernel": "<6.4",
+ "symfony/lock": "<6.4",
+ "symfony/messenger": "<6.4",
+ "symfony/property-info": "<6.4",
+ "symfony/security-bundle": "<6.4",
+ "symfony/security-core": "<6.4",
+ "symfony/validator": "<6.4"
+ },
+ "require-dev": {
+ "doctrine/collections": "^1.0|^2.0",
+ "doctrine/data-fixtures": "^1.1",
+ "doctrine/dbal": "^3.6|^4",
+ "doctrine/orm": "^2.15|^3",
+ "psr/log": "^1|^2|^3",
+ "symfony/cache": "^6.4|^7.0",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/doctrine-messenger": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/form": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/lock": "^6.4|^7.0",
+ "symfony/messenger": "^6.4|^7.0",
+ "symfony/property-access": "^6.4|^7.0",
+ "symfony/property-info": "^6.4|^7.0",
+ "symfony/security-core": "^6.4|^7.0",
+ "symfony/stopwatch": "^6.4|^7.0",
+ "symfony/translation": "^6.4|^7.0",
+ "symfony/uid": "^6.4|^7.0",
+ "symfony/validator": "^6.4|^7.0",
+ "symfony/var-dumper": "^6.4|^7.0"
+ },
+ "type": "symfony-bridge",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Bridge\\Doctrine\\": ""
+ },
+ "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 integration for Doctrine with various Symfony components",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/doctrine-bridge/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-04T16:21:40+00:00"
+ },
+ {
+ "name": "symfony/doctrine-messenger",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/doctrine-messenger.git",
+ "reference": "5a9ebba1b0be17af7b1e6b6433ad2cb6e35e97ca"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/doctrine-messenger/zipball/5a9ebba1b0be17af7b1e6b6433ad2cb6e35e97ca",
+ "reference": "5a9ebba1b0be17af7b1e6b6433ad2cb6e35e97ca",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/dbal": "^3.6|^4",
+ "php": ">=8.2",
+ "symfony/messenger": "^6.4|^7.0",
+ "symfony/service-contracts": "^2.5|^3"
+ },
+ "conflict": {
+ "doctrine/persistence": "<1.3"
+ },
+ "require-dev": {
+ "doctrine/persistence": "^1.3|^2|^3",
+ "symfony/property-access": "^6.4|^7.0",
+ "symfony/serializer": "^6.4|^7.0"
+ },
+ "type": "symfony-messenger-bridge",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Messenger\\Bridge\\Doctrine\\": ""
+ },
+ "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": "Symfony Doctrine Messenger Bridge",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/doctrine-messenger/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-22T20:27:20+00:00"
+ },
+ {
+ "name": "symfony/dotenv",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/dotenv.git",
+ "reference": "8017ea2f0ff4fbda6ae1bf3f5409d5ecff982067"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/dotenv/zipball/8017ea2f0ff4fbda6ae1bf3f5409d5ecff982067",
+ "reference": "8017ea2f0ff4fbda6ae1bf3f5409d5ecff982067",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "conflict": {
+ "symfony/console": "<6.4",
+ "symfony/process": "<6.4"
+ },
+ "require-dev": {
+ "symfony/console": "^6.4|^7.0",
+ "symfony/process": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Dotenv\\": ""
+ },
+ "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": "Registers environment variables from a .env file",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "dotenv",
+ "env",
+ "environment"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/dotenv/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-09T10:53:15+00:00"
+ },
+ {
+ "name": "symfony/error-handler",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/error-handler.git",
+ "reference": "677b24759decff69e65b1e9d1471d90f95ced880"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/error-handler/zipball/677b24759decff69e65b1e9d1471d90f95ced880",
+ "reference": "677b24759decff69e65b1e9d1471d90f95ced880",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "psr/log": "^1|^2|^3",
+ "symfony/var-dumper": "^6.4|^7.0"
+ },
+ "conflict": {
+ "symfony/deprecation-contracts": "<2.5",
+ "symfony/http-kernel": "<6.4"
+ },
+ "require-dev": {
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/serializer": "^6.4|^7.0"
+ },
+ "bin": [
+ "Resources/bin/patch-type-declarations"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\ErrorHandler\\": ""
+ },
+ "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 tools to manage errors and ease debugging PHP code",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/error-handler/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-22T20:27:20+00:00"
+ },
+ {
+ "name": "symfony/event-dispatcher",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/event-dispatcher.git",
+ "reference": "834c28d533dd0636f910909d01b9ff45cc094b5e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/834c28d533dd0636f910909d01b9ff45cc094b5e",
+ "reference": "834c28d533dd0636f910909d01b9ff45cc094b5e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/event-dispatcher-contracts": "^2.5|^3"
+ },
+ "conflict": {
+ "symfony/dependency-injection": "<6.4",
+ "symfony/service-contracts": "<2.5"
+ },
+ "provide": {
+ "psr/event-dispatcher-implementation": "1.0",
+ "symfony/event-dispatcher-implementation": "2.0|3.0"
+ },
+ "require-dev": {
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/error-handler": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/stopwatch": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\EventDispatcher\\": ""
+ },
+ "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 tools that allow your application components to communicate with each other by dispatching events and listening to them",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/event-dispatcher/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/event-dispatcher-contracts",
+ "version": "v3.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/event-dispatcher-contracts.git",
+ "reference": "a76aed96a42d2b521153fb382d418e30d18b59df"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df",
+ "reference": "a76aed96a42d2b521153fb382d418e30d18b59df",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "psr/event-dispatcher": "^1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\EventDispatcher\\": ""
+ }
+ },
+ "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 dispatching event",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.0"
+ },
+ "funding": [
+ {
+ "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": "2023-05-23T14:45:45+00:00"
+ },
+ {
+ "name": "symfony/expression-language",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/expression-language.git",
+ "reference": "0877c599cb260c9614f9229c0a2090d6919fd621"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/expression-language/zipball/0877c599cb260c9614f9229c0a2090d6919fd621",
+ "reference": "0877c599cb260c9614f9229c0a2090d6919fd621",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/cache": "^6.4|^7.0",
+ "symfony/service-contracts": "^2.5|^3"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\ExpressionLanguage\\": ""
+ },
+ "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 an engine that can compile and evaluate expressions",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/expression-language/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/filesystem",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/filesystem.git",
+ "reference": "2890e3a825bc0c0558526c04499c13f83e1b6b12"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/2890e3a825bc0c0558526c04499c13f83e1b6b12",
+ "reference": "2890e3a825bc0c0558526c04499c13f83e1b6b12",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-mbstring": "~1.8"
+ },
+ "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.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/finder",
+ "version": "v7.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/finder.git",
+ "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/6e5688d69f7cfc4ed4a511e96007e06c2d34ce56",
+ "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "symfony/filesystem": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Finder\\": ""
+ },
+ "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": "Finds files and directories via an intuitive fluent interface",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/finder/tree/v7.0.0"
+ },
+ "funding": [
+ {
+ "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": "2023-10-31T17:59:56+00:00"
+ },
+ {
+ "name": "symfony/flex",
+ "version": "v2.4.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/flex.git",
+ "reference": "bec213c39511eda66663baa2ee7440c65f89c695"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/flex/zipball/bec213c39511eda66663baa2ee7440c65f89c695",
+ "reference": "bec213c39511eda66663baa2ee7440c65f89c695",
+ "shasum": ""
+ },
+ "require": {
+ "composer-plugin-api": "^2.1",
+ "php": ">=8.0"
+ },
+ "require-dev": {
+ "composer/composer": "^2.1",
+ "symfony/dotenv": "^5.4|^6.0",
+ "symfony/filesystem": "^5.4|^6.0",
+ "symfony/phpunit-bridge": "^5.4|^6.0",
+ "symfony/process": "^5.4|^6.0"
+ },
+ "type": "composer-plugin",
+ "extra": {
+ "class": "Symfony\\Flex\\Flex"
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Flex\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien.potencier@gmail.com"
+ }
+ ],
+ "description": "Composer plugin for Symfony",
+ "support": {
+ "issues": "https://github.com/symfony/flex/issues",
+ "source": "https://github.com/symfony/flex/tree/v2.4.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-05T18:04:53+00:00"
+ },
+ {
+ "name": "symfony/form",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/form.git",
+ "reference": "5cfe85c74caf924c7cec2134e169320b464ede84"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/form/zipball/5cfe85c74caf924c7cec2134e169320b464ede84",
+ "reference": "5cfe85c74caf924c7cec2134e169320b464ede84",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/event-dispatcher": "^6.4|^7.0",
+ "symfony/options-resolver": "^6.4|^7.0",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-intl-icu": "^1.21",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/property-access": "^6.4|^7.0",
+ "symfony/service-contracts": "^2.5|^3"
+ },
+ "conflict": {
+ "symfony/console": "<6.4",
+ "symfony/dependency-injection": "<6.4",
+ "symfony/doctrine-bridge": "<6.4",
+ "symfony/error-handler": "<6.4",
+ "symfony/framework-bundle": "<6.4",
+ "symfony/http-kernel": "<6.4",
+ "symfony/translation": "<6.4.3|>=7.0,<7.0.3",
+ "symfony/translation-contracts": "<2.5",
+ "symfony/twig-bridge": "<6.4"
+ },
+ "require-dev": {
+ "doctrine/collections": "^1.0|^2.0",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/console": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/html-sanitizer": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/intl": "^6.4|^7.0",
+ "symfony/security-core": "^6.4|^7.0",
+ "symfony/security-csrf": "^6.4|^7.0",
+ "symfony/translation": "^6.4.3|^7.0.3",
+ "symfony/uid": "^6.4|^7.0",
+ "symfony/validator": "^6.4|^7.0",
+ "symfony/var-dumper": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Form\\": ""
+ },
+ "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 to easily create, process and reuse HTML forms",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/form/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-12T11:15:03+00:00"
+ },
+ {
+ "name": "symfony/framework-bundle",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/framework-bundle.git",
+ "reference": "b58bcb2f9c32405b8fbaa24a1e38c8a10bad7b21"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/b58bcb2f9c32405b8fbaa24a1e38c8a10bad7b21",
+ "reference": "b58bcb2f9c32405b8fbaa24a1e38c8a10bad7b21",
+ "shasum": ""
+ },
+ "require": {
+ "composer-runtime-api": ">=2.1",
+ "ext-xml": "*",
+ "php": ">=8.2",
+ "symfony/cache": "^6.4|^7.0",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/error-handler": "^6.4|^7.0",
+ "symfony/event-dispatcher": "^6.4|^7.0",
+ "symfony/filesystem": "^6.4|^7.0",
+ "symfony/finder": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/routing": "^6.4|^7.0"
+ },
+ "conflict": {
+ "doctrine/persistence": "<1.3",
+ "phpdocumentor/reflection-docblock": "<3.2.2",
+ "phpdocumentor/type-resolver": "<1.4.0",
+ "symfony/asset": "<6.4",
+ "symfony/asset-mapper": "<6.4",
+ "symfony/clock": "<6.4",
+ "symfony/console": "<6.4",
+ "symfony/dom-crawler": "<6.4",
+ "symfony/dotenv": "<6.4",
+ "symfony/form": "<6.4",
+ "symfony/http-client": "<6.4",
+ "symfony/lock": "<6.4",
+ "symfony/mailer": "<6.4",
+ "symfony/messenger": "<6.4",
+ "symfony/mime": "<6.4",
+ "symfony/property-access": "<6.4",
+ "symfony/property-info": "<6.4",
+ "symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4",
+ "symfony/security-core": "<6.4",
+ "symfony/security-csrf": "<6.4",
+ "symfony/serializer": "<6.4",
+ "symfony/stopwatch": "<6.4",
+ "symfony/translation": "<6.4",
+ "symfony/twig-bridge": "<6.4",
+ "symfony/twig-bundle": "<6.4",
+ "symfony/validator": "<6.4",
+ "symfony/web-profiler-bundle": "<6.4",
+ "symfony/workflow": "<6.4"
+ },
+ "require-dev": {
+ "doctrine/persistence": "^1.3|^2|^3",
+ "dragonmantank/cron-expression": "^3.1",
+ "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
+ "seld/jsonlint": "^1.10",
+ "symfony/asset": "^6.4|^7.0",
+ "symfony/asset-mapper": "^6.4|^7.0",
+ "symfony/browser-kit": "^6.4|^7.0",
+ "symfony/clock": "^6.4|^7.0",
+ "symfony/console": "^6.4|^7.0",
+ "symfony/css-selector": "^6.4|^7.0",
+ "symfony/dom-crawler": "^6.4|^7.0",
+ "symfony/dotenv": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/form": "^6.4|^7.0",
+ "symfony/html-sanitizer": "^6.4|^7.0",
+ "symfony/http-client": "^6.4|^7.0",
+ "symfony/lock": "^6.4|^7.0",
+ "symfony/mailer": "^6.4|^7.0",
+ "symfony/messenger": "^6.4|^7.0",
+ "symfony/mime": "^6.4|^7.0",
+ "symfony/notifier": "^6.4|^7.0",
+ "symfony/polyfill-intl-icu": "~1.0",
+ "symfony/process": "^6.4|^7.0",
+ "symfony/property-info": "^6.4|^7.0",
+ "symfony/rate-limiter": "^6.4|^7.0",
+ "symfony/scheduler": "^6.4.4|^7.0.4",
+ "symfony/security-bundle": "^6.4|^7.0",
+ "symfony/semaphore": "^6.4|^7.0",
+ "symfony/serializer": "^6.4|^7.0",
+ "symfony/stopwatch": "^6.4|^7.0",
+ "symfony/string": "^6.4|^7.0",
+ "symfony/translation": "^6.4|^7.0",
+ "symfony/twig-bundle": "^6.4|^7.0",
+ "symfony/uid": "^6.4|^7.0",
+ "symfony/validator": "^6.4|^7.0",
+ "symfony/web-link": "^6.4|^7.0",
+ "symfony/workflow": "^6.4|^7.0",
+ "symfony/yaml": "^6.4|^7.0",
+ "twig/twig": "^3.0.4"
+ },
+ "type": "symfony-bundle",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Bundle\\FrameworkBundle\\": ""
+ },
+ "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 a tight integration between Symfony components and the Symfony full-stack framework",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/framework-bundle/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-26T07:52:39+00:00"
+ },
+ {
+ "name": "symfony/http-client",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/http-client.git",
+ "reference": "8384876f49a2316a63f88a9cd12436de6936bee6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/http-client/zipball/8384876f49a2316a63f88a9cd12436de6936bee6",
+ "reference": "8384876f49a2316a63f88a9cd12436de6936bee6",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "psr/log": "^1|^2|^3",
+ "symfony/http-client-contracts": "^3",
+ "symfony/service-contracts": "^2.5|^3"
+ },
+ "conflict": {
+ "php-http/discovery": "<1.15",
+ "symfony/http-foundation": "<6.4"
+ },
+ "provide": {
+ "php-http/async-client-implementation": "*",
+ "php-http/client-implementation": "*",
+ "psr/http-client-implementation": "1.0",
+ "symfony/http-client-implementation": "3.0"
+ },
+ "require-dev": {
+ "amphp/amp": "^2.5",
+ "amphp/http-client": "^4.2.1",
+ "amphp/http-tunnel": "^1.0",
+ "amphp/socket": "^1.1",
+ "guzzlehttp/promises": "^1.4",
+ "nyholm/psr7": "^1.0",
+ "php-http/httplug": "^1.0|^2.0",
+ "psr/http-client": "^1.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/messenger": "^6.4|^7.0",
+ "symfony/process": "^6.4|^7.0",
+ "symfony/stopwatch": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\HttpClient\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "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": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "http"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/http-client/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-15T11:33:06+00:00"
+ },
+ {
+ "name": "symfony/http-client-contracts",
+ "version": "v3.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/http-client-contracts.git",
+ "reference": "1ee70e699b41909c209a0c930f11034b93578654"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/1ee70e699b41909c209a0c930f11034b93578654",
+ "reference": "1ee70e699b41909c209a0c930f11034b93578654",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\HttpClient\\": ""
+ },
+ "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 HTTP clients",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/http-client-contracts/tree/v3.4.0"
+ },
+ "funding": [
+ {
+ "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": "2023-07-30T20:28:31+00:00"
+ },
+ {
+ "name": "symfony/http-foundation",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/http-foundation.git",
+ "reference": "439fdfdd344943254b1ef6278613e79040548045"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/439fdfdd344943254b1ef6278613e79040548045",
+ "reference": "439fdfdd344943254b1ef6278613e79040548045",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-mbstring": "~1.1",
+ "symfony/polyfill-php83": "^1.27"
+ },
+ "conflict": {
+ "doctrine/dbal": "<3.6",
+ "symfony/cache": "<6.4"
+ },
+ "require-dev": {
+ "doctrine/dbal": "^3.6|^4",
+ "predis/predis": "^1.1|^2.0",
+ "symfony/cache": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/mime": "^6.4|^7.0",
+ "symfony/rate-limiter": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\HttpFoundation\\": ""
+ },
+ "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": "Defines an object-oriented layer for the HTTP specification",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/http-foundation/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-08T19:22:56+00:00"
+ },
+ {
+ "name": "symfony/http-kernel",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/http-kernel.git",
+ "reference": "065e2234d907c0fc4fc942bf223f7cfc016d0ac7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/065e2234d907c0fc4fc942bf223f7cfc016d0ac7",
+ "reference": "065e2234d907c0fc4fc942bf223f7cfc016d0ac7",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "psr/log": "^1|^2|^3",
+ "symfony/error-handler": "^6.4|^7.0",
+ "symfony/event-dispatcher": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/polyfill-ctype": "^1.8"
+ },
+ "conflict": {
+ "symfony/browser-kit": "<6.4",
+ "symfony/cache": "<6.4",
+ "symfony/config": "<6.4",
+ "symfony/console": "<6.4",
+ "symfony/dependency-injection": "<6.4",
+ "symfony/doctrine-bridge": "<6.4",
+ "symfony/form": "<6.4",
+ "symfony/http-client": "<6.4",
+ "symfony/http-client-contracts": "<2.5",
+ "symfony/mailer": "<6.4",
+ "symfony/messenger": "<6.4",
+ "symfony/translation": "<6.4",
+ "symfony/translation-contracts": "<2.5",
+ "symfony/twig-bridge": "<6.4",
+ "symfony/validator": "<6.4",
+ "symfony/var-dumper": "<6.4",
+ "twig/twig": "<3.0.4"
+ },
+ "provide": {
+ "psr/log-implementation": "1.0|2.0|3.0"
+ },
+ "require-dev": {
+ "psr/cache": "^1.0|^2.0|^3.0",
+ "symfony/browser-kit": "^6.4|^7.0",
+ "symfony/clock": "^6.4|^7.0",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/console": "^6.4|^7.0",
+ "symfony/css-selector": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/dom-crawler": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/finder": "^6.4|^7.0",
+ "symfony/http-client-contracts": "^2.5|^3",
+ "symfony/process": "^6.4|^7.0",
+ "symfony/property-access": "^6.4|^7.0",
+ "symfony/routing": "^6.4|^7.0",
+ "symfony/serializer": "^6.4.4|^7.0.4",
+ "symfony/stopwatch": "^6.4|^7.0",
+ "symfony/translation": "^6.4|^7.0",
+ "symfony/translation-contracts": "^2.5|^3",
+ "symfony/uid": "^6.4|^7.0",
+ "symfony/validator": "^6.4|^7.0",
+ "symfony/var-exporter": "^6.4|^7.0",
+ "twig/twig": "^3.0.4"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\HttpKernel\\": ""
+ },
+ "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 a structured process for converting a Request into a Response",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/http-kernel/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-27T06:35:35+00:00"
+ },
+ {
+ "name": "symfony/intl",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/intl.git",
+ "reference": "295995df4acf6790a35b9ce6ec32b313efb11ff8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/intl/zipball/295995df4acf6790a35b9ce6ec32b313efb11ff8",
+ "reference": "295995df4acf6790a35b9ce6ec32b313efb11ff8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "symfony/filesystem": "^6.4|^7.0",
+ "symfony/finder": "^6.4|^7.0",
+ "symfony/var-exporter": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Intl\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
+ },
+ {
+ "name": "Eriksen Costa",
+ "email": "eriksen.costa@infranology.com.br"
+ },
+ {
+ "name": "Igor Wiedler",
+ "email": "igor@wiedler.ch"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides access to the localization data of the ICU library",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "i18n",
+ "icu",
+ "internationalization",
+ "intl",
+ "l10n",
+ "localization"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/intl/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/mailer",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/mailer.git",
+ "reference": "72e16d87bf50a3ce195b9470c06bb9d7b816ea85"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/mailer/zipball/72e16d87bf50a3ce195b9470c06bb9d7b816ea85",
+ "reference": "72e16d87bf50a3ce195b9470c06bb9d7b816ea85",
+ "shasum": ""
+ },
+ "require": {
+ "egulias/email-validator": "^2.1.10|^3|^4",
+ "php": ">=8.2",
+ "psr/event-dispatcher": "^1",
+ "psr/log": "^1|^2|^3",
+ "symfony/event-dispatcher": "^6.4|^7.0",
+ "symfony/mime": "^6.4|^7.0",
+ "symfony/service-contracts": "^2.5|^3"
+ },
+ "conflict": {
+ "symfony/http-client-contracts": "<2.5",
+ "symfony/http-kernel": "<6.4",
+ "symfony/messenger": "<6.4",
+ "symfony/mime": "<6.4",
+ "symfony/twig-bridge": "<6.4"
+ },
+ "require-dev": {
+ "symfony/console": "^6.4|^7.0",
+ "symfony/http-client": "^6.4|^7.0",
+ "symfony/messenger": "^6.4|^7.0",
+ "symfony/twig-bridge": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Mailer\\": ""
+ },
+ "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 sending emails",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/mailer/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-03T21:34:19+00:00"
+ },
+ {
+ "name": "symfony/messenger",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/messenger.git",
+ "reference": "804a8997f93313a8f7ed19e8cca3b44fdd18bdec"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/messenger/zipball/804a8997f93313a8f7ed19e8cca3b44fdd18bdec",
+ "reference": "804a8997f93313a8f7ed19e8cca3b44fdd18bdec",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "psr/log": "^1|^2|^3",
+ "symfony/clock": "^6.4|^7.0"
+ },
+ "conflict": {
+ "symfony/console": "<6.4",
+ "symfony/event-dispatcher": "<6.4",
+ "symfony/event-dispatcher-contracts": "<2.5",
+ "symfony/framework-bundle": "<6.4",
+ "symfony/http-kernel": "<6.4",
+ "symfony/serializer": "<6.4"
+ },
+ "require-dev": {
+ "psr/cache": "^1.0|^2.0|^3.0",
+ "symfony/console": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/event-dispatcher": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/process": "^6.4|^7.0",
+ "symfony/property-access": "^6.4|^7.0",
+ "symfony/rate-limiter": "^6.4|^7.0",
+ "symfony/routing": "^6.4|^7.0",
+ "symfony/serializer": "^6.4|^7.0",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/stopwatch": "^6.4|^7.0",
+ "symfony/validator": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Messenger\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Samuel Roze",
+ "email": "samuel.roze@gmail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Helps applications send and receive messages to/from other applications or via message queues",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/messenger/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-26T07:52:39+00:00"
+ },
+ {
+ "name": "symfony/mime",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/mime.git",
+ "reference": "c1ffe24ba6fdc3e3f0f3fcb93519103b326a3716"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/mime/zipball/c1ffe24ba6fdc3e3f0f3fcb93519103b326a3716",
+ "reference": "c1ffe24ba6fdc3e3f0f3fcb93519103b326a3716",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-intl-idn": "^1.10",
+ "symfony/polyfill-mbstring": "^1.0"
+ },
+ "conflict": {
+ "egulias/email-validator": "~3.0.0",
+ "phpdocumentor/reflection-docblock": "<3.2.2",
+ "phpdocumentor/type-resolver": "<1.4.0",
+ "symfony/mailer": "<6.4",
+ "symfony/serializer": "<6.4"
+ },
+ "require-dev": {
+ "egulias/email-validator": "^2.1.10|^3.1|^4",
+ "league/html-to-markdown": "^5.0",
+ "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/property-access": "^6.4|^7.0",
+ "symfony/property-info": "^6.4|^7.0",
+ "symfony/serializer": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Mime\\": ""
+ },
+ "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 manipulating MIME messages",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "mime",
+ "mime-type"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/mime/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-30T08:34:29+00:00"
+ },
+ {
+ "name": "symfony/monolog-bridge",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/monolog-bridge.git",
+ "reference": "5d4f188e60d1e38a1d9d4bb6fbbbc13111dff2b1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/5d4f188e60d1e38a1d9d4bb6fbbbc13111dff2b1",
+ "reference": "5d4f188e60d1e38a1d9d4bb6fbbbc13111dff2b1",
+ "shasum": ""
+ },
+ "require": {
+ "monolog/monolog": "^3",
+ "php": ">=8.2",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/service-contracts": "^2.5|^3"
+ },
+ "conflict": {
+ "symfony/console": "<6.4",
+ "symfony/http-foundation": "<6.4",
+ "symfony/security-core": "<6.4"
+ },
+ "require-dev": {
+ "symfony/console": "^6.4|^7.0",
+ "symfony/http-client": "^6.4|^7.0",
+ "symfony/mailer": "^6.4|^7.0",
+ "symfony/messenger": "^6.4|^7.0",
+ "symfony/mime": "^6.4|^7.0",
+ "symfony/security-core": "^6.4|^7.0",
+ "symfony/var-dumper": "^6.4|^7.0"
+ },
+ "type": "symfony-bridge",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Bridge\\Monolog\\": ""
+ },
+ "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 integration for Monolog with various Symfony components",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/monolog-bridge/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/monolog-bundle",
+ "version": "v3.10.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/monolog-bundle.git",
+ "reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/monolog-bundle/zipball/414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181",
+ "reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181",
+ "shasum": ""
+ },
+ "require": {
+ "monolog/monolog": "^1.25.1 || ^2.0 || ^3.0",
+ "php": ">=7.2.5",
+ "symfony/config": "^5.4 || ^6.0 || ^7.0",
+ "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0",
+ "symfony/http-kernel": "^5.4 || ^6.0 || ^7.0",
+ "symfony/monolog-bridge": "^5.4 || ^6.0 || ^7.0"
+ },
+ "require-dev": {
+ "symfony/console": "^5.4 || ^6.0 || ^7.0",
+ "symfony/phpunit-bridge": "^6.3 || ^7.0",
+ "symfony/yaml": "^5.4 || ^6.0 || ^7.0"
+ },
+ "type": "symfony-bundle",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Bundle\\MonologBundle\\": ""
+ },
+ "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": "Symfony MonologBundle",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "log",
+ "logging"
+ ],
+ "support": {
+ "issues": "https://github.com/symfony/monolog-bundle/issues",
+ "source": "https://github.com/symfony/monolog-bundle/tree/v3.10.0"
+ },
+ "funding": [
+ {
+ "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": "2023-11-06T17:08:13+00:00"
+ },
+ {
+ "name": "symfony/notifier",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/notifier.git",
+ "reference": "515326dab227ecd3198b04df50edf949f7767a9a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/notifier/zipball/515326dab227ecd3198b04df50edf949f7767a9a",
+ "reference": "515326dab227ecd3198b04df50edf949f7767a9a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "psr/log": "^1|^2|^3"
+ },
+ "conflict": {
+ "symfony/event-dispatcher": "<6.4",
+ "symfony/event-dispatcher-contracts": "<2.5",
+ "symfony/http-client-contracts": "<2.5",
+ "symfony/http-kernel": "<6.4"
+ },
+ "require-dev": {
+ "symfony/event-dispatcher-contracts": "^2.5|^3",
+ "symfony/http-client-contracts": "^2.5|^3",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/messenger": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Notifier\\": ""
+ },
+ "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": "Sends notifications via one or more channels (email, SMS, ...)",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "notification",
+ "notifier"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/notifier/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/options-resolver",
+ "version": "v7.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/options-resolver.git",
+ "reference": "700ff4096e346f54cb628ea650767c8130f1001f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/options-resolver/zipball/700ff4096e346f54cb628ea650767c8130f1001f",
+ "reference": "700ff4096e346f54cb628ea650767c8130f1001f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\OptionsResolver\\": ""
+ },
+ "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 an improved replacement for the array_replace PHP function",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "config",
+ "configuration",
+ "options"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/options-resolver/tree/v7.0.0"
+ },
+ "funding": [
+ {
+ "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": "2023-08-08T10:20:21+00:00"
+ },
+ {
+ "name": "symfony/password-hasher",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/password-hasher.git",
+ "reference": "0eba656c16ecdf5588b3ddd2b2337b06173d839f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/password-hasher/zipball/0eba656c16ecdf5588b3ddd2b2337b06173d839f",
+ "reference": "0eba656c16ecdf5588b3ddd2b2337b06173d839f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "conflict": {
+ "symfony/security-core": "<6.4"
+ },
+ "require-dev": {
+ "symfony/console": "^6.4|^7.0",
+ "symfony/security-core": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\PasswordHasher\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Robin Chalas",
+ "email": "robin.chalas@gmail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides password hashing utilities",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "hashing",
+ "password"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/password-hasher/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-12T11:15:03+00:00"
+ },
+ {
+ "name": "symfony/polyfill-intl-grapheme",
+ "version": "v1.29.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
+ "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f",
+ "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "suggest": {
+ "ext-intl": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
+ }
+ },
+ "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": "Symfony polyfill for intl's grapheme_* functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "grapheme",
+ "intl",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0"
+ },
+ "funding": [
+ {
+ "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": "2024-01-29T20:11:03+00:00"
+ },
+ {
+ "name": "symfony/polyfill-intl-icu",
+ "version": "v1.29.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-intl-icu.git",
+ "reference": "07094a28851a49107f3ab4f9120ca2975a64b6e1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/07094a28851a49107f3ab4f9120ca2975a64b6e1",
+ "reference": "07094a28851a49107f3ab4f9120ca2975a64b6e1",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "suggest": {
+ "ext-intl": "For best performance and support of other locales than \"en\""
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Icu\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ],
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "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": "Symfony polyfill for intl's ICU-related data and classes",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "icu",
+ "intl",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.29.0"
+ },
+ "funding": [
+ {
+ "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": "2024-01-29T20:12:16+00:00"
+ },
+ {
+ "name": "symfony/polyfill-intl-idn",
+ "version": "v1.29.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-intl-idn.git",
+ "reference": "a287ed7475f85bf6f61890146edbc932c0fff919"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/a287ed7475f85bf6f61890146edbc932c0fff919",
+ "reference": "a287ed7475f85bf6f61890146edbc932c0fff919",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1",
+ "symfony/polyfill-intl-normalizer": "^1.10",
+ "symfony/polyfill-php72": "^1.10"
+ },
+ "suggest": {
+ "ext-intl": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Idn\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Laurent Bassin",
+ "email": "laurent@bassin.info"
+ },
+ {
+ "name": "Trevor Rowbotham",
+ "email": "trevor.rowbotham@pm.me"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "idn",
+ "intl",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.29.0"
+ },
+ "funding": [
+ {
+ "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": "2024-01-29T20:11:03+00:00"
+ },
+ {
+ "name": "symfony/polyfill-intl-normalizer",
+ "version": "v1.29.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
+ "reference": "bc45c394692b948b4d383a08d7753968bed9a83d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d",
+ "reference": "bc45c394692b948b4d383a08d7753968bed9a83d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "suggest": {
+ "ext-intl": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "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": "Symfony polyfill for intl's Normalizer class and related functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "intl",
+ "normalizer",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0"
+ },
+ "funding": [
+ {
+ "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": "2024-01-29T20:11:03+00:00"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.29.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
+ "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "provide": {
+ "ext-mbstring": "*"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ }
+ },
+ "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": "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.29.0"
+ },
+ "funding": [
+ {
+ "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": "2024-01-29T20:11:03+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php83",
+ "version": "v1.29.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php83.git",
+ "reference": "86fcae159633351e5fd145d1c47de6c528f8caff"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/86fcae159633351e5fd145d1c47de6c528f8caff",
+ "reference": "86fcae159633351e5fd145d1c47de6c528f8caff",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1",
+ "symfony/polyfill-php80": "^1.14"
+ },
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php83\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "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": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php83/tree/v1.29.0"
+ },
+ "funding": [
+ {
+ "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": "2024-01-29T20:11:03+00:00"
+ },
+ {
+ "name": "symfony/process",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/process.git",
+ "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/process/zipball/0e7727191c3b71ebec6d529fa0e50a01ca5679e9",
+ "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Process\\": ""
+ },
+ "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": "Executes commands in sub-processes",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/process/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-22T20:27:20+00:00"
+ },
+ {
+ "name": "symfony/property-access",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/property-access.git",
+ "reference": "44e3746d4de8d0961a44ee332c74dd0918266127"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/property-access/zipball/44e3746d4de8d0961a44ee332c74dd0918266127",
+ "reference": "44e3746d4de8d0961a44ee332c74dd0918266127",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/property-info": "^6.4|^7.0"
+ },
+ "require-dev": {
+ "symfony/cache": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\PropertyAccess\\": ""
+ },
+ "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 functions to read and write from/to an object or array using a simple string notation",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "access",
+ "array",
+ "extraction",
+ "index",
+ "injection",
+ "object",
+ "property",
+ "property-path",
+ "reflection"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/property-access/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-16T13:44:10+00:00"
+ },
+ {
+ "name": "symfony/property-info",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/property-info.git",
+ "reference": "e160f92ea827243abf2dbf36b8460b1377194406"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/property-info/zipball/e160f92ea827243abf2dbf36b8460b1377194406",
+ "reference": "e160f92ea827243abf2dbf36b8460b1377194406",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/string": "^6.4|^7.0"
+ },
+ "conflict": {
+ "phpdocumentor/reflection-docblock": "<5.2",
+ "phpdocumentor/type-resolver": "<1.5.1",
+ "symfony/dependency-injection": "<6.4",
+ "symfony/serializer": "<6.4"
+ },
+ "require-dev": {
+ "phpdocumentor/reflection-docblock": "^5.2",
+ "phpstan/phpdoc-parser": "^1.0",
+ "symfony/cache": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/serializer": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\PropertyInfo\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Kévin Dunglas",
+ "email": "dunglas@gmail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Extracts information about PHP class' properties using metadata of popular sources",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "doctrine",
+ "phpdoc",
+ "property",
+ "symfony",
+ "type",
+ "validator"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/property-info/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/routing",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/routing.git",
+ "reference": "858b26756ffc35a11238b269b484ee3a393a74d3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/routing/zipball/858b26756ffc35a11238b269b484ee3a393a74d3",
+ "reference": "858b26756ffc35a11238b269b484ee3a393a74d3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/deprecation-contracts": "^2.5|^3"
+ },
+ "conflict": {
+ "symfony/config": "<6.4",
+ "symfony/dependency-injection": "<6.4",
+ "symfony/yaml": "<6.4"
+ },
+ "require-dev": {
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/yaml": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Routing\\": ""
+ },
+ "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": "Maps an HTTP request to a set of configuration variables",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "router",
+ "routing",
+ "uri",
+ "url"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/routing/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-30T13:55:15+00:00"
+ },
+ {
+ "name": "symfony/runtime",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/runtime.git",
+ "reference": "ef2c2fd4b40fb8cd22221154399ad8888e81cdb5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/runtime/zipball/ef2c2fd4b40fb8cd22221154399ad8888e81cdb5",
+ "reference": "ef2c2fd4b40fb8cd22221154399ad8888e81cdb5",
+ "shasum": ""
+ },
+ "require": {
+ "composer-plugin-api": "^1.0|^2.0",
+ "php": ">=8.2"
+ },
+ "conflict": {
+ "symfony/dotenv": "<6.4"
+ },
+ "require-dev": {
+ "composer/composer": "^2.6",
+ "symfony/console": "^6.4|^7.0",
+ "symfony/dotenv": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0"
+ },
+ "type": "composer-plugin",
+ "extra": {
+ "class": "Symfony\\Component\\Runtime\\Internal\\ComposerPlugin"
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Runtime\\": "",
+ "Symfony\\Runtime\\Symfony\\Component\\": "Internal/"
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "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": "Enables decoupling PHP applications from global state",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "runtime"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/runtime/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/security-bundle",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/security-bundle.git",
+ "reference": "1755fb50e4da0a0013569752be763d208d690bcd"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/security-bundle/zipball/1755fb50e4da0a0013569752be763d208d690bcd",
+ "reference": "1755fb50e4da0a0013569752be763d208d690bcd",
+ "shasum": ""
+ },
+ "require": {
+ "composer-runtime-api": ">=2.1",
+ "ext-xml": "*",
+ "php": ">=8.2",
+ "symfony/clock": "^6.4|^7.0",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/event-dispatcher": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/password-hasher": "^6.4|^7.0",
+ "symfony/security-core": "^6.4|^7.0",
+ "symfony/security-csrf": "^6.4|^7.0",
+ "symfony/security-http": "^6.4|^7.0",
+ "symfony/service-contracts": "^2.5|^3"
+ },
+ "conflict": {
+ "symfony/browser-kit": "<6.4",
+ "symfony/console": "<6.4",
+ "symfony/framework-bundle": "<6.4",
+ "symfony/http-client": "<6.4",
+ "symfony/ldap": "<6.4",
+ "symfony/serializer": "<6.4",
+ "symfony/twig-bundle": "<6.4",
+ "symfony/validator": "<6.4"
+ },
+ "require-dev": {
+ "symfony/asset": "^6.4|^7.0",
+ "symfony/browser-kit": "^6.4|^7.0",
+ "symfony/console": "^6.4|^7.0",
+ "symfony/css-selector": "^6.4|^7.0",
+ "symfony/dom-crawler": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/form": "^6.4|^7.0",
+ "symfony/framework-bundle": "^6.4|^7.0",
+ "symfony/http-client": "^6.4|^7.0",
+ "symfony/ldap": "^6.4|^7.0",
+ "symfony/process": "^6.4|^7.0",
+ "symfony/rate-limiter": "^6.4|^7.0",
+ "symfony/serializer": "^6.4|^7.0",
+ "symfony/translation": "^6.4|^7.0",
+ "symfony/twig-bridge": "^6.4|^7.0",
+ "symfony/twig-bundle": "^6.4|^7.0",
+ "symfony/validator": "^6.4|^7.0",
+ "symfony/yaml": "^6.4|^7.0",
+ "twig/twig": "^3.0.4",
+ "web-token/jwt-checker": "^3.1",
+ "web-token/jwt-signature-algorithm-ecdsa": "^3.1",
+ "web-token/jwt-signature-algorithm-eddsa": "^3.1",
+ "web-token/jwt-signature-algorithm-hmac": "^3.1",
+ "web-token/jwt-signature-algorithm-none": "^3.1",
+ "web-token/jwt-signature-algorithm-rsa": "^3.1"
+ },
+ "type": "symfony-bundle",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Bundle\\SecurityBundle\\": ""
+ },
+ "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 a tight integration of the Security component into the Symfony full-stack framework",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/security-bundle/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-15T11:33:06+00:00"
+ },
+ {
+ "name": "symfony/security-core",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/security-core.git",
+ "reference": "72b9d961a5dcd21e6bc29b99df51a9000a15dde0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/security-core/zipball/72b9d961a5dcd21e6bc29b99df51a9000a15dde0",
+ "reference": "72b9d961a5dcd21e6bc29b99df51a9000a15dde0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/event-dispatcher-contracts": "^2.5|^3",
+ "symfony/password-hasher": "^6.4|^7.0",
+ "symfony/service-contracts": "^2.5|^3"
+ },
+ "conflict": {
+ "symfony/event-dispatcher": "<6.4",
+ "symfony/http-foundation": "<6.4",
+ "symfony/ldap": "<6.4",
+ "symfony/translation": "<6.4.3|>=7.0,<7.0.3",
+ "symfony/validator": "<6.4"
+ },
+ "require-dev": {
+ "psr/cache": "^1.0|^2.0|^3.0",
+ "psr/container": "^1.1|^2.0",
+ "psr/log": "^1|^2|^3",
+ "symfony/cache": "^6.4|^7.0",
+ "symfony/event-dispatcher": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/ldap": "^6.4|^7.0",
+ "symfony/string": "^6.4|^7.0",
+ "symfony/translation": "^6.4.3|^7.0.3",
+ "symfony/validator": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Security\\Core\\": ""
+ },
+ "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": "Symfony Security Component - Core Library",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/security-core/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/security-csrf",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/security-csrf.git",
+ "reference": "f0f724e599f069b768e335e4bdf795726c7dfe8e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/security-csrf/zipball/f0f724e599f069b768e335e4bdf795726c7dfe8e",
+ "reference": "f0f724e599f069b768e335e4bdf795726c7dfe8e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/security-core": "^6.4|^7.0"
+ },
+ "conflict": {
+ "symfony/http-foundation": "<6.4"
+ },
+ "require-dev": {
+ "symfony/http-foundation": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Security\\Csrf\\": ""
+ },
+ "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": "Symfony Security Component - CSRF Library",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/security-csrf/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/security-http",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/security-http.git",
+ "reference": "f3a70a937128f47366821a9f4b5dbfaa0ba9c862"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/security-http/zipball/f3a70a937128f47366821a9f4b5dbfaa0ba9c862",
+ "reference": "f3a70a937128f47366821a9f4b5dbfaa0ba9c862",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/property-access": "^6.4|^7.0",
+ "symfony/security-core": "^6.4|^7.0",
+ "symfony/service-contracts": "^2.5|^3"
+ },
+ "conflict": {
+ "symfony/clock": "<6.4",
+ "symfony/event-dispatcher": "<6.4",
+ "symfony/http-client-contracts": "<3.0",
+ "symfony/security-bundle": "<6.4",
+ "symfony/security-csrf": "<6.4"
+ },
+ "require-dev": {
+ "psr/log": "^1|^2|^3",
+ "symfony/cache": "^6.4|^7.0",
+ "symfony/clock": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/http-client-contracts": "^3.0",
+ "symfony/rate-limiter": "^6.4|^7.0",
+ "symfony/routing": "^6.4|^7.0",
+ "symfony/security-csrf": "^6.4|^7.0",
+ "symfony/translation": "^6.4|^7.0",
+ "web-token/jwt-checker": "^3.1",
+ "web-token/jwt-signature-algorithm-ecdsa": "^3.1"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Security\\Http\\": ""
+ },
+ "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": "Symfony Security Component - HTTP Integration",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/security-http/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-26T07:52:39+00:00"
+ },
+ {
+ "name": "symfony/serializer",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/serializer.git",
+ "reference": "c71d61c6c37804e10981960e5f5ebc2c8f0a4fbb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/serializer/zipball/c71d61c6c37804e10981960e5f5ebc2c8f0a4fbb",
+ "reference": "c71d61c6c37804e10981960e5f5ebc2c8f0a4fbb",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-ctype": "~1.8"
+ },
+ "conflict": {
+ "phpdocumentor/reflection-docblock": "<3.2.2",
+ "phpdocumentor/type-resolver": "<1.4.0",
+ "symfony/dependency-injection": "<6.4",
+ "symfony/property-access": "<6.4",
+ "symfony/property-info": "<6.4",
+ "symfony/uid": "<6.4",
+ "symfony/validator": "<6.4",
+ "symfony/yaml": "<6.4"
+ },
+ "require-dev": {
+ "phpdocumentor/reflection-docblock": "^3.2|^4.0|^5.0",
+ "seld/jsonlint": "^1.10",
+ "symfony/cache": "^6.4|^7.0",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/console": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/error-handler": "^6.4|^7.0",
+ "symfony/filesystem": "^6.4|^7.0",
+ "symfony/form": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/messenger": "^6.4|^7.0",
+ "symfony/mime": "^6.4|^7.0",
+ "symfony/property-access": "^6.4|^7.0",
+ "symfony/property-info": "^6.4|^7.0",
+ "symfony/translation-contracts": "^2.5|^3",
+ "symfony/uid": "^6.4|^7.0",
+ "symfony/validator": "^6.4|^7.0",
+ "symfony/var-dumper": "^6.4|^7.0",
+ "symfony/var-exporter": "^6.4|^7.0",
+ "symfony/yaml": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Serializer\\": ""
+ },
+ "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": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/serializer/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-22T20:27:20+00:00"
+ },
+ {
+ "name": "symfony/service-contracts",
+ "version": "v3.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/service-contracts.git",
+ "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0",
+ "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "psr/container": "^1.1|^2.0"
+ },
+ "conflict": {
+ "ext-psr": "<1.1|>=2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "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.4.1"
+ },
+ "funding": [
+ {
+ "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": "2023-12-26T14:02:43+00:00"
+ },
+ {
+ "name": "symfony/stimulus-bundle",
+ "version": "v2.16.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/stimulus-bundle.git",
+ "reference": "6add4bdab1b9df4f2b2532a9dcb7b2f26dbba634"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/stimulus-bundle/zipball/6add4bdab1b9df4f2b2532a9dcb7b2f26dbba634",
+ "reference": "6add4bdab1b9df4f2b2532a9dcb7b2f26dbba634",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "symfony/config": "^5.4|^6.0|^7.0",
+ "symfony/dependency-injection": "^5.4|^6.0|^7.0",
+ "symfony/deprecation-contracts": "^2.0|^3.0",
+ "symfony/finder": "^5.4|^6.0|^7.0",
+ "symfony/http-kernel": "^5.4|^6.0|^7.0",
+ "twig/twig": "^2.15.3|~3.8.0"
+ },
+ "require-dev": {
+ "symfony/asset-mapper": "^6.3|^7.0",
+ "symfony/framework-bundle": "^5.4|^6.0|^7.0",
+ "symfony/phpunit-bridge": "^5.4|^6.0|^7.0",
+ "symfony/twig-bundle": "^5.4|^6.0|^7.0",
+ "zenstruck/browser": "^1.4"
+ },
+ "type": "symfony-bundle",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\UX\\StimulusBundle\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Integration with your Symfony app & Stimulus!",
+ "keywords": [
+ "symfony-ux"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/stimulus-bundle/tree/v2.16.0"
+ },
+ "funding": [
+ {
+ "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": "2024-02-29T16:20:46+00:00"
+ },
+ {
+ "name": "symfony/stopwatch",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/stopwatch.git",
+ "reference": "983900d6fddf2b0cbaacacbbad07610854bd8112"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/stopwatch/zipball/983900d6fddf2b0cbaacacbbad07610854bd8112",
+ "reference": "983900d6fddf2b0cbaacacbbad07610854bd8112",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/service-contracts": "^2.5|^3"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Stopwatch\\": ""
+ },
+ "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 a way to profile code",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/stopwatch/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/string",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/string.git",
+ "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/string/zipball/f5832521b998b0bec40bee688ad5de98d4cf111b",
+ "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-intl-grapheme": "~1.0",
+ "symfony/polyfill-intl-normalizer": "~1.0",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "conflict": {
+ "symfony/translation-contracts": "<2.5"
+ },
+ "require-dev": {
+ "symfony/error-handler": "^6.4|^7.0",
+ "symfony/http-client": "^6.4|^7.0",
+ "symfony/intl": "^6.4|^7.0",
+ "symfony/translation-contracts": "^2.5|^3.0",
+ "symfony/var-exporter": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "Resources/functions.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\String\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "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": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "grapheme",
+ "i18n",
+ "string",
+ "unicode",
+ "utf-8",
+ "utf8"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/string/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-01T13:17:36+00:00"
+ },
+ {
+ "name": "symfony/translation",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/translation.git",
+ "reference": "5b75e872f7d135d7abb4613809fadc8d9f3d30a0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/5b75e872f7d135d7abb4613809fadc8d9f3d30a0",
+ "reference": "5b75e872f7d135d7abb4613809fadc8d9f3d30a0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/translation-contracts": "^2.5|^3.0"
+ },
+ "conflict": {
+ "symfony/config": "<6.4",
+ "symfony/console": "<6.4",
+ "symfony/dependency-injection": "<6.4",
+ "symfony/http-client-contracts": "<2.5",
+ "symfony/http-kernel": "<6.4",
+ "symfony/service-contracts": "<2.5",
+ "symfony/twig-bundle": "<6.4",
+ "symfony/yaml": "<6.4"
+ },
+ "provide": {
+ "symfony/translation-implementation": "2.3|3.0"
+ },
+ "require-dev": {
+ "nikic/php-parser": "^4.18|^5.0",
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/console": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/finder": "^6.4|^7.0",
+ "symfony/http-client-contracts": "^2.5|^3.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/intl": "^6.4|^7.0",
+ "symfony/polyfill-intl-icu": "^1.21",
+ "symfony/routing": "^6.4|^7.0",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/yaml": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "Resources/functions.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\Translation\\": ""
+ },
+ "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 tools to internationalize your application",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/translation/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-22T20:27:20+00:00"
+ },
+ {
+ "name": "symfony/translation-contracts",
+ "version": "v3.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/translation-contracts.git",
+ "reference": "06450585bf65e978026bda220cdebca3f867fde7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/06450585bf65e978026bda220cdebca3f867fde7",
+ "reference": "06450585bf65e978026bda220cdebca3f867fde7",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\Translation\\": ""
+ },
+ "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 translation",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/translation-contracts/tree/v3.4.1"
+ },
+ "funding": [
+ {
+ "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": "2023-12-26T14:02:43+00:00"
+ },
+ {
+ "name": "symfony/twig-bridge",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/twig-bridge.git",
+ "reference": "d16aa4eb5bdaeb6e7407782431dc70530f3b1df5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/d16aa4eb5bdaeb6e7407782431dc70530f3b1df5",
+ "reference": "d16aa4eb5bdaeb6e7407782431dc70530f3b1df5",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/translation-contracts": "^2.5|^3",
+ "twig/twig": "^3.0.4"
+ },
+ "conflict": {
+ "phpdocumentor/reflection-docblock": "<3.2.2",
+ "phpdocumentor/type-resolver": "<1.4.0",
+ "symfony/console": "<6.4",
+ "symfony/form": "<6.4",
+ "symfony/http-foundation": "<6.4",
+ "symfony/http-kernel": "<6.4",
+ "symfony/mime": "<6.4",
+ "symfony/serializer": "<6.4",
+ "symfony/translation": "<6.4",
+ "symfony/workflow": "<6.4"
+ },
+ "require-dev": {
+ "egulias/email-validator": "^2.1.10|^3|^4",
+ "league/html-to-markdown": "^5.0",
+ "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
+ "symfony/asset": "^6.4|^7.0",
+ "symfony/asset-mapper": "^6.4|^7.0",
+ "symfony/console": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/finder": "^6.4|^7.0",
+ "symfony/form": "^6.4|^7.0",
+ "symfony/html-sanitizer": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/intl": "^6.4|^7.0",
+ "symfony/mime": "^6.4|^7.0",
+ "symfony/polyfill-intl-icu": "~1.0",
+ "symfony/property-info": "^6.4|^7.0",
+ "symfony/routing": "^6.4|^7.0",
+ "symfony/security-acl": "^2.8|^3.0",
+ "symfony/security-core": "^6.4|^7.0",
+ "symfony/security-csrf": "^6.4|^7.0",
+ "symfony/security-http": "^6.4|^7.0",
+ "symfony/serializer": "^6.4.3|^7.0.3",
+ "symfony/stopwatch": "^6.4|^7.0",
+ "symfony/translation": "^6.4|^7.0",
+ "symfony/web-link": "^6.4|^7.0",
+ "symfony/workflow": "^6.4|^7.0",
+ "symfony/yaml": "^6.4|^7.0",
+ "twig/cssinliner-extra": "^2.12|^3",
+ "twig/inky-extra": "^2.12|^3",
+ "twig/markdown-extra": "^2.12|^3"
+ },
+ "type": "symfony-bridge",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Bridge\\Twig\\": ""
+ },
+ "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 integration for Twig with various Symfony components",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/twig-bridge/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-15T11:33:06+00:00"
+ },
+ {
+ "name": "symfony/twig-bundle",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/twig-bundle.git",
+ "reference": "acab2368f53491e018bf31ef48b39df55a6812ef"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/acab2368f53491e018bf31ef48b39df55a6812ef",
+ "reference": "acab2368f53491e018bf31ef48b39df55a6812ef",
+ "shasum": ""
+ },
+ "require": {
+ "composer-runtime-api": ">=2.1",
+ "php": ">=8.2",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/twig-bridge": "^6.4|^7.0",
+ "twig/twig": "^3.0.4"
+ },
+ "conflict": {
+ "symfony/framework-bundle": "<6.4",
+ "symfony/translation": "<6.4"
+ },
+ "require-dev": {
+ "symfony/asset": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/finder": "^6.4|^7.0",
+ "symfony/form": "^6.4|^7.0",
+ "symfony/framework-bundle": "^6.4|^7.0",
+ "symfony/routing": "^6.4|^7.0",
+ "symfony/stopwatch": "^6.4|^7.0",
+ "symfony/translation": "^6.4|^7.0",
+ "symfony/web-link": "^6.4|^7.0",
+ "symfony/yaml": "^6.4|^7.0"
+ },
+ "type": "symfony-bundle",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Bundle\\TwigBundle\\": ""
+ },
+ "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 a tight integration of Twig into the Symfony full-stack framework",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/twig-bundle/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-15T11:33:06+00:00"
+ },
+ {
+ "name": "symfony/ux-turbo",
+ "version": "v2.16.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/ux-turbo.git",
+ "reference": "d3590a43fee73304855dfc8022ccb57b0df9f03d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/ux-turbo/zipball/d3590a43fee73304855dfc8022ccb57b0df9f03d",
+ "reference": "d3590a43fee73304855dfc8022ccb57b0df9f03d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "symfony/stimulus-bundle": "^2.9.1"
+ },
+ "conflict": {
+ "symfony/flex": "<1.13"
+ },
+ "require-dev": {
+ "doctrine/doctrine-bundle": "^2.4.3",
+ "doctrine/orm": "^2.8 | 3.0",
+ "phpstan/phpstan": "^1.10",
+ "symfony/debug-bundle": "^5.4|^6.0|^7.0",
+ "symfony/expression-language": "^5.4|^6.0|^7.0",
+ "symfony/form": "^5.4|^6.0|^7.0",
+ "symfony/framework-bundle": "^5.4|^6.0|^7.0",
+ "symfony/mercure-bundle": "^0.3.7",
+ "symfony/messenger": "^5.4|^6.0|^7.0",
+ "symfony/panther": "^1.0|^2.0",
+ "symfony/phpunit-bridge": "^5.4|^6.0|^7.0",
+ "symfony/process": "^5.4|6.3.*|^7.0",
+ "symfony/property-access": "^5.4|^6.0|^7.0",
+ "symfony/security-core": "^5.4|^6.0|^7.0",
+ "symfony/stopwatch": "^5.4|^6.0|^7.0",
+ "symfony/twig-bundle": "^5.4|^6.0|^7.0",
+ "symfony/web-profiler-bundle": "^5.4|^6.0|^7.0",
+ "symfony/webpack-encore-bundle": "^2.1.1"
+ },
+ "type": "symfony-bundle",
+ "extra": {
+ "thanks": {
+ "name": "symfony/ux",
+ "url": "https://github.com/symfony/ux"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\UX\\Turbo\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Kévin Dunglas",
+ "email": "kevin@dunglas.fr"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Hotwire Turbo integration for Symfony",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "hotwire",
+ "javascript",
+ "mercure",
+ "symfony-ux",
+ "turbo",
+ "turbo-stream"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/ux-turbo/tree/v2.16.0"
+ },
+ "funding": [
+ {
+ "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": "2024-02-20T16:11:17+00:00"
+ },
+ {
+ "name": "symfony/validator",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/validator.git",
+ "reference": "104bc3620d0ee4091034cfbcdcf82ed727f15b7d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/validator/zipball/104bc3620d0ee4091034cfbcdcf82ed727f15b7d",
+ "reference": "104bc3620d0ee4091034cfbcdcf82ed727f15b7d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/polyfill-php83": "^1.27",
+ "symfony/translation-contracts": "^2.5|^3"
+ },
+ "conflict": {
+ "doctrine/lexer": "<1.1",
+ "symfony/dependency-injection": "<6.4",
+ "symfony/doctrine-bridge": "<7.0",
+ "symfony/expression-language": "<6.4",
+ "symfony/http-kernel": "<6.4",
+ "symfony/intl": "<6.4",
+ "symfony/property-info": "<6.4",
+ "symfony/translation": "<6.4.3|>=7.0,<7.0.3",
+ "symfony/yaml": "<6.4"
+ },
+ "require-dev": {
+ "egulias/email-validator": "^2.1.10|^3|^4",
+ "symfony/cache": "^6.4|^7.0",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/console": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/finder": "^6.4|^7.0",
+ "symfony/http-client": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/intl": "^6.4|^7.0",
+ "symfony/mime": "^6.4|^7.0",
+ "symfony/property-access": "^6.4|^7.0",
+ "symfony/property-info": "^6.4|^7.0",
+ "symfony/translation": "^6.4.3|^7.0.3",
+ "symfony/yaml": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Validator\\": ""
+ },
+ "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 tools to validate values",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/validator/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-22T20:27:20+00:00"
+ },
+ {
+ "name": "symfony/var-dumper",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/var-dumper.git",
+ "reference": "e03ad7c1535e623edbb94c22cc42353e488c6670"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e03ad7c1535e623edbb94c22cc42353e488c6670",
+ "reference": "e03ad7c1535e623edbb94c22cc42353e488c6670",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "conflict": {
+ "symfony/console": "<6.4"
+ },
+ "require-dev": {
+ "ext-iconv": "*",
+ "symfony/console": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/process": "^6.4|^7.0",
+ "symfony/uid": "^6.4|^7.0",
+ "twig/twig": "^3.0.4"
+ },
+ "bin": [
+ "Resources/bin/var-dump-server"
+ ],
+ "type": "library",
+ "autoload": {
+ "files": [
+ "Resources/functions/dump.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\VarDumper\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "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": "Provides mechanisms for walking through any arbitrary PHP variable",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "debug",
+ "dump"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/var-dumper/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-15T11:33:06+00:00"
+ },
+ {
+ "name": "symfony/var-exporter",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/var-exporter.git",
+ "reference": "dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/var-exporter/zipball/dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41",
+ "reference": "dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
+ "symfony/var-dumper": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\VarExporter\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "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": "Allows exporting any serializable PHP data structure to plain PHP code",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "clone",
+ "construct",
+ "export",
+ "hydrate",
+ "instantiate",
+ "lazy-loading",
+ "proxy",
+ "serialize"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/var-exporter/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-26T10:35:24+00:00"
+ },
+ {
+ "name": "symfony/web-link",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/web-link.git",
+ "reference": "855a347feb2ecfc1d1a379c739aff956d4cbec00"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/web-link/zipball/855a347feb2ecfc1d1a379c739aff956d4cbec00",
+ "reference": "855a347feb2ecfc1d1a379c739aff956d4cbec00",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "psr/link": "^1.1|^2.0"
+ },
+ "conflict": {
+ "symfony/http-kernel": "<6.4"
+ },
+ "provide": {
+ "psr/link-implementation": "1.0|2.0"
+ },
+ "require-dev": {
+ "symfony/http-kernel": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\WebLink\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Kévin Dunglas",
+ "email": "dunglas@gmail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Manages links between resources",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "dns-prefetch",
+ "http",
+ "http2",
+ "link",
+ "performance",
+ "prefetch",
+ "preload",
+ "prerender",
+ "psr13",
+ "push"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/web-link/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/yaml",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/yaml.git",
+ "reference": "2d4fca631c00700597e9442a0b2451ce234513d3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/2d4fca631c00700597e9442a0b2451ce234513d3",
+ "reference": "2d4fca631c00700597e9442a0b2451ce234513d3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-ctype": "^1.8"
+ },
+ "conflict": {
+ "symfony/console": "<6.4"
+ },
+ "require-dev": {
+ "symfony/console": "^6.4|^7.0"
+ },
+ "bin": [
+ "Resources/bin/yaml-lint"
+ ],
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Yaml\\": ""
+ },
+ "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": "Loads and dumps YAML files",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/yaml/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "twig/extra-bundle",
+ "version": "v3.8.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/twigphp/twig-extra-bundle.git",
+ "reference": "32807183753de0388c8e59f7ac2d13bb47311140"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/32807183753de0388c8e59f7ac2d13bb47311140",
+ "reference": "32807183753de0388c8e59f7ac2d13bb47311140",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/framework-bundle": "^5.4|^6.0|^7.0",
+ "symfony/twig-bundle": "^5.4|^6.0|^7.0",
+ "twig/twig": "^3.0"
+ },
+ "require-dev": {
+ "league/commonmark": "^1.0|^2.0",
+ "symfony/phpunit-bridge": "^6.4|^7.0",
+ "twig/cache-extra": "^3.0",
+ "twig/cssinliner-extra": "^2.12|^3.0",
+ "twig/html-extra": "^2.12|^3.0",
+ "twig/inky-extra": "^2.12|^3.0",
+ "twig/intl-extra": "^2.12|^3.0",
+ "twig/markdown-extra": "^2.12|^3.0",
+ "twig/string-extra": "^2.12|^3.0"
+ },
+ "type": "symfony-bundle",
+ "autoload": {
+ "psr-4": {
+ "Twig\\Extra\\TwigExtraBundle\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com",
+ "homepage": "http://fabien.potencier.org",
+ "role": "Lead Developer"
+ }
+ ],
+ "description": "A Symfony bundle for extra Twig extensions",
+ "homepage": "https://twig.symfony.com",
+ "keywords": [
+ "bundle",
+ "extra",
+ "twig"
+ ],
+ "support": {
+ "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.8.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/twig/twig",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-11-21T14:02:01+00:00"
+ },
+ {
+ "name": "twig/twig",
+ "version": "v3.8.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/twigphp/Twig.git",
+ "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/twigphp/Twig/zipball/9d15f0ac07f44dc4217883ec6ae02fd555c6f71d",
+ "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/polyfill-ctype": "^1.8",
+ "symfony/polyfill-mbstring": "^1.3",
+ "symfony/polyfill-php80": "^1.22"
+ },
+ "require-dev": {
+ "psr/container": "^1.0|^2.0",
+ "symfony/phpunit-bridge": "^5.4.9|^6.3|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Twig\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com",
+ "homepage": "http://fabien.potencier.org",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Twig Team",
+ "role": "Contributors"
+ },
+ {
+ "name": "Armin Ronacher",
+ "email": "armin.ronacher@active-4.com",
+ "role": "Project Founder"
+ }
+ ],
+ "description": "Twig, the flexible, fast, and secure template language for PHP",
+ "homepage": "https://twig.symfony.com",
+ "keywords": [
+ "templating"
+ ],
+ "support": {
+ "issues": "https://github.com/twigphp/Twig/issues",
+ "source": "https://github.com/twigphp/Twig/tree/v3.8.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/twig/twig",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-11-21T18:54:41+00:00"
+ },
+ {
+ "name": "webmozart/assert",
+ "version": "1.11.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/webmozarts/assert.git",
+ "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
+ "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
+ "shasum": ""
+ },
+ "require": {
+ "ext-ctype": "*",
+ "php": "^7.2 || ^8.0"
+ },
+ "conflict": {
+ "phpstan/phpstan": "<0.12.20",
+ "vimeo/psalm": "<4.6.1 || 4.6.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^8.5.13"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.10-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Webmozart\\Assert\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
+ }
+ ],
+ "description": "Assertions to validate method input/output with nice error messages.",
+ "keywords": [
+ "assert",
+ "check",
+ "validate"
+ ],
+ "support": {
+ "issues": "https://github.com/webmozarts/assert/issues",
+ "source": "https://github.com/webmozarts/assert/tree/1.11.0"
+ },
+ "time": "2022-06-03T18:03:27+00:00"
+ }
+ ],
+ "packages-dev": [
+ {
+ "name": "masterminds/html5",
+ "version": "2.8.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Masterminds/html5-php.git",
+ "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f47dcf3c70c584de14f21143c55d9939631bc6cf",
+ "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "php": ">=5.3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.7-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Masterminds\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Matt Butcher",
+ "email": "technosophos@gmail.com"
+ },
+ {
+ "name": "Matt Farina",
+ "email": "matt@mattfarina.com"
+ },
+ {
+ "name": "Asmir Mustafic",
+ "email": "goetas@gmail.com"
+ }
+ ],
+ "description": "An HTML5 parser and serializer.",
+ "homepage": "http://masterminds.github.io/html5-php",
+ "keywords": [
+ "HTML5",
+ "dom",
+ "html",
+ "parser",
+ "querypath",
+ "serializer",
+ "xml"
+ ],
+ "support": {
+ "issues": "https://github.com/Masterminds/html5-php/issues",
+ "source": "https://github.com/Masterminds/html5-php/tree/2.8.1"
+ },
+ "time": "2023-05-10T11:58:31+00:00"
+ },
+ {
+ "name": "myclabs/deep-copy",
+ "version": "1.11.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/myclabs/DeepCopy.git",
+ "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c",
+ "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1 || ^8.0"
+ },
+ "conflict": {
+ "doctrine/collections": "<1.6.8",
+ "doctrine/common": "<2.13.3 || >=3,<3.2.2"
+ },
+ "require-dev": {
+ "doctrine/collections": "^1.6.8",
+ "doctrine/common": "^2.13.3 || ^3.2.2",
+ "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/DeepCopy/deep_copy.php"
+ ],
+ "psr-4": {
+ "DeepCopy\\": "src/DeepCopy/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Create deep copies (clones) of your objects",
+ "keywords": [
+ "clone",
+ "copy",
+ "duplicate",
+ "object",
+ "object graph"
+ ],
+ "support": {
+ "issues": "https://github.com/myclabs/DeepCopy/issues",
+ "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1"
+ },
+ "funding": [
+ {
+ "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-03-08T13:26:56+00:00"
+ },
+ {
+ "name": "nikic/php-parser",
+ "version": "v5.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nikic/PHP-Parser.git",
+ "reference": "2218c2252c874a4624ab2f613d86ac32d227bc69"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/2218c2252c874a4624ab2f613d86ac32d227bc69",
+ "reference": "2218c2252c874a4624ab2f613d86ac32d227bc69",
+ "shasum": ""
+ },
+ "require": {
+ "ext-ctype": "*",
+ "ext-json": "*",
+ "ext-tokenizer": "*",
+ "php": ">=7.4"
+ },
+ "require-dev": {
+ "ircmaxell/php-yacc": "^0.0.7",
+ "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0"
+ },
+ "bin": [
+ "bin/php-parse"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "PhpParser\\": "lib/PhpParser"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Nikita Popov"
+ }
+ ],
+ "description": "A PHP parser written in PHP",
+ "keywords": [
+ "parser",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/nikic/PHP-Parser/issues",
+ "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.1"
+ },
+ "time": "2024-02-21T19:24:10+00:00"
+ },
+ {
+ "name": "phar-io/manifest",
+ "version": "2.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phar-io/manifest.git",
+ "reference": "97803eca37d319dfa7826cc2437fc020857acb53"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
+ "reference": "97803eca37d319dfa7826cc2437fc020857acb53",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-phar": "*",
+ "ext-xmlwriter": "*",
+ "phar-io/version": "^3.0.1",
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "sebastian@phpeople.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
+ "support": {
+ "issues": "https://github.com/phar-io/manifest/issues",
+ "source": "https://github.com/phar-io/manifest/tree/2.0.3"
+ },
+ "time": "2021-07-20T11:28:43+00:00"
+ },
+ {
+ "name": "phar-io/version",
+ "version": "3.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phar-io/version.git",
+ "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
+ "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "sebastian@phpeople.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Library for handling version information and constraints",
+ "support": {
+ "issues": "https://github.com/phar-io/version/issues",
+ "source": "https://github.com/phar-io/version/tree/3.2.1"
+ },
+ "time": "2022-02-21T01:04:05+00:00"
+ },
+ {
+ "name": "phpunit/php-code-coverage",
+ "version": "9.2.30",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
+ "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca2bd87d2f9215904682a9cb9bb37dda98e76089",
+ "reference": "ca2bd87d2f9215904682a9cb9bb37dda98e76089",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-libxml": "*",
+ "ext-xmlwriter": "*",
+ "nikic/php-parser": "^4.18 || ^5.0",
+ "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"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "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-master": "9.2-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
+ "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
+ "keywords": [
+ "coverage",
+ "testing",
+ "xunit"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
+ "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.30"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-12-22T06:47:57+00:00"
+ },
+ {
+ "name": "phpunit/php-file-iterator",
+ "version": "3.0.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
+ "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
+ "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "FilterIterator implementation that filters files based on a list of suffixes.",
+ "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
+ "keywords": [
+ "filesystem",
+ "iterator"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
+ "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2021-12-02T12:48:52+00:00"
+ },
+ {
+ "name": "phpunit/php-invoker",
+ "version": "3.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-invoker.git",
+ "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
+ "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "ext-pcntl": "*",
+ "phpunit/phpunit": "^9.3"
+ },
+ "suggest": {
+ "ext-pcntl": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Invoke callables with a timeout",
+ "homepage": "https://github.com/sebastianbergmann/php-invoker/",
+ "keywords": [
+ "process"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-invoker/issues",
+ "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-09-28T05:58:55+00:00"
+ },
+ {
+ "name": "phpunit/php-text-template",
+ "version": "2.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-text-template.git",
+ "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
+ "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Simple template engine.",
+ "homepage": "https://github.com/sebastianbergmann/php-text-template/",
+ "keywords": [
+ "template"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-text-template/issues",
+ "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-10-26T05:33:50+00:00"
+ },
+ {
+ "name": "phpunit/php-timer",
+ "version": "5.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-timer.git",
+ "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
+ "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Utility class for timing",
+ "homepage": "https://github.com/sebastianbergmann/php-timer/",
+ "keywords": [
+ "timer"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-timer/issues",
+ "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-10-26T13:16:10+00:00"
+ },
+ {
+ "name": "phpunit/phpunit",
+ "version": "9.6.17",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/phpunit.git",
+ "reference": "1a156980d78a6666721b7e8e8502fe210b587fcd"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1a156980d78a6666721b7e8e8502fe210b587fcd",
+ "reference": "1a156980d78a6666721b7e8e8502fe210b587fcd",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/instantiator": "^1.3.1 || ^2",
+ "ext-dom": "*",
+ "ext-json": "*",
+ "ext-libxml": "*",
+ "ext-mbstring": "*",
+ "ext-xml": "*",
+ "ext-xmlwriter": "*",
+ "myclabs/deep-copy": "^1.10.1",
+ "phar-io/manifest": "^2.0.3",
+ "phar-io/version": "^3.0.2",
+ "php": ">=7.3",
+ "phpunit/php-code-coverage": "^9.2.28",
+ "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.8",
+ "sebastian/diff": "^4.0.3",
+ "sebastian/environment": "^5.1.3",
+ "sebastian/exporter": "^4.0.5",
+ "sebastian/global-state": "^5.0.1",
+ "sebastian/object-enumerator": "^4.0.3",
+ "sebastian/resource-operations": "^3.0.3",
+ "sebastian/type": "^3.2",
+ "sebastian/version": "^3.0.2"
+ },
+ "suggest": {
+ "ext-soap": "To be able to generate mocks based on WSDL files",
+ "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage"
+ },
+ "bin": [
+ "phpunit"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "9.6-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/Framework/Assert/Functions.php"
+ ],
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "The PHP Unit Testing framework.",
+ "homepage": "https://phpunit.de/",
+ "keywords": [
+ "phpunit",
+ "testing",
+ "xunit"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/phpunit/issues",
+ "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.17"
+ },
+ "funding": [
+ {
+ "url": "https://phpunit.de/sponsors.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-02-23T13:14:51+00:00"
+ },
+ {
+ "name": "sebastian/cli-parser",
+ "version": "1.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/cli-parser.git",
+ "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
+ "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for parsing CLI options",
+ "homepage": "https://github.com/sebastianbergmann/cli-parser",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/cli-parser/issues",
+ "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-09-28T06:08:49+00:00"
+ },
+ {
+ "name": "sebastian/code-unit",
+ "version": "1.0.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/code-unit.git",
+ "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120",
+ "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Collection of value objects that represent the PHP code units",
+ "homepage": "https://github.com/sebastianbergmann/code-unit",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/code-unit/issues",
+ "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-10-26T13:08:54+00:00"
+ },
+ {
+ "name": "sebastian/code-unit-reverse-lookup",
+ "version": "2.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
+ "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
+ "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Looks up which function or method a line of code belongs to",
+ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
+ "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-09-28T05:30:19+00:00"
+ },
+ {
+ "name": "sebastian/comparator",
+ "version": "4.0.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/comparator.git",
+ "reference": "fa0f136dd2334583309d32b62544682ee972b51a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a",
+ "reference": "fa0f136dd2334583309d32b62544682ee972b51a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3",
+ "sebastian/diff": "^4.0",
+ "sebastian/exporter": "^4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@2bepublished.at"
+ }
+ ],
+ "description": "Provides the functionality to compare PHP values for equality",
+ "homepage": "https://github.com/sebastianbergmann/comparator",
+ "keywords": [
+ "comparator",
+ "compare",
+ "equality"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/comparator/issues",
+ "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2022-09-14T12:41:17+00:00"
+ },
+ {
+ "name": "sebastian/complexity",
+ "version": "2.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/complexity.git",
+ "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a",
+ "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a",
+ "shasum": ""
+ },
+ "require": {
+ "nikic/php-parser": "^4.18 || ^5.0",
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for calculating the complexity of PHP code units",
+ "homepage": "https://github.com/sebastianbergmann/complexity",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/complexity/issues",
+ "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-12-22T06:19:30+00:00"
+ },
+ {
+ "name": "sebastian/diff",
+ "version": "4.0.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/diff.git",
+ "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131",
+ "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3",
+ "symfony/process": "^4.2 || ^5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Kore Nordmann",
+ "email": "mail@kore-nordmann.de"
+ }
+ ],
+ "description": "Diff implementation",
+ "homepage": "https://github.com/sebastianbergmann/diff",
+ "keywords": [
+ "diff",
+ "udiff",
+ "unidiff",
+ "unified diff"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/diff/issues",
+ "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-05-07T05:35:17+00:00"
+ },
+ {
+ "name": "sebastian/environment",
+ "version": "5.1.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/environment.git",
+ "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed",
+ "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "suggest": {
+ "ext-posix": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Provides functionality to handle HHVM/PHP environments",
+ "homepage": "http://www.github.com/sebastianbergmann/environment",
+ "keywords": [
+ "Xdebug",
+ "environment",
+ "hhvm"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/environment/issues",
+ "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-03T06:03:51+00:00"
+ },
+ {
+ "name": "sebastian/exporter",
+ "version": "4.0.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/exporter.git",
+ "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
+ "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3",
+ "sebastian/recursion-context": "^4.0"
+ },
+ "require-dev": {
+ "ext-mbstring": "*",
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
+ }
+ ],
+ "description": "Provides the functionality to export PHP variables for visualization",
+ "homepage": "https://www.github.com/sebastianbergmann/exporter",
+ "keywords": [
+ "export",
+ "exporter"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/exporter/issues",
+ "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2022-09-14T06:03:37+00:00"
+ },
+ {
+ "name": "sebastian/global-state",
+ "version": "5.0.6",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/global-state.git",
+ "reference": "bde739e7565280bda77be70044ac1047bc007e34"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34",
+ "reference": "bde739e7565280bda77be70044ac1047bc007e34",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3",
+ "sebastian/object-reflector": "^2.0",
+ "sebastian/recursion-context": "^4.0"
+ },
+ "require-dev": {
+ "ext-dom": "*",
+ "phpunit/phpunit": "^9.3"
+ },
+ "suggest": {
+ "ext-uopz": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Snapshotting of global state",
+ "homepage": "http://www.github.com/sebastianbergmann/global-state",
+ "keywords": [
+ "global state"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/global-state/issues",
+ "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-08-02T09:26:13+00:00"
+ },
+ {
+ "name": "sebastian/lines-of-code",
+ "version": "1.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/lines-of-code.git",
+ "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5",
+ "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5",
+ "shasum": ""
+ },
+ "require": {
+ "nikic/php-parser": "^4.18 || ^5.0",
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for counting the lines of code in PHP source code",
+ "homepage": "https://github.com/sebastianbergmann/lines-of-code",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
+ "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-12-22T06:20:34+00:00"
+ },
+ {
+ "name": "sebastian/object-enumerator",
+ "version": "4.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-enumerator.git",
+ "reference": "5c9eeac41b290a3712d88851518825ad78f45c71"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71",
+ "reference": "5c9eeac41b290a3712d88851518825ad78f45c71",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3",
+ "sebastian/object-reflector": "^2.0",
+ "sebastian/recursion-context": "^4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "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/4.0.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-10-26T13:12:34+00:00"
+ },
+ {
+ "name": "sebastian/object-reflector",
+ "version": "2.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-reflector.git",
+ "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
+ "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Allows reflection of object attributes, including inherited and non-public ones",
+ "homepage": "https://github.com/sebastianbergmann/object-reflector/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/object-reflector/issues",
+ "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-10-26T13:14:26+00:00"
+ },
+ {
+ "name": "sebastian/recursion-context",
+ "version": "4.0.5",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/recursion-context.git",
+ "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1",
+ "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ }
+ ],
+ "description": "Provides functionality to recursively process PHP variables",
+ "homepage": "https://github.com/sebastianbergmann/recursion-context",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/recursion-context/issues",
+ "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-03T06:07:39+00:00"
+ },
+ {
+ "name": "sebastian/resource-operations",
+ "version": "3.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/resource-operations.git",
+ "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
+ "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Provides a list of PHP built-in functions that operate on resources",
+ "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/resource-operations/issues",
+ "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-09-28T06:45:17+00:00"
+ },
+ {
+ "name": "sebastian/type",
+ "version": "3.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/type.git",
+ "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7",
+ "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.2-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Collection of value objects that represent the types of the PHP type system",
+ "homepage": "https://github.com/sebastianbergmann/type",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/type/issues",
+ "source": "https://github.com/sebastianbergmann/type/tree/3.2.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-03T06:13:03+00:00"
+ },
+ {
+ "name": "sebastian/version",
+ "version": "3.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/version.git",
+ "reference": "c6c1022351a901512170118436c764e473f6de8c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
+ "reference": "c6c1022351a901512170118436c764e473f6de8c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library 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/3.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2020-09-28T06:39:44+00:00"
+ },
+ {
+ "name": "symfony/browser-kit",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/browser-kit.git",
+ "reference": "725d5b15681685ac17b20b575254c75639722488"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/browser-kit/zipball/725d5b15681685ac17b20b575254c75639722488",
+ "reference": "725d5b15681685ac17b20b575254c75639722488",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/dom-crawler": "^6.4|^7.0"
+ },
+ "require-dev": {
+ "symfony/css-selector": "^6.4|^7.0",
+ "symfony/http-client": "^6.4|^7.0",
+ "symfony/mime": "^6.4|^7.0",
+ "symfony/process": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\BrowserKit\\": ""
+ },
+ "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": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/browser-kit/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/css-selector",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/css-selector.git",
+ "reference": "ec60a4edf94e63b0556b6a0888548bb400a3a3be"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/css-selector/zipball/ec60a4edf94e63b0556b6a0888548bb400a3a3be",
+ "reference": "ec60a4edf94e63b0556b6a0888548bb400a3a3be",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\CssSelector\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Jean-François Simon",
+ "email": "jeanfrancois.simon@sensiolabs.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Converts CSS selectors to XPath expressions",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/css-selector/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/debug-bundle",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/debug-bundle.git",
+ "reference": "b0db5c443883ce5c10c2265c77feb9833c3d9d6d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/b0db5c443883ce5c10c2265c77feb9833c3d9d6d",
+ "reference": "b0db5c443883ce5c10c2265c77feb9833c3d9d6d",
+ "shasum": ""
+ },
+ "require": {
+ "ext-xml": "*",
+ "php": ">=8.2",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/twig-bridge": "^6.4|^7.0",
+ "symfony/var-dumper": "^6.4|^7.0"
+ },
+ "conflict": {
+ "symfony/config": "<6.4",
+ "symfony/dependency-injection": "<6.4"
+ },
+ "require-dev": {
+ "symfony/config": "^6.4|^7.0",
+ "symfony/web-profiler-bundle": "^6.4|^7.0"
+ },
+ "type": "symfony-bundle",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Bundle\\DebugBundle\\": ""
+ },
+ "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 a tight integration of the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/debug-bundle/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/dom-crawler",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/dom-crawler.git",
+ "reference": "6cb272cbec4dc7a30a853d2931766b03bea92dda"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/6cb272cbec4dc7a30a853d2931766b03bea92dda",
+ "reference": "6cb272cbec4dc7a30a853d2931766b03bea92dda",
+ "shasum": ""
+ },
+ "require": {
+ "masterminds/html5": "^2.6",
+ "php": ">=8.2",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "require-dev": {
+ "symfony/css-selector": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\DomCrawler\\": ""
+ },
+ "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": "Eases DOM navigation for HTML and XML documents",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/dom-crawler/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-12T11:15:03+00:00"
+ },
+ {
+ "name": "symfony/maker-bundle",
+ "version": "v1.55.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/maker-bundle.git",
+ "reference": "11a9d3125c5b93ab4043f0f2e9927fdc55881c17"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/11a9d3125c5b93ab4043f0f2e9927fdc55881c17",
+ "reference": "11a9d3125c5b93ab4043f0f2e9927fdc55881c17",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/inflector": "^2.0",
+ "nikic/php-parser": "^4.18|^5.0",
+ "php": ">=8.1",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/console": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/deprecation-contracts": "^2.2|^3",
+ "symfony/filesystem": "^6.4|^7.0",
+ "symfony/finder": "^6.4|^7.0",
+ "symfony/framework-bundle": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/process": "^6.4|^7.0"
+ },
+ "conflict": {
+ "doctrine/doctrine-bundle": "<2.10",
+ "doctrine/orm": "<2.15"
+ },
+ "require-dev": {
+ "composer/semver": "^3.0",
+ "doctrine/doctrine-bundle": "^2.5.0",
+ "doctrine/orm": "^2.15|^3",
+ "symfony/http-client": "^6.4|^7.0",
+ "symfony/phpunit-bridge": "^6.4.1|^7.0",
+ "symfony/security-core": "^6.4|^7.0",
+ "symfony/yaml": "^6.4|^7.0",
+ "twig/twig": "^3.0|^4.x-dev"
+ },
+ "type": "symfony-bundle",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Bundle\\MakerBundle\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony Maker helps you create empty commands, controllers, form classes, tests and more so you can forget about writing boilerplate code.",
+ "homepage": "https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html",
+ "keywords": [
+ "code generator",
+ "dev",
+ "generator",
+ "scaffold",
+ "scaffolding"
+ ],
+ "support": {
+ "issues": "https://github.com/symfony/maker-bundle/issues",
+ "source": "https://github.com/symfony/maker-bundle/tree/v1.55.1"
+ },
+ "funding": [
+ {
+ "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": "2024-02-21T13:41:51+00:00"
+ },
+ {
+ "name": "symfony/phpunit-bridge",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/phpunit-bridge.git",
+ "reference": "54ca13ec990a40411ad978e08d994fca6cdd865f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/54ca13ec990a40411ad978e08d994fca6cdd865f",
+ "reference": "54ca13ec990a40411ad978e08d994fca6cdd865f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5"
+ },
+ "conflict": {
+ "phpunit/phpunit": "<7.5|9.1.2"
+ },
+ "require-dev": {
+ "symfony/deprecation-contracts": "^2.5|^3.0",
+ "symfony/error-handler": "^5.4|^6.4|^7.0",
+ "symfony/polyfill-php81": "^1.27"
+ },
+ "bin": [
+ "bin/simple-phpunit"
+ ],
+ "type": "symfony-bridge",
+ "extra": {
+ "thanks": {
+ "name": "phpunit/phpunit",
+ "url": "https://github.com/sebastianbergmann/phpunit"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Bridge\\PhpUnit\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "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": "Provides utilities for PHPUnit, especially user deprecation notices management",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/phpunit-bridge/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-08T19:22:56+00:00"
+ },
+ {
+ "name": "symfony/web-profiler-bundle",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/web-profiler-bundle.git",
+ "reference": "542daea1345fe181cbfd52db00717174a838ea0a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/542daea1345fe181cbfd52db00717174a838ea0a",
+ "reference": "542daea1345fe181cbfd52db00717174a838ea0a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/framework-bundle": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/routing": "^6.4|^7.0",
+ "symfony/twig-bundle": "^6.4|^7.0",
+ "twig/twig": "^3.0.4"
+ },
+ "conflict": {
+ "symfony/form": "<6.4",
+ "symfony/mailer": "<6.4",
+ "symfony/messenger": "<6.4"
+ },
+ "require-dev": {
+ "symfony/browser-kit": "^6.4|^7.0",
+ "symfony/console": "^6.4|^7.0",
+ "symfony/css-selector": "^6.4|^7.0",
+ "symfony/stopwatch": "^6.4|^7.0"
+ },
+ "type": "symfony-bundle",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Bundle\\WebProfilerBundle\\": ""
+ },
+ "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 a development tool that gives detailed information about the execution of any request",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "dev"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/web-profiler-bundle/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-22T20:27:20+00:00"
+ },
+ {
+ "name": "theseer/tokenizer",
+ "version": "1.2.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/theseer/tokenizer.git",
+ "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96",
+ "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlwriter": "*",
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
+ "support": {
+ "issues": "https://github.com/theseer/tokenizer/issues",
+ "source": "https://github.com/theseer/tokenizer/tree/1.2.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/theseer",
+ "type": "github"
+ }
+ ],
+ "time": "2023-11-20T00:12:19+00:00"
+ }
+ ],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": [],
+ "prefer-stable": true,
+ "prefer-lowest": false,
+ "platform": {
+ "php": ">=8.2",
+ "ext-ctype": "*",
+ "ext-iconv": "*"
+ },
+ "platform-dev": [],
+ "plugin-api-version": "2.6.0"
+}
diff --git a/examples/config/bundles.php b/examples/config/bundles.php
new file mode 100644
index 0000000..4e3a560
--- /dev/null
+++ b/examples/config/bundles.php
@@ -0,0 +1,16 @@
+ ['all' => true],
+ Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
+ Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
+ Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true],
+ Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
+ Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
+ Symfony\UX\StimulusBundle\StimulusBundle::class => ['all' => true],
+ Symfony\UX\Turbo\TurboBundle::class => ['all' => true],
+ Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
+ Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
+ Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
+ Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
+];
diff --git a/examples/config/packages/asset_mapper.yaml b/examples/config/packages/asset_mapper.yaml
new file mode 100644
index 0000000..d1ac653
--- /dev/null
+++ b/examples/config/packages/asset_mapper.yaml
@@ -0,0 +1,5 @@
+framework:
+ asset_mapper:
+ # The paths to make available to the asset mapper.
+ paths:
+ - assets/
diff --git a/examples/config/packages/cache.yaml b/examples/config/packages/cache.yaml
new file mode 100644
index 0000000..6899b72
--- /dev/null
+++ b/examples/config/packages/cache.yaml
@@ -0,0 +1,19 @@
+framework:
+ cache:
+ # Unique name of your app: used to compute stable namespaces for cache keys.
+ #prefix_seed: your_vendor_name/app_name
+
+ # The "app" cache stores to the filesystem by default.
+ # The data in this cache should persist between deploys.
+ # Other options include:
+
+ # Redis
+ #app: cache.adapter.redis
+ #default_redis_provider: redis://localhost
+
+ # APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
+ #app: cache.adapter.apcu
+
+ # Namespaced pools use the above "app" backend by default
+ #pools:
+ #my.dedicated.cache: null
diff --git a/examples/config/packages/debug.yaml b/examples/config/packages/debug.yaml
new file mode 100644
index 0000000..ad874af
--- /dev/null
+++ b/examples/config/packages/debug.yaml
@@ -0,0 +1,5 @@
+when@dev:
+ debug:
+ # Forwards VarDumper Data clones to a centralized server allowing to inspect dumps on CLI or in your browser.
+ # See the "server:dump" command to start a new server.
+ dump_destination: "tcp://%env(VAR_DUMPER_SERVER)%"
diff --git a/examples/config/packages/doctrine.yaml b/examples/config/packages/doctrine.yaml
new file mode 100644
index 0000000..d42c52d
--- /dev/null
+++ b/examples/config/packages/doctrine.yaml
@@ -0,0 +1,50 @@
+doctrine:
+ dbal:
+ url: '%env(resolve:DATABASE_URL)%'
+
+ # IMPORTANT: You MUST configure your server version,
+ # either here or in the DATABASE_URL env var (see .env file)
+ #server_version: '16'
+
+ profiling_collect_backtrace: '%kernel.debug%'
+ use_savepoints: true
+ orm:
+ auto_generate_proxy_classes: true
+ enable_lazy_ghost_objects: true
+ report_fields_where_declared: true
+ validate_xml_mapping: true
+ naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
+ auto_mapping: true
+ mappings:
+ App:
+ type: attribute
+ is_bundle: false
+ dir: '%kernel.project_dir%/src/Entity'
+ prefix: 'App\Entity'
+ alias: App
+
+when@test:
+ doctrine:
+ dbal:
+ # "TEST_TOKEN" is typically set by ParaTest
+ dbname_suffix: '_test%env(default::TEST_TOKEN)%'
+
+when@prod:
+ doctrine:
+ orm:
+ auto_generate_proxy_classes: false
+ proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies'
+ query_cache_driver:
+ type: pool
+ pool: doctrine.system_cache_pool
+ result_cache_driver:
+ type: pool
+ pool: doctrine.result_cache_pool
+
+ framework:
+ cache:
+ pools:
+ doctrine.result_cache_pool:
+ adapter: cache.app
+ doctrine.system_cache_pool:
+ adapter: cache.system
diff --git a/examples/config/packages/doctrine_migrations.yaml b/examples/config/packages/doctrine_migrations.yaml
new file mode 100644
index 0000000..29231d9
--- /dev/null
+++ b/examples/config/packages/doctrine_migrations.yaml
@@ -0,0 +1,6 @@
+doctrine_migrations:
+ migrations_paths:
+ # namespace is arbitrary but should be different from App\Migrations
+ # as migrations classes should NOT be autoloaded
+ 'DoctrineMigrations': '%kernel.project_dir%/migrations'
+ enable_profiler: false
diff --git a/examples/config/packages/framework.yaml b/examples/config/packages/framework.yaml
new file mode 100644
index 0000000..877eb25
--- /dev/null
+++ b/examples/config/packages/framework.yaml
@@ -0,0 +1,16 @@
+# see https://symfony.com/doc/current/reference/configuration/framework.html
+framework:
+ secret: '%env(APP_SECRET)%'
+ #csrf_protection: true
+
+ # Note that the session will be started ONLY if you read or write from it.
+ session: true
+
+ #esi: true
+ #fragments: true
+
+when@test:
+ framework:
+ test: true
+ session:
+ storage_factory_id: session.storage.factory.mock_file
diff --git a/examples/config/packages/mailer.yaml b/examples/config/packages/mailer.yaml
new file mode 100644
index 0000000..56a650d
--- /dev/null
+++ b/examples/config/packages/mailer.yaml
@@ -0,0 +1,3 @@
+framework:
+ mailer:
+ dsn: '%env(MAILER_DSN)%'
diff --git a/examples/config/packages/messenger.yaml b/examples/config/packages/messenger.yaml
new file mode 100644
index 0000000..587083a
--- /dev/null
+++ b/examples/config/packages/messenger.yaml
@@ -0,0 +1,24 @@
+framework:
+ messenger:
+ failure_transport: failed
+
+ transports:
+ # https://symfony.com/doc/current/messenger.html#transport-configuration
+ async:
+ dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
+ options:
+ use_notify: true
+ check_delayed_interval: 60000
+ retry_strategy:
+ max_retries: 3
+ multiplier: 2
+ failed: 'doctrine://default?queue_name=failed'
+ # sync: 'sync://'
+
+ routing:
+ Symfony\Component\Mailer\Messenger\SendEmailMessage: async
+ Symfony\Component\Notifier\Message\ChatMessage: async
+ Symfony\Component\Notifier\Message\SmsMessage: async
+
+ # Route your messages to the transports
+ # 'App\Message\YourMessage': async
diff --git a/examples/config/packages/monolog.yaml b/examples/config/packages/monolog.yaml
new file mode 100644
index 0000000..9db7d8a
--- /dev/null
+++ b/examples/config/packages/monolog.yaml
@@ -0,0 +1,62 @@
+monolog:
+ channels:
+ - deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists
+
+when@dev:
+ monolog:
+ handlers:
+ main:
+ type: stream
+ path: "%kernel.logs_dir%/%kernel.environment%.log"
+ level: debug
+ channels: ["!event"]
+ # uncomment to get logging in your browser
+ # you may have to allow bigger header sizes in your Web server configuration
+ #firephp:
+ # type: firephp
+ # level: info
+ #chromephp:
+ # type: chromephp
+ # level: info
+ console:
+ type: console
+ process_psr_3_messages: false
+ channels: ["!event", "!doctrine", "!console"]
+
+when@test:
+ monolog:
+ handlers:
+ main:
+ type: fingers_crossed
+ action_level: error
+ handler: nested
+ excluded_http_codes: [404, 405]
+ channels: ["!event"]
+ nested:
+ type: stream
+ path: "%kernel.logs_dir%/%kernel.environment%.log"
+ level: debug
+
+when@prod:
+ monolog:
+ handlers:
+ main:
+ type: fingers_crossed
+ action_level: error
+ handler: nested
+ excluded_http_codes: [404, 405]
+ buffer_size: 50 # How many messages should be saved? Prevent memory leaks
+ nested:
+ type: stream
+ path: php://stderr
+ level: debug
+ formatter: monolog.formatter.json
+ console:
+ type: console
+ process_psr_3_messages: false
+ channels: ["!event", "!doctrine"]
+ deprecation:
+ type: stream
+ channels: [deprecation]
+ path: php://stderr
+ formatter: monolog.formatter.json
diff --git a/examples/config/packages/notifier.yaml b/examples/config/packages/notifier.yaml
new file mode 100644
index 0000000..d02f986
--- /dev/null
+++ b/examples/config/packages/notifier.yaml
@@ -0,0 +1,12 @@
+framework:
+ notifier:
+ chatter_transports:
+ texter_transports:
+ channel_policy:
+ # use chat/slack, chat/telegram, sms/twilio or sms/nexmo
+ urgent: ['email']
+ high: ['email']
+ medium: ['email']
+ low: ['email']
+ admin_recipients:
+ - { email: admin@example.com }
diff --git a/examples/config/packages/routing.yaml b/examples/config/packages/routing.yaml
new file mode 100644
index 0000000..8166181
--- /dev/null
+++ b/examples/config/packages/routing.yaml
@@ -0,0 +1,10 @@
+framework:
+ router:
+ # Configure how to generate URLs in non-HTTP contexts, such as CLI commands.
+ # See https://symfony.com/doc/current/routing.html#generating-urls-in-commands
+ #default_uri: http://localhost
+
+when@prod:
+ framework:
+ router:
+ strict_requirements: null
diff --git a/examples/config/packages/security.yaml b/examples/config/packages/security.yaml
new file mode 100644
index 0000000..367af25
--- /dev/null
+++ b/examples/config/packages/security.yaml
@@ -0,0 +1,39 @@
+security:
+ # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
+ password_hashers:
+ Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
+ # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
+ providers:
+ users_in_memory: { memory: null }
+ firewalls:
+ dev:
+ pattern: ^/(_(profiler|wdt)|css|images|js)/
+ security: false
+ main:
+ lazy: true
+ provider: users_in_memory
+
+ # activate different ways to authenticate
+ # https://symfony.com/doc/current/security.html#the-firewall
+
+ # https://symfony.com/doc/current/security/impersonating_user.html
+ # switch_user: true
+
+ # Easy way to control access for large sections of your site
+ # Note: Only the *first* access control that matches will be used
+ access_control:
+ # - { path: ^/admin, roles: ROLE_ADMIN }
+ # - { path: ^/profile, roles: ROLE_USER }
+
+when@test:
+ security:
+ password_hashers:
+ # By default, password hashers are resource intensive and take time. This is
+ # important to generate secure password hashes. In tests however, secure hashes
+ # are not important, waste resources and increase test times. The following
+ # reduces the work factor to the lowest possible values.
+ Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
+ algorithm: auto
+ cost: 4 # Lowest possible value for bcrypt
+ time_cost: 3 # Lowest possible value for argon
+ memory_cost: 10 # Lowest possible value for argon
diff --git a/examples/config/packages/translation.yaml b/examples/config/packages/translation.yaml
new file mode 100644
index 0000000..b3f8f9c
--- /dev/null
+++ b/examples/config/packages/translation.yaml
@@ -0,0 +1,7 @@
+framework:
+ default_locale: en
+ translator:
+ default_path: '%kernel.project_dir%/translations'
+ fallbacks:
+ - en
+ providers:
diff --git a/examples/config/packages/twig.yaml b/examples/config/packages/twig.yaml
new file mode 100644
index 0000000..3f795d9
--- /dev/null
+++ b/examples/config/packages/twig.yaml
@@ -0,0 +1,6 @@
+twig:
+ file_name_pattern: '*.twig'
+
+when@test:
+ twig:
+ strict_variables: true
diff --git a/examples/config/packages/validator.yaml b/examples/config/packages/validator.yaml
new file mode 100644
index 0000000..dd47a6a
--- /dev/null
+++ b/examples/config/packages/validator.yaml
@@ -0,0 +1,11 @@
+framework:
+ validation:
+ # Enables validator auto-mapping support.
+ # For instance, basic validation constraints will be inferred from Doctrine's metadata.
+ #auto_mapping:
+ # App\Entity\: []
+
+when@test:
+ framework:
+ validation:
+ not_compromised_password: false
diff --git a/examples/config/packages/web_profiler.yaml b/examples/config/packages/web_profiler.yaml
new file mode 100644
index 0000000..b946111
--- /dev/null
+++ b/examples/config/packages/web_profiler.yaml
@@ -0,0 +1,17 @@
+when@dev:
+ web_profiler:
+ toolbar: true
+ intercept_redirects: false
+
+ framework:
+ profiler:
+ only_exceptions: false
+ collect_serializer_data: true
+
+when@test:
+ web_profiler:
+ toolbar: false
+ intercept_redirects: false
+
+ framework:
+ profiler: { collect: false }
diff --git a/examples/config/preload.php b/examples/config/preload.php
new file mode 100644
index 0000000..db37723
--- /dev/null
+++ b/examples/config/preload.php
@@ -0,0 +1,5 @@
+ [
+ 'path' => './assets/app.js',
+ 'entrypoint' => true,
+ ],
+ '@hotwired/stimulus' => [
+ 'version' => '3.2.2',
+ ],
+ '@symfony/stimulus-bundle' => [
+ 'path' => './vendor/symfony/stimulus-bundle/assets/dist/loader.js',
+ ],
+ '@hotwired/turbo' => [
+ 'version' => '7.3.0',
+ ],
+];
diff --git a/examples/infrastructure/docker/docker-compose.builder.yml b/examples/infrastructure/docker/docker-compose.builder.yml
new file mode 100644
index 0000000..f2b4807
--- /dev/null
+++ b/examples/infrastructure/docker/docker-compose.builder.yml
@@ -0,0 +1,25 @@
+version: '3.7'
+
+volumes:
+ builder-data: {}
+
+services:
+ builder:
+ build:
+ context: services/php
+ target: builder
+ depends_on:
+ - postgres
+ environment:
+ - COMPOSER_MEMORY_LIMIT=-1
+ - UID=${USER_ID}
+ # The following list contains the common environment variables exposed by CI platforms
+ - GITHUB_ACTIONS
+ - CI # Travis CI, CircleCI, Cirrus CI, Gitlab CI, Appveyor, CodeShip, dsari
+ - CONTINUOUS_INTEGRATION # Travis CI, Cirrus CI
+ - BUILD_NUMBER # Jenkins, TeamCity
+ - RUN_ID # TaskCluster, dsari
+ volumes:
+ - "builder-data:/home/app"
+ - "${COMPOSER_CACHE_DIR}:/home/app/.composer/cache"
+ - "../..:/var/www:cached"
diff --git a/examples/infrastructure/docker/docker-compose.docker-for-x.yml b/examples/infrastructure/docker/docker-compose.docker-for-x.yml
new file mode 100644
index 0000000..dcc24b0
--- /dev/null
+++ b/examples/infrastructure/docker/docker-compose.docker-for-x.yml
@@ -0,0 +1,13 @@
+# This file is used only when using Docker for Mac or Windows
+
+version: '3.7'
+
+services:
+ router:
+ # Docker for Mac or Windows does not support the "network_mode=host"
+ # So we use the default network mode and we map all needed ports
+ network_mode: "${PROJECT_NAME}_default"
+ ports:
+ - "80:80"
+ - "443:443"
+ - "8080:8080"
diff --git a/examples/infrastructure/docker/docker-compose.worker.yml b/examples/infrastructure/docker/docker-compose.worker.yml
new file mode 100644
index 0000000..a8a17d1
--- /dev/null
+++ b/examples/infrastructure/docker/docker-compose.worker.yml
@@ -0,0 +1,20 @@
+version: '3.7'
+
+# this is a template to factorize the service definitions
+x-services-templates:
+ worker_base: &worker_base
+ build:
+ context: services/php
+ target: worker
+ depends_on:
+ - postgres
+ #- rabbitmq
+ volumes:
+ - "../..:/var/www:cached"
+ labels:
+ - "docker-starter.worker.${PROJECT_NAME}=true"
+
+# services:
+# worker_messenger:
+# <<: *worker_base
+# command: php -d memory_limit=1G /var/www/bin/console messenger:consume async --memory-limit=128M
diff --git a/examples/infrastructure/docker/docker-compose.yml b/examples/infrastructure/docker/docker-compose.yml
new file mode 100644
index 0000000..230a21a
--- /dev/null
+++ b/examples/infrastructure/docker/docker-compose.yml
@@ -0,0 +1,38 @@
+version: '3.7'
+
+volumes:
+ postgres-data: {}
+
+services:
+ router:
+ build: services/router
+ volumes:
+ - "/var/run/docker.sock:/var/run/docker.sock"
+ - "./services/router/certs:/etc/ssl/certs"
+ network_mode: host
+
+ frontend:
+ build:
+ context: services/php
+ target: frontend
+ depends_on:
+ - postgres
+ volumes:
+ - "../..:/var/www:cached"
+ environment:
+ - "PHP_VERSION=${PHP_VERSION}"
+ labels:
+ - "traefik.enable=true"
+ - "traefik.http.routers.${PROJECT_NAME}-frontend.rule=Host(${PROJECT_DOMAINS})"
+ - "traefik.http.routers.${PROJECT_NAME}-frontend.tls=true"
+ - "traefik.http.routers.${PROJECT_NAME}-frontend-unsecure.rule=Host(${PROJECT_DOMAINS})"
+ # Comment the next line to be able to access frontend via HTTP instead of HTTPS
+ - "traefik.http.routers.${PROJECT_NAME}-frontend-unsecure.middlewares=redirect-to-https@file"
+
+ postgres:
+ image: postgres:16
+ environment:
+ - POSTGRES_USER=app
+ - POSTGRES_PASSWORD=app
+ volumes:
+ - postgres-data:/var/lib/postgresql/data
diff --git a/examples/infrastructure/docker/services/php/Dockerfile b/examples/infrastructure/docker/services/php/Dockerfile
new file mode 100644
index 0000000..c4ef231
--- /dev/null
+++ b/examples/infrastructure/docker/services/php/Dockerfile
@@ -0,0 +1,121 @@
+# hadolint global ignore=DL3008
+
+FROM debian:12.5-slim as php-base
+
+SHELL ["/bin/bash", "-o", "pipefail", "-c"]
+
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+ curl \
+ ca-certificates \
+ gnupg \
+ && curl -sSLo /tmp/debsuryorg-archive-keyring.deb https://packages.sury.org/debsuryorg-archive-keyring.deb \
+ && dpkg -i /tmp/debsuryorg-archive-keyring.deb \
+ && echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php bookworm main" > /etc/apt/sources.list.d/sury.list \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*
+
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+ procps \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*
+
+ARG PHP_VERSION
+
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+ "php${PHP_VERSION}-apcu" \
+ "php${PHP_VERSION}-bcmath" \
+ "php${PHP_VERSION}-cli" \
+ "php${PHP_VERSION}-common" \
+ "php${PHP_VERSION}-curl" \
+ "php${PHP_VERSION}-iconv" \
+ "php${PHP_VERSION}-intl" \
+ "php${PHP_VERSION}-mbstring" \
+ "php${PHP_VERSION}-pgsql" \
+ "php${PHP_VERSION}-uuid" \
+ "php${PHP_VERSION}-xml" \
+ "php${PHP_VERSION}-zip" \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*
+
+# Fake user to maps with the one on the host
+ARG USER_ID
+COPY entrypoint /
+RUN addgroup --gid $USER_ID app && \
+ adduser --system --uid $USER_ID --home /home/app --shell /bin/bash app && \
+ curl -Ls https://github.com/tianon/gosu/releases/download/1.17/gosu-amd64 | \
+ install /dev/stdin /usr/local/bin/gosu && \
+ sed "s/{{ application_user }}/app/g" -i /entrypoint
+
+# Configuration
+COPY base/php-configuration /etc/php/${PHP_VERSION}
+
+WORKDIR /var/www
+ENTRYPOINT [ "/entrypoint" ]
+
+FROM php-base as frontend
+
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+ nginx \
+ "php${PHP_VERSION}-fpm" \
+ runit \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/* \
+ && rm -r "/etc/php/${PHP_VERSION}/fpm/pool.d/"
+
+RUN useradd -s /bin/false nginx
+
+COPY frontend/php-configuration /etc/php/${PHP_VERSION}
+COPY frontend/etc/nginx/. /etc/nginx/
+COPY frontend/etc/service/. /etc/service/
+
+RUN phpenmod app-default \
+ && phpenmod app-fpm
+
+EXPOSE 80
+
+CMD ["runsvdir", "-P", "/etc/service"]
+
+FROM php-base as worker
+
+FROM php-base as builder
+
+SHELL ["/bin/bash", "-o", "pipefail", "-c"]
+
+ARG NODEJS_VERSION=20.x
+RUN curl -s https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /usr/share/keyrings/nodesource.gpg \
+ && echo "deb [signed-by=/usr/share/keyrings/nodesource.gpg] https://deb.nodesource.com/node_${NODEJS_VERSION} nodistro main" > /etc/apt/sources.list.d/nodesource.list
+
+# Default toys
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+ git \
+ make \
+ nodejs \
+ sudo \
+ unzip \
+ && apt-get clean \
+ && npm install -g yarn@1.22 \
+ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*
+
+# Config
+COPY builder/etc/. /etc/
+COPY builder/php-configuration /etc/php/${PHP_VERSION}
+RUN adduser app sudo \
+ && mkdir /var/log/php \
+ && chmod 777 /var/log/php \
+ && phpenmod app-default \
+ && phpenmod app-builder
+
+# Composer
+COPY --from=composer/composer:2.7.1 /usr/bin/composer /usr/bin/composer
+RUN mkdir -p "/home/app/.composer/cache" \
+ && chown app: /home/app/.composer -R
+
+# Third party tools
+ENV PATH="$PATH:/var/www/tools/bin"
+
+WORKDIR /var/www
diff --git a/examples/infrastructure/docker/services/php/base/php-configuration/mods-available/app-default.ini b/examples/infrastructure/docker/services/php/base/php-configuration/mods-available/app-default.ini
new file mode 100644
index 0000000..17d01e4
--- /dev/null
+++ b/examples/infrastructure/docker/services/php/base/php-configuration/mods-available/app-default.ini
@@ -0,0 +1,27 @@
+; priority=30
+[PHP]
+short_open_tag = Off
+memory_limit = 512M
+error_reporting = E_ALL
+display_errors = On
+display_startup_errors = On
+error_log = /proc/self/fd/2
+log_errors = On
+log_errors_max_len = 0
+max_execution_time = 0
+always_populate_raw_post_data = -1
+upload_max_filesize = 20M
+post_max_size = 20M
+[Date]
+date.timezone = UTC
+[Phar]
+phar.readonly = Off
+[opcache]
+opcache.memory_consumption=256
+opcache.max_accelerated_files=20000
+realpath_cache_size=4096K
+realpath_cache_ttl=600
+opcache.error_log = /proc/self/fd/2
+[apc]
+apc.enabled=1
+apc.enable_cli=1
diff --git a/examples/infrastructure/docker/services/php/builder/etc/sudoers.d/sudo b/examples/infrastructure/docker/services/php/builder/etc/sudoers.d/sudo
new file mode 100644
index 0000000..b835421
--- /dev/null
+++ b/examples/infrastructure/docker/services/php/builder/etc/sudoers.d/sudo
@@ -0,0 +1 @@
+%sudo ALL=(ALL) NOPASSWD: ALL
diff --git a/examples/infrastructure/docker/services/php/builder/php-configuration/mods-available/app-builder.ini b/examples/infrastructure/docker/services/php/builder/php-configuration/mods-available/app-builder.ini
new file mode 100644
index 0000000..3016083
--- /dev/null
+++ b/examples/infrastructure/docker/services/php/builder/php-configuration/mods-available/app-builder.ini
@@ -0,0 +1,5 @@
+; priority=40
+[PHP]
+error_log = /var/log/php/error.log
+[opcache]
+opcache.error_log = /var/log/php/opcache.log
diff --git a/examples/infrastructure/docker/services/php/entrypoint b/examples/infrastructure/docker/services/php/entrypoint
new file mode 100755
index 0000000..1f15e84
--- /dev/null
+++ b/examples/infrastructure/docker/services/php/entrypoint
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+set -e
+set -u
+
+if [ $(id -u) != 0 ]; then
+ echo "Running this image as non root is not allowed"
+ exit 1
+fi
+
+: "${UID:=0}"
+: "${GID:=${UID}}"
+
+if [ "$#" = 0 ]; then
+ set -- "$(command -v bash 2>/dev/null || command -v sh)" -l
+fi
+
+if [ "$UID" != 0 ]; then
+ usermod -u "$UID" "{{ application_user }}" >/dev/null 2>/dev/null && {
+ groupmod -g "$GID" "{{ application_user }}" >/dev/null 2>/dev/null ||
+ usermod -a -G "$GID" "{{ application_user }}" >/dev/null 2>/dev/null
+ }
+ set -- gosu "${UID}:${GID}" "${@}"
+fi
+
+exec "$@"
diff --git a/examples/infrastructure/docker/services/php/frontend/etc/nginx/environments b/examples/infrastructure/docker/services/php/frontend/etc/nginx/environments
new file mode 100644
index 0000000..e69de29
diff --git a/examples/infrastructure/docker/services/php/frontend/etc/nginx/nginx.conf b/examples/infrastructure/docker/services/php/frontend/etc/nginx/nginx.conf
new file mode 100644
index 0000000..8e939f7
--- /dev/null
+++ b/examples/infrastructure/docker/services/php/frontend/etc/nginx/nginx.conf
@@ -0,0 +1,74 @@
+user nginx;
+pid /var/run/nginx.pid;
+daemon off;
+error_log /proc/self/fd/2;
+include /etc/nginx/modules-enabled/*.conf;
+
+http {
+ access_log /proc/self/fd/1;
+ sendfile on;
+ tcp_nopush on;
+ tcp_nodelay on;
+ keepalive_timeout 65;
+ types_hash_max_size 2048;
+ include /etc/nginx/mime.types;
+ default_type application/octet-stream;
+ client_max_body_size 20m;
+ server_tokens off;
+
+ gzip on;
+ gzip_disable "msie6";
+ gzip_vary on;
+ gzip_proxied any;
+ gzip_comp_level 6;
+ gzip_buffers 16 8k;
+ gzip_http_version 1.1;
+ gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
+
+ server {
+ listen 0.0.0.0:80;
+ root /var/www/public;
+
+ location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg)$ {
+ access_log off;
+ add_header Cache-Control "no-cache";
+ }
+
+ # Remove this block if you want to access to PHP FPM monitoring
+ # dashboard (on URL: /php-fpm-status). WARNING: on production, you must
+ # secure this page (by user IP address, with a password, for example)
+ location ~ ^/php-fpm-status$ {
+ deny all;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ fastcgi_index index.php;
+ include fastcgi_params;
+ fastcgi_pass 127.0.0.1:9000;
+ }
+
+ location / {
+ # try to serve file directly, fallback to index.php
+ try_files $uri /index.php$is_args$args;
+ }
+
+ location ~ ^/index\.php(/|$) {
+ fastcgi_pass 127.0.0.1:9000;
+ fastcgi_split_path_info ^(.+\.php)(/.*)$;
+
+ include fastcgi_params;
+ include environments;
+
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ fastcgi_param HTTPS on;
+ fastcgi_param SERVER_NAME $http_host;
+ # # Uncomment if you want to use /php-fpm-status endpoint **with**
+ # # real request URI. It may have some side effects, that's why it's
+ # # commented by default
+ # fastcgi_param SCRIPT_NAME $request_uri;
+ }
+
+ error_log /proc/self/fd/2;
+ access_log /proc/self/fd/1;
+ }
+}
+
+events {}
diff --git a/examples/infrastructure/docker/services/php/frontend/etc/service/nginx/run b/examples/infrastructure/docker/services/php/frontend/etc/service/nginx/run
new file mode 100755
index 0000000..14cd019
--- /dev/null
+++ b/examples/infrastructure/docker/services/php/frontend/etc/service/nginx/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+exec /usr/sbin/nginx
diff --git a/examples/infrastructure/docker/services/php/frontend/etc/service/php-fpm/run b/examples/infrastructure/docker/services/php/frontend/etc/service/php-fpm/run
new file mode 100755
index 0000000..1bcdb2b
--- /dev/null
+++ b/examples/infrastructure/docker/services/php/frontend/etc/service/php-fpm/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+exec /usr/sbin/php-fpm${PHP_VERSION} -y /etc/php/${PHP_VERSION}/fpm/php-fpm.conf -O
diff --git a/examples/infrastructure/docker/services/php/frontend/php-configuration/fpm/php-fpm.conf b/examples/infrastructure/docker/services/php/frontend/php-configuration/fpm/php-fpm.conf
new file mode 100644
index 0000000..38b5901
--- /dev/null
+++ b/examples/infrastructure/docker/services/php/frontend/php-configuration/fpm/php-fpm.conf
@@ -0,0 +1,19 @@
+[global]
+pid = /var/run/php-fpm.pid
+error_log = /proc/self/fd/2
+daemonize = no
+
+[www]
+user = app
+group = app
+listen = 127.0.0.1:9000
+pm = dynamic
+pm.max_children = 25
+pm.start_servers = 2
+pm.min_spare_servers = 2
+pm.max_spare_servers = 3
+pm.max_requests = 500
+pm.status_path = /php-fpm-status
+clear_env = no
+request_terminate_timeout = 120s
+catch_workers_output = yes
diff --git a/examples/infrastructure/docker/services/php/frontend/php-configuration/mods-available/app-fpm.ini b/examples/infrastructure/docker/services/php/frontend/php-configuration/mods-available/app-fpm.ini
new file mode 100644
index 0000000..f3f541d
--- /dev/null
+++ b/examples/infrastructure/docker/services/php/frontend/php-configuration/mods-available/app-fpm.ini
@@ -0,0 +1,5 @@
+; priority=40
+[PHP]
+expose_php = off
+memory_limit = 128M
+max_execution_time = 30
diff --git a/examples/infrastructure/docker/services/router/Dockerfile b/examples/infrastructure/docker/services/router/Dockerfile
new file mode 100644
index 0000000..cbd3f79
--- /dev/null
+++ b/examples/infrastructure/docker/services/router/Dockerfile
@@ -0,0 +1,5 @@
+FROM traefik:v3.0
+
+COPY traefik /etc/traefik
+
+VOLUME [ "/etc/ssl/certs" ]
diff --git a/examples/infrastructure/docker/services/router/certs/.gitkeep b/examples/infrastructure/docker/services/router/certs/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/examples/infrastructure/docker/services/router/generate-ssl.sh b/examples/infrastructure/docker/services/router/generate-ssl.sh
new file mode 100755
index 0000000..f9d49fb
--- /dev/null
+++ b/examples/infrastructure/docker/services/router/generate-ssl.sh
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+
+# Script used in dev to generate a basic SSL cert
+
+BASE=$(dirname $0)
+
+CERTS_DIR=$BASE/certs
+
+rm -rf $CERTS_DIR
+mkdir -p $CERTS_DIR
+
+openssl req -x509 -sha256 -newkey rsa:4096 \
+ -keyout $CERTS_DIR/key.pem \
+ -out $CERTS_DIR/cert.pem \
+ -days 3650 -nodes -config \
+ $BASE/openssl.cnf
diff --git a/examples/infrastructure/docker/services/router/openssl.cnf b/examples/infrastructure/docker/services/router/openssl.cnf
new file mode 100644
index 0000000..ff68b84
--- /dev/null
+++ b/examples/infrastructure/docker/services/router/openssl.cnf
@@ -0,0 +1,19 @@
+# Configuration used in dev to generate a basic SSL cert
+[req]
+default_bits = 2048
+prompt = no
+default_md = sha256
+distinguished_name = dn
+x509_extensions = v3_req
+
+[v3_req]
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid:always,issuer:always
+basicConstraints=CA:true
+subjectAltName = @alt_names
+
+[dn]
+CN=app.test
+
+[alt_names]
+DNS.1 = app.test
diff --git a/examples/infrastructure/docker/services/router/traefik/dynamic_conf.yaml b/examples/infrastructure/docker/services/router/traefik/dynamic_conf.yaml
new file mode 100644
index 0000000..5680885
--- /dev/null
+++ b/examples/infrastructure/docker/services/router/traefik/dynamic_conf.yaml
@@ -0,0 +1,12 @@
+tls:
+ stores:
+ default:
+ defaultCertificate:
+ certFile: /etc/ssl/certs/cert.pem
+ keyFile: /etc/ssl/certs/key.pem
+
+http:
+ middlewares:
+ redirect-to-https:
+ redirectScheme:
+ scheme: https
diff --git a/examples/infrastructure/docker/services/router/traefik/traefik.yaml b/examples/infrastructure/docker/services/router/traefik/traefik.yaml
new file mode 100644
index 0000000..a4c101a
--- /dev/null
+++ b/examples/infrastructure/docker/services/router/traefik/traefik.yaml
@@ -0,0 +1,28 @@
+global:
+ checkNewVersion: false
+ sendAnonymousUsage: false
+
+providers:
+ docker:
+ exposedByDefault: false
+ file:
+ filename: /etc/traefik/dynamic_conf.yaml
+
+# # Uncomment get all DEBUG logs
+#log:
+# level: "DEBUG"
+
+# # Uncomment to view all access logs
+#accessLog: {}
+
+api:
+ dashboard: true
+ insecure: true # No authentication are required
+
+entryPoints:
+ http:
+ address: ":80"
+ https:
+ address: ":443"
+ traefik: # this one exists by default
+ address: ":8080"
diff --git a/examples/migrations/.gitignore b/examples/migrations/.gitignore
new file mode 100644
index 0000000..e69de29
diff --git a/examples/phpstan.neon b/examples/phpstan.neon
new file mode 100644
index 0000000..2db6d86
--- /dev/null
+++ b/examples/phpstan.neon
@@ -0,0 +1,31 @@
+parameters:
+ level: 6
+ paths:
+ - src
+ - public
+ - castor.php
+ - .castor/
+ scanFiles:
+ - .castor.stub.php
+ tmpDir: tools/phpstan/var
+ inferPrivatePropertyTypeFromConstructor: true
+
+ symfony:
+ container_xml_path: var/cache/dev/App_KernelDevDebugContainer.xml'
+
+ typeAliases:
+ ContextData: '''
+ array{
+ project_name: string,
+ root_domain: string,
+ extra_domains: string[],
+ php_version: string,
+ docker_compose_files: string[],
+ macos: bool,
+ power_shell: bool,
+ user_id: int,
+ root_dir: string,
+ env: string,
+ composer_cache_dir: string,
+ }
+ '''
diff --git a/examples/phpunit.xml.dist b/examples/phpunit.xml.dist
new file mode 100644
index 0000000..6c4bfed
--- /dev/null
+++ b/examples/phpunit.xml.dist
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tests
+
+
+
+
+
+ src
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/public/index.php b/examples/public/index.php
new file mode 100644
index 0000000..7fbc8cf
--- /dev/null
+++ b/examples/public/index.php
@@ -0,0 +1,9 @@
+render('homepage/index.html.twig', [
+ 'controller_name' => 'HomepageController',
+ ]);
+ }
+}
diff --git a/examples/src/Entity/.gitignore b/examples/src/Entity/.gitignore
new file mode 100644
index 0000000..e69de29
diff --git a/examples/src/Kernel.php b/examples/src/Kernel.php
new file mode 100644
index 0000000..779cd1f
--- /dev/null
+++ b/examples/src/Kernel.php
@@ -0,0 +1,11 @@
+
+
+
+
+ {% block title %}Welcome!{% endblock %}
+
+ {% block stylesheets %}
+ {% endblock %}
+
+ {% block javascripts %}
+ {% block importmap %}{{ importmap('app') }}{% endblock %}
+ {% endblock %}
+
+
+ {% block body %}{% endblock %}
+
+
diff --git a/examples/tests/bootstrap.php b/examples/tests/bootstrap.php
new file mode 100644
index 0000000..5160486
--- /dev/null
+++ b/examples/tests/bootstrap.php
@@ -0,0 +1,11 @@
+bootEnv(dirname(__DIR__) . '/.env');
+}
diff --git a/examples/tools/bin/php-cs-fixer b/examples/tools/bin/php-cs-fixer
new file mode 120000
index 0000000..8b6029f
--- /dev/null
+++ b/examples/tools/bin/php-cs-fixer
@@ -0,0 +1 @@
+../php-cs-fixer/vendor/bin/php-cs-fixer
\ No newline at end of file
diff --git a/examples/tools/bin/phpstan b/examples/tools/bin/phpstan
new file mode 120000
index 0000000..c10edfd
--- /dev/null
+++ b/examples/tools/bin/phpstan
@@ -0,0 +1 @@
+../phpstan/vendor/bin/phpstan
\ No newline at end of file
diff --git a/examples/tools/php-cs-fixer/.gitignore b/examples/tools/php-cs-fixer/.gitignore
new file mode 100644
index 0000000..57872d0
--- /dev/null
+++ b/examples/tools/php-cs-fixer/.gitignore
@@ -0,0 +1 @@
+/vendor/
diff --git a/examples/tools/php-cs-fixer/composer.json b/examples/tools/php-cs-fixer/composer.json
new file mode 100644
index 0000000..c216598
--- /dev/null
+++ b/examples/tools/php-cs-fixer/composer.json
@@ -0,0 +1,12 @@
+{
+ "type": "project",
+ "require": {
+ "friendsofphp/php-cs-fixer": "^3.47.1"
+ },
+ "config": {
+ "platform": {
+ "php": "8.1"
+ },
+ "sort-packages": true
+ }
+}
diff --git a/examples/tools/php-cs-fixer/composer.lock b/examples/tools/php-cs-fixer/composer.lock
new file mode 100644
index 0000000..6e1c4b1
--- /dev/null
+++ b/examples/tools/php-cs-fixer/composer.lock
@@ -0,0 +1,1845 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+ "This file is @generated automatically"
+ ],
+ "content-hash": "74ae7a6662eee7cb4b9ed2a50b72ec98",
+ "packages": [
+ {
+ "name": "composer/pcre",
+ "version": "3.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/pcre.git",
+ "reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/pcre/zipball/00104306927c7a0919b4ced2aaa6782c1e61a3c9",
+ "reference": "00104306927c7a0919b4ced2aaa6782c1e61a3c9",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.4 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.3",
+ "phpstan/phpstan-strict-rules": "^1.1",
+ "symfony/phpunit-bridge": "^5"
+ },
+ "type": "library",
+ "extra": {
+ "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.1.1"
+ },
+ "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": "2023-10-11T07:11:09+00:00"
+ },
+ {
+ "name": "composer/semver",
+ "version": "3.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/semver.git",
+ "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32",
+ "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3.2 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.4",
+ "symfony/phpunit-bridge": "^4.2 || ^5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\Semver\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nils Adermann",
+ "email": "naderman@naderman.de",
+ "homepage": "http://www.naderman.de"
+ },
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ },
+ {
+ "name": "Rob Bast",
+ "email": "rob.bast@gmail.com",
+ "homepage": "http://robbast.nl"
+ }
+ ],
+ "description": "Semver library that offers utilities, version constraint parsing and validation.",
+ "keywords": [
+ "semantic",
+ "semver",
+ "validation",
+ "versioning"
+ ],
+ "support": {
+ "irc": "ircs://irc.libera.chat:6697/composer",
+ "issues": "https://github.com/composer/semver/issues",
+ "source": "https://github.com/composer/semver/tree/3.4.0"
+ },
+ "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": "2023-08-31T09:50:34+00:00"
+ },
+ {
+ "name": "composer/xdebug-handler",
+ "version": "3.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/xdebug-handler.git",
+ "reference": "ced299686f41dce890debac69273b47ffe98a40c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c",
+ "reference": "ced299686f41dce890debac69273b47ffe98a40c",
+ "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",
+ "symfony/phpunit-bridge": "^6.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Composer\\XdebugHandler\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "John Stevenson",
+ "email": "john-stevenson@blueyonder.co.uk"
+ }
+ ],
+ "description": "Restarts a process without Xdebug.",
+ "keywords": [
+ "Xdebug",
+ "performance"
+ ],
+ "support": {
+ "irc": "irc://irc.freenode.org/composer",
+ "issues": "https://github.com/composer/xdebug-handler/issues",
+ "source": "https://github.com/composer/xdebug-handler/tree/3.0.3"
+ },
+ "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": "2022-02-25T21:32:43+00:00"
+ },
+ {
+ "name": "friendsofphp/php-cs-fixer",
+ "version": "v3.47.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
+ "reference": "173c60d1eff911c9c54322704623a45561d3241d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/173c60d1eff911c9c54322704623a45561d3241d",
+ "reference": "173c60d1eff911c9c54322704623a45561d3241d",
+ "shasum": ""
+ },
+ "require": {
+ "composer/semver": "^3.4",
+ "composer/xdebug-handler": "^3.0.3",
+ "ext-filter": "*",
+ "ext-json": "*",
+ "ext-tokenizer": "*",
+ "php": "^7.4 || ^8.0",
+ "sebastian/diff": "^4.0 || ^5.0",
+ "symfony/console": "^5.4 || ^6.0 || ^7.0",
+ "symfony/event-dispatcher": "^5.4 || ^6.0 || ^7.0",
+ "symfony/filesystem": "^5.4 || ^6.0 || ^7.0",
+ "symfony/finder": "^5.4 || ^6.0 || ^7.0",
+ "symfony/options-resolver": "^5.4 || ^6.0 || ^7.0",
+ "symfony/polyfill-mbstring": "^1.28",
+ "symfony/polyfill-php80": "^1.28",
+ "symfony/polyfill-php81": "^1.28",
+ "symfony/process": "^5.4 || ^6.0 || ^7.0",
+ "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0"
+ },
+ "require-dev": {
+ "facile-it/paraunit": "^1.3 || ^2.0",
+ "justinrainbow/json-schema": "^5.2",
+ "keradus/cli-executor": "^2.1",
+ "mikey179/vfsstream": "^1.6.11",
+ "php-coveralls/php-coveralls": "^2.7",
+ "php-cs-fixer/accessible-object": "^1.1",
+ "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.4",
+ "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.4",
+ "phpunit/phpunit": "^9.6 || ^10.5.5",
+ "symfony/yaml": "^5.4 || ^6.0 || ^7.0"
+ },
+ "suggest": {
+ "ext-dom": "For handling output formats in XML",
+ "ext-mbstring": "For handling non-UTF8 characters."
+ },
+ "bin": [
+ "php-cs-fixer"
+ ],
+ "type": "application",
+ "autoload": {
+ "psr-4": {
+ "PhpCsFixer\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Dariusz Rumiński",
+ "email": "dariusz.ruminski@gmail.com"
+ }
+ ],
+ "description": "A tool to automatically fix PHP code style",
+ "keywords": [
+ "Static code analysis",
+ "fixer",
+ "standards",
+ "static analysis"
+ ],
+ "support": {
+ "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
+ "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.47.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/keradus",
+ "type": "github"
+ }
+ ],
+ "time": "2024-01-16T18:54:21+00:00"
+ },
+ {
+ "name": "psr/container",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/container.git",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+ "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.4.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Container\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common Container Interface (PHP FIG PSR-11)",
+ "homepage": "https://github.com/php-fig/container",
+ "keywords": [
+ "PSR-11",
+ "container",
+ "container-interface",
+ "container-interop",
+ "psr"
+ ],
+ "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": "psr/event-dispatcher",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/event-dispatcher.git",
+ "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0",
+ "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\EventDispatcher\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "http://www.php-fig.org/"
+ }
+ ],
+ "description": "Standard interfaces for event handling.",
+ "keywords": [
+ "events",
+ "psr",
+ "psr-14"
+ ],
+ "support": {
+ "issues": "https://github.com/php-fig/event-dispatcher/issues",
+ "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0"
+ },
+ "time": "2019-01-08T18:20:26+00:00"
+ },
+ {
+ "name": "psr/log",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
+ "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/log/tree/3.0.0"
+ },
+ "time": "2021-07-14T16:46:02+00:00"
+ },
+ {
+ "name": "sebastian/diff",
+ "version": "5.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/diff.git",
+ "reference": "fbf413a49e54f6b9b17e12d900ac7f6101591b7f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/fbf413a49e54f6b9b17e12d900ac7f6101591b7f",
+ "reference": "fbf413a49e54f6b9b17e12d900ac7f6101591b7f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0",
+ "symfony/process": "^4.2 || ^5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Kore Nordmann",
+ "email": "mail@kore-nordmann.de"
+ }
+ ],
+ "description": "Diff implementation",
+ "homepage": "https://github.com/sebastianbergmann/diff",
+ "keywords": [
+ "diff",
+ "udiff",
+ "unidiff",
+ "unified diff"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/diff/issues",
+ "security": "https://github.com/sebastianbergmann/diff/security/policy",
+ "source": "https://github.com/sebastianbergmann/diff/tree/5.1.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-12-22T10:55:06+00:00"
+ },
+ {
+ "name": "symfony/console",
+ "version": "v6.4.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/console.git",
+ "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/console/zipball/0254811a143e6bc6c8deea08b589a7e68a37f625",
+ "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "symfony/deprecation-contracts": "^2.5|^3",
+ "symfony/polyfill-mbstring": "~1.0",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/string": "^5.4|^6.0|^7.0"
+ },
+ "conflict": {
+ "symfony/dependency-injection": "<5.4",
+ "symfony/dotenv": "<5.4",
+ "symfony/event-dispatcher": "<5.4",
+ "symfony/lock": "<5.4",
+ "symfony/process": "<5.4"
+ },
+ "provide": {
+ "psr/log-implementation": "1.0|2.0|3.0"
+ },
+ "require-dev": {
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^5.4|^6.0|^7.0",
+ "symfony/dependency-injection": "^5.4|^6.0|^7.0",
+ "symfony/event-dispatcher": "^5.4|^6.0|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/lock": "^5.4|^6.0|^7.0",
+ "symfony/messenger": "^5.4|^6.0|^7.0",
+ "symfony/process": "^5.4|^6.0|^7.0",
+ "symfony/stopwatch": "^5.4|^6.0|^7.0",
+ "symfony/var-dumper": "^5.4|^6.0|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Console\\": ""
+ },
+ "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": "Eases the creation of beautiful and testable command line interfaces",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "cli",
+ "command-line",
+ "console",
+ "terminal"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/console/tree/v6.4.2"
+ },
+ "funding": [
+ {
+ "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": "2023-12-10T16:15:48+00:00"
+ },
+ {
+ "name": "symfony/deprecation-contracts",
+ "version": "v3.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/deprecation-contracts.git",
+ "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf",
+ "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "files": [
+ "function.php"
+ ]
+ },
+ "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": "A generic function and convention to trigger deprecation notices",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0"
+ },
+ "funding": [
+ {
+ "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": "2023-05-23T14:45:45+00:00"
+ },
+ {
+ "name": "symfony/event-dispatcher",
+ "version": "v6.4.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/event-dispatcher.git",
+ "reference": "e95216850555cd55e71b857eb9d6c2674124603a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/e95216850555cd55e71b857eb9d6c2674124603a",
+ "reference": "e95216850555cd55e71b857eb9d6c2674124603a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "symfony/event-dispatcher-contracts": "^2.5|^3"
+ },
+ "conflict": {
+ "symfony/dependency-injection": "<5.4",
+ "symfony/service-contracts": "<2.5"
+ },
+ "provide": {
+ "psr/event-dispatcher-implementation": "1.0",
+ "symfony/event-dispatcher-implementation": "2.0|3.0"
+ },
+ "require-dev": {
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^5.4|^6.0|^7.0",
+ "symfony/dependency-injection": "^5.4|^6.0|^7.0",
+ "symfony/error-handler": "^5.4|^6.0|^7.0",
+ "symfony/expression-language": "^5.4|^6.0|^7.0",
+ "symfony/http-foundation": "^5.4|^6.0|^7.0",
+ "symfony/service-contracts": "^2.5|^3",
+ "symfony/stopwatch": "^5.4|^6.0|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\EventDispatcher\\": ""
+ },
+ "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 tools that allow your application components to communicate with each other by dispatching events and listening to them",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.2"
+ },
+ "funding": [
+ {
+ "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": "2023-12-27T22:16:42+00:00"
+ },
+ {
+ "name": "symfony/event-dispatcher-contracts",
+ "version": "v3.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/event-dispatcher-contracts.git",
+ "reference": "a76aed96a42d2b521153fb382d418e30d18b59df"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df",
+ "reference": "a76aed96a42d2b521153fb382d418e30d18b59df",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "psr/event-dispatcher": "^1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\EventDispatcher\\": ""
+ }
+ },
+ "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 dispatching event",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.0"
+ },
+ "funding": [
+ {
+ "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": "2023-05-23T14:45:45+00:00"
+ },
+ {
+ "name": "symfony/filesystem",
+ "version": "v6.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/filesystem.git",
+ "reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/952a8cb588c3bc6ce76f6023000fb932f16a6e59",
+ "reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-mbstring": "~1.8"
+ },
+ "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/v6.4.0"
+ },
+ "funding": [
+ {
+ "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": "2023-07-26T17:27:13+00:00"
+ },
+ {
+ "name": "symfony/finder",
+ "version": "v6.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/finder.git",
+ "reference": "11d736e97f116ac375a81f96e662911a34cd50ce"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/11d736e97f116ac375a81f96e662911a34cd50ce",
+ "reference": "11d736e97f116ac375a81f96e662911a34cd50ce",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "symfony/filesystem": "^6.0|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Finder\\": ""
+ },
+ "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": "Finds files and directories via an intuitive fluent interface",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/finder/tree/v6.4.0"
+ },
+ "funding": [
+ {
+ "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": "2023-10-31T17:30:12+00:00"
+ },
+ {
+ "name": "symfony/options-resolver",
+ "version": "v6.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/options-resolver.git",
+ "reference": "22301f0e7fdeaacc14318928612dee79be99860e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/options-resolver/zipball/22301f0e7fdeaacc14318928612dee79be99860e",
+ "reference": "22301f0e7fdeaacc14318928612dee79be99860e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "symfony/deprecation-contracts": "^2.5|^3"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\OptionsResolver\\": ""
+ },
+ "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 an improved replacement for the array_replace PHP function",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "config",
+ "configuration",
+ "options"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/options-resolver/tree/v6.4.0"
+ },
+ "funding": [
+ {
+ "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": "2023-08-08T10:16:24+00:00"
+ },
+ {
+ "name": "symfony/polyfill-ctype",
+ "version": "v1.28.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-ctype.git",
+ "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
+ "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "provide": {
+ "ext-ctype": "*"
+ },
+ "suggest": {
+ "ext-ctype": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.28-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Ctype\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Gert de Pagter",
+ "email": "BackEndTea@gmail.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for ctype functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "ctype",
+ "polyfill",
+ "portable"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0"
+ },
+ "funding": [
+ {
+ "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": "2023-01-26T09:26:14+00:00"
+ },
+ {
+ "name": "symfony/polyfill-intl-grapheme",
+ "version": "v1.28.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
+ "reference": "875e90aeea2777b6f135677f618529449334a612"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612",
+ "reference": "875e90aeea2777b6f135677f618529449334a612",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "suggest": {
+ "ext-intl": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.28-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
+ }
+ },
+ "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": "Symfony polyfill for intl's grapheme_* functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "grapheme",
+ "intl",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0"
+ },
+ "funding": [
+ {
+ "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": "2023-01-26T09:26:14+00:00"
+ },
+ {
+ "name": "symfony/polyfill-intl-normalizer",
+ "version": "v1.28.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
+ "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92",
+ "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "suggest": {
+ "ext-intl": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.28-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "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": "Symfony polyfill for intl's Normalizer class and related functions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "intl",
+ "normalizer",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0"
+ },
+ "funding": [
+ {
+ "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": "2023-01-26T09:26:14+00:00"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.28.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "42292d99c55abe617799667f454222c54c60e229"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229",
+ "reference": "42292d99c55abe617799667f454222c54c60e229",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "provide": {
+ "ext-mbstring": "*"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.28-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ }
+ },
+ "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": "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.28.0"
+ },
+ "funding": [
+ {
+ "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": "2023-07-28T09:04:16+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php80",
+ "version": "v1.28.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php80.git",
+ "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
+ "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.28-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php80\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ion Bazan",
+ "email": "ion.bazan@gmail.com"
+ },
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0"
+ },
+ "funding": [
+ {
+ "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": "2023-01-26T09:26:14+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php81",
+ "version": "v1.28.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php81.git",
+ "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b",
+ "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.28-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php81\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "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": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php81/tree/v1.28.0"
+ },
+ "funding": [
+ {
+ "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": "2023-01-26T09:26:14+00:00"
+ },
+ {
+ "name": "symfony/process",
+ "version": "v6.4.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/process.git",
+ "reference": "c4b1ef0bc80533d87a2e969806172f1c2a980241"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/process/zipball/c4b1ef0bc80533d87a2e969806172f1c2a980241",
+ "reference": "c4b1ef0bc80533d87a2e969806172f1c2a980241",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Process\\": ""
+ },
+ "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": "Executes commands in sub-processes",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/process/tree/v6.4.2"
+ },
+ "funding": [
+ {
+ "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": "2023-12-22T16:42:54+00:00"
+ },
+ {
+ "name": "symfony/service-contracts",
+ "version": "v3.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/service-contracts.git",
+ "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0",
+ "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "psr/container": "^1.1|^2.0"
+ },
+ "conflict": {
+ "ext-psr": "<1.1|>=2"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "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.4.1"
+ },
+ "funding": [
+ {
+ "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": "2023-12-26T14:02:43+00:00"
+ },
+ {
+ "name": "symfony/stopwatch",
+ "version": "v6.4.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/stopwatch.git",
+ "reference": "fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/stopwatch/zipball/fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2",
+ "reference": "fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "symfony/service-contracts": "^2.5|^3"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Stopwatch\\": ""
+ },
+ "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 a way to profile code",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/stopwatch/tree/v6.4.0"
+ },
+ "funding": [
+ {
+ "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": "2023-02-16T10:14:28+00:00"
+ },
+ {
+ "name": "symfony/string",
+ "version": "v6.4.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/string.git",
+ "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/string/zipball/7cb80bc10bfcdf6b5492741c0b9357dac66940bc",
+ "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-intl-grapheme": "~1.0",
+ "symfony/polyfill-intl-normalizer": "~1.0",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "conflict": {
+ "symfony/translation-contracts": "<2.5"
+ },
+ "require-dev": {
+ "symfony/error-handler": "^5.4|^6.0|^7.0",
+ "symfony/http-client": "^5.4|^6.0|^7.0",
+ "symfony/intl": "^6.2|^7.0",
+ "symfony/translation-contracts": "^2.5|^3.0",
+ "symfony/var-exporter": "^5.4|^6.0|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "Resources/functions.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\String\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "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": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "grapheme",
+ "i18n",
+ "string",
+ "unicode",
+ "utf-8",
+ "utf8"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/string/tree/v6.4.2"
+ },
+ "funding": [
+ {
+ "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": "2023-12-10T16:15:48+00:00"
+ }
+ ],
+ "packages-dev": [],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": [],
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": [],
+ "platform-dev": [],
+ "platform-overrides": {
+ "php": "8.1"
+ },
+ "plugin-api-version": "2.6.0"
+}
diff --git a/examples/tools/phpstan/.gitignore b/examples/tools/phpstan/.gitignore
new file mode 100644
index 0000000..31b30cc
--- /dev/null
+++ b/examples/tools/phpstan/.gitignore
@@ -0,0 +1,2 @@
+/var/
+/vendor/
diff --git a/examples/tools/phpstan/composer.json b/examples/tools/phpstan/composer.json
new file mode 100644
index 0000000..2c38af5
--- /dev/null
+++ b/examples/tools/phpstan/composer.json
@@ -0,0 +1,17 @@
+{
+ "type": "project",
+ "require": {
+ "phpstan/extension-installer": "^1.3.1",
+ "phpstan/phpstan": "^1.10.56",
+ "phpstan/phpstan-symfony": "^1.3.7"
+ },
+ "config": {
+ "allow-plugins": {
+ "phpstan/extension-installer": true
+ },
+ "platform": {
+ "php": "8.1"
+ },
+ "sort-packages": true
+ }
+}
diff --git a/examples/tools/phpstan/composer.lock b/examples/tools/phpstan/composer.lock
new file mode 100644
index 0000000..e91f1bc
--- /dev/null
+++ b/examples/tools/phpstan/composer.lock
@@ -0,0 +1,200 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+ "This file is @generated automatically"
+ ],
+ "content-hash": "e2bde0ca0bcc114a0ba6528759a1ec8e",
+ "packages": [
+ {
+ "name": "phpstan/extension-installer",
+ "version": "1.3.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpstan/extension-installer.git",
+ "reference": "f45734bfb9984c6c56c4486b71230355f066a58a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/f45734bfb9984c6c56c4486b71230355f066a58a",
+ "reference": "f45734bfb9984c6c56c4486b71230355f066a58a",
+ "shasum": ""
+ },
+ "require": {
+ "composer-plugin-api": "^2.0",
+ "php": "^7.2 || ^8.0",
+ "phpstan/phpstan": "^1.9.0"
+ },
+ "require-dev": {
+ "composer/composer": "^2.0",
+ "php-parallel-lint/php-parallel-lint": "^1.2.0",
+ "phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0"
+ },
+ "type": "composer-plugin",
+ "extra": {
+ "class": "PHPStan\\ExtensionInstaller\\Plugin"
+ },
+ "autoload": {
+ "psr-4": {
+ "PHPStan\\ExtensionInstaller\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Composer plugin for automatic installation of PHPStan extensions",
+ "support": {
+ "issues": "https://github.com/phpstan/extension-installer/issues",
+ "source": "https://github.com/phpstan/extension-installer/tree/1.3.1"
+ },
+ "time": "2023-05-24T08:59:17+00:00"
+ },
+ {
+ "name": "phpstan/phpstan",
+ "version": "1.10.56",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpstan/phpstan.git",
+ "reference": "27816a01aea996191ee14d010f325434c0ee76fa"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/27816a01aea996191ee14d010f325434c0ee76fa",
+ "reference": "27816a01aea996191ee14d010f325434c0ee76fa",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2|^8.0"
+ },
+ "conflict": {
+ "phpstan/phpstan-shim": "*"
+ },
+ "bin": [
+ "phpstan",
+ "phpstan.phar"
+ ],
+ "type": "library",
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "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": [
+ {
+ "url": "https://github.com/ondrejmirtes",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/phpstan",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-01-15T10:43:00+00:00"
+ },
+ {
+ "name": "phpstan/phpstan-symfony",
+ "version": "1.3.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpstan/phpstan-symfony.git",
+ "reference": "ef7db637be9b85fa00278fc3477ac66abe8eb7d1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/ef7db637be9b85fa00278fc3477ac66abe8eb7d1",
+ "reference": "ef7db637be9b85fa00278fc3477ac66abe8eb7d1",
+ "shasum": ""
+ },
+ "require": {
+ "ext-simplexml": "*",
+ "php": "^7.2 || ^8.0",
+ "phpstan/phpstan": "^1.10.36"
+ },
+ "conflict": {
+ "symfony/framework-bundle": "<3.0"
+ },
+ "require-dev": {
+ "nikic/php-parser": "^4.13.0",
+ "php-parallel-lint/php-parallel-lint": "^1.2",
+ "phpstan/phpstan-phpunit": "^1.3.11",
+ "phpstan/phpstan-strict-rules": "^1.5.1",
+ "phpunit/phpunit": "^8.5.29 || ^9.5",
+ "psr/container": "1.0 || 1.1.1",
+ "symfony/config": "^5.4 || ^6.1",
+ "symfony/console": "^5.4 || ^6.1",
+ "symfony/dependency-injection": "^5.4 || ^6.1",
+ "symfony/form": "^5.4 || ^6.1",
+ "symfony/framework-bundle": "^5.4 || ^6.1",
+ "symfony/http-foundation": "^5.4 || ^6.1",
+ "symfony/messenger": "^5.4",
+ "symfony/polyfill-php80": "^1.24",
+ "symfony/serializer": "^5.4",
+ "symfony/service-contracts": "^2.2.0"
+ },
+ "type": "phpstan-extension",
+ "extra": {
+ "phpstan": {
+ "includes": [
+ "extension.neon",
+ "rules.neon"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "PHPStan\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Lukáš Unger",
+ "email": "looky.msc@gmail.com",
+ "homepage": "https://lookyman.net"
+ }
+ ],
+ "description": "Symfony Framework extensions and rules for PHPStan",
+ "support": {
+ "issues": "https://github.com/phpstan/phpstan-symfony/issues",
+ "source": "https://github.com/phpstan/phpstan-symfony/tree/1.3.7"
+ },
+ "time": "2024-01-10T21:54:42+00:00"
+ }
+ ],
+ "packages-dev": [],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": [],
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": [],
+ "platform-dev": [],
+ "platform-overrides": {
+ "php": "8.1"
+ },
+ "plugin-api-version": "2.6.0"
+}
diff --git a/examples/translations/.gitignore b/examples/translations/.gitignore
new file mode 100644
index 0000000..e69de29
From da7f1798dac1020cb27b90ff05a6cf34b2596edb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 23:34:49 +0100
Subject: [PATCH 19/32] bundle: enhance the configuration parsing + add
AliasForArgument
---
phpstan-baseline.neon | 7 ++-
src/Metrics/Collector/DogStatsD.php | 1 -
src/Metrics/Collector/Graphite.php | 20 ++++-----
src/Metrics/Collector/Telegraf.php | 13 +++---
src/Metrics/Utils/Box.php | 2 +
.../BeberleiMetricsExtension.php | 45 ++++++++++++-------
.../DependencyInjection/Configuration.php | 14 ++++--
7 files changed, 64 insertions(+), 38 deletions(-)
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index a5dbf7a..842fe65 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -1,7 +1,12 @@
parameters:
ignoreErrors:
-
- message: "#^Variable \\$name might not be defined\\.$#"
+ message: "#^Parameter \\#1 \\$callback of function set_error_handler expects \\(callable\\(int, string, string, int\\)\\: bool\\)\\|null, Closure\\(\\)\\: null given\\.$#"
+ count: 1
+ path: src/Metrics/Utils/Box.php
+
+ -
+ message: "#^Cannot access offset 'null' on 0\\|0\\.0\\|''\\|'0'\\|array\\{\\}\\|false\\|null\\.$#"
count: 1
path: src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
diff --git a/src/Metrics/Collector/DogStatsD.php b/src/Metrics/Collector/DogStatsD.php
index 0604ecf..58f87f0 100644
--- a/src/Metrics/Collector/DogStatsD.php
+++ b/src/Metrics/Collector/DogStatsD.php
@@ -61,7 +61,6 @@ public function flush(): void
private function doFlush(): void
{
-
$fp = fsockopen('udp://' . $this->host, $this->port, $errno, $errstr, 1.0);
if (!$fp) {
diff --git a/src/Metrics/Collector/Graphite.php b/src/Metrics/Collector/Graphite.php
index 9ff5930..b0d7ccd 100644
--- a/src/Metrics/Collector/Graphite.php
+++ b/src/Metrics/Collector/Graphite.php
@@ -58,6 +58,16 @@ public function flush(): void
Box::box($this->doFlush(...));
}
+ public function push(string $variable, int|float $value, ?int $time = null): void
+ {
+ $this->data[] = sprintf(
+ \is_float($value) ? "%s %.18f %d\n" : "%s %d %d\n",
+ $variable,
+ $value,
+ $time ?: time()
+ );
+ }
+
private function doFlush(): void
{
$fp = fsockopen($this->protocol . '://' . $this->host, $this->port);
@@ -74,14 +84,4 @@ private function doFlush(): void
$this->data = [];
}
-
- public function push(string $variable, int|float $value, ?int $time = null): void
- {
- $this->data[] = sprintf(
- \is_float($value) ? "%s %.18f %d\n" : "%s %d %d\n",
- $variable,
- $value,
- $time ?: time()
- );
- }
}
diff --git a/src/Metrics/Collector/Telegraf.php b/src/Metrics/Collector/Telegraf.php
index e2b2905..773e863 100644
--- a/src/Metrics/Collector/Telegraf.php
+++ b/src/Metrics/Collector/Telegraf.php
@@ -71,9 +71,14 @@ public function flush(): void
Box::box($this->doFlush(...));
}
- private function doFlush(): void
+ public function setTags(array $tags): void
{
+ $this->tags = http_build_query($tags, '', ',');
+ $this->tags = \strlen($this->tags) > 0 ? ',' . $this->tags : $this->tags;
+ }
+ private function doFlush(): void
+ {
$fp = fsockopen('udp://' . $this->host, $this->port, $errno, $errstr, 1.0);
if (!$fp) {
@@ -88,10 +93,4 @@ private function doFlush(): void
$this->data = [];
}
-
- public function setTags(array $tags): void
- {
- $this->tags = http_build_query($tags, '', ',');
- $this->tags = \strlen($this->tags) > 0 ? ',' . $this->tags : $this->tags;
- }
}
diff --git a/src/Metrics/Utils/Box.php b/src/Metrics/Utils/Box.php
index b191fe5..ffe2fb1 100644
--- a/src/Metrics/Utils/Box.php
+++ b/src/Metrics/Utils/Box.php
@@ -15,5 +15,7 @@ public static function box(callable $callable): mixed
} finally {
restore_error_handler();
}
+
+ return null;
}
}
diff --git a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
index b9a209e..7f2ada3 100644
--- a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
+++ b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
@@ -3,9 +3,11 @@
namespace Beberlei\Bundle\MetricsBundle\DependencyInjection;
use Beberlei\Metrics\Collector\CollectorInterface;
+use Prometheus\Collector;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
@@ -20,19 +22,31 @@ public function load(array $configs, ContainerBuilder $container): void
$loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
$loader->load('metrics.xml');
+ if (!$config['collectors']) {
+ $config['collectors']['null'] = [
+ 'type' => 'null',
+ ];
+ }
foreach ($config['collectors'] as $name => $colConfig) {
$definition = $this->createCollector($colConfig['type'], $colConfig);
$container->setDefinition('beberlei_metrics.collector.' . $name, $definition);
+ $container->registerAliasForArgument('beberlei_metrics.collector.' . $name, CollectorInterface::class, $name);
}
- if ($config['default'] && $container->hasDefinition('beberlei_metrics.collector.' . $config['default'])) {
+ if ($config['default']) {
+ if (!$container->hasDefinition('beberlei_metrics.collector.' . $config['default'])) {
+ throw new InvalidArgumentException(sprintf('The default collector "%s" does not exist.', $config['default']));
+ }
$name = $config['default'];
- } elseif (1 !== \count($config['collectors'])) {
- throw new \LogicException('You should select a default collector');
+ } elseif (1 === \count($config['collectors'])) {
+ $name = key($config['collectors']);
+ } else {
+ throw new InvalidArgumentException('No default collector is configured and there is more than one collector. Please define a default collector');
}
- $container->setAlias('beberlei_metrics.collector', 'beberlei_metrics.collector.' . $name);
- $container->setAlias(CollectorInterface::class, 'beberlei_metrics.collector');
+ if ($name) {
+ $container->setAlias(CollectorInterface::class, 'beberlei_metrics.collector.' . $name);
+ }
}
private function createCollector(string $type, array $config): ChildDefinition
@@ -42,8 +56,9 @@ private function createCollector(string $type, array $config): ChildDefinition
// Theses listeners should be as late as possible
$definition->addTag('kernel.event_listener', ['method' => 'flush', 'priority' => -1024, 'event' => 'kernel.terminate']);
$definition->addTag('kernel.event_listener', ['method' => 'flush', 'priority' => -1024, 'event' => 'console.terminate']);
+ $definition->addTag(CollectorInterface::class);
- if (\count($config['tags']) > 0) {
+ if ($config['tags'] ?? []) {
$definition->addMethodCall('setTags', [$config['tags']]);
}
@@ -54,9 +69,9 @@ private function createCollector(string $type, array $config): ChildDefinition
return $definition;
case 'graphite':
- $definition->replaceArgument(0, $config['host'] ?: 'localhost');
- $definition->replaceArgument(1, $config['port'] ?: 2003);
- $definition->replaceArgument(2, $config['protocol'] ?: 'tcp');
+ $definition->replaceArgument(0, $config['host'] ?? 'localhost');
+ $definition->replaceArgument(1, $config['port'] ?? 2003);
+ $definition->replaceArgument(2, $config['protocol'] ?? 'tcp');
return $definition;
case 'influxdb':
@@ -64,7 +79,7 @@ private function createCollector(string $type, array $config): ChildDefinition
return $definition;
case 'librato':
- $definition->replaceArgument(1, $config['source']);
+ $definition->replaceArgument(1, $config['host']);
$definition->replaceArgument(2, $config['username']);
$definition->replaceArgument(3, $config['password']);
@@ -80,19 +95,19 @@ private function createCollector(string $type, array $config): ChildDefinition
return $definition;
case 'statsd':
case 'dogstatsd':
- $definition->replaceArgument(0, $config['host'] ?: 'localhost');
- $definition->replaceArgument(1, $config['port'] ?: 8125);
+ $definition->replaceArgument(0, $config['host'] ?? 'localhost');
+ $definition->replaceArgument(1, $config['port'] ?? 8125);
$definition->replaceArgument(2, (string) $config['prefix']);
return $definition;
case 'telegraf':
- $definition->replaceArgument(0, $config['host'] ?: 'localhost');
- $definition->replaceArgument(1, $config['port'] ?: 8125);
+ $definition->replaceArgument(0, $config['host'] ?? 'localhost');
+ $definition->replaceArgument(1, $config['port'] ?? 8125);
$definition->replaceArgument(2, (string) $config['prefix']);
return $definition;
default:
- throw new \InvalidArgumentException(sprintf('The type "%s" is not supported', $type));
+ throw new \InvalidArgumentException(sprintf('The type "%s" is not supported.', $type));
}
}
}
diff --git a/src/MetricsBundle/DependencyInjection/Configuration.php b/src/MetricsBundle/DependencyInjection/Configuration.php
index cbdf163..239ab05 100644
--- a/src/MetricsBundle/DependencyInjection/Configuration.php
+++ b/src/MetricsBundle/DependencyInjection/Configuration.php
@@ -21,11 +21,17 @@ public function getConfigTreeBuilder(): TreeBuilder
->defaultNull()
->end()
->arrayNode('collectors')
- ->isRequired()
->useAttributeAsKey('name')
->prototype('array')
->children()
- ->scalarNode('type')->isRequired()->end()
+ ->scalarNode('type')
+ ->isRequired()
+ ->validate()
+ ->ifTrue(static fn ($v) => !\is_string($v))
+ ->thenInvalid('The type must be a string got "%s".')
+ ->end()
+
+ ->end()
->scalarNode('connection')->defaultNull()->end()
->scalarNode('file')->defaultNull()->end()
->scalarNode('host')->defaultNull()->end()
@@ -44,8 +50,8 @@ public function getConfigTreeBuilder(): TreeBuilder
->end()
->end()
->validate()
- ->ifTrue(static fn ($v): bool => 'librato' === $v['type'] && empty($v['source']))
- ->thenInvalid('The source has to be specified to use a Librato')
+ ->ifTrue(static fn ($v): bool => 'librato' === $v['type'] && empty($v['host']))
+ ->thenInvalid('The host has to be specified to use a Librato')
->end()
->validate()
->ifTrue(static fn ($v): bool => 'librato' === $v['type'] && empty($v['username']))
From 2163463dda5764b69a4623c52064d0e285f40bdb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 23:44:47 +0100
Subject: [PATCH 20/32] collector: drop librato integration
---
README.md | 12 ----
composer.json | 2 -
src/Metrics/Collector/Librato.php | 66 -------------------
src/Metrics/Factory.php | 25 -------
.../BeberleiMetricsExtension.php | 6 --
.../DependencyInjection/Configuration.php | 12 ----
.../Resources/config/metrics.xml | 11 ----
tests/Metrics/FactoryTest.php | 5 --
.../BeberleiMetricsExtensionTest.php | 24 -------
9 files changed, 163 deletions(-)
delete mode 100644 src/Metrics/Collector/Librato.php
diff --git a/README.md b/README.md
index 27e3b03..f160c04 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,6 @@ Currently supported backends:
* Graphite
* InfluxDB
* Telegraf
-* Librato
* Logger (Psr\Log\LoggerInterface)
* Null (Dummy that does nothing)
* Prometheus
@@ -70,12 +69,6 @@ $collector->flush();
'foo.beberlei.de',
- 'username' => 'foo',
- 'password' => 'bar',
-));
-
$null = \Beberlei\Metrics\Factory::create('null');
```
@@ -106,11 +99,6 @@ beberlei_metrics:
collectors:
foo:
type: statsd
- librato:
- type: librato
- username: foo
- password: bar
- source: hermes10
dbal:
type: doctrine_dbal
connection: metrics # using the connection named "metrics"
diff --git a/composer.json b/composer.json
index faf7084..7646e0a 100644
--- a/composer.json
+++ b/composer.json
@@ -25,7 +25,6 @@
"jimdo/prometheus_client_php": "^0.5.1",
"symfony/config": "^5.4 || ^6.4 || ^7.0",
"symfony/dependency-injection": "^5.4 || ^6.4 || ^7.0",
- "symfony/http-client": "^5.4 || ^6.4 || ^7.0",
"symfony/http-kernel": "^5.4 || ^6.4 || ^7.0",
"symfony/phpunit-bridge": "^6.4.4 || ^7.0"
},
@@ -50,7 +49,6 @@
},
"suggest": {
"corley/influxdb-sdk": "For InfluxDB integration",
- "kriswallsmith/buzz": "For Librato integration",
"jimdo/prometheus_client_php": "For Prometheus integration"
},
"config": {
diff --git a/src/Metrics/Collector/Librato.php b/src/Metrics/Collector/Librato.php
deleted file mode 100644
index 3830a58..0000000
--- a/src/Metrics/Collector/Librato.php
+++ /dev/null
@@ -1,66 +0,0 @@
- [], 'gauges' => []];
-
- public function __construct(
- private readonly HttpClientInterface $httpClient,
- private readonly string $source,
- private readonly string $username,
- private readonly string $password
- ) {
- }
-
- public function measure(string $variable, int $value, array $tags = []): void
- {
- $this->data['gauges'][] = ['source' => $this->source, 'name' => $variable, 'value' => $value];
- }
-
- public function increment(string $variable, array $tags = []): void
- {
- $this->data['counters'][] = ['source' => $this->source, 'name' => $variable, 'value' => 1];
- }
-
- public function decrement(string $variable, array $tags = []): void
- {
- $this->data['counters'][] = ['source' => $this->source, 'name' => $variable, 'value' => -1];
- }
-
- public function timing(string $variable, int $time, array $tags = []): void
- {
- $this->data['gauges'][] = ['source' => $this->source, 'name' => $variable, 'value' => $time];
- }
-
- public function flush(): void
- {
- if (!$this->data['gauges'] && !$this->data['counters']) {
- return;
- }
-
- try {
- $this->httpClient->request('POST', 'https://metrics-api.librato.com/v1/metrics', [
- 'auth_basic' => [$this->username, $this->password],
- 'json' => $this->data,
- ]);
- $this->data = ['gauges' => [], 'counters' => []];
- } catch (ExceptionInterface) {
- }
- }
-}
diff --git a/src/Metrics/Factory.php b/src/Metrics/Factory.php
index 3016ce3..95aa387 100644
--- a/src/Metrics/Factory.php
+++ b/src/Metrics/Factory.php
@@ -18,19 +18,14 @@
use Beberlei\Metrics\Collector\DogStatsD;
use Beberlei\Metrics\Collector\Graphite;
use Beberlei\Metrics\Collector\InfluxDB;
-use Beberlei\Metrics\Collector\Librato;
use Beberlei\Metrics\Collector\Logger;
use Beberlei\Metrics\Collector\NullCollector;
use Beberlei\Metrics\Collector\Prometheus;
use Beberlei\Metrics\Collector\StatsD;
use Beberlei\Metrics\Collector\Telegraf;
-use Symfony\Component\HttpClient\HttpClient;
-use Symfony\Contracts\HttpClient\HttpClientInterface;
abstract class Factory
{
- private static HttpClientInterface $httpClient;
-
/**
* @throws MetricsException
*/
@@ -115,21 +110,6 @@ public static function create(string $type, array $options = []): CollectorInter
return new Graphite($options['host'], $options['port']);
- case 'librato':
- if (!isset($options['hostname'])) {
- throw new MetricsException('Hostname is required for librato collector.');
- }
-
- if (!isset($options['username'])) {
- throw new MetricsException('No username given for librato collector.');
- }
-
- if (!isset($options['password'])) {
- throw new MetricsException('No password given for librato collector.');
- }
-
- return new Librato(self::getHttpClient(), $options['hostname'], $options['username'], $options['password']);
-
case 'doctrine_dbal':
if (!isset($options['connection'])) {
throw new MetricsException('connection is required for Doctrine DBAL collector.');
@@ -167,9 +147,4 @@ public static function create(string $type, array $options = []): CollectorInter
throw new MetricsException(sprintf('Unknown metrics collector given (%s).', $type));
}
}
-
- private static function getHttpClient(): HttpClientInterface
- {
- return self::$httpClient ??= HttpClient::create();
- }
}
diff --git a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
index 7f2ada3..7b3ca6c 100644
--- a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
+++ b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
@@ -77,12 +77,6 @@ private function createCollector(string $type, array $config): ChildDefinition
case 'influxdb':
$definition->replaceArgument(0, new Reference($config['influxdb_client']));
- return $definition;
- case 'librato':
- $definition->replaceArgument(1, $config['host']);
- $definition->replaceArgument(2, $config['username']);
- $definition->replaceArgument(3, $config['password']);
-
return $definition;
case 'logger':
case 'null':
diff --git a/src/MetricsBundle/DependencyInjection/Configuration.php b/src/MetricsBundle/DependencyInjection/Configuration.php
index 239ab05..919c68f 100644
--- a/src/MetricsBundle/DependencyInjection/Configuration.php
+++ b/src/MetricsBundle/DependencyInjection/Configuration.php
@@ -49,18 +49,6 @@ public function getConfigTreeBuilder(): TreeBuilder
->prototype('scalar')->end()
->end()
->end()
- ->validate()
- ->ifTrue(static fn ($v): bool => 'librato' === $v['type'] && empty($v['host']))
- ->thenInvalid('The host has to be specified to use a Librato')
- ->end()
- ->validate()
- ->ifTrue(static fn ($v): bool => 'librato' === $v['type'] && empty($v['username']))
- ->thenInvalid('The username has to be specified to use a Librato')
- ->end()
- ->validate()
- ->ifTrue(static fn ($v): bool => 'librato' === $v['type'] && empty($v['password']))
- ->thenInvalid('The password has to be specified to use a Librato')
- ->end()
->validate()
->ifTrue(static fn ($v): bool => 'prometheus' === $v['type'] && empty($v['prometheus_collector_registry']))
->thenInvalid('The prometheus_collector_registry has to be specified to use a Prometheus')
diff --git a/src/MetricsBundle/Resources/config/metrics.xml b/src/MetricsBundle/Resources/config/metrics.xml
index 0d53ed4..71b7e5d 100644
--- a/src/MetricsBundle/Resources/config/metrics.xml
+++ b/src/MetricsBundle/Resources/config/metrics.xml
@@ -5,11 +5,6 @@
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
-
-
-
-
-
@@ -22,12 +17,6 @@
-
-
-
-
-
-
diff --git a/tests/Metrics/FactoryTest.php b/tests/Metrics/FactoryTest.php
index 607e16e..109f812 100644
--- a/tests/Metrics/FactoryTest.php
+++ b/tests/Metrics/FactoryTest.php
@@ -6,7 +6,6 @@
use Beberlei\Metrics\Collector\DogStatsD;
use Beberlei\Metrics\Collector\Graphite;
use Beberlei\Metrics\Collector\InfluxDB;
-use Beberlei\Metrics\Collector\Librato;
use Beberlei\Metrics\Collector\Logger;
use Beberlei\Metrics\Collector\NullCollector;
use Beberlei\Metrics\Collector\Prometheus;
@@ -33,7 +32,6 @@ public function getCreateValidMetricTests(): iterable
yield [DogStatsD::class, 'dogstatsd', ['host' => 'localhost']];
yield [Graphite::class, 'graphite'];
yield [Graphite::class, 'graphite', ['host' => 'localhost', 'port' => 1234]];
- yield [Librato::class, 'librato', ['hostname' => 'foobar.com', 'username' => 'username', 'password' => 'password']];
yield [DoctrineDBAL::class, 'doctrine_dbal', ['connection' => $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock()]];
yield [Logger::class, 'logger', ['logger' => new NullLogger()]];
yield [NullCollector::class, 'null'];
@@ -61,9 +59,6 @@ public function getCreateThrowExceptionIfOptionsAreInvalidTests(): iterable
yield ['You should specified a host and a port if you specified a prefix.', 'dogstatsd', ['port' => '1234', 'prefix' => 'prefix']];
yield ['You should specified a host and a port if you specified a prefix.', 'dogstatsd', ['hostname' => 'foobar.com', 'prefix' => 'prefix']];
yield ['You should specified a host if you specified a port.', 'graphite', ['port' => '1234']];
- yield ['Hostname is required for librato collector.', 'librato'];
- yield ['No username given for librato collector.', 'librato', ['hostname' => 'foobar.com']];
- yield ['No password given for librato collector.', 'librato', ['hostname' => 'foobar.com', 'username' => 'username']];
yield ['connection is required for Doctrine DBAL collector.', 'doctrine_dbal'];
yield ["Missing 'logger' key with logger service.", 'logger'];
yield ["Missing 'client' key for InfluxDB collector.", 'influxdb'];
diff --git a/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php b/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
index 554730d..f4989d4 100644
--- a/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
+++ b/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
@@ -18,7 +18,6 @@
use Beberlei\Metrics\Collector\Graphite;
use Beberlei\Metrics\Collector\InfluxDB;
use Beberlei\Metrics\Collector\InMemory;
-use Beberlei\Metrics\Collector\Librato;
use Beberlei\Metrics\Collector\Logger;
use Beberlei\Metrics\Collector\NullCollector;
use Beberlei\Metrics\Collector\Prometheus;
@@ -51,29 +50,6 @@ public function testWithGraphite(): void
$this->assertSame(1234, $this->getProperty($collector, 'port'));
}
- /**
- * The source has to be specified to use a Librato.
- */
- public function testWithLibratoAndInvalidConfiguration(): void
- {
- $this->expectException(InvalidConfigurationException::class);
-
- $container = $this->createContainer(['collectors' => ['simple' => ['type' => 'librato']]], ['beberlei_metrics.collector.librato']);
-
- $this->assertInstanceOf(Librato::class, $container->get('beberlei_metrics.collector.librato'));
- }
-
- public function testWithLibrato(): void
- {
- $container = $this->createContainer(['collectors' => ['full' => ['type' => 'librato', 'source' => 'foo.beberlei.de', 'username' => 'foo', 'password' => 'bar']]], ['beberlei_metrics.collector.full']);
-
- $collector = $container->get('beberlei_metrics.collector.full');
- $this->assertInstanceOf(Librato::class, $collector);
- $this->assertSame('foo.beberlei.de', $this->getProperty($collector, 'source'));
- $this->assertSame('foo', $this->getProperty($collector, 'username'));
- $this->assertSame('bar', $this->getProperty($collector, 'password'));
- }
-
public function testWithLogger(): void
{
$container = $this->createContainer(['collectors' => ['logger' => ['type' => 'logger']]], ['beberlei_metrics.collector.logger']);
From c4b8b61328d46c2abae49ffc20015c68d3dcd71c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 23:57:25 +0100
Subject: [PATCH 21/32] chore: fixed license
---
.php-cs-fixer.php | 15 +++++++++++++++
LICENSE.md | 19 +++++++++++++++++++
examples/castor.php | 7 +++++++
examples/config/bundles.php | 7 +++++++
examples/config/preload.php | 7 +++++++
examples/importmap.php | 14 +++++---------
examples/public/index.php | 7 +++++++
.../src/Controller/HomepageController.php | 7 +++++++
examples/src/Kernel.php | 7 +++++++
examples/tests/bootstrap.php | 7 +++++++
src/Metrics/Collector/CollectorInterface.php | 14 +++++---------
src/Metrics/Collector/DoctrineDBAL.php | 14 +++++---------
src/Metrics/Collector/DogStatsD.php | 14 +++++---------
.../Collector/GaugeableCollectorInterface.php | 14 +++++---------
src/Metrics/Collector/Graphite.php | 14 +++++---------
src/Metrics/Collector/InMemory.php | 14 +++++---------
src/Metrics/Collector/InfluxDB.php | 14 +++++---------
src/Metrics/Collector/Logger.php | 14 +++++---------
src/Metrics/Collector/NullCollector.php | 14 +++++---------
src/Metrics/Collector/Prometheus.php | 14 +++++---------
src/Metrics/Collector/StatsD.php | 14 +++++---------
.../Collector/TaggableCollectorInterface.php | 14 +++++---------
src/Metrics/Collector/Telegraf.php | 14 +++++---------
src/Metrics/Factory.php | 14 +++++---------
src/Metrics/MetricsException.php | 14 +++++---------
src/Metrics/Utils/Box.php | 7 +++++++
src/MetricsBundle/BeberleiMetricsBundle.php | 14 +++++---------
.../BeberleiMetricsExtension.php | 7 +++++++
.../DependencyInjection/Configuration.php | 7 +++++++
tests/Metrics/Collector/InMemoryTest.php | 14 +++++---------
tests/Metrics/Collector/InfluxDBTest.php | 14 +++++---------
tests/Metrics/Collector/PrometheusTest.php | 14 +++++---------
tests/Metrics/FactoryTest.php | 7 +++++++
.../BeberleiMetricsExtensionTest.php | 14 +++++---------
34 files changed, 216 insertions(+), 189 deletions(-)
create mode 100644 LICENSE.md
diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php
index 312ddf8..e7dbb96 100644
--- a/.php-cs-fixer.php
+++ b/.php-cs-fixer.php
@@ -1,5 +1,19 @@
ignoreVCSIgnored(true)
->in(__DIR__)
@@ -16,6 +30,7 @@
'@Symfony' => true,
'@Symfony:risky' => true,
'heredoc_indentation' => false,
+ 'header_comment' => ['header' => $fileHeaderComment],
'single_line_empty_body' => false,
'ordered_types' => false, // From @PhpCsFixer but we don't want it
'php_unit_internal_class' => false, // From @PhpCsFixer but we don't want it
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..a96b463
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,19 @@
+Copyright (c) 2004-preset Benjamin Eberlei
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/examples/castor.php b/examples/castor.php
index a07f644..dbe4049 100644
--- a/examples/castor.php
+++ b/examples/castor.php
@@ -1,5 +1,12 @@
['all' => true],
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
diff --git a/examples/config/preload.php b/examples/config/preload.php
index db37723..f12aeeb 100644
--- a/examples/config/preload.php
+++ b/examples/config/preload.php
@@ -1,5 +1,12 @@
[
'path' => './assets/app.js',
diff --git a/examples/public/index.php b/examples/public/index.php
index 7fbc8cf..52e8536 100644
--- a/examples/public/index.php
+++ b/examples/public/index.php
@@ -1,5 +1,12 @@
Date: Fri, 1 Mar 2024 07:11:25 +0100
Subject: [PATCH 22/32] collector: fix doctrine dbal deprecations
---
src/Metrics/Collector/DoctrineDBAL.php | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/src/Metrics/Collector/DoctrineDBAL.php b/src/Metrics/Collector/DoctrineDBAL.php
index b8f6046..b3088dc 100644
--- a/src/Metrics/Collector/DoctrineDBAL.php
+++ b/src/Metrics/Collector/DoctrineDBAL.php
@@ -10,6 +10,7 @@
namespace Beberlei\Metrics\Collector;
use Doctrine\DBAL\Connection;
+use Doctrine\DBAL\ParameterType;
/**
* Sends statistics to a relational database.
@@ -29,28 +30,28 @@ class DoctrineDBAL implements CollectorInterface
private array $data = [];
public function __construct(
- private readonly Connection $conn
+ private readonly Connection $conn,
) {
}
public function measure(string $variable, int $value, array $tags = []): void
{
- $this->data[] = [$variable, $value, date('Y-m-d')];
+ $this->data[] = [$variable, $value, date('Y-m-d H:i:s')];
}
public function increment(string $variable, array $tags = []): void
{
- $this->data[] = [$variable, 1, date('Y-m-d')];
+ $this->data[] = [$variable, 1, date('Y-m-d H:i:s')];
}
public function decrement(string $variable, array $tags = []): void
{
- $this->data[] = [$variable, -1, date('Y-m-d')];
+ $this->data[] = [$variable, -1, date('Y-m-d H:i:s')];
}
public function timing(string $variable, int $time, array $tags = []): void
{
- $this->data[] = [$variable, $time, date('Y-m-d')];
+ $this->data[] = [$variable, $time, date('Y-m-d H:i:s')];
}
public function flush(): void
@@ -65,9 +66,9 @@ public function flush(): void
$stmt = $this->conn->prepare('INSERT INTO metrics (metric, measurement, created) VALUES (?, ?, ?)');
foreach ($this->data as $measurement) {
- $stmt->bindParam(1, $measurement[0]);
- $stmt->bindParam(2, $measurement[1]);
- $stmt->bindParam(3, $measurement[2]);
+ $stmt->bindValue(1, $measurement[0]);
+ $stmt->bindValue(2, $measurement[1], ParameterType::INTEGER);
+ $stmt->bindValue(3, $measurement[2], ParameterType::STRING);
$stmt->executeStatement();
}
From 9b2b101e7bb75bc97bd2d79762bc029856b7ccd4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Fri, 1 Mar 2024 12:15:13 +0100
Subject: [PATCH 23/32] collector: change inner dependency of InfluxDB
---
composer.json | 3 +-
src/Metrics/Collector/InfluxDB.php | 22 +++-
src/Metrics/Factory.php | 10 +-
.../BeberleiMetricsExtension.php | 29 ++++-
.../DependencyInjection/Configuration.php | 30 +++--
.../Resources/config/metrics.xml | 6 +-
tests/Metrics/Collector/InfluxDBTest.php | 120 +++++++++++++-----
tests/Metrics/FactoryTest.php | 10 +-
.../BeberleiMetricsExtensionTest.php | 18 +--
9 files changed, 162 insertions(+), 86 deletions(-)
diff --git a/composer.json b/composer.json
index 7646e0a..ac277fc 100644
--- a/composer.json
+++ b/composer.json
@@ -20,8 +20,8 @@
},
"require-dev": {
"php": ">=8.1",
- "corley/influxdb-sdk": "^0.5.1",
"doctrine/dbal": "^2.0",
+ "influxdb/influxdb-php": "^1.15",
"jimdo/prometheus_client_php": "^0.5.1",
"symfony/config": "^5.4 || ^6.4 || ^7.0",
"symfony/dependency-injection": "^5.4 || ^6.4 || ^7.0",
@@ -48,7 +48,6 @@
}
},
"suggest": {
- "corley/influxdb-sdk": "For InfluxDB integration",
"jimdo/prometheus_client_php": "For Prometheus integration"
},
"config": {
diff --git a/src/Metrics/Collector/InfluxDB.php b/src/Metrics/Collector/InfluxDB.php
index 19e8590..6c3935b 100644
--- a/src/Metrics/Collector/InfluxDB.php
+++ b/src/Metrics/Collector/InfluxDB.php
@@ -9,14 +9,16 @@
namespace Beberlei\Metrics\Collector;
-use InfluxDB\Client;
+use InfluxDB\Database;
+use InfluxDB\Exception;
+use InfluxDB\Point;
class InfluxDB implements CollectorInterface, TaggableCollectorInterface
{
private array $data = [];
public function __construct(
- private readonly Client $client,
+ private readonly Database $database,
private array $tags = [],
) {
}
@@ -43,12 +45,18 @@ public function timing(string $variable, int $time, array $tags = []): void
public function flush(): void
{
+ $points = [];
foreach ($this->data as $data) {
- try {
- $this->client->mark(['points' => [['measurement' => $data[0], 'fields' => ['value' => $data[1]]]], 'tags' => $data[2] + $this->tags]);
- } catch (\Exception) {
- continue;
- }
+ $points[] = new Point(
+ $data[0],
+ $data[1],
+ $this->tags + $data[2],
+ );
+ }
+
+ try {
+ $this->database->writePoints($points, Database::PRECISION_SECONDS);
+ } catch (Exception) {
}
$this->data = [];
diff --git a/src/Metrics/Factory.php b/src/Metrics/Factory.php
index f56c48b..349dbc6 100644
--- a/src/Metrics/Factory.php
+++ b/src/Metrics/Factory.php
@@ -115,24 +115,24 @@ public static function create(string $type, array $options = []): CollectorInter
case 'logger':
if (!isset($options['logger'])) {
- throw new MetricsException("Missing 'logger' key with logger service.");
+ throw new MetricsException('Missing "logger" key with logger service.');
}
return new Logger($options['logger']);
case 'influxdb':
- if (!isset($options['client'])) {
- throw new MetricsException("Missing 'client' key for InfluxDB collector.");
+ if (!isset($options['database'])) {
+ throw new MetricsException('Missing "database" key for InfluxDB collector.');
}
- return new InfluxDB($options['client']);
+ return new InfluxDB($options['database']);
case 'null':
return new NullCollector();
case 'prometheus':
if (!isset($options['collector_registry'])) {
- throw new MetricsException("Missing 'collector_registry' key for Prometheus collector.");
+ throw new MetricsException('Missing "collector_registry" key for Prometheus collector.');
}
$namespace = $options['namespace'] ?? '';
diff --git a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
index 3b228c5..080ee4a 100644
--- a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
+++ b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
@@ -10,7 +10,6 @@
namespace Beberlei\Bundle\MetricsBundle\DependencyInjection;
use Beberlei\Metrics\Collector\CollectorInterface;
-use Prometheus\Collector;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -64,6 +63,7 @@ private function createCollector(string $type, array $config): ChildDefinition
$definition->addTag('kernel.event_listener', ['method' => 'flush', 'priority' => -1024, 'event' => 'kernel.terminate']);
$definition->addTag('kernel.event_listener', ['method' => 'flush', 'priority' => -1024, 'event' => 'console.terminate']);
$definition->addTag(CollectorInterface::class);
+ // $definition->addTag('kernel.reset');
if ($config['tags'] ?? []) {
$definition->addMethodCall('setTags', [$config['tags']]);
@@ -76,13 +76,28 @@ private function createCollector(string $type, array $config): ChildDefinition
return $definition;
case 'graphite':
- $definition->replaceArgument(0, $config['host'] ?? 'localhost');
+ $definition->replaceArgument(0, $config['host']);
$definition->replaceArgument(1, $config['port'] ?? 2003);
$definition->replaceArgument(2, $config['protocol'] ?? 'tcp');
return $definition;
case 'influxdb':
- $definition->replaceArgument(0, new Reference($config['influxdb_client']));
+ if (!class_exists(\InfluxDB\Client::class)) {
+ throw new \LogicException('The "influxdb/influxdb-php" package is required to use the "influxdb" collector.');
+ }
+ if ($config['service']) {
+ $definition->replaceArgument(0, new Reference($config['service']));
+ } else {
+ $database = new ChildDefinition('beberlei_metrics.collector_proto.influxdb.database');
+ $database->replaceArgument(0, sprintf('influxdb://%s:%s@%s:%s/%s',
+ $config['username'],
+ $config['password'],
+ $config['host'],
+ $config['port'] ?? 8086,
+ $config['database'],
+ ));
+ $definition->replaceArgument(0, $database);
+ }
return $definition;
case 'logger':
@@ -96,15 +111,15 @@ private function createCollector(string $type, array $config): ChildDefinition
return $definition;
case 'statsd':
case 'dogstatsd':
- $definition->replaceArgument(0, $config['host'] ?? 'localhost');
+ $definition->replaceArgument(0, $config['host']);
$definition->replaceArgument(1, $config['port'] ?? 8125);
- $definition->replaceArgument(2, (string) $config['prefix']);
+ $definition->replaceArgument(2, $config['prefix']);
return $definition;
case 'telegraf':
- $definition->replaceArgument(0, $config['host'] ?? 'localhost');
+ $definition->replaceArgument(0, $config['host']);
$definition->replaceArgument(1, $config['port'] ?? 8125);
- $definition->replaceArgument(2, (string) $config['prefix']);
+ $definition->replaceArgument(2, $config['prefix']);
return $definition;
default:
diff --git a/src/MetricsBundle/DependencyInjection/Configuration.php b/src/MetricsBundle/DependencyInjection/Configuration.php
index f8fb443..1246ed3 100644
--- a/src/MetricsBundle/DependencyInjection/Configuration.php
+++ b/src/MetricsBundle/DependencyInjection/Configuration.php
@@ -39,26 +39,32 @@ public function getConfigTreeBuilder(): TreeBuilder
->end()
->end()
- ->scalarNode('connection')->defaultNull()->end()
- ->scalarNode('file')->defaultNull()->end()
- ->scalarNode('host')->defaultNull()->end()
- ->scalarNode('password')->defaultNull()->end()
- ->integerNode('port')->defaultNull()->end()
- ->scalarNode('prefix')->defaultNull()->end()
+ ->scalarNode('host')->defaultValue('localhost')->end()
->scalarNode('protocol')->defaultNull()->end()
- ->scalarNode('source')->defaultNull()->end()
- ->scalarNode('username')->defaultNull()->end()
- ->scalarNode('influxdb_client')->defaultNull()->end()
- ->scalarNode('prometheus_collector_registry')->defaultNull()->info('It must to contain service id for Prometheus\\CollectorRegistry class instance.')->end()
- ->scalarNode('namespace')->defaultValue('')->end()
+ ->integerNode('port')->defaultNull()->end()
+ ->scalarNode('username')->defaultValue('')->end()
+ ->scalarNode('password')->defaultValue('')->end()
+ ->scalarNode('prefix')->defaultValue('')->end()
+ ->scalarNode('service')->defaultNull()->end()
->arrayNode('tags')
->defaultValue([])
->prototype('scalar')->end()
->end()
+ // Doctrine DBAL stuff
+ ->scalarNode('connection')->defaultNull()->end()
+ // Prom stuff
+ ->scalarNode('prometheus_collector_registry')->defaultNull()->info('It must to contain service id for Prometheus\\CollectorRegistry class instance.')->end()
+ ->scalarNode('namespace')->defaultValue('')->end()
+ // InfluxDB stuff
+ ->scalarNode('database')->defaultValue('')->end()
->end()
->validate()
->ifTrue(static fn ($v): bool => 'prometheus' === $v['type'] && empty($v['prometheus_collector_registry']))
- ->thenInvalid('The prometheus_collector_registry has to be specified to use a Prometheus')
+ ->thenInvalid('The "prometheus_collector_registry" has to be specified to use a Prometheus')
+ ->end()
+ ->validate()
+ ->ifTrue(static fn ($v): bool => 'influxdb' === $v['type'] && empty($v['database']))
+ ->thenInvalid('The "database" has to be specified to use a InfluxDB')
->end()
->end()
->end()
diff --git a/src/MetricsBundle/Resources/config/metrics.xml b/src/MetricsBundle/Resources/config/metrics.xml
index 71b7e5d..bd54cc8 100644
--- a/src/MetricsBundle/Resources/config/metrics.xml
+++ b/src/MetricsBundle/Resources/config/metrics.xml
@@ -14,8 +14,12 @@
+
+
+
+
-
+
diff --git a/tests/Metrics/Collector/InfluxDBTest.php b/tests/Metrics/Collector/InfluxDBTest.php
index be44fc6..d026dd4 100644
--- a/tests/Metrics/Collector/InfluxDBTest.php
+++ b/tests/Metrics/Collector/InfluxDBTest.php
@@ -10,34 +10,31 @@
namespace Beberlei\Metrics\Tests\Collector;
use Beberlei\Metrics\Collector\InfluxDB;
-use InfluxDB\Client;
+use InfluxDB\Database;
+use InfluxDB\Point;
+use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
class InfluxDBTest extends TestCase
{
- /**
- * @var \PHPUnit_Framework_MockObject_MockObject
- */
- private $client;
+ private MockObject&Database $database;
private InfluxDB $collector;
protected function setUp(): void
{
- $this->client = $this->getMockBuilder(Client::class)
+ $this->database = $this->getMockBuilder(Database::class)
->disableOriginalConstructor()
->getMock()
;
- $this->collector = new InfluxDB($this->client);
+ $this->collector = new InfluxDB($this->database);
}
public function testCollectIncrement(): void
{
- $expectedArgs = ['points' => [['measurement' => 'series-name', 'fields' => ['value' => 1]]], 'tags' => []];
-
- $this->client->expects($this->once())
- ->method('mark')
- ->with($expectedArgs)
+ $this->database->expects($this->once())
+ ->method('writePoints')
+ ->with($this->isType('array'))
;
$this->collector->increment('series-name');
@@ -46,11 +43,20 @@ public function testCollectIncrement(): void
public function testCollectDecrement(): void
{
- $expectedArgs = ['points' => [['measurement' => 'series-name', 'fields' => ['value' => -1]]], 'tags' => []];
-
- $this->client->expects($this->once())
- ->method('mark')
- ->with($expectedArgs)
+ $this->database->expects($this->once())
+ ->method('writePoints')
+ ->with($this->callback(function ($arg0) {
+ $this->assertIsArray($arg0);
+ $this->assertCount(1, $arg0);
+ $this->assertArrayHasKey(0, $arg0);
+ $point = $arg0[0];
+ $this->assertInstanceOf(Point::class, $point);
+ $this->assertSame('series-name', $point->getMeasurement());
+ $this->assertSame(['value' => '-1i'], $point->getFields());
+ $this->assertSame([], $point->getTags());
+
+ return true;
+ }))
;
$this->collector->decrement('series-name');
@@ -59,11 +65,20 @@ public function testCollectDecrement(): void
public function testCollectTiming(): void
{
- $expectedArgs = ['points' => [['measurement' => 'series-name', 'fields' => ['value' => 47]]], 'tags' => []];
-
- $this->client->expects($this->once())
- ->method('mark')
- ->with($expectedArgs)
+ $this->database->expects($this->once())
+ ->method('writePoints')
+ ->with($this->callback(function ($arg0) {
+ $this->assertIsArray($arg0);
+ $this->assertCount(1, $arg0);
+ $this->assertArrayHasKey(0, $arg0);
+ $point = $arg0[0];
+ $this->assertInstanceOf(Point::class, $point);
+ $this->assertSame('series-name', $point->getMeasurement());
+ $this->assertSame(['value' => '47i'], $point->getFields());
+ $this->assertSame([], $point->getTags());
+
+ return true;
+ }))
;
$this->collector->timing('series-name', 47);
@@ -72,11 +87,20 @@ public function testCollectTiming(): void
public function testCollectMeasure(): void
{
- $expectedArgs = ['points' => [['measurement' => 'series-name', 'fields' => ['value' => 47]]], 'tags' => []];
-
- $this->client->expects($this->once())
- ->method('mark')
- ->with($expectedArgs)
+ $this->database->expects($this->once())
+ ->method('writePoints')
+ ->with($this->callback(function ($arg0) {
+ $this->assertIsArray($arg0);
+ $this->assertCount(1, $arg0);
+ $this->assertArrayHasKey(0, $arg0);
+ $point = $arg0[0];
+ $this->assertInstanceOf(Point::class, $point);
+ $this->assertSame('series-name', $point->getMeasurement());
+ $this->assertSame(['value' => '47i'], $point->getFields());
+ $this->assertSame([], $point->getTags());
+
+ return true;
+ }))
;
$this->collector->measure('series-name', 47);
@@ -87,15 +111,47 @@ public function testCollectMeasureWithTags(): void
{
$expectedTags = ['dc' => 'west', 'node' => 'nemesis101'];
- $expectedArgs = ['points' => [['measurement' => 'series-name', 'fields' => ['value' => 47]]], 'tags' => $expectedTags];
-
- $this->client->expects($this->once())
- ->method('mark')
- ->with($expectedArgs)
+ $this->database->expects($this->once())
+ ->method('writePoints')
+ ->with($this->callback(function ($arg0) use ($expectedTags) {
+ $this->assertIsArray($arg0);
+ $this->assertCount(1, $arg0);
+ $this->assertArrayHasKey(0, $arg0);
+ $point = $arg0[0];
+ $this->assertInstanceOf(Point::class, $point);
+ $this->assertSame('series-name', $point->getMeasurement());
+ $this->assertSame(['value' => '47i'], $point->getFields());
+ $this->assertSame($expectedTags, $point->getTags());
+
+ return true;
+ }))
;
$this->collector->setTags($expectedTags);
$this->collector->measure('series-name', 47);
$this->collector->flush();
}
+
+ public function testCollectMeasureWithTagsMerged(): void
+ {
+ $this->database->expects($this->once())
+ ->method('writePoints')
+ ->with($this->callback(function ($arg0) {
+ $this->assertIsArray($arg0);
+ $this->assertCount(1, $arg0);
+ $this->assertArrayHasKey(0, $arg0);
+ $point = $arg0[0];
+ $this->assertInstanceOf(Point::class, $point);
+ $this->assertSame('series-name', $point->getMeasurement());
+ $this->assertSame(['value' => '47i'], $point->getFields());
+ $this->assertSame(['dc' => 'west', 'node' => 'nemesis101', 'foo' => 'bar'], $point->getTags());
+
+ return true;
+ }))
+ ;
+
+ $collector = new InfluxDB($this->database, ['dc' => 'west', 'node' => 'nemesis101']);
+ $collector->measure('series-name', 47, ['foo' => 'bar']);
+ $collector->flush();
+ }
}
diff --git a/tests/Metrics/FactoryTest.php b/tests/Metrics/FactoryTest.php
index 123455e..e6d98b2 100644
--- a/tests/Metrics/FactoryTest.php
+++ b/tests/Metrics/FactoryTest.php
@@ -20,7 +20,7 @@
use Beberlei\Metrics\Factory;
use Beberlei\Metrics\MetricsException;
use Doctrine\DBAL\Connection;
-use InfluxDB\Client;
+use InfluxDB\Database;
use PHPUnit\Framework\TestCase;
use Prometheus\CollectorRegistry;
use Psr\Log\NullLogger;
@@ -42,7 +42,7 @@ public function getCreateValidMetricTests(): iterable
yield [DoctrineDBAL::class, 'doctrine_dbal', ['connection' => $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock()]];
yield [Logger::class, 'logger', ['logger' => new NullLogger()]];
yield [NullCollector::class, 'null'];
- yield [InfluxDB::class, 'influxdb', ['client' => $this->getMockBuilder(Client::class)->disableOriginalConstructor()->getMock()]];
+ yield [InfluxDB::class, 'influxdb', ['database' => $this->getMockBuilder(Database::class)->disableOriginalConstructor()->getMock()]];
yield [Prometheus::class, 'prometheus', ['collector_registry' => $this->getMockBuilder(CollectorRegistry::class)->disableOriginalConstructor()->getMock()]];
yield [Prometheus::class, 'prometheus', ['collector_registry' => $this->getMockBuilder(CollectorRegistry::class)->disableOriginalConstructor()->getMock(), 'namespace' => 'some_namespace']];
}
@@ -67,9 +67,9 @@ public function getCreateThrowExceptionIfOptionsAreInvalidTests(): iterable
yield ['You should specified a host and a port if you specified a prefix.', 'dogstatsd', ['hostname' => 'foobar.com', 'prefix' => 'prefix']];
yield ['You should specified a host if you specified a port.', 'graphite', ['port' => '1234']];
yield ['connection is required for Doctrine DBAL collector.', 'doctrine_dbal'];
- yield ["Missing 'logger' key with logger service.", 'logger'];
- yield ["Missing 'client' key for InfluxDB collector.", 'influxdb'];
- yield ["Missing 'collector_registry' key for Prometheus collector.", 'prometheus'];
+ yield ['Missing "logger" key with logger service.', 'logger'];
+ yield ['Missing "database" key for InfluxDB collector.', 'influxdb'];
+ yield ['Missing "collector_registry" key for Prometheus collector.', 'prometheus'];
}
/**
diff --git a/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php b/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
index 7080858..c698eda 100644
--- a/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
+++ b/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
@@ -19,7 +19,6 @@
use Beberlei\Metrics\Collector\Prometheus;
use Beberlei\Metrics\Collector\StatsD;
use Beberlei\Metrics\Collector\Telegraf;
-use InfluxDB\Client;
use PHPUnit\Framework\TestCase;
use Prometheus\CollectorRegistry;
use Psr\Log\NullLogger;
@@ -117,28 +116,17 @@ public function testWithTelegraf(): void
public function testWithInfluxDB(): void
{
- $influxDBClientMock = $this->getMockBuilder(Client::class)
- ->disableOriginalConstructor()
- ->getMock()
- ;
-
- $container = $this->createContainer(['collectors' => ['influxdb' => ['type' => 'influxdb', 'influxdb_client' => 'influxdb_client_mock']]], ['beberlei_metrics.collector.influxdb'], ['influxdb_client_mock' => $influxDBClientMock]);
+ $container = $this->createContainer(['collectors' => ['influxdb' => ['type' => 'influxdb', 'database' => 'foobar']]], ['beberlei_metrics.collector.influxdb']);
$collector = $container->get('beberlei_metrics.collector.influxdb');
$this->assertInstanceOf(InfluxDB::class, $collector);
- $this->assertSame($influxDBClientMock, $this->getProperty($collector, 'client'));
}
public function testWithInfluxDBAndWithTags(): void
{
$expectedTags = ['string_tag' => 'first_value', 'int_tag' => 123];
- $influxDBClientMock = $this->getMockBuilder(Client::class)
- ->disableOriginalConstructor()
- ->getMock()
- ;
-
- $container = $this->createContainer(['collectors' => ['influxdb' => ['type' => 'influxdb', 'influxdb_client' => 'influxdb_client_mock', 'tags' => $expectedTags]]], ['beberlei_metrics.collector.influxdb'], ['influxdb_client_mock' => $influxDBClientMock]);
+ $container = $this->createContainer(['collectors' => ['influxdb' => ['type' => 'influxdb', 'database' => 'foobar', 'tags' => $expectedTags]]], ['beberlei_metrics.collector.influxdb']);
$collector = $container->get('beberlei_metrics.collector.influxdb');
$this->assertInstanceOf(InfluxDB::class, $collector);
@@ -203,7 +191,7 @@ public function testWithPrometheusAndWithTags(): void
public function testValidationWhenTypeIsPrometheusAndPrometheusCollectorRegistryIsNotSpecified(): void
{
$this->expectException(InvalidConfigurationException::class);
- $this->expectExceptionMessage('The prometheus_collector_registry has to be specified to use a Prometheus');
+ $this->expectExceptionMessage('The "prometheus_collector_registry" has to be specified to use a Prometheus');
$this->createContainer(['collectors' => ['prometheus' => ['type' => 'prometheus']]]);
}
From ceae017961eb0dae559335e5b19e1e88f901de3d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Fri, 1 Mar 2024 14:14:45 +0100
Subject: [PATCH 24/32] collector: rename InfluxDB to InfluxDbV1
---
README.md | 2 +-
composer.json | 2 ++
src/Metrics/Collector/{InfluxDB.php => InfluxDbV1.php} | 2 +-
src/Metrics/Factory.php | 6 +++---
.../DependencyInjection/BeberleiMetricsExtension.php | 4 ++--
src/MetricsBundle/Resources/config/metrics.xml | 4 ++--
.../Collector/{InfluxDBTest.php => InfluxDbV1Test.php} | 10 +++++-----
tests/Metrics/FactoryTest.php | 6 +++---
.../BeberleiMetricsExtensionTest.php | 10 +++++-----
9 files changed, 24 insertions(+), 22 deletions(-)
rename src/Metrics/Collector/{InfluxDB.php => InfluxDbV1.php} (95%)
rename tests/Metrics/Collector/{InfluxDBTest.php => InfluxDbV1Test.php} (94%)
diff --git a/README.md b/README.md
index f160c04..ad0fd99 100644
--- a/README.md
+++ b/README.md
@@ -106,7 +106,7 @@ beberlei_metrics:
type: monolog
influxdb:
type: influxdb
- influxdb_client: influxdb_client_service # using the InfluxDB client service named "influxdb_client_service"
+ database: metrics
tags:
dc: "west"
node_instance: "hermes10"
diff --git a/composer.json b/composer.json
index ac277fc..e8b17cf 100644
--- a/composer.json
+++ b/composer.json
@@ -30,6 +30,7 @@
},
"conflict": {
"doctrine/dbal": "<2",
+ "influxdb/influxdb-php": "<1.15",
"jimdo/prometheus_client_php": "<0.5.1",
"symfony/config": "<5.4",
"symfony/dependency-injection": "<5.4",
@@ -48,6 +49,7 @@
}
},
"suggest": {
+ "influxdb/influxdb-php": "For InfluxDB integration",
"jimdo/prometheus_client_php": "For Prometheus integration"
},
"config": {
diff --git a/src/Metrics/Collector/InfluxDB.php b/src/Metrics/Collector/InfluxDbV1.php
similarity index 95%
rename from src/Metrics/Collector/InfluxDB.php
rename to src/Metrics/Collector/InfluxDbV1.php
index 6c3935b..3d8bde3 100644
--- a/src/Metrics/Collector/InfluxDB.php
+++ b/src/Metrics/Collector/InfluxDbV1.php
@@ -13,7 +13,7 @@
use InfluxDB\Exception;
use InfluxDB\Point;
-class InfluxDB implements CollectorInterface, TaggableCollectorInterface
+class InfluxDbV1 implements CollectorInterface, TaggableCollectorInterface
{
private array $data = [];
diff --git a/src/Metrics/Factory.php b/src/Metrics/Factory.php
index 349dbc6..32680a8 100644
--- a/src/Metrics/Factory.php
+++ b/src/Metrics/Factory.php
@@ -13,7 +13,7 @@
use Beberlei\Metrics\Collector\DoctrineDBAL;
use Beberlei\Metrics\Collector\DogStatsD;
use Beberlei\Metrics\Collector\Graphite;
-use Beberlei\Metrics\Collector\InfluxDB;
+use Beberlei\Metrics\Collector\InfluxDbV1;
use Beberlei\Metrics\Collector\Logger;
use Beberlei\Metrics\Collector\NullCollector;
use Beberlei\Metrics\Collector\Prometheus;
@@ -120,12 +120,12 @@ public static function create(string $type, array $options = []): CollectorInter
return new Logger($options['logger']);
- case 'influxdb':
+ case 'influxdb_v1':
if (!isset($options['database'])) {
throw new MetricsException('Missing "database" key for InfluxDB collector.');
}
- return new InfluxDB($options['database']);
+ return new InfluxDbV1($options['database']);
case 'null':
return new NullCollector();
diff --git a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
index 080ee4a..5620df7 100644
--- a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
+++ b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
@@ -81,14 +81,14 @@ private function createCollector(string $type, array $config): ChildDefinition
$definition->replaceArgument(2, $config['protocol'] ?? 'tcp');
return $definition;
- case 'influxdb':
+ case 'influxdb_v1':
if (!class_exists(\InfluxDB\Client::class)) {
throw new \LogicException('The "influxdb/influxdb-php" package is required to use the "influxdb" collector.');
}
if ($config['service']) {
$definition->replaceArgument(0, new Reference($config['service']));
} else {
- $database = new ChildDefinition('beberlei_metrics.collector_proto.influxdb.database');
+ $database = new ChildDefinition('beberlei_metrics.collector_proto.influxdb_v1.database');
$database->replaceArgument(0, sprintf('influxdb://%s:%s@%s:%s/%s',
$config['username'],
$config['password'],
diff --git a/src/MetricsBundle/Resources/config/metrics.xml b/src/MetricsBundle/Resources/config/metrics.xml
index bd54cc8..e0bcb14 100644
--- a/src/MetricsBundle/Resources/config/metrics.xml
+++ b/src/MetricsBundle/Resources/config/metrics.xml
@@ -14,11 +14,11 @@
-
+
-
+
diff --git a/tests/Metrics/Collector/InfluxDBTest.php b/tests/Metrics/Collector/InfluxDbV1Test.php
similarity index 94%
rename from tests/Metrics/Collector/InfluxDBTest.php
rename to tests/Metrics/Collector/InfluxDbV1Test.php
index d026dd4..e072c2f 100644
--- a/tests/Metrics/Collector/InfluxDBTest.php
+++ b/tests/Metrics/Collector/InfluxDbV1Test.php
@@ -9,17 +9,17 @@
namespace Beberlei\Metrics\Tests\Collector;
-use Beberlei\Metrics\Collector\InfluxDB;
+use Beberlei\Metrics\Collector\InfluxDbV1;
use InfluxDB\Database;
use InfluxDB\Point;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
-class InfluxDBTest extends TestCase
+class InfluxDbV1Test extends TestCase
{
private MockObject&Database $database;
- private InfluxDB $collector;
+ private InfluxDbV1 $collector;
protected function setUp(): void
{
@@ -27,7 +27,7 @@ protected function setUp(): void
->disableOriginalConstructor()
->getMock()
;
- $this->collector = new InfluxDB($this->database);
+ $this->collector = new InfluxDbV1($this->database);
}
public function testCollectIncrement(): void
@@ -150,7 +150,7 @@ public function testCollectMeasureWithTagsMerged(): void
}))
;
- $collector = new InfluxDB($this->database, ['dc' => 'west', 'node' => 'nemesis101']);
+ $collector = new InfluxDbV1($this->database, ['dc' => 'west', 'node' => 'nemesis101']);
$collector->measure('series-name', 47, ['foo' => 'bar']);
$collector->flush();
}
diff --git a/tests/Metrics/FactoryTest.php b/tests/Metrics/FactoryTest.php
index e6d98b2..6c08fc4 100644
--- a/tests/Metrics/FactoryTest.php
+++ b/tests/Metrics/FactoryTest.php
@@ -12,7 +12,7 @@
use Beberlei\Metrics\Collector\DoctrineDBAL;
use Beberlei\Metrics\Collector\DogStatsD;
use Beberlei\Metrics\Collector\Graphite;
-use Beberlei\Metrics\Collector\InfluxDB;
+use Beberlei\Metrics\Collector\InfluxDbV1;
use Beberlei\Metrics\Collector\Logger;
use Beberlei\Metrics\Collector\NullCollector;
use Beberlei\Metrics\Collector\Prometheus;
@@ -42,7 +42,7 @@ public function getCreateValidMetricTests(): iterable
yield [DoctrineDBAL::class, 'doctrine_dbal', ['connection' => $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock()]];
yield [Logger::class, 'logger', ['logger' => new NullLogger()]];
yield [NullCollector::class, 'null'];
- yield [InfluxDB::class, 'influxdb', ['database' => $this->getMockBuilder(Database::class)->disableOriginalConstructor()->getMock()]];
+ yield [InfluxDbV1::class, 'influxdb_v1', ['database' => $this->getMockBuilder(Database::class)->disableOriginalConstructor()->getMock()]];
yield [Prometheus::class, 'prometheus', ['collector_registry' => $this->getMockBuilder(CollectorRegistry::class)->disableOriginalConstructor()->getMock()]];
yield [Prometheus::class, 'prometheus', ['collector_registry' => $this->getMockBuilder(CollectorRegistry::class)->disableOriginalConstructor()->getMock(), 'namespace' => 'some_namespace']];
}
@@ -68,7 +68,7 @@ public function getCreateThrowExceptionIfOptionsAreInvalidTests(): iterable
yield ['You should specified a host if you specified a port.', 'graphite', ['port' => '1234']];
yield ['connection is required for Doctrine DBAL collector.', 'doctrine_dbal'];
yield ['Missing "logger" key with logger service.', 'logger'];
- yield ['Missing "database" key for InfluxDB collector.', 'influxdb'];
+ yield ['Missing "database" key for InfluxDB collector.', 'influxdb_v1'];
yield ['Missing "collector_registry" key for Prometheus collector.', 'prometheus'];
}
diff --git a/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php b/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
index c698eda..c0e8115 100644
--- a/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
+++ b/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
@@ -12,7 +12,7 @@
use Beberlei\Bundle\MetricsBundle\DependencyInjection\BeberleiMetricsExtension;
use Beberlei\Metrics\Collector\DogStatsD;
use Beberlei\Metrics\Collector\Graphite;
-use Beberlei\Metrics\Collector\InfluxDB;
+use Beberlei\Metrics\Collector\InfluxDbV1;
use Beberlei\Metrics\Collector\InMemory;
use Beberlei\Metrics\Collector\Logger;
use Beberlei\Metrics\Collector\NullCollector;
@@ -116,20 +116,20 @@ public function testWithTelegraf(): void
public function testWithInfluxDB(): void
{
- $container = $this->createContainer(['collectors' => ['influxdb' => ['type' => 'influxdb', 'database' => 'foobar']]], ['beberlei_metrics.collector.influxdb']);
+ $container = $this->createContainer(['collectors' => ['influxdb' => ['type' => 'influxdb_v1', 'database' => 'foobar']]], ['beberlei_metrics.collector.influxdb']);
$collector = $container->get('beberlei_metrics.collector.influxdb');
- $this->assertInstanceOf(InfluxDB::class, $collector);
+ $this->assertInstanceOf(InfluxDbV1::class, $collector);
}
public function testWithInfluxDBAndWithTags(): void
{
$expectedTags = ['string_tag' => 'first_value', 'int_tag' => 123];
- $container = $this->createContainer(['collectors' => ['influxdb' => ['type' => 'influxdb', 'database' => 'foobar', 'tags' => $expectedTags]]], ['beberlei_metrics.collector.influxdb']);
+ $container = $this->createContainer(['collectors' => ['influxdb' => ['type' => 'influxdb_v1', 'database' => 'foobar', 'tags' => $expectedTags]]], ['beberlei_metrics.collector.influxdb']);
$collector = $container->get('beberlei_metrics.collector.influxdb');
- $this->assertInstanceOf(InfluxDB::class, $collector);
+ $this->assertInstanceOf(InfluxDbV1::class, $collector);
$this->assertEquals($expectedTags, $this->getProperty($collector, 'tags'));
}
From a6bf9abcfef0c82a5e39bd4772ed7ef1418ecbc9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Fri, 1 Mar 2024 14:24:53 +0100
Subject: [PATCH 25/32] bundle: enhance configuration + add kernel.reset tag
---
.../BeberleiMetricsExtension.php | 15 ++++++++++++++-
.../DependencyInjection/Configuration.php | 9 +++------
.../BeberleiMetricsExtensionTest.php | 7 +++++++
3 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
index 5620df7..0c9815d 100644
--- a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
+++ b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
@@ -20,6 +20,19 @@
class BeberleiMetricsExtension extends Extension
{
+ public const TYPES = [
+ 'doctrine_dbal',
+ 'dogstatsd',
+ 'graphite',
+ 'influxdb_v1',
+ 'logger',
+ 'memory',
+ 'null',
+ 'prometheus',
+ 'statsd',
+ 'telegraf',
+ ];
+
public function load(array $configs, ContainerBuilder $container): void
{
$configuration = $this->getConfiguration($configs, $container) ?? throw new \LogicException('Expected configuration to be set');
@@ -63,7 +76,7 @@ private function createCollector(string $type, array $config): ChildDefinition
$definition->addTag('kernel.event_listener', ['method' => 'flush', 'priority' => -1024, 'event' => 'kernel.terminate']);
$definition->addTag('kernel.event_listener', ['method' => 'flush', 'priority' => -1024, 'event' => 'console.terminate']);
$definition->addTag(CollectorInterface::class);
- // $definition->addTag('kernel.reset');
+ $definition->addTag('kernel.reset', ['method' => 'flush']);
if ($config['tags'] ?? []) {
$definition->addMethodCall('setTags', [$config['tags']]);
diff --git a/src/MetricsBundle/DependencyInjection/Configuration.php b/src/MetricsBundle/DependencyInjection/Configuration.php
index 1246ed3..f7a36e6 100644
--- a/src/MetricsBundle/DependencyInjection/Configuration.php
+++ b/src/MetricsBundle/DependencyInjection/Configuration.php
@@ -31,13 +31,10 @@ public function getConfigTreeBuilder(): TreeBuilder
->useAttributeAsKey('name')
->prototype('array')
->children()
- ->scalarNode('type')
+ ->enumNode('type')
+ ->values(BeberleiMetricsExtension::TYPES)
->isRequired()
- ->validate()
- ->ifTrue(static fn ($v) => !\is_string($v))
- ->thenInvalid('The type must be a string got "%s".')
- ->end()
-
+ ->cannotBeEmpty()
->end()
->scalarNode('host')->defaultValue('localhost')->end()
->scalarNode('protocol')->defaultNull()->end()
diff --git a/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php b/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
index c0e8115..4374562 100644
--- a/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
+++ b/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
@@ -195,6 +195,13 @@ public function testValidationWhenTypeIsPrometheusAndPrometheusCollectorRegistry
$this->createContainer(['collectors' => ['prometheus' => ['type' => 'prometheus']]]);
}
+ public function testWithInvalid(): void
+ {
+ $this->expectException(InvalidConfigurationException::class);
+ $this->expectExceptionMessageMatches('/^The value "invalid" is not allowed for path "beberlei_metrics.collectors.invalid.type". Permissible values: /');
+ $this->createContainer(['collectors' => ['invalid' => ['type' => 'invalid']]]);
+ }
+
private function createContainer($configs, array $publicServices = [], array $additionalServices = []): ContainerBuilder
{
$container = new ContainerBuilder();
From e0c3d027dd8e410389d047fb7757097785ed2224 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Fri, 1 Mar 2024 16:50:14 +0100
Subject: [PATCH 26/32] collector: change inner dependency of Prometheus
---
src/Metrics/Collector/Prometheus.php | 76 +++--
.../BeberleiMetricsExtension.php | 25 +-
.../DependencyInjection/Configuration.php | 4 -
.../Resources/config/metrics.xml | 5 +
tests/Metrics/Collector/PrometheusTest.php | 292 +++++-------------
.../BeberleiMetricsExtensionTest.php | 24 +-
6 files changed, 143 insertions(+), 283 deletions(-)
diff --git a/src/Metrics/Collector/Prometheus.php b/src/Metrics/Collector/Prometheus.php
index 9be13d3..a2bf557 100644
--- a/src/Metrics/Collector/Prometheus.php
+++ b/src/Metrics/Collector/Prometheus.php
@@ -10,15 +10,14 @@
namespace Beberlei\Metrics\Collector;
use Prometheus\CollectorRegistry;
-use Prometheus\Exception\MetricNotFoundException;
-use Prometheus\Gauge;
-class Prometheus implements CollectorInterface, TaggableCollectorInterface
+class Prometheus implements CollectorInterface, GaugeableCollectorInterface, TaggableCollectorInterface
{
- private array $data = ['counters' => [], 'gauges' => []];
+ private array $counters = [];
+ private array $gauges = [];
public function __construct(
- private readonly CollectorRegistry $collectorRegistry,
+ private readonly CollectorRegistry $registry,
private readonly string $namespace = '',
private array $tags = [],
) {
@@ -26,49 +25,55 @@ public function __construct(
public function measure(string $variable, int $value, array $tags = []): void
{
- $this->data['gauges'][] = ['name' => $variable, 'value' => $value];
+ $this->gauge($variable, $value, $tags);
}
public function increment(string $variable, array $tags = []): void
{
- $this->data['counters'][] = ['name' => $variable, 'value' => 1];
+ $this->counters[] = ['variable' => $variable, 'value' => 1, 'tags' => $tags];
}
public function decrement(string $variable, array $tags = []): void
{
- $this->data['counters'][] = ['name' => $variable, 'value' => -1];
+ $this->counters[] = ['variable' => $variable, 'value' => -1, 'tags' => $tags];
}
public function timing(string $variable, int $time, array $tags = []): void
{
- $this->measure($variable, $time);
+ $this->gauge($variable, $time, $tags);
}
- public function flush(): void
+ public function gauge(string $variable, string|int $value, array $tags = []): void
{
- if (!$this->data['gauges'] && !$this->data['counters']) {
- return;
- }
-
- $tagsValues = array_values($this->tags);
-
- foreach ($this->data['counters'] as $counterData) {
- $gauge = $this->getOrRegisterGaugeForVariable($counterData['name']);
+ $this->gauges[] = ['variable' => $variable, 'value' => $value, 'tags' => $tags];
+ }
- if ($counterData['value'] > 0) {
- $gauge->inc($tagsValues);
- } elseif ($counterData['value'] < 0) {
- $gauge->dec($tagsValues);
+ public function flush(): void
+ {
+ try {
+ foreach ($this->counters as $counter) {
+ $variable = $this->normalizeVariable($counter['variable']);
+ $labels = $this->tags + $counter['tags'];
+ $this
+ ->registry
+ ->getOrRegisterCounter($this->namespace, $variable, '', $labels)
+ ->incBy($counter['value'], $labels)
+ ;
}
- }
- foreach ($this->data['gauges'] as $gaugeData) {
- $gauge = $this->getOrRegisterGaugeForVariable($gaugeData['name']);
-
- $gauge->set($gaugeData['value'], $tagsValues);
+ foreach ($this->gauges as $gauge) {
+ $variable = $this->normalizeVariable($gauge['variable']);
+ $labels = $this->tags + $gauge['tags'];
+ $this
+ ->registry
+ ->getOrRegisterGauge($this->namespace, $variable, '', $labels)
+ ->set($gauge['value'], $labels)
+ ;
+ }
+ } catch (\Exception) {
}
- $this->data = ['counters' => [], 'gauges' => []];
+ $this->counters = $this->gauges = [];
}
public function setTags(array $tags): void
@@ -76,19 +81,8 @@ public function setTags(array $tags): void
$this->tags = $tags;
}
- private function getOrRegisterGaugeForVariable(string $variable): Gauge
+ private function normalizeVariable(string $variable): string
{
- try {
- $gauge = $this->collectorRegistry->getGauge($this->namespace, $variable);
- } catch (MetricNotFoundException) {
- $gauge = $this->collectorRegistry->registerGauge(
- $this->namespace,
- $variable,
- '',
- array_keys($this->tags)
- );
- }
-
- return $gauge;
+ return str_replace(['.', ':'], ['_', '_'], $variable);
}
}
diff --git a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
index 0c9815d..1d8bdd5 100644
--- a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
+++ b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
@@ -10,6 +10,7 @@
namespace Beberlei\Bundle\MetricsBundle\DependencyInjection;
use Beberlei\Metrics\Collector\CollectorInterface;
+use Prometheus\CollectorRegistry;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -47,7 +48,7 @@ public function load(array $configs, ContainerBuilder $container): void
];
}
foreach ($config['collectors'] as $name => $colConfig) {
- $definition = $this->createCollector($colConfig['type'], $colConfig);
+ $definition = $this->createCollector($container, $name, $colConfig['type'], $colConfig);
$container->setDefinition('beberlei_metrics.collector.' . $name, $definition);
$container->registerAliasForArgument('beberlei_metrics.collector.' . $name, CollectorInterface::class, $name);
}
@@ -63,12 +64,10 @@ public function load(array $configs, ContainerBuilder $container): void
throw new InvalidArgumentException('No default collector is configured and there is more than one collector. Please define a default collector');
}
- if ($name) {
- $container->setAlias(CollectorInterface::class, 'beberlei_metrics.collector.' . $name);
- }
+ $container->setAlias(CollectorInterface::class, 'beberlei_metrics.collector.' . $name);
}
- private function createCollector(string $type, array $config): ChildDefinition
+ private function createCollector(ContainerBuilder $container, string $name, string $type, array $config): ChildDefinition
{
$definition = new ChildDefinition('beberlei_metrics.collector_proto.' . $config['type']);
@@ -118,7 +117,21 @@ private function createCollector(string $type, array $config): ChildDefinition
case 'memory':
return $definition;
case 'prometheus':
- $definition->replaceArgument(0, new Reference($config['prometheus_collector_registry']));
+ if (!class_exists(CollectorRegistry::class)) {
+ throw new \LogicException('The "promphp/prometheus_client_php" package is required to use the "prometheus" collector.');
+ }
+ if ($config['service']) {
+ $definition->replaceArgument(0, new Reference($config['service']));
+ } else {
+ $database = new ChildDefinition('beberlei_metrics.collector_proto.prometheus.registry');
+ $container->setDefinition($id = 'beberlei_metrics.collector.' . $name . '.prometheus.registry', $database);
+
+ $definition->replaceArgument(0, new Reference($id));
+ if (!$container->hasAlias(CollectorRegistry::class)) {
+ $container->setAlias(CollectorRegistry::class, $id);
+ }
+ }
+
$definition->replaceArgument(1, $config['namespace']);
return $definition;
diff --git a/src/MetricsBundle/DependencyInjection/Configuration.php b/src/MetricsBundle/DependencyInjection/Configuration.php
index f7a36e6..21bab64 100644
--- a/src/MetricsBundle/DependencyInjection/Configuration.php
+++ b/src/MetricsBundle/DependencyInjection/Configuration.php
@@ -55,10 +55,6 @@ public function getConfigTreeBuilder(): TreeBuilder
// InfluxDB stuff
->scalarNode('database')->defaultValue('')->end()
->end()
- ->validate()
- ->ifTrue(static fn ($v): bool => 'prometheus' === $v['type'] && empty($v['prometheus_collector_registry']))
- ->thenInvalid('The "prometheus_collector_registry" has to be specified to use a Prometheus')
- ->end()
->validate()
->ifTrue(static fn ($v): bool => 'influxdb' === $v['type'] && empty($v['database']))
->thenInvalid('The "database" has to be specified to use a InfluxDB')
diff --git a/src/MetricsBundle/Resources/config/metrics.xml b/src/MetricsBundle/Resources/config/metrics.xml
index e0bcb14..fd1f01c 100644
--- a/src/MetricsBundle/Resources/config/metrics.xml
+++ b/src/MetricsBundle/Resources/config/metrics.xml
@@ -27,6 +27,11 @@
+
+
+
+
+
diff --git a/tests/Metrics/Collector/PrometheusTest.php b/tests/Metrics/Collector/PrometheusTest.php
index 0dde72b..c8c1393 100644
--- a/tests/Metrics/Collector/PrometheusTest.php
+++ b/tests/Metrics/Collector/PrometheusTest.php
@@ -10,271 +10,138 @@
namespace Beberlei\Metrics\Tests\Collector;
use Beberlei\Metrics\Collector\Prometheus;
-use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Prometheus\CollectorRegistry;
-use Prometheus\Exception\MetricNotFoundException;
-use Prometheus\Gauge;
+use Prometheus\Storage\InMemory;
class PrometheusTest extends TestCase
{
- public const TEST_NAMESPACE = 'some_metric_namespace';
-
- public const TEST_VARIABLE_NAME = 'some_variable_name';
-
- private MockObject&CollectorRegistry $collectorRegistryMock;
+ private const TEST_NAMESPACE = 'some_metric_namespace';
+ private const TEST_VARIABLE_NAME = 'some_variable_name';
+ private CollectorRegistry $collectorRegistry;
private Prometheus $collector;
protected function setUp(): void
{
- $this->collectorRegistryMock = $this->getMockBuilder(CollectorRegistry::class)
- ->disableOriginalConstructor()
- ->getMock()
- ;
-
- $this->collector = new Prometheus($this->collectorRegistryMock, self::TEST_NAMESPACE);
+ $this->collectorRegistry = new CollectorRegistry(new InMemory(), false);
+ $this->collector = new Prometheus($this->collectorRegistry, self::TEST_NAMESPACE);
}
public function testMeasure(): void
{
$expectedVariableValue = 123;
+ $labels = [];
- $gaugeMock = $this->getMockBuilder(Gauge::class)
- ->disableOriginalConstructor()
- ->getMock()
- ;
- $gaugeMock
- ->expects($this->once())
- ->method('set')
- ->with($expectedVariableValue, [])
- ;
-
- $this->collectorRegistryMock
- ->expects($this->once())
- ->method('getGauge')
- ->with(self::TEST_NAMESPACE, self::TEST_VARIABLE_NAME)
- ->willReturn($gaugeMock)
- ;
-
+ $this->collector->setTags($labels);
$this->collector->measure(self::TEST_VARIABLE_NAME, $expectedVariableValue);
$this->collector->flush();
+
+ $data = $this->collectorRegistry->getMetricFamilySamples()[0]->getSamples()[0];
+ $this->assertSame(self::TEST_NAMESPACE . '_' . self::TEST_VARIABLE_NAME, $data->getName());
+ $this->assertSame((string) $expectedVariableValue, $data->getValue());
+ $this->assertSame($labels, $data->getLabelValues());
}
public function testMeasureWithTags(): void
{
$expectedVariableValue = 123;
- $expectedTagsValues = ['value1', 'value2'];
-
- $gaugeMock = $this->getMockBuilder(Gauge::class)
- ->disableOriginalConstructor()
- ->getMock()
- ;
- $gaugeMock
- ->expects($this->once())
- ->method('set')
- ->with($expectedVariableValue, $expectedTagsValues)
- ;
-
- $this->collectorRegistryMock
- ->expects($this->once())
- ->method('getGauge')
- ->with(self::TEST_NAMESPACE, self::TEST_VARIABLE_NAME)
- ->willReturn($gaugeMock)
- ;
-
- $this->collector->setTags(['tag1' => 'value1', 'tag2' => 'value2']);
+ $labels = ['tag1' => 'value1', 'tag2' => 'value2'];
+ $this->collector->setTags($labels);
$this->collector->measure(self::TEST_VARIABLE_NAME, $expectedVariableValue);
$this->collector->flush();
+
+ $data = $this->collectorRegistry->getMetricFamilySamples()[0]->getSamples()[0];
+ $this->assertSame(self::TEST_NAMESPACE . '_' . self::TEST_VARIABLE_NAME, $data->getName());
+ $this->assertSame((string) $expectedVariableValue, $data->getValue());
+ $this->assertSame($labels, $data->getLabelValues());
}
public function testIncrement(): void
{
- $gaugeMock = $this->getMockBuilder(Gauge::class)
- ->disableOriginalConstructor()
- ->getMock()
- ;
- $gaugeMock
- ->expects($this->once())
- ->method('inc')
- ->with([])
- ;
-
- $this->collectorRegistryMock
- ->expects($this->once())
- ->method('getGauge')
- ->with(self::TEST_NAMESPACE, self::TEST_VARIABLE_NAME)
- ->willReturn($gaugeMock)
- ;
+ $labels = [];
+ $this->collector->setTags($labels);
$this->collector->increment(self::TEST_VARIABLE_NAME);
$this->collector->flush();
+
+ $data = $this->collectorRegistry->getMetricFamilySamples()[0]->getSamples()[0];
+ $this->assertSame(self::TEST_NAMESPACE . '_' . self::TEST_VARIABLE_NAME, $data->getName());
+ $this->assertSame('1', $data->getValue());
+ $this->assertSame($labels, $data->getLabelValues());
}
public function testIncrementWithTags(): void
{
- $expectedTagsValues = ['value1', 'value2'];
-
- $gaugeMock = $this->getMockBuilder(Gauge::class)
- ->disableOriginalConstructor()
- ->getMock()
- ;
- $gaugeMock
- ->expects($this->once())
- ->method('inc')
- ->with($expectedTagsValues)
- ;
-
- $this->collectorRegistryMock
- ->expects($this->once())
- ->method('getGauge')
- ->with(self::TEST_NAMESPACE, self::TEST_VARIABLE_NAME)
- ->willReturn($gaugeMock)
- ;
-
- $this->collector->setTags(['tag1' => 'value1', 'tag2' => 'value2']);
+ $labels = ['value1', 'value2'];
+ $this->collector->setTags($labels);
$this->collector->increment(self::TEST_VARIABLE_NAME);
$this->collector->flush();
+
+ $data = $this->collectorRegistry->getMetricFamilySamples()[0]->getSamples()[0];
+ $this->assertSame(self::TEST_NAMESPACE . '_' . self::TEST_VARIABLE_NAME, $data->getName());
+ $this->assertSame('1', $data->getValue());
+ $this->assertSame($labels, $data->getLabelValues());
}
public function testDecrement(): void
{
- $gaugeMock = $this->getMockBuilder(Gauge::class)
- ->disableOriginalConstructor()
- ->getMock()
- ;
- $gaugeMock
- ->expects($this->once())
- ->method('dec')
- ->with([])
- ;
-
- $this->collectorRegistryMock
- ->expects($this->once())
- ->method('getGauge')
- ->with(self::TEST_NAMESPACE, self::TEST_VARIABLE_NAME)
- ->willReturn($gaugeMock)
- ;
+ $labels = [];
+ $this->collector->setTags($labels);
$this->collector->decrement(self::TEST_VARIABLE_NAME);
$this->collector->flush();
+
+ $data = $this->collectorRegistry->getMetricFamilySamples()[0]->getSamples()[0];
+ $this->assertSame(self::TEST_NAMESPACE . '_' . self::TEST_VARIABLE_NAME, $data->getName());
+ $this->assertSame('-1', $data->getValue());
+ $this->assertSame($labels, $data->getLabelValues());
}
public function testDecrementWithTags(): void
{
- $expectedTagsValues = ['value1', 'value2'];
-
- $gaugeMock = $this->getMockBuilder(Gauge::class)
- ->disableOriginalConstructor()
- ->getMock()
- ;
- $gaugeMock
- ->expects($this->once())
- ->method('dec')
- ->with($expectedTagsValues)
- ;
-
- $this->collectorRegistryMock
- ->expects($this->once())
- ->method('getGauge')
- ->with(self::TEST_NAMESPACE, self::TEST_VARIABLE_NAME)
- ->willReturn($gaugeMock)
- ;
-
- $this->collector->setTags(['tag1' => 'value1', 'tag2' => 'value2']);
+ $labels = ['value1', 'value2'];
+ $this->collector->setTags($labels);
$this->collector->decrement(self::TEST_VARIABLE_NAME);
$this->collector->flush();
+
+ $data = $this->collectorRegistry->getMetricFamilySamples()[0]->getSamples()[0];
+ $this->assertSame(self::TEST_NAMESPACE . '_' . self::TEST_VARIABLE_NAME, $data->getName());
+ $this->assertSame('-1', $data->getValue());
+ $this->assertSame($labels, $data->getLabelValues());
}
public function testTiming(): void
{
$expectedVariableValue = 123;
+ $labels = [];
- $gaugeMock = $this->getMockBuilder(Gauge::class)
- ->disableOriginalConstructor()
- ->getMock()
- ;
- $gaugeMock
- ->expects($this->once())
- ->method('set')
- ->with($expectedVariableValue, [])
- ;
-
- $this->collectorRegistryMock
- ->expects($this->once())
- ->method('getGauge')
- ->with(self::TEST_NAMESPACE, self::TEST_VARIABLE_NAME)
- ->willReturn($gaugeMock)
- ;
-
+ $this->collector->setTags($labels);
$this->collector->timing(self::TEST_VARIABLE_NAME, $expectedVariableValue);
$this->collector->flush();
+
+ $data = $this->collectorRegistry->getMetricFamilySamples()[0]->getSamples()[0];
+ $this->assertSame(self::TEST_NAMESPACE . '_' . self::TEST_VARIABLE_NAME, $data->getName());
+ $this->assertSame((string) $expectedVariableValue, $data->getValue());
+ $this->assertSame($labels, $data->getLabelValues());
}
public function testTimingWithTags(): void
{
$expectedVariableValue = 123;
- $expectedTagsValues = ['value1', 'value2'];
-
- $gaugeMock = $this->getMockBuilder(Gauge::class)
- ->disableOriginalConstructor()
- ->getMock()
- ;
- $gaugeMock
- ->expects($this->once())
- ->method('set')
- ->with($expectedVariableValue, $expectedTagsValues)
- ;
-
- $this->collectorRegistryMock
- ->expects($this->once())
- ->method('getGauge')
- ->with(self::TEST_NAMESPACE, self::TEST_VARIABLE_NAME)
- ->willReturn($gaugeMock)
- ;
-
- $this->collector->setTags(['tag1' => 'value1', 'tag2' => 'value2']);
+ $labels = ['tag1' => 'value1', 'tag2' => 'value2'];
+ $this->collector->setTags($labels);
$this->collector->timing(self::TEST_VARIABLE_NAME, $expectedVariableValue);
$this->collector->flush();
- }
-
- public function testMeasureWhenSetNewVariableWithTags(): void
- {
- $expectedVariableValue = 123;
- $expectedTagsNames = ['tag1', 'tag2'];
- $expectedTagsValues = ['value1', 'value2'];
-
- $gaugeMock = $this->getMockBuilder(Gauge::class)
- ->disableOriginalConstructor()
- ->getMock()
- ;
- $gaugeMock
- ->expects($this->once())
- ->method('set')
- ->with($expectedVariableValue, $expectedTagsValues)
- ;
-
- $this->collectorRegistryMock
- ->expects($this->once())
- ->method('getGauge')
- ->with(self::TEST_NAMESPACE, self::TEST_VARIABLE_NAME)
- ->willThrowException(new MetricNotFoundException())
- ;
- $this->collectorRegistryMock
- ->expects($this->once())
- ->method('registerGauge')
- ->with(self::TEST_NAMESPACE, self::TEST_VARIABLE_NAME, '', $expectedTagsNames)
- ->willReturn($gaugeMock)
- ;
-
- $this->collector->setTags(['tag1' => 'value1', 'tag2' => 'value2']);
- $this->collector->measure(self::TEST_VARIABLE_NAME, $expectedVariableValue);
- $this->collector->flush();
+ $data = $this->collectorRegistry->getMetricFamilySamples()[0]->getSamples()[0];
+ $this->assertSame(self::TEST_NAMESPACE . '_' . self::TEST_VARIABLE_NAME, $data->getName());
+ $this->assertSame((string) $expectedVariableValue, $data->getValue());
+ $this->assertSame($labels, $data->getLabelValues());
}
/**
@@ -283,34 +150,21 @@ public function testMeasureWhenSetNewVariableWithTags(): void
public function testFlushWhenCallsTwiceWithDifferentData(): void
{
$firstExpectedVariableValue = 123;
- $secondExpectedVariableValue = 321;
- $gaugeMock = $this->getMockBuilder(Gauge::class)
- ->disableOriginalConstructor()
- ->getMock()
- ;
- $gaugeMock
- ->expects($matcher = $this->exactly(2))
- ->method('set')
- ->willReturnCallback(function ($value) use ($matcher) {
- match ($matcher->getInvocationCount()) {
- 1 => $this->assertEquals(123, $value),
- 2 => $this->assertEquals(321, $value),
- };
- })
- ;
-
- $this->collectorRegistryMock
- ->expects($this->exactly(2))
- ->method('getGauge')
- ->with(self::TEST_NAMESPACE, self::TEST_VARIABLE_NAME)
- ->willReturn($gaugeMock)
- ;
-
- $this->collector->measure(self::TEST_VARIABLE_NAME, $firstExpectedVariableValue);
+ $this->collector->timing(self::TEST_VARIABLE_NAME, $firstExpectedVariableValue);
$this->collector->flush();
- $this->collector->measure(self::TEST_VARIABLE_NAME, $secondExpectedVariableValue);
+ $data = $this->collectorRegistry->getMetricFamilySamples()[0]->getSamples()[0];
+ $this->assertSame(self::TEST_NAMESPACE . '_' . self::TEST_VARIABLE_NAME, $data->getName());
+ $this->assertSame((string) $firstExpectedVariableValue, $data->getValue());
+
+ $secondExpectedVariableValue = 321;
+
+ $this->collector->timing(self::TEST_VARIABLE_NAME, $secondExpectedVariableValue);
$this->collector->flush();
+
+ $data = $this->collectorRegistry->getMetricFamilySamples()[0]->getSamples()[0];
+ $this->assertSame(self::TEST_NAMESPACE . '_' . self::TEST_VARIABLE_NAME, $data->getName());
+ $this->assertSame((string) $secondExpectedVariableValue, $data->getValue());
}
}
diff --git a/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php b/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
index 4374562..6497d98 100644
--- a/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
+++ b/tests/MetricsBundle/DependencyInjection/BeberleiMetricsExtensionTest.php
@@ -140,11 +140,11 @@ public function testWithPrometheus(): void
->getMock()
;
- $container = $this->createContainer(['collectors' => ['prometheus' => ['type' => 'prometheus', 'prometheus_collector_registry' => 'prometheus_collector_registry_mock']]], ['beberlei_metrics.collector.prometheus'], ['prometheus_collector_registry_mock' => $prometheusCollectorRegistryMock]);
+ $container = $this->createContainer(['collectors' => ['prometheus' => ['type' => 'prometheus', 'service' => 'prometheus_collector_registry_mock']]], ['beberlei_metrics.collector.prometheus'], ['prometheus_collector_registry_mock' => $prometheusCollectorRegistryMock]);
$collector = $container->get('beberlei_metrics.collector.prometheus');
$this->assertInstanceOf(Prometheus::class, $collector);
- $this->assertSame($prometheusCollectorRegistryMock, $this->getProperty($collector, 'collectorRegistry'));
+ $this->assertSame($prometheusCollectorRegistryMock, $this->getProperty($collector, 'registry'));
$this->assertSame('', $this->getProperty($collector, 'namespace'));
}
@@ -164,11 +164,11 @@ public function testWithPrometheusAndWithNamespace(): void
->getMock()
;
- $container = $this->createContainer(['collectors' => ['prometheus' => ['type' => 'prometheus', 'prometheus_collector_registry' => 'prometheus_collector_registry_mock', 'namespace' => $expectedNamespace]]], ['beberlei_metrics.collector.prometheus'], ['prometheus_collector_registry_mock' => $prometheusCollectorRegistryMock]);
+ $container = $this->createContainer(['collectors' => ['prometheus' => ['type' => 'prometheus', 'service' => 'prometheus_collector_registry_mock', 'namespace' => $expectedNamespace]]], ['beberlei_metrics.collector.prometheus'], ['prometheus_collector_registry_mock' => $prometheusCollectorRegistryMock]);
$collector = $container->get('beberlei_metrics.collector.prometheus');
$this->assertInstanceOf(Prometheus::class, $collector);
- $this->assertSame($prometheusCollectorRegistryMock, $this->getProperty($collector, 'collectorRegistry'));
+ $this->assertSame($prometheusCollectorRegistryMock, $this->getProperty($collector, 'registry'));
$this->assertSame($expectedNamespace, $this->getProperty($collector, 'namespace'));
}
@@ -181,7 +181,7 @@ public function testWithPrometheusAndWithTags(): void
->getMock()
;
- $container = $this->createContainer(['collectors' => ['prometheus' => ['type' => 'prometheus', 'prometheus_collector_registry' => 'prometheus_collector_registry_mock', 'tags' => $expectedTags]]], ['beberlei_metrics.collector.prometheus'], ['prometheus_collector_registry_mock' => $prometheusCollectorRegistryMock]);
+ $container = $this->createContainer(['collectors' => ['prometheus' => ['type' => 'prometheus', 'service' => 'prometheus_collector_registry_mock', 'tags' => $expectedTags]]], ['beberlei_metrics.collector.prometheus'], ['prometheus_collector_registry_mock' => $prometheusCollectorRegistryMock]);
$collector = $container->get('beberlei_metrics.collector.prometheus');
$this->assertInstanceOf(Prometheus::class, $collector);
@@ -190,9 +190,10 @@ public function testWithPrometheusAndWithTags(): void
public function testValidationWhenTypeIsPrometheusAndPrometheusCollectorRegistryIsNotSpecified(): void
{
- $this->expectException(InvalidConfigurationException::class);
- $this->expectExceptionMessage('The "prometheus_collector_registry" has to be specified to use a Prometheus');
- $this->createContainer(['collectors' => ['prometheus' => ['type' => 'prometheus']]]);
+ $container = $this->createContainer(['collectors' => ['prometheus' => ['type' => 'prometheus']]], ['beberlei_metrics.collector.prometheus']);
+
+ $collector = $container->get('beberlei_metrics.collector.prometheus');
+ $this->assertInstanceOf(Prometheus::class, $collector);
}
public function testWithInvalid(): void
@@ -224,11 +225,8 @@ private function createContainer($configs, array $publicServices = [], array $ad
return $container;
}
- private function getProperty(?object $object, string $property)
+ private function getProperty(?object $object, string $property): mixed
{
- $reflectionProperty = new \ReflectionProperty($object::class, $property);
- $reflectionProperty->setAccessible(true);
-
- return $reflectionProperty->getValue($object);
+ return (new \ReflectionProperty($object::class, $property))->getValue($object);
}
}
From 8679461259133e660970e6c50fff26118c142979 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Fri, 1 Mar 2024 14:35:37 +0100
Subject: [PATCH 27/32] composer: cleaning
---
composer.json | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/composer.json b/composer.json
index e8b17cf..09097d2 100644
--- a/composer.json
+++ b/composer.json
@@ -23,19 +23,14 @@
"doctrine/dbal": "^2.0",
"influxdb/influxdb-php": "^1.15",
"jimdo/prometheus_client_php": "^0.5.1",
- "symfony/config": "^5.4 || ^6.4 || ^7.0",
- "symfony/dependency-injection": "^5.4 || ^6.4 || ^7.0",
- "symfony/http-kernel": "^5.4 || ^6.4 || ^7.0",
+ "symfony/framework-bundle": "^5.4 || ^6.4 || ^7.0",
"symfony/phpunit-bridge": "^6.4.4 || ^7.0"
},
"conflict": {
"doctrine/dbal": "<2",
"influxdb/influxdb-php": "<1.15",
"jimdo/prometheus_client_php": "<0.5.1",
- "symfony/config": "<5.4",
- "symfony/dependency-injection": "<5.4",
- "symfony/http-client": "<5.4",
- "symfony/http-kernel": "<5.4"
+ "symfony/framework-bundle": "<5.4"
},
"autoload": {
"psr-4": {
From 669d5a36580f0c8f86d6713b41e5dfd90eb47cce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Fri, 1 Mar 2024 17:07:38 +0100
Subject: [PATCH 28/32] doc: reword the readme
---
README.md | 111 +++++++++++++++++++++++++++++++-----------------------
1 file changed, 63 insertions(+), 48 deletions(-)
diff --git a/README.md b/README.md
index ad0fd99..091abc5 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,5 @@
# Metrics
-[![Build Status](https://travis-ci.org/beberlei/metrics.svg?branch=master)](https://travis-ci.org/beberlei/metrics)
-
Simple library that abstracts different metrics collectors. I find this
necessary to have a consistent and simple metrics API that doesn't cause vendor
lock-in.
@@ -11,20 +9,20 @@ It also ships with a Symfony Bundle. **This is not a library for displaying metr
Currently supported backends:
* Doctrine DBAL
+* DogStatsD
* Graphite
-* InfluxDB
-* Telegraf
+* InfluxDb (version 1)
* Logger (Psr\Log\LoggerInterface)
* Null (Dummy that does nothing)
* Prometheus
* StatsD
-* DogStatsD
+* Telegraf
## Installation
Using Composer:
-```bash
+```
composer require beberlei/metrics
```
@@ -33,16 +31,12 @@ composer require beberlei/metrics
You can instantiate clients:
```php
-increment('foo.bar');
$collector->decrement('foo.bar');
@@ -54,86 +48,107 @@ $value = 1234;
$collector->measure('foo.bar', $value);
```
-Some backends defer sending and aggregate all information, make sure to call
+All backends defer sending and aggregate all information, make sure to call
flush:
```php
-flush();
```
## Configuration
```php
- ['all' => true],
+];
-class AppKernel extends Kernel
-{
- public function registerBundles()
- {
- //..
- $bundles[] = new \Beberlei\Bundle\MetricsBundle\BeberleiMetricsBundle();
- //..
- }
-}
```
-Do Configuration:
+Do some configuration:
```yaml
# app/config/config.yml
beberlei_metrics:
- default: foo
+ default: statsd
collectors:
- foo:
- type: statsd
- dbal:
- type: doctrine_dbal
- connection: metrics # using the connection named "metrics"
- monolog:
- type: monolog
influxdb:
type: influxdb
database: metrics
- tags:
+ # If you want to use a custom database service
+ # It must be an instance of "InfluxDB\Database"
+ # In this case, you can omit de "database" option
+ # service: my.service.id
+ tags: # optional
dc: "west"
node_instance: "hermes10"
prometheus:
type: prometheus
- prometheus_collector_registry: prometheus_collector_registry_service # using the Prometheus collector registry service named "prometheus_collector_registry_service"
+ # If you want to use a custom registry service
+ # It must be an instance of "Prometheus\CollectorRegistry"
+ # By default it uses an "Prometheus\Storage\InMemory" adapter
+ # service: my.service.id
namespace: app_name # optional
- tags:
+ tags: # optional
dc: "west"
node_instance: "hermes10"
+ statsd:
+ type: statsd
+ # host: localhost # default
+ # port: 8125 # default
+ # prefix: '' # default
+ dogstatsd:
+ type: dogstatsd
+ # host: localhost # default
+ # port: 8125 # default
+ # prefix: '' # default
+ dbal:
+ type: doctrine_dbal
+ # Use another connection, by default it uses the default connection
+ # connection: metrics
+ monolog:
+ type: monolog
```
-This adds collectors to the Metrics registry. The functions are automatically
-included in the Bundle class so that in your code you can just start using the
-convenient functions. Metrics are also added as services:
+Then, you can inject the `Beberlei\Metrics\Collector\CollectorInterface` and
+start using it:
```php
-get('beberlei_metrics.collector.foo');
+ public function doSomething(): void
+ {
+ $this->collector->increment('foo.bar');
+ }
+}
```
-and the default collector can be fetched:
+The `Beberlei\Metrics\Collector\CollectorInterface` is automatically aliased to
+the default collector.
+If you want to inject a specific collector, you must use the `#[Target]` attribute:
```php
-get('beberlei_metrics.collector');
+public function __construct(
+ #[Target('name_of_the_collector')]
+ CollectorInterface $memoryCollector,
+) {
```
-
From bfab645bd9c210e7b9b52ae345ff16c5cfcb175c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Fri, 1 Mar 2024 17:27:59 +0100
Subject: [PATCH 29/32] chore: remove the TaggableCollectorInterface
---
README.md | 4 +
src/Metrics/Collector/InfluxDbV1.php | 7 +-
src/Metrics/Collector/NullCollector.php | 6 +-
src/Metrics/Collector/Prometheus.php | 9 +-
.../Collector/TaggableCollectorInterface.php | 15 ----
src/Metrics/Collector/Telegraf.php | 13 ++-
.../BeberleiMetricsExtension.php | 72 ++++++++-------
.../Resources/config/metrics.xml | 36 ++++----
tests/Metrics/Collector/InfluxDbV1Test.php | 41 +++++----
tests/Metrics/Collector/PrometheusTest.php | 88 ++++++++++---------
10 files changed, 143 insertions(+), 148 deletions(-)
delete mode 100644 src/Metrics/Collector/TaggableCollectorInterface.php
diff --git a/README.md b/README.md
index 091abc5..cffc412 100644
--- a/README.md
+++ b/README.md
@@ -86,6 +86,10 @@ beberlei_metrics:
influxdb:
type: influxdb
database: metrics
+ # host: localhost # option
+ # username: username # optional
+ # password: password # optional
+ # port: 8086 # optional
# If you want to use a custom database service
# It must be an instance of "InfluxDB\Database"
# In this case, you can omit de "database" option
diff --git a/src/Metrics/Collector/InfluxDbV1.php b/src/Metrics/Collector/InfluxDbV1.php
index 3d8bde3..2330927 100644
--- a/src/Metrics/Collector/InfluxDbV1.php
+++ b/src/Metrics/Collector/InfluxDbV1.php
@@ -13,7 +13,7 @@
use InfluxDB\Exception;
use InfluxDB\Point;
-class InfluxDbV1 implements CollectorInterface, TaggableCollectorInterface
+class InfluxDbV1 implements CollectorInterface
{
private array $data = [];
@@ -61,9 +61,4 @@ public function flush(): void
$this->data = [];
}
-
- public function setTags(array $tags): void
- {
- $this->tags = $tags;
- }
}
diff --git a/src/Metrics/Collector/NullCollector.php b/src/Metrics/Collector/NullCollector.php
index 5920334..51560f0 100644
--- a/src/Metrics/Collector/NullCollector.php
+++ b/src/Metrics/Collector/NullCollector.php
@@ -9,7 +9,7 @@
namespace Beberlei\Metrics\Collector;
-class NullCollector implements CollectorInterface, GaugeableCollectorInterface, TaggableCollectorInterface
+class NullCollector implements CollectorInterface, GaugeableCollectorInterface
{
public function increment(string $variable, array $tags = []): void
{
@@ -34,8 +34,4 @@ public function gauge(string $variable, string|int $value, array $tags = []): vo
public function flush(): void
{
}
-
- public function setTags(array $tags): void
- {
- }
}
diff --git a/src/Metrics/Collector/Prometheus.php b/src/Metrics/Collector/Prometheus.php
index a2bf557..1478ebd 100644
--- a/src/Metrics/Collector/Prometheus.php
+++ b/src/Metrics/Collector/Prometheus.php
@@ -11,7 +11,7 @@
use Prometheus\CollectorRegistry;
-class Prometheus implements CollectorInterface, GaugeableCollectorInterface, TaggableCollectorInterface
+class Prometheus implements CollectorInterface, GaugeableCollectorInterface
{
private array $counters = [];
private array $gauges = [];
@@ -19,7 +19,7 @@ class Prometheus implements CollectorInterface, GaugeableCollectorInterface, Tag
public function __construct(
private readonly CollectorRegistry $registry,
private readonly string $namespace = '',
- private array $tags = [],
+ private readonly array $tags = [],
) {
}
@@ -76,11 +76,6 @@ public function flush(): void
$this->counters = $this->gauges = [];
}
- public function setTags(array $tags): void
- {
- $this->tags = $tags;
- }
-
private function normalizeVariable(string $variable): string
{
return str_replace(['.', ':'], ['_', '_'], $variable);
diff --git a/src/Metrics/Collector/TaggableCollectorInterface.php b/src/Metrics/Collector/TaggableCollectorInterface.php
deleted file mode 100644
index 31650b5..0000000
--- a/src/Metrics/Collector/TaggableCollectorInterface.php
+++ /dev/null
@@ -1,15 +0,0 @@
-tags = http_build_query($tags, '', ',');
+ $this->tags = \strlen($this->tags) > 0 ? ',' . $this->tags : $this->tags;
}
public function measure(string $variable, int $value, array $tags = []): void
@@ -67,12 +70,6 @@ public function flush(): void
Box::box($this->doFlush(...));
}
- public function setTags(array $tags): void
- {
- $this->tags = http_build_query($tags, '', ',');
- $this->tags = \strlen($this->tags) > 0 ? ',' . $this->tags : $this->tags;
- }
-
private function doFlush(): void
{
$fp = fsockopen('udp://' . $this->host, $this->port, $errno, $errstr, 1.0);
diff --git a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
index 1d8bdd5..c297317 100644
--- a/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
+++ b/src/MetricsBundle/DependencyInjection/BeberleiMetricsExtension.php
@@ -77,76 +77,82 @@ private function createCollector(ContainerBuilder $container, string $name, stri
$definition->addTag(CollectorInterface::class);
$definition->addTag('kernel.reset', ['method' => 'flush']);
- if ($config['tags'] ?? []) {
- $definition->addMethodCall('setTags', [$config['tags']]);
- }
+ $tags = $config['tags'] ?? [];
switch ($type) {
- case 'doctrine_dbal':
- $ref = $config['connection'] ? sprintf('doctrine.dbal.%s_connection', $config['connection']) : 'database_connection';
- $definition->replaceArgument(0, new Reference($ref));
-
- return $definition;
- case 'graphite':
- $definition->replaceArgument(0, $config['host']);
- $definition->replaceArgument(1, $config['port'] ?? 2003);
- $definition->replaceArgument(2, $config['protocol'] ?? 'tcp');
-
- return $definition;
case 'influxdb_v1':
if (!class_exists(\InfluxDB\Client::class)) {
throw new \LogicException('The "influxdb/influxdb-php" package is required to use the "influxdb" collector.');
}
+
if ($config['service']) {
- $definition->replaceArgument(0, new Reference($config['service']));
+ $database = new Reference($config['service']);
} else {
$database = new ChildDefinition('beberlei_metrics.collector_proto.influxdb_v1.database');
- $database->replaceArgument(0, sprintf('influxdb://%s:%s@%s:%s/%s',
+ $database->replaceArgument('$dsn', sprintf('influxdb://%s:%s@%s:%s/%s',
$config['username'],
$config['password'],
$config['host'],
$config['port'] ?? 8086,
$config['database'],
));
- $definition->replaceArgument(0, $database);
}
- return $definition;
- case 'logger':
- case 'null':
- case 'memory':
+ $definition->replaceArgument('$database', $database);
+ $definition->replaceArgument('$tags', $tags);
+
return $definition;
case 'prometheus':
if (!class_exists(CollectorRegistry::class)) {
throw new \LogicException('The "promphp/prometheus_client_php" package is required to use the "prometheus" collector.');
}
+
if ($config['service']) {
- $definition->replaceArgument(0, new Reference($config['service']));
+ $registryId = $config['service'];
} else {
- $database = new ChildDefinition('beberlei_metrics.collector_proto.prometheus.registry');
- $container->setDefinition($id = 'beberlei_metrics.collector.' . $name . '.prometheus.registry', $database);
+ $container->setDefinition(
+ $registryId = 'beberlei_metrics.collector.' . $name . '.prometheus.registry',
+ new ChildDefinition('beberlei_metrics.collector_proto.prometheus.registry'),
+ );
- $definition->replaceArgument(0, new Reference($id));
if (!$container->hasAlias(CollectorRegistry::class)) {
- $container->setAlias(CollectorRegistry::class, $id);
+ $container->setAlias(CollectorRegistry::class, $registryId);
}
}
- $definition->replaceArgument(1, $config['namespace']);
+ $definition->replaceArgument('$registry', new Reference($registryId));
+ $definition->replaceArgument('$namespace', $config['namespace']);
+ $definition->replaceArgument('$tags', $tags);
+
+ return $definition;
+ case 'graphite':
+ $definition->replaceArgument('$host', $config['host']);
+ $definition->replaceArgument('$port', $config['port'] ?? 2003);
+ $definition->replaceArgument('$protocol', $config['protocol'] ?? 'tcp');
return $definition;
case 'statsd':
case 'dogstatsd':
- $definition->replaceArgument(0, $config['host']);
- $definition->replaceArgument(1, $config['port'] ?? 8125);
- $definition->replaceArgument(2, $config['prefix']);
+ $definition->replaceArgument('$host', $config['host']);
+ $definition->replaceArgument('$port', $config['port'] ?? 8125);
+ $definition->replaceArgument('$prefix', $config['prefix']);
return $definition;
case 'telegraf':
- $definition->replaceArgument(0, $config['host']);
- $definition->replaceArgument(1, $config['port'] ?? 8125);
- $definition->replaceArgument(2, $config['prefix']);
+ $definition->replaceArgument('$host', $config['host']);
+ $definition->replaceArgument('$port', $config['port'] ?? 8125);
+ $definition->replaceArgument('$prefix', $config['prefix']);
+ $definition->replaceArgument('$tags', $tags);
+ return $definition;
+ case 'doctrine_dbal':
+ $ref = $config['connection'] ? sprintf('doctrine.dbal.%s_connection', $config['connection']) : 'database_connection';
+ $definition->replaceArgument('$conn', new Reference($ref));
+
+ return $definition;
+ case 'logger':
+ case 'memory':
+ case 'null':
return $definition;
default:
throw new \InvalidArgumentException(sprintf('The type "%s" is not supported.', $type));
diff --git a/src/MetricsBundle/Resources/config/metrics.xml b/src/MetricsBundle/Resources/config/metrics.xml
index fd1f01c..145d5b6 100644
--- a/src/MetricsBundle/Resources/config/metrics.xml
+++ b/src/MetricsBundle/Resources/config/metrics.xml
@@ -7,19 +7,19 @@
-
+ should be defined the extension
-
-
-
+ should be defined the extension
+ should be defined the extension
+ should be defined the extension
-
+ should be defined the extension
-
+ should be defined the extension
@@ -33,23 +33,25 @@
-
-
+ should be defined the extension
+ should be defined the extension
+ should be defined the extension
-
-
-
+ should be defined the extension
+ should be defined the extension
+ should be defined the extension
-
-
-
+ should be defined the extension
+ should be defined the extension
+ should be defined the extension
-
-
-
+ should be defined the extension
+ should be defined the extension
+ should be defined the extension
+ should be defined the extension
diff --git a/tests/Metrics/Collector/InfluxDbV1Test.php b/tests/Metrics/Collector/InfluxDbV1Test.php
index e072c2f..2690f31 100644
--- a/tests/Metrics/Collector/InfluxDbV1Test.php
+++ b/tests/Metrics/Collector/InfluxDbV1Test.php
@@ -19,30 +19,31 @@ class InfluxDbV1Test extends TestCase
{
private MockObject&Database $database;
- private InfluxDbV1 $collector;
-
protected function setUp(): void
{
$this->database = $this->getMockBuilder(Database::class)
->disableOriginalConstructor()
->getMock()
;
- $this->collector = new InfluxDbV1($this->database);
}
public function testCollectIncrement(): void
{
+ $collector = $this->createCollector([]);
+
$this->database->expects($this->once())
->method('writePoints')
->with($this->isType('array'))
;
- $this->collector->increment('series-name');
- $this->collector->flush();
+ $collector->increment('series-name');
+ $collector->flush();
}
public function testCollectDecrement(): void
{
+ $collector = $this->createCollector([]);
+
$this->database->expects($this->once())
->method('writePoints')
->with($this->callback(function ($arg0) {
@@ -59,12 +60,14 @@ public function testCollectDecrement(): void
}))
;
- $this->collector->decrement('series-name');
- $this->collector->flush();
+ $collector->decrement('series-name');
+ $collector->flush();
}
public function testCollectTiming(): void
{
+ $collector = $this->createCollector([]);
+
$this->database->expects($this->once())
->method('writePoints')
->with($this->callback(function ($arg0) {
@@ -81,12 +84,14 @@ public function testCollectTiming(): void
}))
;
- $this->collector->timing('series-name', 47);
- $this->collector->flush();
+ $collector->timing('series-name', 47);
+ $collector->flush();
}
public function testCollectMeasure(): void
{
+ $collector = $this->createCollector([]);
+
$this->database->expects($this->once())
->method('writePoints')
->with($this->callback(function ($arg0) {
@@ -103,13 +108,14 @@ public function testCollectMeasure(): void
}))
;
- $this->collector->measure('series-name', 47);
- $this->collector->flush();
+ $collector->measure('series-name', 47);
+ $collector->flush();
}
public function testCollectMeasureWithTags(): void
{
$expectedTags = ['dc' => 'west', 'node' => 'nemesis101'];
+ $collector = $this->createCollector($expectedTags);
$this->database->expects($this->once())
->method('writePoints')
@@ -127,13 +133,14 @@ public function testCollectMeasureWithTags(): void
}))
;
- $this->collector->setTags($expectedTags);
- $this->collector->measure('series-name', 47);
- $this->collector->flush();
+ $collector->measure('series-name', 47);
+ $collector->flush();
}
public function testCollectMeasureWithTagsMerged(): void
{
+ $collector = $this->createCollector(['dc' => 'west', 'node' => 'nemesis101']);
+
$this->database->expects($this->once())
->method('writePoints')
->with($this->callback(function ($arg0) {
@@ -150,8 +157,12 @@ public function testCollectMeasureWithTagsMerged(): void
}))
;
- $collector = new InfluxDbV1($this->database, ['dc' => 'west', 'node' => 'nemesis101']);
$collector->measure('series-name', 47, ['foo' => 'bar']);
$collector->flush();
}
+
+ private function createCollector(array $tags): InfluxDbV1
+ {
+ return new InfluxDbV1($this->database, $tags);
+ }
}
diff --git a/tests/Metrics/Collector/PrometheusTest.php b/tests/Metrics/Collector/PrometheusTest.php
index c8c1393..2bfe99a 100644
--- a/tests/Metrics/Collector/PrometheusTest.php
+++ b/tests/Metrics/Collector/PrometheusTest.php
@@ -19,13 +19,11 @@ class PrometheusTest extends TestCase
private const TEST_NAMESPACE = 'some_metric_namespace';
private const TEST_VARIABLE_NAME = 'some_variable_name';
- private CollectorRegistry $collectorRegistry;
- private Prometheus $collector;
+ private CollectorRegistry $registry;
protected function setUp(): void
{
- $this->collectorRegistry = new CollectorRegistry(new InMemory(), false);
- $this->collector = new Prometheus($this->collectorRegistry, self::TEST_NAMESPACE);
+ $this->registry = new CollectorRegistry(new InMemory(), false);
}
public function testMeasure(): void
@@ -33,11 +31,11 @@ public function testMeasure(): void
$expectedVariableValue = 123;
$labels = [];
- $this->collector->setTags($labels);
- $this->collector->measure(self::TEST_VARIABLE_NAME, $expectedVariableValue);
- $this->collector->flush();
+ $collector = $this->createCollector($labels);
+ $collector->measure(self::TEST_VARIABLE_NAME, $expectedVariableValue);
+ $collector->flush();
- $data = $this->collectorRegistry->getMetricFamilySamples()[0]->getSamples()[0];
+ $data = $this->registry->getMetricFamilySamples()[0]->getSamples()[0];
$this->assertSame(self::TEST_NAMESPACE . '_' . self::TEST_VARIABLE_NAME, $data->getName());
$this->assertSame((string) $expectedVariableValue, $data->getValue());
$this->assertSame($labels, $data->getLabelValues());
@@ -48,11 +46,11 @@ public function testMeasureWithTags(): void
$expectedVariableValue = 123;
$labels = ['tag1' => 'value1', 'tag2' => 'value2'];
- $this->collector->setTags($labels);
- $this->collector->measure(self::TEST_VARIABLE_NAME, $expectedVariableValue);
- $this->collector->flush();
+ $collector = $this->createCollector($labels);
+ $collector->measure(self::TEST_VARIABLE_NAME, $expectedVariableValue);
+ $collector->flush();
- $data = $this->collectorRegistry->getMetricFamilySamples()[0]->getSamples()[0];
+ $data = $this->registry->getMetricFamilySamples()[0]->getSamples()[0];
$this->assertSame(self::TEST_NAMESPACE . '_' . self::TEST_VARIABLE_NAME, $data->getName());
$this->assertSame((string) $expectedVariableValue, $data->getValue());
$this->assertSame($labels, $data->getLabelValues());
@@ -62,11 +60,11 @@ public function testIncrement(): void
{
$labels = [];
- $this->collector->setTags($labels);
- $this->collector->increment(self::TEST_VARIABLE_NAME);
- $this->collector->flush();
+ $collector = $this->createCollector($labels);
+ $collector->increment(self::TEST_VARIABLE_NAME);
+ $collector->flush();
- $data = $this->collectorRegistry->getMetricFamilySamples()[0]->getSamples()[0];
+ $data = $this->registry->getMetricFamilySamples()[0]->getSamples()[0];
$this->assertSame(self::TEST_NAMESPACE . '_' . self::TEST_VARIABLE_NAME, $data->getName());
$this->assertSame('1', $data->getValue());
$this->assertSame($labels, $data->getLabelValues());
@@ -76,11 +74,11 @@ public function testIncrementWithTags(): void
{
$labels = ['value1', 'value2'];
- $this->collector->setTags($labels);
- $this->collector->increment(self::TEST_VARIABLE_NAME);
- $this->collector->flush();
+ $collector = $this->createCollector($labels);
+ $collector->increment(self::TEST_VARIABLE_NAME);
+ $collector->flush();
- $data = $this->collectorRegistry->getMetricFamilySamples()[0]->getSamples()[0];
+ $data = $this->registry->getMetricFamilySamples()[0]->getSamples()[0];
$this->assertSame(self::TEST_NAMESPACE . '_' . self::TEST_VARIABLE_NAME, $data->getName());
$this->assertSame('1', $data->getValue());
$this->assertSame($labels, $data->getLabelValues());
@@ -90,11 +88,11 @@ public function testDecrement(): void
{
$labels = [];
- $this->collector->setTags($labels);
- $this->collector->decrement(self::TEST_VARIABLE_NAME);
- $this->collector->flush();
+ $collector = $this->createCollector($labels);
+ $collector->decrement(self::TEST_VARIABLE_NAME);
+ $collector->flush();
- $data = $this->collectorRegistry->getMetricFamilySamples()[0]->getSamples()[0];
+ $data = $this->registry->getMetricFamilySamples()[0]->getSamples()[0];
$this->assertSame(self::TEST_NAMESPACE . '_' . self::TEST_VARIABLE_NAME, $data->getName());
$this->assertSame('-1', $data->getValue());
$this->assertSame($labels, $data->getLabelValues());
@@ -104,11 +102,11 @@ public function testDecrementWithTags(): void
{
$labels = ['value1', 'value2'];
- $this->collector->setTags($labels);
- $this->collector->decrement(self::TEST_VARIABLE_NAME);
- $this->collector->flush();
+ $collector = $this->createCollector($labels);
+ $collector->decrement(self::TEST_VARIABLE_NAME);
+ $collector->flush();
- $data = $this->collectorRegistry->getMetricFamilySamples()[0]->getSamples()[0];
+ $data = $this->registry->getMetricFamilySamples()[0]->getSamples()[0];
$this->assertSame(self::TEST_NAMESPACE . '_' . self::TEST_VARIABLE_NAME, $data->getName());
$this->assertSame('-1', $data->getValue());
$this->assertSame($labels, $data->getLabelValues());
@@ -119,11 +117,11 @@ public function testTiming(): void
$expectedVariableValue = 123;
$labels = [];
- $this->collector->setTags($labels);
- $this->collector->timing(self::TEST_VARIABLE_NAME, $expectedVariableValue);
- $this->collector->flush();
+ $collector = $this->createCollector($labels);
+ $collector->timing(self::TEST_VARIABLE_NAME, $expectedVariableValue);
+ $collector->flush();
- $data = $this->collectorRegistry->getMetricFamilySamples()[0]->getSamples()[0];
+ $data = $this->registry->getMetricFamilySamples()[0]->getSamples()[0];
$this->assertSame(self::TEST_NAMESPACE . '_' . self::TEST_VARIABLE_NAME, $data->getName());
$this->assertSame((string) $expectedVariableValue, $data->getValue());
$this->assertSame($labels, $data->getLabelValues());
@@ -134,11 +132,11 @@ public function testTimingWithTags(): void
$expectedVariableValue = 123;
$labels = ['tag1' => 'value1', 'tag2' => 'value2'];
- $this->collector->setTags($labels);
- $this->collector->timing(self::TEST_VARIABLE_NAME, $expectedVariableValue);
- $this->collector->flush();
+ $collector = $this->createCollector($labels);
+ $collector->timing(self::TEST_VARIABLE_NAME, $expectedVariableValue);
+ $collector->flush();
- $data = $this->collectorRegistry->getMetricFamilySamples()[0]->getSamples()[0];
+ $data = $this->registry->getMetricFamilySamples()[0]->getSamples()[0];
$this->assertSame(self::TEST_NAMESPACE . '_' . self::TEST_VARIABLE_NAME, $data->getName());
$this->assertSame((string) $expectedVariableValue, $data->getValue());
$this->assertSame($labels, $data->getLabelValues());
@@ -151,20 +149,26 @@ public function testFlushWhenCallsTwiceWithDifferentData(): void
{
$firstExpectedVariableValue = 123;
- $this->collector->timing(self::TEST_VARIABLE_NAME, $firstExpectedVariableValue);
- $this->collector->flush();
+ $collector = $this->createCollector([]);
+ $collector->timing(self::TEST_VARIABLE_NAME, $firstExpectedVariableValue);
+ $collector->flush();
- $data = $this->collectorRegistry->getMetricFamilySamples()[0]->getSamples()[0];
+ $data = $this->registry->getMetricFamilySamples()[0]->getSamples()[0];
$this->assertSame(self::TEST_NAMESPACE . '_' . self::TEST_VARIABLE_NAME, $data->getName());
$this->assertSame((string) $firstExpectedVariableValue, $data->getValue());
$secondExpectedVariableValue = 321;
- $this->collector->timing(self::TEST_VARIABLE_NAME, $secondExpectedVariableValue);
- $this->collector->flush();
+ $collector->timing(self::TEST_VARIABLE_NAME, $secondExpectedVariableValue);
+ $collector->flush();
- $data = $this->collectorRegistry->getMetricFamilySamples()[0]->getSamples()[0];
+ $data = $this->registry->getMetricFamilySamples()[0]->getSamples()[0];
$this->assertSame(self::TEST_NAMESPACE . '_' . self::TEST_VARIABLE_NAME, $data->getName());
$this->assertSame((string) $secondExpectedVariableValue, $data->getValue());
}
+
+ private function createCollector(array $tags): Prometheus
+ {
+ return new Prometheus($this->registry, self::TEST_NAMESPACE, $tags);
+ }
}
From 4d8365b414817c963f1cc073998d5a8b57afd7c7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 23:36:11 +0100
Subject: [PATCH 30/32] example: add very basic integration
---
composer.json | 8 +-
examples/.castor/docker.php | 2 +-
examples/.castor/qa.php | 2 +-
examples/.env | 11 -
examples/.gitignore | 5 -
examples/README.md | 10 +-
examples/assets/app.js | 10 -
examples/assets/bootstrap.js | 5 -
examples/assets/controllers.json | 15 -
.../assets/controllers/hello_controller.js | 16 -
examples/assets/styles/app.css | 3 -
examples/castor.php | 10 +-
examples/composer.json | 43 +-
examples/composer.lock | 4884 +++++------------
examples/config/bundles.php | 5 +-
examples/config/packages/asset_mapper.yaml | 5 -
examples/config/packages/mailer.yaml | 3 -
examples/config/packages/messenger.yaml | 24 -
examples/config/packages/metrics.yaml | 31 +
examples/config/packages/notifier.yaml | 12 -
examples/config/packages/security.yaml | 39 -
examples/config/packages/translation.yaml | 7 -
examples/config/packages/twig.yaml | 2 +
examples/config/packages/validator.yaml | 11 -
examples/config/routes/security.yaml | 3 -
examples/config/services.yaml | 19 +-
examples/importmap.php | 24 -
.../docker/docker-compose.builder.yml | 1 +
.../infrastructure/docker/docker-compose.yml | 105 +
.../php/frontend/etc/nginx/nginx.conf | 5 -
.../docker/services/prometheus/prometheus.yml | 14 +
.../docker/services/vector/vector.yaml | 62 +
examples/migrations/.gitignore | 0
examples/migrations/Version20240302012809.php | 32 +
examples/phpstan.neon | 2 +-
examples/src/Controller/.gitignore | 0
.../src/Controller/HomepageController.php | 39 +-
.../src/Controller/PrometheusController.php | 34 +
examples/src/Entity/.gitignore | 0
examples/src/Entity/Metrics.php | 36 +
examples/src/Repository/.gitignore | 0
examples/src/Repository/MetricsRepository.php | 30 +
examples/symfony.lock | 109 +-
examples/templates/base.html.twig | 1 -
examples/templates/homepage/index.html.twig | 56 +
examples/translations/.gitignore | 0
46 files changed, 1879 insertions(+), 3856 deletions(-)
delete mode 100644 examples/assets/app.js
delete mode 100644 examples/assets/bootstrap.js
delete mode 100644 examples/assets/controllers.json
delete mode 100644 examples/assets/controllers/hello_controller.js
delete mode 100644 examples/assets/styles/app.css
delete mode 100644 examples/config/packages/asset_mapper.yaml
delete mode 100644 examples/config/packages/mailer.yaml
delete mode 100644 examples/config/packages/messenger.yaml
create mode 100644 examples/config/packages/metrics.yaml
delete mode 100644 examples/config/packages/notifier.yaml
delete mode 100644 examples/config/packages/security.yaml
delete mode 100644 examples/config/packages/translation.yaml
delete mode 100644 examples/config/packages/validator.yaml
delete mode 100644 examples/config/routes/security.yaml
delete mode 100644 examples/importmap.php
create mode 100644 examples/infrastructure/docker/services/prometheus/prometheus.yml
create mode 100644 examples/infrastructure/docker/services/vector/vector.yaml
delete mode 100644 examples/migrations/.gitignore
create mode 100644 examples/migrations/Version20240302012809.php
delete mode 100644 examples/src/Controller/.gitignore
create mode 100644 examples/src/Controller/PrometheusController.php
delete mode 100644 examples/src/Entity/.gitignore
create mode 100644 examples/src/Entity/Metrics.php
delete mode 100644 examples/src/Repository/.gitignore
create mode 100644 examples/src/Repository/MetricsRepository.php
create mode 100644 examples/templates/homepage/index.html.twig
delete mode 100644 examples/translations/.gitignore
diff --git a/composer.json b/composer.json
index 09097d2..7ff4fbe 100644
--- a/composer.json
+++ b/composer.json
@@ -22,14 +22,14 @@
"php": ">=8.1",
"doctrine/dbal": "^2.0",
"influxdb/influxdb-php": "^1.15",
- "jimdo/prometheus_client_php": "^0.5.1",
+ "promphp/prometheus_client_php": "^2",
"symfony/framework-bundle": "^5.4 || ^6.4 || ^7.0",
"symfony/phpunit-bridge": "^6.4.4 || ^7.0"
},
"conflict": {
"doctrine/dbal": "<2",
"influxdb/influxdb-php": "<1.15",
- "jimdo/prometheus_client_php": "<0.5.1",
+ "promphp/prometheus_client_php": "<2",
"symfony/framework-bundle": "<5.4"
},
"autoload": {
@@ -44,8 +44,10 @@
}
},
"suggest": {
+ "doctrine/dbal": "For Doctrine DBAL integration",
"influxdb/influxdb-php": "For InfluxDB integration",
- "jimdo/prometheus_client_php": "For Prometheus integration"
+ "symfony/framework-bundle": "For Symfony integration",
+ "promphp/prometheus_client_php": "For Prometheus integration"
},
"config": {
"sort-packages": true
diff --git a/examples/.castor/docker.php b/examples/.castor/docker.php
index 3640ec7..99938d1 100644
--- a/examples/.castor/docker.php
+++ b/examples/.castor/docker.php
@@ -304,7 +304,7 @@ function create_default_context(): Context
// If the directory does not exist, we create it. Otherwise, docker
// will do, as root, and the user will not be able to write in it.
if (!is_dir($composerCacheDir)) {
- mkdir($composerCacheDir, 0777, true);
+ mkdir($composerCacheDir, 0o777, true);
}
}
diff --git a/examples/.castor/qa.php b/examples/.castor/qa.php
index 32d5202..b068c4d 100644
--- a/examples/.castor/qa.php
+++ b/examples/.castor/qa.php
@@ -16,7 +16,7 @@ function all(): int
$phpstan = phpstan();
// $phpunit = phpunit();
- return max($cs, $phpstan/*, $phpunit*/);
+ return max($cs, $phpstan/* , $phpunit */);
}
#[AsTask(description: 'Installs tooling')]
diff --git a/examples/.env b/examples/.env
index 1bb8dab..a4f9456 100644
--- a/examples/.env
+++ b/examples/.env
@@ -28,14 +28,3 @@ APP_SECRET=acbff843d79416cbb1432679dc4f3ead
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4"
DATABASE_URL="postgresql://app:app@postgres:5432/app?serverVersion=16&charset=utf8"
###< doctrine/doctrine-bundle ###
-
-###> symfony/messenger ###
-# Choose one of the transports below
-# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages
-# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages
-MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0
-###< symfony/messenger ###
-
-###> symfony/mailer ###
-# MAILER_DSN=null://null
-###< symfony/mailer ###
diff --git a/examples/.gitignore b/examples/.gitignore
index 2ea9c84..1a2a239 100644
--- a/examples/.gitignore
+++ b/examples/.gitignore
@@ -23,8 +23,3 @@
.phpunit.result.cache
/phpunit.xml
###< symfony/phpunit-bridge ###
-
-###> symfony/asset-mapper ###
-/public/assets/
-/assets/vendor/
-###< symfony/asset-mapper ###
diff --git a/examples/README.md b/examples/README.md
index 64af536..5749442 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -1,4 +1,8 @@
-# My project
+# Symfony demo application
+
+This application use
+[jolicode/docker-starter](https://github.com/jolicode/docker-starter) to provide
+a local development environment.
## Running the application locally
@@ -7,8 +11,6 @@
A Docker environment is provided and requires you to have these tools available:
* Docker
- * Bash
- * PHP >= 8.1
* [Castor](https://github.com/jolicode/castor#installation)
#### Castor
@@ -50,7 +52,7 @@ This IP is probably `127.0.0.1` unless you run Docker in a special VM (like dock
> The router binds port 80 and 443, that's why it will work with `127.0.0.1`
```
-echo '127.0.0.1 app.test www.app.test' | sudo tee -a /etc/hosts
+echo '127.0.0.1 symfony-metrics.test grafana.symfony-metrics.test' | sudo tee -a /etc/hosts
```
### Starting the stack
diff --git a/examples/assets/app.js b/examples/assets/app.js
deleted file mode 100644
index 8725cc5..0000000
--- a/examples/assets/app.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import './bootstrap.js';
-/*
- * Welcome to your app's main JavaScript file!
- *
- * This file will be included onto the page via the importmap() Twig function,
- * which should already be in your base.html.twig.
- */
-import './styles/app.css';
-
-console.log('This log comes from assets/app.js - welcome to AssetMapper! 🎉');
diff --git a/examples/assets/bootstrap.js b/examples/assets/bootstrap.js
deleted file mode 100644
index d4e50c9..0000000
--- a/examples/assets/bootstrap.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import { startStimulusApp } from '@symfony/stimulus-bundle';
-
-const app = startStimulusApp();
-// register any custom, 3rd party controllers here
-// app.register('some_controller_name', SomeImportedController);
diff --git a/examples/assets/controllers.json b/examples/assets/controllers.json
deleted file mode 100644
index 29ea244..0000000
--- a/examples/assets/controllers.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "controllers": {
- "@symfony/ux-turbo": {
- "turbo-core": {
- "enabled": true,
- "fetch": "eager"
- },
- "mercure-turbo-stream": {
- "enabled": false,
- "fetch": "eager"
- }
- }
- },
- "entrypoints": []
-}
diff --git a/examples/assets/controllers/hello_controller.js b/examples/assets/controllers/hello_controller.js
deleted file mode 100644
index e847027..0000000
--- a/examples/assets/controllers/hello_controller.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import { Controller } from '@hotwired/stimulus';
-
-/*
- * This is an example Stimulus controller!
- *
- * Any element with a data-controller="hello" attribute will cause
- * this controller to be executed. The name "hello" comes from the filename:
- * hello_controller.js -> "hello"
- *
- * Delete this file or adapt it for your use!
- */
-export default class extends Controller {
- connect() {
- this.element.textContent = 'Hello Stimulus! Edit me in assets/controllers/hello_controller.js';
- }
-}
diff --git a/examples/assets/styles/app.css b/examples/assets/styles/app.css
deleted file mode 100644
index dd6181a..0000000
--- a/examples/assets/styles/app.css
+++ /dev/null
@@ -1,3 +0,0 @@
-body {
- background-color: skyblue;
-}
diff --git a/examples/castor.php b/examples/castor.php
index dbe4049..6ac71e5 100644
--- a/examples/castor.php
+++ b/examples/castor.php
@@ -30,13 +30,10 @@ function create_default_variables(): array
return [
'project_name' => 'symfony-metrics',
'root_domain' => 'symfony-metrics.test',
- 'extra_domains' => [
- 'grafana.symfony-metrics.test',
- ],
];
}
-#[AsTask(description: 'Builds and starts the infrastructure, then install the application (composer, yarn, ...)')]
+#[AsTask(description: 'Builds and starts the infrastructure, then install the application (composer, ...)')]
function start(): void
{
io()->title('Starting the stack');
@@ -56,7 +53,7 @@ function start(): void
about();
}
-#[AsTask(description: 'Installs the application (composer, yarn, ...)', namespace: 'app', aliases: ['install'])]
+#[AsTask(description: 'Installs the application (composer, ...)', namespace: 'app', aliases: ['install'])]
function install(): void
{
io()->title('Installing the application');
@@ -64,9 +61,6 @@ function install(): void
io()->section('Installing PHP dependencies');
docker_compose_run('composer install -n --prefer-dist --optimize-autoloader');
- io()->section('Installing importmap');
- docker_compose_run('bin/console importmap:install');
-
qa\install();
}
diff --git a/examples/composer.json b/examples/composer.json
index 8d11ee5..1dd83d7 100644
--- a/examples/composer.json
+++ b/examples/composer.json
@@ -3,47 +3,33 @@
"license": "proprietary",
"minimum-stability": "stable",
"prefer-stable": true,
+ "repositories": [
+ {
+ "type": "path",
+ "url": "/metrics"
+ }
+ ],
"require": {
- "php": ">=8.2",
+ "php": ">=8.3",
"ext-ctype": "*",
"ext-iconv": "*",
+ "beberlei/metrics": "*@dev",
"doctrine/dbal": "^3",
"doctrine/doctrine-bundle": "^2.11",
"doctrine/doctrine-migrations-bundle": "^3.3",
"doctrine/orm": "^3.0",
+ "influxdb/influxdb-php": "^1.15",
"phpdocumentor/reflection-docblock": "^5.3",
"phpstan/phpdoc-parser": "^1.26",
- "symfony/asset": "7.0.*",
- "symfony/asset-mapper": "7.0.*",
+ "promphp/prometheus_client_php": "^2.10",
"symfony/console": "7.0.*",
- "symfony/doctrine-messenger": "7.0.*",
"symfony/dotenv": "7.0.*",
- "symfony/expression-language": "7.0.*",
"symfony/flex": "^2",
- "symfony/form": "7.0.*",
"symfony/framework-bundle": "7.0.*",
- "symfony/http-client": "7.0.*",
- "symfony/intl": "7.0.*",
- "symfony/mailer": "7.0.*",
- "symfony/mime": "7.0.*",
"symfony/monolog-bundle": "^3.0",
- "symfony/notifier": "7.0.*",
- "symfony/process": "7.0.*",
- "symfony/property-access": "7.0.*",
- "symfony/property-info": "7.0.*",
"symfony/runtime": "7.0.*",
- "symfony/security-bundle": "7.0.*",
- "symfony/serializer": "7.0.*",
- "symfony/stimulus-bundle": "^2.16",
- "symfony/string": "7.0.*",
- "symfony/translation": "7.0.*",
- "symfony/twig-bundle": "7.0.*",
- "symfony/ux-turbo": "^2.16",
- "symfony/validator": "7.0.*",
- "symfony/web-link": "7.0.*",
- "symfony/yaml": "7.0.*",
- "twig/extra-bundle": "^2.12|^3.0",
- "twig/twig": "^2.12|^3.0"
+ "symfony/uid": "7.0.*",
+ "symfony/yaml": "7.0.*"
},
"config": {
"allow-plugins": {
@@ -76,8 +62,7 @@
"scripts": {
"auto-scripts": {
"cache:clear": "symfony-cmd",
- "assets:install %PUBLIC_DIR%": "symfony-cmd",
- "importmap:install": "symfony-cmd"
+ "assets:install %PUBLIC_DIR%": "symfony-cmd"
},
"post-install-cmd": [
"@auto-scripts"
@@ -97,8 +82,6 @@
},
"require-dev": {
"phpunit/phpunit": "^9.5",
- "symfony/browser-kit": "7.0.*",
- "symfony/css-selector": "7.0.*",
"symfony/debug-bundle": "7.0.*",
"symfony/maker-bundle": "^1.0",
"symfony/phpunit-bridge": "^7.0",
diff --git a/examples/composer.lock b/examples/composer.lock
index 7e98a61..be4b0da 100644
--- a/examples/composer.lock
+++ b/examples/composer.lock
@@ -4,88 +4,74 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "a081757e3f87e400b4b604ce219bee18",
+ "content-hash": "8d17d049d9055c18f7e29bb59065459f",
"packages": [
{
- "name": "composer/semver",
- "version": "3.4.0",
- "source": {
- "type": "git",
- "url": "https://github.com/composer/semver.git",
- "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32"
- },
+ "name": "beberlei/metrics",
+ "version": "dev-massive-code-grooming",
"dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32",
- "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32",
- "shasum": ""
+ "type": "path",
+ "url": "/metrics",
+ "reference": "e27a066968ab3726df32364b8afe679562672783"
},
"require": {
- "php": "^5.3.2 || ^7.0 || ^8.0"
+ "psr/log": "^1.0 || ^2.0 || ^3.0"
+ },
+ "conflict": {
+ "doctrine/dbal": "<2",
+ "influxdb/influxdb-php": "<1.15",
+ "promphp/prometheus_client_php": "<2",
+ "symfony/framework-bundle": "<5.4"
},
"require-dev": {
- "phpstan/phpstan": "^1.4",
- "symfony/phpunit-bridge": "^4.2 || ^5"
+ "doctrine/dbal": "^2.0",
+ "influxdb/influxdb-php": "^1.15",
+ "php": ">=8.1",
+ "promphp/prometheus_client_php": "^2",
+ "symfony/framework-bundle": "^5.4 || ^6.4 || ^7.0",
+ "symfony/phpunit-bridge": "^6.4.4 || ^7.0"
+ },
+ "suggest": {
+ "doctrine/dbal": "For Doctrine DBAL integration",
+ "influxdb/influxdb-php": "For InfluxDB integration",
+ "promphp/prometheus_client_php": "For Prometheus integration",
+ "symfony/framework-bundle": "For Symfony integration"
},
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "3.x-dev"
+ "autoload": {
+ "psr-4": {
+ "Beberlei\\Metrics\\": "src/Metrics",
+ "Beberlei\\Bundle\\MetricsBundle\\": "src/MetricsBundle"
}
},
- "autoload": {
+ "autoload-dev": {
"psr-4": {
- "Composer\\Semver\\": "src"
+ "Beberlei\\Bundle\\MetricsBundle\\": "src/MetricsBundle"
}
},
- "notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
- "name": "Nils Adermann",
- "email": "naderman@naderman.de",
- "homepage": "http://www.naderman.de"
- },
- {
- "name": "Jordi Boggiano",
- "email": "j.boggiano@seld.be",
- "homepage": "http://seld.be"
+ "name": "Benjamin Eberlei",
+ "email": "kontakt@beberlei.de",
+ "role": "Project Founder"
},
{
- "name": "Rob Bast",
- "email": "rob.bast@gmail.com",
- "homepage": "http://robbast.nl"
+ "name": "Grégoire Pineau",
+ "email": "lyrixx@lyrixx.info",
+ "role": "Lead Developer"
}
],
- "description": "Semver library that offers utilities, version constraint parsing and validation.",
+ "description": "Simple library to talk to metrics collector services.",
"keywords": [
- "semantic",
- "semver",
- "validation",
- "versioning"
- ],
- "support": {
- "irc": "ircs://irc.libera.chat:6697/composer",
- "issues": "https://github.com/composer/semver/issues",
- "source": "https://github.com/composer/semver/tree/3.4.0"
- },
- "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"
- }
+ "logging",
+ "metrics"
],
- "time": "2023-08-31T09:50:34+00:00"
+ "transport-options": {
+ "relative": false
+ }
},
{
"name": "doctrine/cache",
@@ -1306,40 +1292,256 @@
"time": "2023-08-16T21:49:04+00:00"
},
{
- "name": "egulias/email-validator",
- "version": "4.0.2",
+ "name": "guzzlehttp/guzzle",
+ "version": "7.8.1",
"source": {
"type": "git",
- "url": "https://github.com/egulias/EmailValidator.git",
- "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e"
+ "url": "https://github.com/guzzle/guzzle.git",
+ "reference": "41042bc7ab002487b876a0683fc8dce04ddce104"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ebaaf5be6c0286928352e054f2d5125608e5405e",
- "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e",
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104",
+ "reference": "41042bc7ab002487b876a0683fc8dce04ddce104",
"shasum": ""
},
"require": {
- "doctrine/lexer": "^2.0 || ^3.0",
- "php": ">=8.1",
- "symfony/polyfill-intl-idn": "^1.26"
+ "ext-json": "*",
+ "guzzlehttp/promises": "^1.5.3 || ^2.0.1",
+ "guzzlehttp/psr7": "^1.9.1 || ^2.5.1",
+ "php": "^7.2.5 || ^8.0",
+ "psr/http-client": "^1.0",
+ "symfony/deprecation-contracts": "^2.2 || ^3.0"
+ },
+ "provide": {
+ "psr/http-client-implementation": "1.0"
},
"require-dev": {
- "phpunit/phpunit": "^10.2",
- "vimeo/psalm": "^5.12"
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "ext-curl": "*",
+ "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999",
+ "php-http/message-factory": "^1.1",
+ "phpunit/phpunit": "^8.5.36 || ^9.6.15",
+ "psr/log": "^1.1 || ^2.0 || ^3.0"
},
"suggest": {
- "ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation"
+ "ext-curl": "Required for CURL handler support",
+ "ext-intl": "Required for Internationalized Domain Name (IDN) support",
+ "psr/log": "Required for using the Log middleware"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-master": "4.0.x-dev"
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/functions_include.php"
+ ],
+ "psr-4": {
+ "GuzzleHttp\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Jeremy Lindblom",
+ "email": "jeremeamia@gmail.com",
+ "homepage": "https://github.com/jeremeamia"
+ },
+ {
+ "name": "George Mponos",
+ "email": "gmponos@gmail.com",
+ "homepage": "https://github.com/gmponos"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://github.com/sagikazarmark"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "Guzzle is a PHP HTTP client library",
+ "keywords": [
+ "client",
+ "curl",
+ "framework",
+ "http",
+ "http client",
+ "psr-18",
+ "psr-7",
+ "rest",
+ "web service"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/guzzle/issues",
+ "source": "https://github.com/guzzle/guzzle/tree/7.8.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-12-03T20:35:24+00:00"
+ },
+ {
+ "name": "guzzlehttp/promises",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/promises.git",
+ "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223",
+ "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2.5 || ^8.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "phpunit/phpunit": "^8.5.36 || ^9.6.15"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "GuzzleHttp\\Promise\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ }
+ ],
+ "description": "Guzzle promises library",
+ "keywords": [
+ "promise"
+ ],
+ "support": {
+ "issues": "https://github.com/guzzle/promises/issues",
+ "source": "https://github.com/guzzle/promises/tree/2.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-12-03T20:19:20+00:00"
+ },
+ {
+ "name": "guzzlehttp/psr7",
+ "version": "2.6.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/guzzle/psr7.git",
+ "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221",
+ "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2.5 || ^8.0",
+ "psr/http-factory": "^1.0",
+ "psr/http-message": "^1.1 || ^2.0",
+ "ralouphie/getallheaders": "^3.0"
+ },
+ "provide": {
+ "psr/http-factory-implementation": "1.0",
+ "psr/http-message-implementation": "1.0"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.8.2",
+ "http-interop/http-factory-tests": "^0.9",
+ "phpunit/phpunit": "^8.5.36 || ^9.6.15"
+ },
+ "suggest": {
+ "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": false
}
},
"autoload": {
"psr-4": {
- "Egulias\\EmailValidator\\": "src"
+ "GuzzleHttp\\Psr7\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -1348,29 +1550,138 @@
],
"authors": [
{
- "name": "Eduardo Gulias Davis"
+ "name": "Graham Campbell",
+ "email": "hello@gjcampbell.co.uk",
+ "homepage": "https://github.com/GrahamCampbell"
+ },
+ {
+ "name": "Michael Dowling",
+ "email": "mtdowling@gmail.com",
+ "homepage": "https://github.com/mtdowling"
+ },
+ {
+ "name": "George Mponos",
+ "email": "gmponos@gmail.com",
+ "homepage": "https://github.com/gmponos"
+ },
+ {
+ "name": "Tobias Nyholm",
+ "email": "tobias.nyholm@gmail.com",
+ "homepage": "https://github.com/Nyholm"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://github.com/sagikazarmark"
+ },
+ {
+ "name": "Tobias Schultze",
+ "email": "webmaster@tubo-world.de",
+ "homepage": "https://github.com/Tobion"
+ },
+ {
+ "name": "Márk Sági-Kazár",
+ "email": "mark.sagikazar@gmail.com",
+ "homepage": "https://sagikazarmark.hu"
}
],
- "description": "A library for validating emails against several RFCs",
- "homepage": "https://github.com/egulias/EmailValidator",
+ "description": "PSR-7 message implementation that also provides common utility methods",
"keywords": [
- "email",
- "emailvalidation",
- "emailvalidator",
- "validation",
- "validator"
+ "http",
+ "message",
+ "psr-7",
+ "request",
+ "response",
+ "stream",
+ "uri",
+ "url"
],
"support": {
- "issues": "https://github.com/egulias/EmailValidator/issues",
- "source": "https://github.com/egulias/EmailValidator/tree/4.0.2"
+ "issues": "https://github.com/guzzle/psr7/issues",
+ "source": "https://github.com/guzzle/psr7/tree/2.6.2"
},
"funding": [
{
- "url": "https://github.com/egulias",
+ "url": "https://github.com/GrahamCampbell",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/Nyholm",
"type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-12-03T20:05:35+00:00"
+ },
+ {
+ "name": "influxdb/influxdb-php",
+ "version": "1.15.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/influxdata/influxdb-php.git",
+ "reference": "d6e59f4f04ab9107574fda69c2cbe36671253d03"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/influxdata/influxdb-php/zipball/d6e59f4f04ab9107574fda69c2cbe36671253d03",
+ "reference": "d6e59f4f04ab9107574fda69c2cbe36671253d03",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/guzzle": "^6.0|^7.0",
+ "php": "^5.5 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "dms/phpunit-arraysubset-asserts": "^0.2.1",
+ "phpunit/phpunit": "^9.5"
+ },
+ "suggest": {
+ "ext-curl": "Curl extension, needed for Curl driver",
+ "stefanotorresi/influxdb-php-async": "An asyncronous client for InfluxDB, implemented via ReactPHP."
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "InfluxDB\\": "src/InfluxDB"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Stephen Hoogendijk",
+ "email": "stephen@tca0.nl"
+ },
+ {
+ "name": "Daniel Martinez",
+ "email": "danimartcas@hotmail.com"
+ },
+ {
+ "name": "Gianluca Arbezzano",
+ "email": "gianarb92@gmail.com"
}
],
- "time": "2023-10-06T06:47:41+00:00"
+ "description": "InfluxDB client library for PHP",
+ "keywords": [
+ "client",
+ "influxdata",
+ "influxdb",
+ "influxdb class",
+ "influxdb client",
+ "influxdb library",
+ "time series"
+ ],
+ "support": {
+ "issues": "https://github.com/influxdata/influxdb-php/issues",
+ "source": "https://github.com/influxdata/influxdb-php/tree/1.15.2"
+ },
+ "abandoned": true,
+ "time": "2020-12-26T17:45:17+00:00"
},
{
"name": "monolog/monolog",
@@ -1688,6 +1999,73 @@
},
"time": "2024-02-23T16:05:55+00:00"
},
+ {
+ "name": "promphp/prometheus_client_php",
+ "version": "v2.10.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PromPHP/prometheus_client_php.git",
+ "reference": "a09ea80ec1ec26dd1d4853e9af2a811e898dbfeb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PromPHP/prometheus_client_php/zipball/a09ea80ec1ec26dd1d4853e9af2a811e898dbfeb",
+ "reference": "a09ea80ec1ec26dd1d4853e9af2a811e898dbfeb",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "php": "^7.2|^8.0"
+ },
+ "replace": {
+ "endclothing/prometheus_client_php": "*",
+ "jimdo/prometheus_client_php": "*",
+ "lkaemmerling/prometheus_client_php": "*"
+ },
+ "require-dev": {
+ "guzzlehttp/guzzle": "^6.3|^7.0",
+ "phpstan/extension-installer": "^1.0",
+ "phpstan/phpstan": "^1.5.4",
+ "phpstan/phpstan-phpunit": "^1.1.0",
+ "phpstan/phpstan-strict-rules": "^1.1.0",
+ "phpunit/phpunit": "^9.4",
+ "squizlabs/php_codesniffer": "^3.6",
+ "symfony/polyfill-apcu": "^1.6"
+ },
+ "suggest": {
+ "ext-apc": "Required if using APCu.",
+ "ext-redis": "Required if using Redis.",
+ "promphp/prometheus_push_gateway_php": "An easy client for using Prometheus PushGateway.",
+ "symfony/polyfill-apcu": "Required if you use APCu on PHP8.0+"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Prometheus\\": "src/Prometheus/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Lukas Kämmerling",
+ "email": "kontakt@lukas-kaemmerling.de"
+ }
+ ],
+ "description": "Prometheus instrumentation library for PHP applications.",
+ "support": {
+ "issues": "https://github.com/PromPHP/prometheus_client_php/issues",
+ "source": "https://github.com/PromPHP/prometheus_client_php/tree/v2.10.0"
+ },
+ "time": "2024-02-01T13:28:34+00:00"
+ },
{
"name": "psr/cache",
"version": "3.0.0",
@@ -1737,54 +2115,6 @@
},
"time": "2021-02-03T23:26:27+00:00"
},
- {
- "name": "psr/clock",
- "version": "1.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/php-fig/clock.git",
- "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d",
- "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d",
- "shasum": ""
- },
- "require": {
- "php": "^7.0 || ^8.0"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Psr\\Clock\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "PHP-FIG",
- "homepage": "https://www.php-fig.org/"
- }
- ],
- "description": "Common interface for reading the clock.",
- "homepage": "https://github.com/php-fig/clock",
- "keywords": [
- "clock",
- "now",
- "psr",
- "psr-20",
- "time"
- ],
- "support": {
- "issues": "https://github.com/php-fig/clock/issues",
- "source": "https://github.com/php-fig/clock/tree/1.0.0"
- },
- "time": "2022-11-25T14:36:26+00:00"
- },
{
"name": "psr/container",
"version": "2.0.2",
@@ -1889,34 +2219,32 @@
"time": "2019-01-08T18:20:26+00:00"
},
{
- "name": "psr/link",
- "version": "2.0.1",
+ "name": "psr/http-client",
+ "version": "1.0.3",
"source": {
"type": "git",
- "url": "https://github.com/php-fig/link.git",
- "reference": "84b159194ecfd7eaa472280213976e96415433f7"
+ "url": "https://github.com/php-fig/http-client.git",
+ "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/link/zipball/84b159194ecfd7eaa472280213976e96415433f7",
- "reference": "84b159194ecfd7eaa472280213976e96415433f7",
+ "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
+ "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
"shasum": ""
},
"require": {
- "php": ">=8.0.0"
- },
- "suggest": {
- "fig/link-util": "Provides some useful PSR-13 utilities"
+ "php": "^7.0 || ^8.0",
+ "psr/http-message": "^1.0 || ^2.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.0.x-dev"
+ "dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
- "Psr\\Link\\": "src/"
+ "Psr\\Http\\Client\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -1926,50 +2254,49 @@
"authors": [
{
"name": "PHP-FIG",
- "homepage": "http://www.php-fig.org/"
+ "homepage": "https://www.php-fig.org/"
}
],
- "description": "Common interfaces for HTTP links",
- "homepage": "https://github.com/php-fig/link",
+ "description": "Common interface for HTTP clients",
+ "homepage": "https://github.com/php-fig/http-client",
"keywords": [
"http",
- "http-link",
- "link",
+ "http-client",
"psr",
- "psr-13",
- "rest"
+ "psr-18"
],
"support": {
- "source": "https://github.com/php-fig/link/tree/2.0.1"
+ "source": "https://github.com/php-fig/http-client"
},
- "time": "2021-03-11T23:00:27+00:00"
+ "time": "2023-09-23T14:17:50+00:00"
},
{
- "name": "psr/log",
- "version": "3.0.0",
+ "name": "psr/http-factory",
+ "version": "1.0.2",
"source": {
"type": "git",
- "url": "https://github.com/php-fig/log.git",
- "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
+ "url": "https://github.com/php-fig/http-factory.git",
+ "reference": "e616d01114759c4c489f93b099585439f795fe35"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
- "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
+ "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35",
+ "reference": "e616d01114759c4c489f93b099585439f795fe35",
"shasum": ""
},
"require": {
- "php": ">=8.0.0"
+ "php": ">=7.0.0",
+ "psr/http-message": "^1.0 || ^2.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.x-dev"
+ "dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
- "Psr\\Log\\": "src"
+ "Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -1982,51 +2309,49 @@
"homepage": "https://www.php-fig.org/"
}
],
- "description": "Common interface for logging libraries",
- "homepage": "https://github.com/php-fig/log",
+ "description": "Common interfaces for PSR-7 HTTP message factories",
"keywords": [
- "log",
+ "factory",
+ "http",
+ "message",
"psr",
- "psr-3"
+ "psr-17",
+ "psr-7",
+ "request",
+ "response"
],
"support": {
- "source": "https://github.com/php-fig/log/tree/3.0.0"
+ "source": "https://github.com/php-fig/http-factory/tree/1.0.2"
},
- "time": "2021-07-14T16:46:02+00:00"
+ "time": "2023-04-10T20:10:41+00:00"
},
{
- "name": "symfony/asset",
- "version": "v7.0.3",
+ "name": "psr/http-message",
+ "version": "2.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/asset.git",
- "reference": "3ae493792fc17cc31b84e231f30f2d154575f171"
+ "url": "https://github.com/php-fig/http-message.git",
+ "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/asset/zipball/3ae493792fc17cc31b84e231f30f2d154575f171",
- "reference": "3ae493792fc17cc31b84e231f30f2d154575f171",
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
+ "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
"shasum": ""
},
"require": {
- "php": ">=8.2"
- },
- "conflict": {
- "symfony/http-foundation": "<6.4"
- },
- "require-dev": {
- "symfony/http-client": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0"
+ "php": "^7.2 || ^8.0"
},
"type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
"autoload": {
"psr-4": {
- "Symfony\\Component\\Asset\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
+ "Psr\\Http\\Message\\": "src/"
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -2034,76 +2359,100 @@
],
"authors": [
{
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
}
],
- "description": "Manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files",
- "homepage": "https://symfony.com",
+ "description": "Common interface for HTTP messages",
+ "homepage": "https://github.com/php-fig/http-message",
+ "keywords": [
+ "http",
+ "http-message",
+ "psr",
+ "psr-7",
+ "request",
+ "response"
+ ],
"support": {
- "source": "https://github.com/symfony/asset/tree/v7.0.3"
+ "source": "https://github.com/php-fig/http-message/tree/2.0"
},
- "funding": [
- {
- "url": "https://symfony.com/sponsor",
- "type": "custom"
- },
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
+ "time": "2023-04-04T09:54:51+00:00"
+ },
+ {
+ "name": "psr/log",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001",
+ "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
{
- "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
- "type": "tidelift"
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
}
],
- "time": "2024-01-23T15:02:46+00:00"
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/log/tree/3.0.0"
+ },
+ "time": "2021-07-14T16:46:02+00:00"
},
{
- "name": "symfony/asset-mapper",
- "version": "v7.0.4",
+ "name": "ralouphie/getallheaders",
+ "version": "3.0.3",
"source": {
"type": "git",
- "url": "https://github.com/symfony/asset-mapper.git",
- "reference": "7cd421551f53849f641a1a3499392ed5c81598a8"
+ "url": "https://github.com/ralouphie/getallheaders.git",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/asset-mapper/zipball/7cd421551f53849f641a1a3499392ed5c81598a8",
- "reference": "7cd421551f53849f641a1a3499392ed5c81598a8",
+ "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
+ "reference": "120b605dfeb996808c31b6477290a714d356e822",
"shasum": ""
},
"require": {
- "composer/semver": "^3.0",
- "php": ">=8.2",
- "symfony/filesystem": "^6.4|^7.0",
- "symfony/http-client": "^6.4|^7.0"
- },
- "conflict": {
- "symfony/framework-bundle": "<6.4"
+ "php": ">=5.6"
},
"require-dev": {
- "symfony/asset": "^6.4|^7.0",
- "symfony/browser-kit": "^6.4|^7.0",
- "symfony/console": "^6.4|^7.0",
- "symfony/event-dispatcher-contracts": "^3.0",
- "symfony/finder": "^6.4|^7.0",
- "symfony/framework-bundle": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/web-link": "^6.4|^7.0"
+ "php-coveralls/php-coveralls": "^2.1",
+ "phpunit/phpunit": "^5 || ^6.5"
},
"type": "library",
"autoload": {
- "psr-4": {
- "Symfony\\Component\\AssetMapper\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
+ "files": [
+ "src/getallheaders.php"
]
},
"notification-url": "https://packagist.org/downloads/",
@@ -2112,34 +2461,16 @@
],
"authors": [
{
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
+ "name": "Ralph Khattar",
+ "email": "ralph.khattar@gmail.com"
}
],
- "description": "Maps directories of assets & makes them available in a public directory with versioned filenames.",
- "homepage": "https://symfony.com",
+ "description": "A polyfill for getallheaders.",
"support": {
- "source": "https://github.com/symfony/asset-mapper/tree/v7.0.4"
+ "issues": "https://github.com/ralouphie/getallheaders/issues",
+ "source": "https://github.com/ralouphie/getallheaders/tree/develop"
},
- "funding": [
- {
- "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": "2024-02-22T20:27:20+00:00"
+ "time": "2019-03-08T08:55:37+00:00"
},
{
"name": "symfony/cache",
@@ -2313,80 +2644,6 @@
],
"time": "2023-09-25T12:52:38+00:00"
},
- {
- "name": "symfony/clock",
- "version": "v7.0.3",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/clock.git",
- "reference": "1c680e565dc0044d8ed3baeb57835fcacd9c6aed"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/clock/zipball/1c680e565dc0044d8ed3baeb57835fcacd9c6aed",
- "reference": "1c680e565dc0044d8ed3baeb57835fcacd9c6aed",
- "shasum": ""
- },
- "require": {
- "php": ">=8.2",
- "psr/clock": "^1.0",
- "symfony/polyfill-php83": "^1.28"
- },
- "provide": {
- "psr/clock-implementation": "1.0"
- },
- "type": "library",
- "autoload": {
- "files": [
- "Resources/now.php"
- ],
- "psr-4": {
- "Symfony\\Component\\Clock\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "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": "Decouples applications from the system clock",
- "homepage": "https://symfony.com",
- "keywords": [
- "clock",
- "psr20",
- "time"
- ],
- "support": {
- "source": "https://github.com/symfony/clock/tree/v7.0.3"
- },
- "funding": [
- {
- "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": "2024-01-23T15:02:46+00:00"
- },
{
"name": "symfony/config",
"version": "v7.0.4",
@@ -2809,93 +3066,21 @@
"time": "2024-02-04T16:21:40+00:00"
},
{
- "name": "symfony/doctrine-messenger",
+ "name": "symfony/dotenv",
"version": "v7.0.4",
"source": {
"type": "git",
- "url": "https://github.com/symfony/doctrine-messenger.git",
- "reference": "5a9ebba1b0be17af7b1e6b6433ad2cb6e35e97ca"
+ "url": "https://github.com/symfony/dotenv.git",
+ "reference": "8017ea2f0ff4fbda6ae1bf3f5409d5ecff982067"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/doctrine-messenger/zipball/5a9ebba1b0be17af7b1e6b6433ad2cb6e35e97ca",
- "reference": "5a9ebba1b0be17af7b1e6b6433ad2cb6e35e97ca",
+ "url": "https://api.github.com/repos/symfony/dotenv/zipball/8017ea2f0ff4fbda6ae1bf3f5409d5ecff982067",
+ "reference": "8017ea2f0ff4fbda6ae1bf3f5409d5ecff982067",
"shasum": ""
},
"require": {
- "doctrine/dbal": "^3.6|^4",
- "php": ">=8.2",
- "symfony/messenger": "^6.4|^7.0",
- "symfony/service-contracts": "^2.5|^3"
- },
- "conflict": {
- "doctrine/persistence": "<1.3"
- },
- "require-dev": {
- "doctrine/persistence": "^1.3|^2|^3",
- "symfony/property-access": "^6.4|^7.0",
- "symfony/serializer": "^6.4|^7.0"
- },
- "type": "symfony-messenger-bridge",
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Messenger\\Bridge\\Doctrine\\": ""
- },
- "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": "Symfony Doctrine Messenger Bridge",
- "homepage": "https://symfony.com",
- "support": {
- "source": "https://github.com/symfony/doctrine-messenger/tree/v7.0.4"
- },
- "funding": [
- {
- "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": "2024-02-22T20:27:20+00:00"
- },
- {
- "name": "symfony/dotenv",
- "version": "v7.0.4",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/dotenv.git",
- "reference": "8017ea2f0ff4fbda6ae1bf3f5409d5ecff982067"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/dotenv/zipball/8017ea2f0ff4fbda6ae1bf3f5409d5ecff982067",
- "reference": "8017ea2f0ff4fbda6ae1bf3f5409d5ecff982067",
- "shasum": ""
- },
- "require": {
- "php": ">=8.2"
+ "php": ">=8.2"
},
"conflict": {
"symfony/console": "<6.4",
@@ -3185,69 +3370,6 @@
],
"time": "2023-05-23T14:45:45+00:00"
},
- {
- "name": "symfony/expression-language",
- "version": "v7.0.3",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/expression-language.git",
- "reference": "0877c599cb260c9614f9229c0a2090d6919fd621"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/expression-language/zipball/0877c599cb260c9614f9229c0a2090d6919fd621",
- "reference": "0877c599cb260c9614f9229c0a2090d6919fd621",
- "shasum": ""
- },
- "require": {
- "php": ">=8.2",
- "symfony/cache": "^6.4|^7.0",
- "symfony/service-contracts": "^2.5|^3"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\ExpressionLanguage\\": ""
- },
- "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 an engine that can compile and evaluate expressions",
- "homepage": "https://symfony.com",
- "support": {
- "source": "https://github.com/symfony/expression-language/tree/v7.0.3"
- },
- "funding": [
- {
- "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": "2024-01-23T15:02:46+00:00"
- },
{
"name": "symfony/filesystem",
"version": "v7.0.3",
@@ -3440,102 +3562,6 @@
],
"time": "2024-02-05T18:04:53+00:00"
},
- {
- "name": "symfony/form",
- "version": "v7.0.4",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/form.git",
- "reference": "5cfe85c74caf924c7cec2134e169320b464ede84"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/form/zipball/5cfe85c74caf924c7cec2134e169320b464ede84",
- "reference": "5cfe85c74caf924c7cec2134e169320b464ede84",
- "shasum": ""
- },
- "require": {
- "php": ">=8.2",
- "symfony/event-dispatcher": "^6.4|^7.0",
- "symfony/options-resolver": "^6.4|^7.0",
- "symfony/polyfill-ctype": "~1.8",
- "symfony/polyfill-intl-icu": "^1.21",
- "symfony/polyfill-mbstring": "~1.0",
- "symfony/property-access": "^6.4|^7.0",
- "symfony/service-contracts": "^2.5|^3"
- },
- "conflict": {
- "symfony/console": "<6.4",
- "symfony/dependency-injection": "<6.4",
- "symfony/doctrine-bridge": "<6.4",
- "symfony/error-handler": "<6.4",
- "symfony/framework-bundle": "<6.4",
- "symfony/http-kernel": "<6.4",
- "symfony/translation": "<6.4.3|>=7.0,<7.0.3",
- "symfony/translation-contracts": "<2.5",
- "symfony/twig-bridge": "<6.4"
- },
- "require-dev": {
- "doctrine/collections": "^1.0|^2.0",
- "symfony/config": "^6.4|^7.0",
- "symfony/console": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/html-sanitizer": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/intl": "^6.4|^7.0",
- "symfony/security-core": "^6.4|^7.0",
- "symfony/security-csrf": "^6.4|^7.0",
- "symfony/translation": "^6.4.3|^7.0.3",
- "symfony/uid": "^6.4|^7.0",
- "symfony/validator": "^6.4|^7.0",
- "symfony/var-dumper": "^6.4|^7.0"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Form\\": ""
- },
- "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 to easily create, process and reuse HTML forms",
- "homepage": "https://symfony.com",
- "support": {
- "source": "https://github.com/symfony/form/tree/v7.0.4"
- },
- "funding": [
- {
- "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": "2024-02-12T11:15:03+00:00"
- },
{
"name": "symfony/framework-bundle",
"version": "v7.0.4",
@@ -3683,54 +3709,42 @@
"time": "2024-02-26T07:52:39+00:00"
},
{
- "name": "symfony/http-client",
+ "name": "symfony/http-foundation",
"version": "v7.0.4",
"source": {
"type": "git",
- "url": "https://github.com/symfony/http-client.git",
- "reference": "8384876f49a2316a63f88a9cd12436de6936bee6"
+ "url": "https://github.com/symfony/http-foundation.git",
+ "reference": "439fdfdd344943254b1ef6278613e79040548045"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-client/zipball/8384876f49a2316a63f88a9cd12436de6936bee6",
- "reference": "8384876f49a2316a63f88a9cd12436de6936bee6",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/439fdfdd344943254b1ef6278613e79040548045",
+ "reference": "439fdfdd344943254b1ef6278613e79040548045",
"shasum": ""
},
"require": {
"php": ">=8.2",
- "psr/log": "^1|^2|^3",
- "symfony/http-client-contracts": "^3",
- "symfony/service-contracts": "^2.5|^3"
+ "symfony/polyfill-mbstring": "~1.1",
+ "symfony/polyfill-php83": "^1.27"
},
"conflict": {
- "php-http/discovery": "<1.15",
- "symfony/http-foundation": "<6.4"
- },
- "provide": {
- "php-http/async-client-implementation": "*",
- "php-http/client-implementation": "*",
- "psr/http-client-implementation": "1.0",
- "symfony/http-client-implementation": "3.0"
+ "doctrine/dbal": "<3.6",
+ "symfony/cache": "<6.4"
},
"require-dev": {
- "amphp/amp": "^2.5",
- "amphp/http-client": "^4.2.1",
- "amphp/http-tunnel": "^1.0",
- "amphp/socket": "^1.1",
- "guzzlehttp/promises": "^1.4",
- "nyholm/psr7": "^1.0",
- "php-http/httplug": "^1.0|^2.0",
- "psr/http-client": "^1.0",
+ "doctrine/dbal": "^3.6|^4",
+ "predis/predis": "^1.1|^2.0",
+ "symfony/cache": "^6.4|^7.0",
"symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
"symfony/http-kernel": "^6.4|^7.0",
- "symfony/messenger": "^6.4|^7.0",
- "symfony/process": "^6.4|^7.0",
- "symfony/stopwatch": "^6.4|^7.0"
+ "symfony/mime": "^6.4|^7.0",
+ "symfony/rate-limiter": "^6.4|^7.0"
},
"type": "library",
"autoload": {
"psr-4": {
- "Symfony\\Component\\HttpClient\\": ""
+ "Symfony\\Component\\HttpFoundation\\": ""
},
"exclude-from-classmap": [
"/Tests/"
@@ -3742,21 +3756,18 @@
],
"authors": [
{
- "name": "Nicolas Grekas",
- "email": "p@tchwork.com"
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously",
+ "description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
- "keywords": [
- "http"
- ],
"support": {
- "source": "https://github.com/symfony/http-client/tree/v7.0.4"
+ "source": "https://github.com/symfony/http-foundation/tree/v7.0.4"
},
"funding": [
{
@@ -3772,1917 +3783,80 @@
"type": "tidelift"
}
],
- "time": "2024-02-15T11:33:06+00:00"
+ "time": "2024-02-08T19:22:56+00:00"
},
{
- "name": "symfony/http-client-contracts",
- "version": "v3.4.0",
+ "name": "symfony/http-kernel",
+ "version": "v7.0.4",
"source": {
"type": "git",
- "url": "https://github.com/symfony/http-client-contracts.git",
- "reference": "1ee70e699b41909c209a0c930f11034b93578654"
+ "url": "https://github.com/symfony/http-kernel.git",
+ "reference": "065e2234d907c0fc4fc942bf223f7cfc016d0ac7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/1ee70e699b41909c209a0c930f11034b93578654",
- "reference": "1ee70e699b41909c209a0c930f11034b93578654",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/065e2234d907c0fc4fc942bf223f7cfc016d0ac7",
+ "reference": "065e2234d907c0fc4fc942bf223f7cfc016d0ac7",
"shasum": ""
},
"require": {
- "php": ">=8.1"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "3.4-dev"
- },
- "thanks": {
- "name": "symfony/contracts",
- "url": "https://github.com/symfony/contracts"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Contracts\\HttpClient\\": ""
- },
- "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 HTTP clients",
- "homepage": "https://symfony.com",
- "keywords": [
- "abstractions",
- "contracts",
- "decoupling",
- "interfaces",
- "interoperability",
- "standards"
- ],
- "support": {
- "source": "https://github.com/symfony/http-client-contracts/tree/v3.4.0"
- },
- "funding": [
- {
- "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": "2023-07-30T20:28:31+00:00"
- },
- {
- "name": "symfony/http-foundation",
- "version": "v7.0.4",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/http-foundation.git",
- "reference": "439fdfdd344943254b1ef6278613e79040548045"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/http-foundation/zipball/439fdfdd344943254b1ef6278613e79040548045",
- "reference": "439fdfdd344943254b1ef6278613e79040548045",
- "shasum": ""
- },
- "require": {
- "php": ">=8.2",
- "symfony/polyfill-mbstring": "~1.1",
- "symfony/polyfill-php83": "^1.27"
- },
- "conflict": {
- "doctrine/dbal": "<3.6",
- "symfony/cache": "<6.4"
- },
- "require-dev": {
- "doctrine/dbal": "^3.6|^4",
- "predis/predis": "^1.1|^2.0",
- "symfony/cache": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/mime": "^6.4|^7.0",
- "symfony/rate-limiter": "^6.4|^7.0"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\HttpFoundation\\": ""
- },
- "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": "Defines an object-oriented layer for the HTTP specification",
- "homepage": "https://symfony.com",
- "support": {
- "source": "https://github.com/symfony/http-foundation/tree/v7.0.4"
- },
- "funding": [
- {
- "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": "2024-02-08T19:22:56+00:00"
- },
- {
- "name": "symfony/http-kernel",
- "version": "v7.0.4",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/http-kernel.git",
- "reference": "065e2234d907c0fc4fc942bf223f7cfc016d0ac7"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/http-kernel/zipball/065e2234d907c0fc4fc942bf223f7cfc016d0ac7",
- "reference": "065e2234d907c0fc4fc942bf223f7cfc016d0ac7",
- "shasum": ""
- },
- "require": {
- "php": ">=8.2",
- "psr/log": "^1|^2|^3",
- "symfony/error-handler": "^6.4|^7.0",
- "symfony/event-dispatcher": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/polyfill-ctype": "^1.8"
- },
- "conflict": {
- "symfony/browser-kit": "<6.4",
- "symfony/cache": "<6.4",
- "symfony/config": "<6.4",
- "symfony/console": "<6.4",
- "symfony/dependency-injection": "<6.4",
- "symfony/doctrine-bridge": "<6.4",
- "symfony/form": "<6.4",
- "symfony/http-client": "<6.4",
- "symfony/http-client-contracts": "<2.5",
- "symfony/mailer": "<6.4",
- "symfony/messenger": "<6.4",
- "symfony/translation": "<6.4",
- "symfony/translation-contracts": "<2.5",
- "symfony/twig-bridge": "<6.4",
- "symfony/validator": "<6.4",
- "symfony/var-dumper": "<6.4",
- "twig/twig": "<3.0.4"
- },
- "provide": {
- "psr/log-implementation": "1.0|2.0|3.0"
- },
- "require-dev": {
- "psr/cache": "^1.0|^2.0|^3.0",
- "symfony/browser-kit": "^6.4|^7.0",
- "symfony/clock": "^6.4|^7.0",
- "symfony/config": "^6.4|^7.0",
- "symfony/console": "^6.4|^7.0",
- "symfony/css-selector": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/dom-crawler": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/finder": "^6.4|^7.0",
- "symfony/http-client-contracts": "^2.5|^3",
- "symfony/process": "^6.4|^7.0",
- "symfony/property-access": "^6.4|^7.0",
- "symfony/routing": "^6.4|^7.0",
- "symfony/serializer": "^6.4.4|^7.0.4",
- "symfony/stopwatch": "^6.4|^7.0",
- "symfony/translation": "^6.4|^7.0",
- "symfony/translation-contracts": "^2.5|^3",
- "symfony/uid": "^6.4|^7.0",
- "symfony/validator": "^6.4|^7.0",
- "symfony/var-exporter": "^6.4|^7.0",
- "twig/twig": "^3.0.4"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\HttpKernel\\": ""
- },
- "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 a structured process for converting a Request into a Response",
- "homepage": "https://symfony.com",
- "support": {
- "source": "https://github.com/symfony/http-kernel/tree/v7.0.4"
- },
- "funding": [
- {
- "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": "2024-02-27T06:35:35+00:00"
- },
- {
- "name": "symfony/intl",
- "version": "v7.0.3",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/intl.git",
- "reference": "295995df4acf6790a35b9ce6ec32b313efb11ff8"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/intl/zipball/295995df4acf6790a35b9ce6ec32b313efb11ff8",
- "reference": "295995df4acf6790a35b9ce6ec32b313efb11ff8",
- "shasum": ""
- },
- "require": {
- "php": ">=8.2"
- },
- "require-dev": {
- "symfony/filesystem": "^6.4|^7.0",
- "symfony/finder": "^6.4|^7.0",
- "symfony/var-exporter": "^6.4|^7.0"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Intl\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Bernhard Schussek",
- "email": "bschussek@gmail.com"
- },
- {
- "name": "Eriksen Costa",
- "email": "eriksen.costa@infranology.com.br"
- },
- {
- "name": "Igor Wiedler",
- "email": "igor@wiedler.ch"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Provides access to the localization data of the ICU library",
- "homepage": "https://symfony.com",
- "keywords": [
- "i18n",
- "icu",
- "internationalization",
- "intl",
- "l10n",
- "localization"
- ],
- "support": {
- "source": "https://github.com/symfony/intl/tree/v7.0.3"
- },
- "funding": [
- {
- "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": "2024-01-23T15:02:46+00:00"
- },
- {
- "name": "symfony/mailer",
- "version": "v7.0.4",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/mailer.git",
- "reference": "72e16d87bf50a3ce195b9470c06bb9d7b816ea85"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/mailer/zipball/72e16d87bf50a3ce195b9470c06bb9d7b816ea85",
- "reference": "72e16d87bf50a3ce195b9470c06bb9d7b816ea85",
- "shasum": ""
- },
- "require": {
- "egulias/email-validator": "^2.1.10|^3|^4",
- "php": ">=8.2",
- "psr/event-dispatcher": "^1",
- "psr/log": "^1|^2|^3",
- "symfony/event-dispatcher": "^6.4|^7.0",
- "symfony/mime": "^6.4|^7.0",
- "symfony/service-contracts": "^2.5|^3"
- },
- "conflict": {
- "symfony/http-client-contracts": "<2.5",
- "symfony/http-kernel": "<6.4",
- "symfony/messenger": "<6.4",
- "symfony/mime": "<6.4",
- "symfony/twig-bridge": "<6.4"
- },
- "require-dev": {
- "symfony/console": "^6.4|^7.0",
- "symfony/http-client": "^6.4|^7.0",
- "symfony/messenger": "^6.4|^7.0",
- "symfony/twig-bridge": "^6.4|^7.0"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Mailer\\": ""
- },
- "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 sending emails",
- "homepage": "https://symfony.com",
- "support": {
- "source": "https://github.com/symfony/mailer/tree/v7.0.4"
- },
- "funding": [
- {
- "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": "2024-02-03T21:34:19+00:00"
- },
- {
- "name": "symfony/messenger",
- "version": "v7.0.4",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/messenger.git",
- "reference": "804a8997f93313a8f7ed19e8cca3b44fdd18bdec"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/messenger/zipball/804a8997f93313a8f7ed19e8cca3b44fdd18bdec",
- "reference": "804a8997f93313a8f7ed19e8cca3b44fdd18bdec",
- "shasum": ""
- },
- "require": {
- "php": ">=8.2",
- "psr/log": "^1|^2|^3",
- "symfony/clock": "^6.4|^7.0"
- },
- "conflict": {
- "symfony/console": "<6.4",
- "symfony/event-dispatcher": "<6.4",
- "symfony/event-dispatcher-contracts": "<2.5",
- "symfony/framework-bundle": "<6.4",
- "symfony/http-kernel": "<6.4",
- "symfony/serializer": "<6.4"
- },
- "require-dev": {
- "psr/cache": "^1.0|^2.0|^3.0",
- "symfony/console": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/event-dispatcher": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/process": "^6.4|^7.0",
- "symfony/property-access": "^6.4|^7.0",
- "symfony/rate-limiter": "^6.4|^7.0",
- "symfony/routing": "^6.4|^7.0",
- "symfony/serializer": "^6.4|^7.0",
- "symfony/service-contracts": "^2.5|^3",
- "symfony/stopwatch": "^6.4|^7.0",
- "symfony/validator": "^6.4|^7.0"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Messenger\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Samuel Roze",
- "email": "samuel.roze@gmail.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Helps applications send and receive messages to/from other applications or via message queues",
- "homepage": "https://symfony.com",
- "support": {
- "source": "https://github.com/symfony/messenger/tree/v7.0.4"
- },
- "funding": [
- {
- "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": "2024-02-26T07:52:39+00:00"
- },
- {
- "name": "symfony/mime",
- "version": "v7.0.3",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/mime.git",
- "reference": "c1ffe24ba6fdc3e3f0f3fcb93519103b326a3716"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/mime/zipball/c1ffe24ba6fdc3e3f0f3fcb93519103b326a3716",
- "reference": "c1ffe24ba6fdc3e3f0f3fcb93519103b326a3716",
- "shasum": ""
- },
- "require": {
- "php": ">=8.2",
- "symfony/polyfill-intl-idn": "^1.10",
- "symfony/polyfill-mbstring": "^1.0"
- },
- "conflict": {
- "egulias/email-validator": "~3.0.0",
- "phpdocumentor/reflection-docblock": "<3.2.2",
- "phpdocumentor/type-resolver": "<1.4.0",
- "symfony/mailer": "<6.4",
- "symfony/serializer": "<6.4"
- },
- "require-dev": {
- "egulias/email-validator": "^2.1.10|^3.1|^4",
- "league/html-to-markdown": "^5.0",
- "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/property-access": "^6.4|^7.0",
- "symfony/property-info": "^6.4|^7.0",
- "symfony/serializer": "^6.4|^7.0"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Mime\\": ""
- },
- "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 manipulating MIME messages",
- "homepage": "https://symfony.com",
- "keywords": [
- "mime",
- "mime-type"
- ],
- "support": {
- "source": "https://github.com/symfony/mime/tree/v7.0.3"
- },
- "funding": [
- {
- "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": "2024-01-30T08:34:29+00:00"
- },
- {
- "name": "symfony/monolog-bridge",
- "version": "v7.0.3",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/monolog-bridge.git",
- "reference": "5d4f188e60d1e38a1d9d4bb6fbbbc13111dff2b1"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/5d4f188e60d1e38a1d9d4bb6fbbbc13111dff2b1",
- "reference": "5d4f188e60d1e38a1d9d4bb6fbbbc13111dff2b1",
- "shasum": ""
- },
- "require": {
- "monolog/monolog": "^3",
- "php": ">=8.2",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/service-contracts": "^2.5|^3"
- },
- "conflict": {
- "symfony/console": "<6.4",
- "symfony/http-foundation": "<6.4",
- "symfony/security-core": "<6.4"
- },
- "require-dev": {
- "symfony/console": "^6.4|^7.0",
- "symfony/http-client": "^6.4|^7.0",
- "symfony/mailer": "^6.4|^7.0",
- "symfony/messenger": "^6.4|^7.0",
- "symfony/mime": "^6.4|^7.0",
- "symfony/security-core": "^6.4|^7.0",
- "symfony/var-dumper": "^6.4|^7.0"
- },
- "type": "symfony-bridge",
- "autoload": {
- "psr-4": {
- "Symfony\\Bridge\\Monolog\\": ""
- },
- "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 integration for Monolog with various Symfony components",
- "homepage": "https://symfony.com",
- "support": {
- "source": "https://github.com/symfony/monolog-bridge/tree/v7.0.3"
- },
- "funding": [
- {
- "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": "2024-01-23T15:02:46+00:00"
- },
- {
- "name": "symfony/monolog-bundle",
- "version": "v3.10.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/monolog-bundle.git",
- "reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/monolog-bundle/zipball/414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181",
- "reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181",
- "shasum": ""
- },
- "require": {
- "monolog/monolog": "^1.25.1 || ^2.0 || ^3.0",
- "php": ">=7.2.5",
- "symfony/config": "^5.4 || ^6.0 || ^7.0",
- "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0",
- "symfony/http-kernel": "^5.4 || ^6.0 || ^7.0",
- "symfony/monolog-bridge": "^5.4 || ^6.0 || ^7.0"
- },
- "require-dev": {
- "symfony/console": "^5.4 || ^6.0 || ^7.0",
- "symfony/phpunit-bridge": "^6.3 || ^7.0",
- "symfony/yaml": "^5.4 || ^6.0 || ^7.0"
- },
- "type": "symfony-bundle",
- "extra": {
- "branch-alias": {
- "dev-master": "3.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Bundle\\MonologBundle\\": ""
- },
- "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": "Symfony MonologBundle",
- "homepage": "https://symfony.com",
- "keywords": [
- "log",
- "logging"
- ],
- "support": {
- "issues": "https://github.com/symfony/monolog-bundle/issues",
- "source": "https://github.com/symfony/monolog-bundle/tree/v3.10.0"
- },
- "funding": [
- {
- "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": "2023-11-06T17:08:13+00:00"
- },
- {
- "name": "symfony/notifier",
- "version": "v7.0.3",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/notifier.git",
- "reference": "515326dab227ecd3198b04df50edf949f7767a9a"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/notifier/zipball/515326dab227ecd3198b04df50edf949f7767a9a",
- "reference": "515326dab227ecd3198b04df50edf949f7767a9a",
- "shasum": ""
- },
- "require": {
- "php": ">=8.2",
- "psr/log": "^1|^2|^3"
- },
- "conflict": {
- "symfony/event-dispatcher": "<6.4",
- "symfony/event-dispatcher-contracts": "<2.5",
- "symfony/http-client-contracts": "<2.5",
- "symfony/http-kernel": "<6.4"
- },
- "require-dev": {
- "symfony/event-dispatcher-contracts": "^2.5|^3",
- "symfony/http-client-contracts": "^2.5|^3",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/messenger": "^6.4|^7.0"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Notifier\\": ""
- },
- "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": "Sends notifications via one or more channels (email, SMS, ...)",
- "homepage": "https://symfony.com",
- "keywords": [
- "notification",
- "notifier"
- ],
- "support": {
- "source": "https://github.com/symfony/notifier/tree/v7.0.3"
- },
- "funding": [
- {
- "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": "2024-01-23T15:02:46+00:00"
- },
- {
- "name": "symfony/options-resolver",
- "version": "v7.0.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/options-resolver.git",
- "reference": "700ff4096e346f54cb628ea650767c8130f1001f"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/options-resolver/zipball/700ff4096e346f54cb628ea650767c8130f1001f",
- "reference": "700ff4096e346f54cb628ea650767c8130f1001f",
- "shasum": ""
- },
- "require": {
- "php": ">=8.2",
- "symfony/deprecation-contracts": "^2.5|^3"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\OptionsResolver\\": ""
- },
- "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 an improved replacement for the array_replace PHP function",
- "homepage": "https://symfony.com",
- "keywords": [
- "config",
- "configuration",
- "options"
- ],
- "support": {
- "source": "https://github.com/symfony/options-resolver/tree/v7.0.0"
- },
- "funding": [
- {
- "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": "2023-08-08T10:20:21+00:00"
- },
- {
- "name": "symfony/password-hasher",
- "version": "v7.0.4",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/password-hasher.git",
- "reference": "0eba656c16ecdf5588b3ddd2b2337b06173d839f"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/password-hasher/zipball/0eba656c16ecdf5588b3ddd2b2337b06173d839f",
- "reference": "0eba656c16ecdf5588b3ddd2b2337b06173d839f",
- "shasum": ""
- },
- "require": {
- "php": ">=8.2"
- },
- "conflict": {
- "symfony/security-core": "<6.4"
- },
- "require-dev": {
- "symfony/console": "^6.4|^7.0",
- "symfony/security-core": "^6.4|^7.0"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\PasswordHasher\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Robin Chalas",
- "email": "robin.chalas@gmail.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Provides password hashing utilities",
- "homepage": "https://symfony.com",
- "keywords": [
- "hashing",
- "password"
- ],
- "support": {
- "source": "https://github.com/symfony/password-hasher/tree/v7.0.4"
- },
- "funding": [
- {
- "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": "2024-02-12T11:15:03+00:00"
- },
- {
- "name": "symfony/polyfill-intl-grapheme",
- "version": "v1.29.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
- "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f",
- "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1"
- },
- "suggest": {
- "ext-intl": "For best performance"
- },
- "type": "library",
- "extra": {
- "thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
- }
- },
- "autoload": {
- "files": [
- "bootstrap.php"
- ],
- "psr-4": {
- "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
- }
- },
- "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": "Symfony polyfill for intl's grapheme_* functions",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "grapheme",
- "intl",
- "polyfill",
- "portable",
- "shim"
- ],
- "support": {
- "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0"
- },
- "funding": [
- {
- "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": "2024-01-29T20:11:03+00:00"
- },
- {
- "name": "symfony/polyfill-intl-icu",
- "version": "v1.29.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/polyfill-intl-icu.git",
- "reference": "07094a28851a49107f3ab4f9120ca2975a64b6e1"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/07094a28851a49107f3ab4f9120ca2975a64b6e1",
- "reference": "07094a28851a49107f3ab4f9120ca2975a64b6e1",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1"
- },
- "suggest": {
- "ext-intl": "For best performance and support of other locales than \"en\""
- },
- "type": "library",
- "extra": {
- "thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
- }
- },
- "autoload": {
- "files": [
- "bootstrap.php"
- ],
- "psr-4": {
- "Symfony\\Polyfill\\Intl\\Icu\\": ""
- },
- "classmap": [
- "Resources/stubs"
- ],
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "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": "Symfony polyfill for intl's ICU-related data and classes",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "icu",
- "intl",
- "polyfill",
- "portable",
- "shim"
- ],
- "support": {
- "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.29.0"
- },
- "funding": [
- {
- "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": "2024-01-29T20:12:16+00:00"
- },
- {
- "name": "symfony/polyfill-intl-idn",
- "version": "v1.29.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/polyfill-intl-idn.git",
- "reference": "a287ed7475f85bf6f61890146edbc932c0fff919"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/a287ed7475f85bf6f61890146edbc932c0fff919",
- "reference": "a287ed7475f85bf6f61890146edbc932c0fff919",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1",
- "symfony/polyfill-intl-normalizer": "^1.10",
- "symfony/polyfill-php72": "^1.10"
- },
- "suggest": {
- "ext-intl": "For best performance"
- },
- "type": "library",
- "extra": {
- "thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
- }
- },
- "autoload": {
- "files": [
- "bootstrap.php"
- ],
- "psr-4": {
- "Symfony\\Polyfill\\Intl\\Idn\\": ""
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Laurent Bassin",
- "email": "laurent@bassin.info"
- },
- {
- "name": "Trevor Rowbotham",
- "email": "trevor.rowbotham@pm.me"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "idn",
- "intl",
- "polyfill",
- "portable",
- "shim"
- ],
- "support": {
- "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.29.0"
- },
- "funding": [
- {
- "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": "2024-01-29T20:11:03+00:00"
- },
- {
- "name": "symfony/polyfill-intl-normalizer",
- "version": "v1.29.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
- "reference": "bc45c394692b948b4d383a08d7753968bed9a83d"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d",
- "reference": "bc45c394692b948b4d383a08d7753968bed9a83d",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1"
- },
- "suggest": {
- "ext-intl": "For best performance"
- },
- "type": "library",
- "extra": {
- "thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
- }
- },
- "autoload": {
- "files": [
- "bootstrap.php"
- ],
- "psr-4": {
- "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
- },
- "classmap": [
- "Resources/stubs"
- ]
- },
- "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": "Symfony polyfill for intl's Normalizer class and related functions",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "intl",
- "normalizer",
- "polyfill",
- "portable",
- "shim"
- ],
- "support": {
- "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0"
- },
- "funding": [
- {
- "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": "2024-01-29T20:11:03+00:00"
- },
- {
- "name": "symfony/polyfill-mbstring",
- "version": "v1.29.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
- "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1"
- },
- "provide": {
- "ext-mbstring": "*"
- },
- "suggest": {
- "ext-mbstring": "For best performance"
- },
- "type": "library",
- "extra": {
- "thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
- }
- },
- "autoload": {
- "files": [
- "bootstrap.php"
- ],
- "psr-4": {
- "Symfony\\Polyfill\\Mbstring\\": ""
- }
- },
- "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": "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.29.0"
- },
- "funding": [
- {
- "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": "2024-01-29T20:11:03+00:00"
- },
- {
- "name": "symfony/polyfill-php83",
- "version": "v1.29.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/polyfill-php83.git",
- "reference": "86fcae159633351e5fd145d1c47de6c528f8caff"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/86fcae159633351e5fd145d1c47de6c528f8caff",
- "reference": "86fcae159633351e5fd145d1c47de6c528f8caff",
- "shasum": ""
- },
- "require": {
- "php": ">=7.1",
- "symfony/polyfill-php80": "^1.14"
- },
- "type": "library",
- "extra": {
- "thanks": {
- "name": "symfony/polyfill",
- "url": "https://github.com/symfony/polyfill"
- }
- },
- "autoload": {
- "files": [
- "bootstrap.php"
- ],
- "psr-4": {
- "Symfony\\Polyfill\\Php83\\": ""
- },
- "classmap": [
- "Resources/stubs"
- ]
- },
- "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": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions",
- "homepage": "https://symfony.com",
- "keywords": [
- "compatibility",
- "polyfill",
- "portable",
- "shim"
- ],
- "support": {
- "source": "https://github.com/symfony/polyfill-php83/tree/v1.29.0"
- },
- "funding": [
- {
- "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": "2024-01-29T20:11:03+00:00"
- },
- {
- "name": "symfony/process",
- "version": "v7.0.4",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/process.git",
- "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/0e7727191c3b71ebec6d529fa0e50a01ca5679e9",
- "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9",
- "shasum": ""
- },
- "require": {
- "php": ">=8.2"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Process\\": ""
- },
- "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": "Executes commands in sub-processes",
- "homepage": "https://symfony.com",
- "support": {
- "source": "https://github.com/symfony/process/tree/v7.0.4"
- },
- "funding": [
- {
- "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": "2024-02-22T20:27:20+00:00"
- },
- {
- "name": "symfony/property-access",
- "version": "v7.0.4",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/property-access.git",
- "reference": "44e3746d4de8d0961a44ee332c74dd0918266127"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/property-access/zipball/44e3746d4de8d0961a44ee332c74dd0918266127",
- "reference": "44e3746d4de8d0961a44ee332c74dd0918266127",
- "shasum": ""
- },
- "require": {
- "php": ">=8.2",
- "symfony/property-info": "^6.4|^7.0"
- },
- "require-dev": {
- "symfony/cache": "^6.4|^7.0"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\PropertyAccess\\": ""
- },
- "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 functions to read and write from/to an object or array using a simple string notation",
- "homepage": "https://symfony.com",
- "keywords": [
- "access",
- "array",
- "extraction",
- "index",
- "injection",
- "object",
- "property",
- "property-path",
- "reflection"
- ],
- "support": {
- "source": "https://github.com/symfony/property-access/tree/v7.0.4"
- },
- "funding": [
- {
- "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": "2024-02-16T13:44:10+00:00"
- },
- {
- "name": "symfony/property-info",
- "version": "v7.0.3",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/property-info.git",
- "reference": "e160f92ea827243abf2dbf36b8460b1377194406"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/property-info/zipball/e160f92ea827243abf2dbf36b8460b1377194406",
- "reference": "e160f92ea827243abf2dbf36b8460b1377194406",
- "shasum": ""
- },
- "require": {
- "php": ">=8.2",
- "symfony/string": "^6.4|^7.0"
- },
- "conflict": {
- "phpdocumentor/reflection-docblock": "<5.2",
- "phpdocumentor/type-resolver": "<1.5.1",
- "symfony/dependency-injection": "<6.4",
- "symfony/serializer": "<6.4"
- },
- "require-dev": {
- "phpdocumentor/reflection-docblock": "^5.2",
- "phpstan/phpdoc-parser": "^1.0",
- "symfony/cache": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/serializer": "^6.4|^7.0"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\PropertyInfo\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Kévin Dunglas",
- "email": "dunglas@gmail.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Extracts information about PHP class' properties using metadata of popular sources",
- "homepage": "https://symfony.com",
- "keywords": [
- "doctrine",
- "phpdoc",
- "property",
- "symfony",
- "type",
- "validator"
- ],
- "support": {
- "source": "https://github.com/symfony/property-info/tree/v7.0.3"
- },
- "funding": [
- {
- "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": "2024-01-23T15:02:46+00:00"
- },
- {
- "name": "symfony/routing",
- "version": "v7.0.3",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/routing.git",
- "reference": "858b26756ffc35a11238b269b484ee3a393a74d3"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/routing/zipball/858b26756ffc35a11238b269b484ee3a393a74d3",
- "reference": "858b26756ffc35a11238b269b484ee3a393a74d3",
- "shasum": ""
- },
- "require": {
- "php": ">=8.2",
- "symfony/deprecation-contracts": "^2.5|^3"
- },
- "conflict": {
- "symfony/config": "<6.4",
- "symfony/dependency-injection": "<6.4",
- "symfony/yaml": "<6.4"
- },
- "require-dev": {
- "psr/log": "^1|^2|^3",
- "symfony/config": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/yaml": "^6.4|^7.0"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Routing\\": ""
- },
- "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": "Maps an HTTP request to a set of configuration variables",
- "homepage": "https://symfony.com",
- "keywords": [
- "router",
- "routing",
- "uri",
- "url"
- ],
- "support": {
- "source": "https://github.com/symfony/routing/tree/v7.0.3"
- },
- "funding": [
- {
- "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": "2024-01-30T13:55:15+00:00"
- },
- {
- "name": "symfony/runtime",
- "version": "v7.0.3",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/runtime.git",
- "reference": "ef2c2fd4b40fb8cd22221154399ad8888e81cdb5"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/runtime/zipball/ef2c2fd4b40fb8cd22221154399ad8888e81cdb5",
- "reference": "ef2c2fd4b40fb8cd22221154399ad8888e81cdb5",
- "shasum": ""
- },
- "require": {
- "composer-plugin-api": "^1.0|^2.0",
- "php": ">=8.2"
- },
- "conflict": {
- "symfony/dotenv": "<6.4"
- },
- "require-dev": {
- "composer/composer": "^2.6",
- "symfony/console": "^6.4|^7.0",
- "symfony/dotenv": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0"
- },
- "type": "composer-plugin",
- "extra": {
- "class": "Symfony\\Component\\Runtime\\Internal\\ComposerPlugin"
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Runtime\\": "",
- "Symfony\\Runtime\\Symfony\\Component\\": "Internal/"
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "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": "Enables decoupling PHP applications from global state",
- "homepage": "https://symfony.com",
- "keywords": [
- "runtime"
- ],
- "support": {
- "source": "https://github.com/symfony/runtime/tree/v7.0.3"
- },
- "funding": [
- {
- "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": "2024-01-23T15:02:46+00:00"
- },
- {
- "name": "symfony/security-bundle",
- "version": "v7.0.4",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/security-bundle.git",
- "reference": "1755fb50e4da0a0013569752be763d208d690bcd"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/security-bundle/zipball/1755fb50e4da0a0013569752be763d208d690bcd",
- "reference": "1755fb50e4da0a0013569752be763d208d690bcd",
- "shasum": ""
- },
- "require": {
- "composer-runtime-api": ">=2.1",
- "ext-xml": "*",
- "php": ">=8.2",
- "symfony/clock": "^6.4|^7.0",
- "symfony/config": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/event-dispatcher": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/password-hasher": "^6.4|^7.0",
- "symfony/security-core": "^6.4|^7.0",
- "symfony/security-csrf": "^6.4|^7.0",
- "symfony/security-http": "^6.4|^7.0",
- "symfony/service-contracts": "^2.5|^3"
+ "php": ">=8.2",
+ "psr/log": "^1|^2|^3",
+ "symfony/error-handler": "^6.4|^7.0",
+ "symfony/event-dispatcher": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/polyfill-ctype": "^1.8"
},
"conflict": {
"symfony/browser-kit": "<6.4",
+ "symfony/cache": "<6.4",
+ "symfony/config": "<6.4",
"symfony/console": "<6.4",
- "symfony/framework-bundle": "<6.4",
+ "symfony/dependency-injection": "<6.4",
+ "symfony/doctrine-bridge": "<6.4",
+ "symfony/form": "<6.4",
"symfony/http-client": "<6.4",
- "symfony/ldap": "<6.4",
- "symfony/serializer": "<6.4",
- "symfony/twig-bundle": "<6.4",
- "symfony/validator": "<6.4"
+ "symfony/http-client-contracts": "<2.5",
+ "symfony/mailer": "<6.4",
+ "symfony/messenger": "<6.4",
+ "symfony/translation": "<6.4",
+ "symfony/translation-contracts": "<2.5",
+ "symfony/twig-bridge": "<6.4",
+ "symfony/validator": "<6.4",
+ "symfony/var-dumper": "<6.4",
+ "twig/twig": "<3.0.4"
+ },
+ "provide": {
+ "psr/log-implementation": "1.0|2.0|3.0"
},
"require-dev": {
- "symfony/asset": "^6.4|^7.0",
+ "psr/cache": "^1.0|^2.0|^3.0",
"symfony/browser-kit": "^6.4|^7.0",
+ "symfony/clock": "^6.4|^7.0",
+ "symfony/config": "^6.4|^7.0",
"symfony/console": "^6.4|^7.0",
"symfony/css-selector": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
"symfony/dom-crawler": "^6.4|^7.0",
"symfony/expression-language": "^6.4|^7.0",
- "symfony/form": "^6.4|^7.0",
- "symfony/framework-bundle": "^6.4|^7.0",
- "symfony/http-client": "^6.4|^7.0",
- "symfony/ldap": "^6.4|^7.0",
+ "symfony/finder": "^6.4|^7.0",
+ "symfony/http-client-contracts": "^2.5|^3",
"symfony/process": "^6.4|^7.0",
- "symfony/rate-limiter": "^6.4|^7.0",
- "symfony/serializer": "^6.4|^7.0",
+ "symfony/property-access": "^6.4|^7.0",
+ "symfony/routing": "^6.4|^7.0",
+ "symfony/serializer": "^6.4.4|^7.0.4",
+ "symfony/stopwatch": "^6.4|^7.0",
"symfony/translation": "^6.4|^7.0",
- "symfony/twig-bridge": "^6.4|^7.0",
- "symfony/twig-bundle": "^6.4|^7.0",
+ "symfony/translation-contracts": "^2.5|^3",
+ "symfony/uid": "^6.4|^7.0",
"symfony/validator": "^6.4|^7.0",
- "symfony/yaml": "^6.4|^7.0",
- "twig/twig": "^3.0.4",
- "web-token/jwt-checker": "^3.1",
- "web-token/jwt-signature-algorithm-ecdsa": "^3.1",
- "web-token/jwt-signature-algorithm-eddsa": "^3.1",
- "web-token/jwt-signature-algorithm-hmac": "^3.1",
- "web-token/jwt-signature-algorithm-none": "^3.1",
- "web-token/jwt-signature-algorithm-rsa": "^3.1"
+ "symfony/var-exporter": "^6.4|^7.0",
+ "twig/twig": "^3.0.4"
},
- "type": "symfony-bundle",
+ "type": "library",
"autoload": {
"psr-4": {
- "Symfony\\Bundle\\SecurityBundle\\": ""
+ "Symfony\\Component\\HttpKernel\\": ""
},
"exclude-from-classmap": [
"/Tests/"
@@ -5702,10 +3876,10 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Provides a tight integration of the Security component into the Symfony full-stack framework",
+ "description": "Provides a structured process for converting a Request into a Response",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/security-bundle/tree/v7.0.4"
+ "source": "https://github.com/symfony/http-kernel/tree/v7.0.4"
},
"funding": [
{
@@ -5721,52 +3895,46 @@
"type": "tidelift"
}
],
- "time": "2024-02-15T11:33:06+00:00"
+ "time": "2024-02-27T06:35:35+00:00"
},
{
- "name": "symfony/security-core",
+ "name": "symfony/monolog-bridge",
"version": "v7.0.3",
"source": {
"type": "git",
- "url": "https://github.com/symfony/security-core.git",
- "reference": "72b9d961a5dcd21e6bc29b99df51a9000a15dde0"
+ "url": "https://github.com/symfony/monolog-bridge.git",
+ "reference": "5d4f188e60d1e38a1d9d4bb6fbbbc13111dff2b1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/security-core/zipball/72b9d961a5dcd21e6bc29b99df51a9000a15dde0",
- "reference": "72b9d961a5dcd21e6bc29b99df51a9000a15dde0",
+ "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/5d4f188e60d1e38a1d9d4bb6fbbbc13111dff2b1",
+ "reference": "5d4f188e60d1e38a1d9d4bb6fbbbc13111dff2b1",
"shasum": ""
},
"require": {
+ "monolog/monolog": "^3",
"php": ">=8.2",
- "symfony/event-dispatcher-contracts": "^2.5|^3",
- "symfony/password-hasher": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
"symfony/service-contracts": "^2.5|^3"
},
"conflict": {
- "symfony/event-dispatcher": "<6.4",
+ "symfony/console": "<6.4",
"symfony/http-foundation": "<6.4",
- "symfony/ldap": "<6.4",
- "symfony/translation": "<6.4.3|>=7.0,<7.0.3",
- "symfony/validator": "<6.4"
+ "symfony/security-core": "<6.4"
},
"require-dev": {
- "psr/cache": "^1.0|^2.0|^3.0",
- "psr/container": "^1.1|^2.0",
- "psr/log": "^1|^2|^3",
- "symfony/cache": "^6.4|^7.0",
- "symfony/event-dispatcher": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/ldap": "^6.4|^7.0",
- "symfony/string": "^6.4|^7.0",
- "symfony/translation": "^6.4.3|^7.0.3",
- "symfony/validator": "^6.4|^7.0"
+ "symfony/console": "^6.4|^7.0",
+ "symfony/http-client": "^6.4|^7.0",
+ "symfony/mailer": "^6.4|^7.0",
+ "symfony/messenger": "^6.4|^7.0",
+ "symfony/mime": "^6.4|^7.0",
+ "symfony/security-core": "^6.4|^7.0",
+ "symfony/var-dumper": "^6.4|^7.0"
},
- "type": "library",
+ "type": "symfony-bridge",
"autoload": {
"psr-4": {
- "Symfony\\Component\\Security\\Core\\": ""
+ "Symfony\\Bridge\\Monolog\\": ""
},
"exclude-from-classmap": [
"/Tests/"
@@ -5786,10 +3954,10 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Symfony Security Component - Core Library",
+ "description": "Provides integration for Monolog with various Symfony components",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/security-core/tree/v7.0.3"
+ "source": "https://github.com/symfony/monolog-bridge/tree/v7.0.3"
},
"funding": [
{
@@ -5808,33 +3976,41 @@
"time": "2024-01-23T15:02:46+00:00"
},
{
- "name": "symfony/security-csrf",
- "version": "v7.0.3",
+ "name": "symfony/monolog-bundle",
+ "version": "v3.10.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/security-csrf.git",
- "reference": "f0f724e599f069b768e335e4bdf795726c7dfe8e"
+ "url": "https://github.com/symfony/monolog-bundle.git",
+ "reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/security-csrf/zipball/f0f724e599f069b768e335e4bdf795726c7dfe8e",
- "reference": "f0f724e599f069b768e335e4bdf795726c7dfe8e",
+ "url": "https://api.github.com/repos/symfony/monolog-bundle/zipball/414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181",
+ "reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/security-core": "^6.4|^7.0"
- },
- "conflict": {
- "symfony/http-foundation": "<6.4"
+ "monolog/monolog": "^1.25.1 || ^2.0 || ^3.0",
+ "php": ">=7.2.5",
+ "symfony/config": "^5.4 || ^6.0 || ^7.0",
+ "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0",
+ "symfony/http-kernel": "^5.4 || ^6.0 || ^7.0",
+ "symfony/monolog-bridge": "^5.4 || ^6.0 || ^7.0"
},
"require-dev": {
- "symfony/http-foundation": "^6.4|^7.0"
+ "symfony/console": "^5.4 || ^6.0 || ^7.0",
+ "symfony/phpunit-bridge": "^6.3 || ^7.0",
+ "symfony/yaml": "^5.4 || ^6.0 || ^7.0"
+ },
+ "type": "symfony-bundle",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
},
- "type": "library",
"autoload": {
"psr-4": {
- "Symfony\\Component\\Security\\Csrf\\": ""
+ "Symfony\\Bundle\\MonologBundle\\": ""
},
"exclude-from-classmap": [
"/Tests/"
@@ -5854,10 +4030,15 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Symfony Security Component - CSRF Library",
+ "description": "Symfony MonologBundle",
"homepage": "https://symfony.com",
+ "keywords": [
+ "log",
+ "logging"
+ ],
"support": {
- "source": "https://github.com/symfony/security-csrf/tree/v7.0.3"
+ "issues": "https://github.com/symfony/monolog-bundle/issues",
+ "source": "https://github.com/symfony/monolog-bundle/tree/v3.10.0"
},
"funding": [
{
@@ -5873,59 +4054,42 @@
"type": "tidelift"
}
],
- "time": "2024-01-23T15:02:46+00:00"
+ "time": "2023-11-06T17:08:13+00:00"
},
{
- "name": "symfony/security-http",
- "version": "v7.0.4",
+ "name": "symfony/polyfill-intl-grapheme",
+ "version": "v1.29.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/security-http.git",
- "reference": "f3a70a937128f47366821a9f4b5dbfaa0ba9c862"
+ "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
+ "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/security-http/zipball/f3a70a937128f47366821a9f4b5dbfaa0ba9c862",
- "reference": "f3a70a937128f47366821a9f4b5dbfaa0ba9c862",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/32a9da87d7b3245e09ac426c83d334ae9f06f80f",
+ "reference": "32a9da87d7b3245e09ac426c83d334ae9f06f80f",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/polyfill-mbstring": "~1.0",
- "symfony/property-access": "^6.4|^7.0",
- "symfony/security-core": "^6.4|^7.0",
- "symfony/service-contracts": "^2.5|^3"
- },
- "conflict": {
- "symfony/clock": "<6.4",
- "symfony/event-dispatcher": "<6.4",
- "symfony/http-client-contracts": "<3.0",
- "symfony/security-bundle": "<6.4",
- "symfony/security-csrf": "<6.4"
+ "php": ">=7.1"
},
- "require-dev": {
- "psr/log": "^1|^2|^3",
- "symfony/cache": "^6.4|^7.0",
- "symfony/clock": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/http-client-contracts": "^3.0",
- "symfony/rate-limiter": "^6.4|^7.0",
- "symfony/routing": "^6.4|^7.0",
- "symfony/security-csrf": "^6.4|^7.0",
- "symfony/translation": "^6.4|^7.0",
- "web-token/jwt-checker": "^3.1",
- "web-token/jwt-signature-algorithm-ecdsa": "^3.1"
+ "suggest": {
+ "ext-intl": "For best performance"
},
"type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
"autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
"psr-4": {
- "Symfony\\Component\\Security\\Http\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
+ "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -5933,18 +4097,26 @@
],
"authors": [
{
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Symfony Security Component - HTTP Integration",
+ "description": "Symfony polyfill for intl's grapheme_* functions",
"homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "grapheme",
+ "intl",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
"support": {
- "source": "https://github.com/symfony/security-http/tree/v7.0.4"
+ "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.29.0"
},
"funding": [
{
@@ -5960,66 +4132,44 @@
"type": "tidelift"
}
],
- "time": "2024-02-26T07:52:39+00:00"
+ "time": "2024-01-29T20:11:03+00:00"
},
{
- "name": "symfony/serializer",
- "version": "v7.0.4",
+ "name": "symfony/polyfill-intl-normalizer",
+ "version": "v1.29.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/serializer.git",
- "reference": "c71d61c6c37804e10981960e5f5ebc2c8f0a4fbb"
+ "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
+ "reference": "bc45c394692b948b4d383a08d7753968bed9a83d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/serializer/zipball/c71d61c6c37804e10981960e5f5ebc2c8f0a4fbb",
- "reference": "c71d61c6c37804e10981960e5f5ebc2c8f0a4fbb",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/bc45c394692b948b4d383a08d7753968bed9a83d",
+ "reference": "bc45c394692b948b4d383a08d7753968bed9a83d",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/polyfill-ctype": "~1.8"
+ "php": ">=7.1"
},
- "conflict": {
- "phpdocumentor/reflection-docblock": "<3.2.2",
- "phpdocumentor/type-resolver": "<1.4.0",
- "symfony/dependency-injection": "<6.4",
- "symfony/property-access": "<6.4",
- "symfony/property-info": "<6.4",
- "symfony/uid": "<6.4",
- "symfony/validator": "<6.4",
- "symfony/yaml": "<6.4"
+ "suggest": {
+ "ext-intl": "For best performance"
},
- "require-dev": {
- "phpdocumentor/reflection-docblock": "^3.2|^4.0|^5.0",
- "seld/jsonlint": "^1.10",
- "symfony/cache": "^6.4|^7.0",
- "symfony/config": "^6.4|^7.0",
- "symfony/console": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/error-handler": "^6.4|^7.0",
- "symfony/filesystem": "^6.4|^7.0",
- "symfony/form": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/messenger": "^6.4|^7.0",
- "symfony/mime": "^6.4|^7.0",
- "symfony/property-access": "^6.4|^7.0",
- "symfony/property-info": "^6.4|^7.0",
- "symfony/translation-contracts": "^2.5|^3",
- "symfony/uid": "^6.4|^7.0",
- "symfony/validator": "^6.4|^7.0",
- "symfony/var-dumper": "^6.4|^7.0",
- "symfony/var-exporter": "^6.4|^7.0",
- "symfony/yaml": "^6.4|^7.0"
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
},
- "type": "library",
"autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
"psr-4": {
- "Symfony\\Component\\Serializer\\": ""
+ "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
},
- "exclude-from-classmap": [
- "/Tests/"
+ "classmap": [
+ "Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
@@ -6028,18 +4178,26 @@
],
"authors": [
{
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.",
+ "description": "Symfony polyfill for intl's Normalizer class and related functions",
"homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "intl",
+ "normalizer",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
"support": {
- "source": "https://github.com/symfony/serializer/tree/v7.0.4"
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.29.0"
},
"funding": [
{
@@ -6055,46 +4213,45 @@
"type": "tidelift"
}
],
- "time": "2024-02-22T20:27:20+00:00"
+ "time": "2024-01-29T20:11:03+00:00"
},
{
- "name": "symfony/service-contracts",
- "version": "v3.4.1",
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.29.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/service-contracts.git",
- "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0"
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0",
- "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
+ "reference": "9773676c8a1bb1f8d4340a62efe641cf76eda7ec",
"shasum": ""
},
"require": {
- "php": ">=8.1",
- "psr/container": "^1.1|^2.0"
+ "php": ">=7.1"
},
- "conflict": {
- "ext-psr": "<1.1|>=2"
+ "provide": {
+ "ext-mbstring": "*"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-main": "3.4-dev"
- },
"thanks": {
- "name": "symfony/contracts",
- "url": "https://github.com/symfony/contracts"
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
"psr-4": {
- "Symfony\\Contracts\\Service\\": ""
- },
- "exclude-from-classmap": [
- "/Test/"
- ]
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -6110,18 +4267,17 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Generic abstractions related to writing services",
+ "description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
- "abstractions",
- "contracts",
- "decoupling",
- "interfaces",
- "interoperability",
- "standards"
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
],
"support": {
- "source": "https://github.com/symfony/service-contracts/tree/v3.4.1"
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.29.0"
},
"funding": [
{
@@ -6137,60 +4293,68 @@
"type": "tidelift"
}
],
- "time": "2023-12-26T14:02:43+00:00"
+ "time": "2024-01-29T20:11:03+00:00"
},
{
- "name": "symfony/stimulus-bundle",
- "version": "v2.16.0",
+ "name": "symfony/polyfill-php83",
+ "version": "v1.29.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/stimulus-bundle.git",
- "reference": "6add4bdab1b9df4f2b2532a9dcb7b2f26dbba634"
+ "url": "https://github.com/symfony/polyfill-php83.git",
+ "reference": "86fcae159633351e5fd145d1c47de6c528f8caff"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/stimulus-bundle/zipball/6add4bdab1b9df4f2b2532a9dcb7b2f26dbba634",
- "reference": "6add4bdab1b9df4f2b2532a9dcb7b2f26dbba634",
+ "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/86fcae159633351e5fd145d1c47de6c528f8caff",
+ "reference": "86fcae159633351e5fd145d1c47de6c528f8caff",
"shasum": ""
},
"require": {
- "php": ">=8.1",
- "symfony/config": "^5.4|^6.0|^7.0",
- "symfony/dependency-injection": "^5.4|^6.0|^7.0",
- "symfony/deprecation-contracts": "^2.0|^3.0",
- "symfony/finder": "^5.4|^6.0|^7.0",
- "symfony/http-kernel": "^5.4|^6.0|^7.0",
- "twig/twig": "^2.15.3|~3.8.0"
+ "php": ">=7.1",
+ "symfony/polyfill-php80": "^1.14"
},
- "require-dev": {
- "symfony/asset-mapper": "^6.3|^7.0",
- "symfony/framework-bundle": "^5.4|^6.0|^7.0",
- "symfony/phpunit-bridge": "^5.4|^6.0|^7.0",
- "symfony/twig-bundle": "^5.4|^6.0|^7.0",
- "zenstruck/browser": "^1.4"
+ "type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
},
- "type": "symfony-bundle",
"autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
"psr-4": {
- "Symfony\\UX\\StimulusBundle\\": "src"
- }
+ "Symfony\\Polyfill\\Php83\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
},
"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": "Integration with your Symfony app & Stimulus!",
+ "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
"keywords": [
- "symfony-ux"
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
],
"support": {
- "source": "https://github.com/symfony/stimulus-bundle/tree/v2.16.0"
+ "source": "https://github.com/symfony/polyfill-php83/tree/v1.29.0"
},
"funding": [
{
@@ -6206,34 +4370,45 @@
"type": "tidelift"
}
],
- "time": "2024-02-29T16:20:46+00:00"
+ "time": "2024-01-29T20:11:03+00:00"
},
{
- "name": "symfony/stopwatch",
- "version": "v7.0.3",
+ "name": "symfony/polyfill-uuid",
+ "version": "v1.29.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/stopwatch.git",
- "reference": "983900d6fddf2b0cbaacacbbad07610854bd8112"
+ "url": "https://github.com/symfony/polyfill-uuid.git",
+ "reference": "3abdd21b0ceaa3000ee950097bc3cf9efc137853"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/stopwatch/zipball/983900d6fddf2b0cbaacacbbad07610854bd8112",
- "reference": "983900d6fddf2b0cbaacacbbad07610854bd8112",
+ "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/3abdd21b0ceaa3000ee950097bc3cf9efc137853",
+ "reference": "3abdd21b0ceaa3000ee950097bc3cf9efc137853",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/service-contracts": "^2.5|^3"
+ "php": ">=7.1"
+ },
+ "provide": {
+ "ext-uuid": "*"
+ },
+ "suggest": {
+ "ext-uuid": "For best performance"
},
"type": "library",
+ "extra": {
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
"autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
"psr-4": {
- "Symfony\\Component\\Stopwatch\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
+ "Symfony\\Polyfill\\Uuid\\": ""
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -6241,18 +4416,24 @@
],
"authors": [
{
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
+ "name": "Grégoire Pineau",
+ "email": "lyrixx@lyrixx.info"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Provides a way to profile code",
+ "description": "Symfony polyfill for uuid functions",
"homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "uuid"
+ ],
"support": {
- "source": "https://github.com/symfony/stopwatch/tree/v7.0.3"
+ "source": "https://github.com/symfony/polyfill-uuid/tree/v1.29.0"
},
"funding": [
{
@@ -6268,46 +4449,43 @@
"type": "tidelift"
}
],
- "time": "2024-01-23T15:02:46+00:00"
+ "time": "2024-01-29T20:11:03+00:00"
},
{
- "name": "symfony/string",
- "version": "v7.0.4",
+ "name": "symfony/routing",
+ "version": "v7.0.3",
"source": {
"type": "git",
- "url": "https://github.com/symfony/string.git",
- "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b"
+ "url": "https://github.com/symfony/routing.git",
+ "reference": "858b26756ffc35a11238b269b484ee3a393a74d3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/f5832521b998b0bec40bee688ad5de98d4cf111b",
- "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b",
+ "url": "https://api.github.com/repos/symfony/routing/zipball/858b26756ffc35a11238b269b484ee3a393a74d3",
+ "reference": "858b26756ffc35a11238b269b484ee3a393a74d3",
"shasum": ""
},
"require": {
"php": ">=8.2",
- "symfony/polyfill-ctype": "~1.8",
- "symfony/polyfill-intl-grapheme": "~1.0",
- "symfony/polyfill-intl-normalizer": "~1.0",
- "symfony/polyfill-mbstring": "~1.0"
+ "symfony/deprecation-contracts": "^2.5|^3"
},
"conflict": {
- "symfony/translation-contracts": "<2.5"
+ "symfony/config": "<6.4",
+ "symfony/dependency-injection": "<6.4",
+ "symfony/yaml": "<6.4"
},
"require-dev": {
- "symfony/error-handler": "^6.4|^7.0",
- "symfony/http-client": "^6.4|^7.0",
- "symfony/intl": "^6.4|^7.0",
- "symfony/translation-contracts": "^2.5|^3.0",
- "symfony/var-exporter": "^6.4|^7.0"
+ "psr/log": "^1|^2|^3",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/yaml": "^6.4|^7.0"
},
"type": "library",
"autoload": {
- "files": [
- "Resources/functions.php"
- ],
"psr-4": {
- "Symfony\\Component\\String\\": ""
+ "Symfony\\Component\\Routing\\": ""
},
"exclude-from-classmap": [
"/Tests/"
@@ -6319,26 +4497,24 @@
],
"authors": [
{
- "name": "Nicolas Grekas",
- "email": "p@tchwork.com"
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
+ "description": "Maps an HTTP request to a set of configuration variables",
"homepage": "https://symfony.com",
"keywords": [
- "grapheme",
- "i18n",
- "string",
- "unicode",
- "utf-8",
- "utf8"
+ "router",
+ "routing",
+ "uri",
+ "url"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v7.0.4"
+ "source": "https://github.com/symfony/routing/tree/v7.0.3"
},
"funding": [
{
@@ -6354,62 +4530,44 @@
"type": "tidelift"
}
],
- "time": "2024-02-01T13:17:36+00:00"
+ "time": "2024-01-30T13:55:15+00:00"
},
{
- "name": "symfony/translation",
- "version": "v7.0.4",
+ "name": "symfony/runtime",
+ "version": "v7.0.3",
"source": {
"type": "git",
- "url": "https://github.com/symfony/translation.git",
- "reference": "5b75e872f7d135d7abb4613809fadc8d9f3d30a0"
+ "url": "https://github.com/symfony/runtime.git",
+ "reference": "ef2c2fd4b40fb8cd22221154399ad8888e81cdb5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation/zipball/5b75e872f7d135d7abb4613809fadc8d9f3d30a0",
- "reference": "5b75e872f7d135d7abb4613809fadc8d9f3d30a0",
+ "url": "https://api.github.com/repos/symfony/runtime/zipball/ef2c2fd4b40fb8cd22221154399ad8888e81cdb5",
+ "reference": "ef2c2fd4b40fb8cd22221154399ad8888e81cdb5",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/polyfill-mbstring": "~1.0",
- "symfony/translation-contracts": "^2.5|^3.0"
+ "composer-plugin-api": "^1.0|^2.0",
+ "php": ">=8.2"
},
"conflict": {
- "symfony/config": "<6.4",
- "symfony/console": "<6.4",
- "symfony/dependency-injection": "<6.4",
- "symfony/http-client-contracts": "<2.5",
- "symfony/http-kernel": "<6.4",
- "symfony/service-contracts": "<2.5",
- "symfony/twig-bundle": "<6.4",
- "symfony/yaml": "<6.4"
- },
- "provide": {
- "symfony/translation-implementation": "2.3|3.0"
+ "symfony/dotenv": "<6.4"
},
"require-dev": {
- "nikic/php-parser": "^4.18|^5.0",
- "psr/log": "^1|^2|^3",
- "symfony/config": "^6.4|^7.0",
+ "composer/composer": "^2.6",
"symfony/console": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/finder": "^6.4|^7.0",
- "symfony/http-client-contracts": "^2.5|^3.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/intl": "^6.4|^7.0",
- "symfony/polyfill-intl-icu": "^1.21",
- "symfony/routing": "^6.4|^7.0",
- "symfony/service-contracts": "^2.5|^3",
- "symfony/yaml": "^6.4|^7.0"
+ "symfony/dotenv": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0"
+ },
+ "type": "composer-plugin",
+ "extra": {
+ "class": "Symfony\\Component\\Runtime\\Internal\\ComposerPlugin"
},
- "type": "library",
"autoload": {
- "files": [
- "Resources/functions.php"
- ],
"psr-4": {
- "Symfony\\Component\\Translation\\": ""
+ "Symfony\\Component\\Runtime\\": "",
+ "Symfony\\Runtime\\Symfony\\Component\\": "Internal/"
},
"exclude-from-classmap": [
"/Tests/"
@@ -6421,18 +4579,21 @@
],
"authors": [
{
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Provides tools to internationalize your application",
+ "description": "Enables decoupling PHP applications from global state",
"homepage": "https://symfony.com",
+ "keywords": [
+ "runtime"
+ ],
"support": {
- "source": "https://github.com/symfony/translation/tree/v7.0.4"
+ "source": "https://github.com/symfony/runtime/tree/v7.0.3"
},
"funding": [
{
@@ -6448,24 +4609,28 @@
"type": "tidelift"
}
],
- "time": "2024-02-22T20:27:20+00:00"
+ "time": "2024-01-23T15:02:46+00:00"
},
{
- "name": "symfony/translation-contracts",
+ "name": "symfony/service-contracts",
"version": "v3.4.1",
"source": {
"type": "git",
- "url": "https://github.com/symfony/translation-contracts.git",
- "reference": "06450585bf65e978026bda220cdebca3f867fde7"
+ "url": "https://github.com/symfony/service-contracts.git",
+ "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/06450585bf65e978026bda220cdebca3f867fde7",
- "reference": "06450585bf65e978026bda220cdebca3f867fde7",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0",
+ "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0",
"shasum": ""
},
"require": {
- "php": ">=8.1"
+ "php": ">=8.1",
+ "psr/container": "^1.1|^2.0"
+ },
+ "conflict": {
+ "ext-psr": "<1.1|>=2"
},
"type": "library",
"extra": {
@@ -6479,7 +4644,7 @@
},
"autoload": {
"psr-4": {
- "Symfony\\Contracts\\Translation\\": ""
+ "Symfony\\Contracts\\Service\\": ""
},
"exclude-from-classmap": [
"/Test/"
@@ -6499,7 +4664,7 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Generic abstractions related to translation",
+ "description": "Generic abstractions related to writing services",
"homepage": "https://symfony.com",
"keywords": [
"abstractions",
@@ -6510,7 +4675,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/translation-contracts/tree/v3.4.1"
+ "source": "https://github.com/symfony/service-contracts/tree/v3.4.1"
},
"funding": [
{
@@ -6529,73 +4694,27 @@
"time": "2023-12-26T14:02:43+00:00"
},
{
- "name": "symfony/twig-bridge",
- "version": "v7.0.4",
+ "name": "symfony/stopwatch",
+ "version": "v7.0.3",
"source": {
"type": "git",
- "url": "https://github.com/symfony/twig-bridge.git",
- "reference": "d16aa4eb5bdaeb6e7407782431dc70530f3b1df5"
+ "url": "https://github.com/symfony/stopwatch.git",
+ "reference": "983900d6fddf2b0cbaacacbbad07610854bd8112"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/d16aa4eb5bdaeb6e7407782431dc70530f3b1df5",
- "reference": "d16aa4eb5bdaeb6e7407782431dc70530f3b1df5",
+ "url": "https://api.github.com/repos/symfony/stopwatch/zipball/983900d6fddf2b0cbaacacbbad07610854bd8112",
+ "reference": "983900d6fddf2b0cbaacacbbad07610854bd8112",
"shasum": ""
},
"require": {
"php": ">=8.2",
- "symfony/translation-contracts": "^2.5|^3",
- "twig/twig": "^3.0.4"
- },
- "conflict": {
- "phpdocumentor/reflection-docblock": "<3.2.2",
- "phpdocumentor/type-resolver": "<1.4.0",
- "symfony/console": "<6.4",
- "symfony/form": "<6.4",
- "symfony/http-foundation": "<6.4",
- "symfony/http-kernel": "<6.4",
- "symfony/mime": "<6.4",
- "symfony/serializer": "<6.4",
- "symfony/translation": "<6.4",
- "symfony/workflow": "<6.4"
- },
- "require-dev": {
- "egulias/email-validator": "^2.1.10|^3|^4",
- "league/html-to-markdown": "^5.0",
- "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
- "symfony/asset": "^6.4|^7.0",
- "symfony/asset-mapper": "^6.4|^7.0",
- "symfony/console": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/finder": "^6.4|^7.0",
- "symfony/form": "^6.4|^7.0",
- "symfony/html-sanitizer": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/intl": "^6.4|^7.0",
- "symfony/mime": "^6.4|^7.0",
- "symfony/polyfill-intl-icu": "~1.0",
- "symfony/property-info": "^6.4|^7.0",
- "symfony/routing": "^6.4|^7.0",
- "symfony/security-acl": "^2.8|^3.0",
- "symfony/security-core": "^6.4|^7.0",
- "symfony/security-csrf": "^6.4|^7.0",
- "symfony/security-http": "^6.4|^7.0",
- "symfony/serializer": "^6.4.3|^7.0.3",
- "symfony/stopwatch": "^6.4|^7.0",
- "symfony/translation": "^6.4|^7.0",
- "symfony/web-link": "^6.4|^7.0",
- "symfony/workflow": "^6.4|^7.0",
- "symfony/yaml": "^6.4|^7.0",
- "twig/cssinliner-extra": "^2.12|^3",
- "twig/inky-extra": "^2.12|^3",
- "twig/markdown-extra": "^2.12|^3"
+ "symfony/service-contracts": "^2.5|^3"
},
- "type": "symfony-bridge",
+ "type": "library",
"autoload": {
"psr-4": {
- "Symfony\\Bridge\\Twig\\": ""
+ "Symfony\\Component\\Stopwatch\\": ""
},
"exclude-from-classmap": [
"/Tests/"
@@ -6615,10 +4734,10 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Provides integration for Twig with various Symfony components",
+ "description": "Provides a way to profile code",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/twig-bridge/tree/v7.0.4"
+ "source": "https://github.com/symfony/stopwatch/tree/v7.0.3"
},
"funding": [
{
@@ -6634,52 +4753,46 @@
"type": "tidelift"
}
],
- "time": "2024-02-15T11:33:06+00:00"
+ "time": "2024-01-23T15:02:46+00:00"
},
{
- "name": "symfony/twig-bundle",
+ "name": "symfony/string",
"version": "v7.0.4",
"source": {
"type": "git",
- "url": "https://github.com/symfony/twig-bundle.git",
- "reference": "acab2368f53491e018bf31ef48b39df55a6812ef"
+ "url": "https://github.com/symfony/string.git",
+ "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/acab2368f53491e018bf31ef48b39df55a6812ef",
- "reference": "acab2368f53491e018bf31ef48b39df55a6812ef",
+ "url": "https://api.github.com/repos/symfony/string/zipball/f5832521b998b0bec40bee688ad5de98d4cf111b",
+ "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b",
"shasum": ""
},
"require": {
- "composer-runtime-api": ">=2.1",
"php": ">=8.2",
- "symfony/config": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/twig-bridge": "^6.4|^7.0",
- "twig/twig": "^3.0.4"
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-intl-grapheme": "~1.0",
+ "symfony/polyfill-intl-normalizer": "~1.0",
+ "symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
- "symfony/framework-bundle": "<6.4",
- "symfony/translation": "<6.4"
+ "symfony/translation-contracts": "<2.5"
},
"require-dev": {
- "symfony/asset": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/finder": "^6.4|^7.0",
- "symfony/form": "^6.4|^7.0",
- "symfony/framework-bundle": "^6.4|^7.0",
- "symfony/routing": "^6.4|^7.0",
- "symfony/stopwatch": "^6.4|^7.0",
- "symfony/translation": "^6.4|^7.0",
- "symfony/web-link": "^6.4|^7.0",
- "symfony/yaml": "^6.4|^7.0"
+ "symfony/error-handler": "^6.4|^7.0",
+ "symfony/http-client": "^6.4|^7.0",
+ "symfony/intl": "^6.4|^7.0",
+ "symfony/translation-contracts": "^2.5|^3.0",
+ "symfony/var-exporter": "^6.4|^7.0"
},
- "type": "symfony-bundle",
+ "type": "library",
"autoload": {
+ "files": [
+ "Resources/functions.php"
+ ],
"psr-4": {
- "Symfony\\Bundle\\TwigBundle\\": ""
+ "Symfony\\Component\\String\\": ""
},
"exclude-from-classmap": [
"/Tests/"
@@ -6691,114 +4804,26 @@
],
"authors": [
{
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Provides a tight integration of Twig into the Symfony full-stack framework",
- "homepage": "https://symfony.com",
- "support": {
- "source": "https://github.com/symfony/twig-bundle/tree/v7.0.4"
- },
- "funding": [
- {
- "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": "2024-02-15T11:33:06+00:00"
- },
- {
- "name": "symfony/ux-turbo",
- "version": "v2.16.0",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/ux-turbo.git",
- "reference": "d3590a43fee73304855dfc8022ccb57b0df9f03d"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/ux-turbo/zipball/d3590a43fee73304855dfc8022ccb57b0df9f03d",
- "reference": "d3590a43fee73304855dfc8022ccb57b0df9f03d",
- "shasum": ""
- },
- "require": {
- "php": ">=8.1",
- "symfony/stimulus-bundle": "^2.9.1"
- },
- "conflict": {
- "symfony/flex": "<1.13"
- },
- "require-dev": {
- "doctrine/doctrine-bundle": "^2.4.3",
- "doctrine/orm": "^2.8 | 3.0",
- "phpstan/phpstan": "^1.10",
- "symfony/debug-bundle": "^5.4|^6.0|^7.0",
- "symfony/expression-language": "^5.4|^6.0|^7.0",
- "symfony/form": "^5.4|^6.0|^7.0",
- "symfony/framework-bundle": "^5.4|^6.0|^7.0",
- "symfony/mercure-bundle": "^0.3.7",
- "symfony/messenger": "^5.4|^6.0|^7.0",
- "symfony/panther": "^1.0|^2.0",
- "symfony/phpunit-bridge": "^5.4|^6.0|^7.0",
- "symfony/process": "^5.4|6.3.*|^7.0",
- "symfony/property-access": "^5.4|^6.0|^7.0",
- "symfony/security-core": "^5.4|^6.0|^7.0",
- "symfony/stopwatch": "^5.4|^6.0|^7.0",
- "symfony/twig-bundle": "^5.4|^6.0|^7.0",
- "symfony/web-profiler-bundle": "^5.4|^6.0|^7.0",
- "symfony/webpack-encore-bundle": "^2.1.1"
- },
- "type": "symfony-bundle",
- "extra": {
- "thanks": {
- "name": "symfony/ux",
- "url": "https://github.com/symfony/ux"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\UX\\Turbo\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Kévin Dunglas",
- "email": "kevin@dunglas.fr"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Hotwire Turbo integration for Symfony",
+ "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
"homepage": "https://symfony.com",
"keywords": [
- "hotwire",
- "javascript",
- "mercure",
- "symfony-ux",
- "turbo",
- "turbo-stream"
+ "grapheme",
+ "i18n",
+ "string",
+ "unicode",
+ "utf-8",
+ "utf8"
],
"support": {
- "source": "https://github.com/symfony/ux-turbo/tree/v2.16.0"
+ "source": "https://github.com/symfony/string/tree/v7.0.4"
},
"funding": [
{
@@ -6814,62 +4839,33 @@
"type": "tidelift"
}
],
- "time": "2024-02-20T16:11:17+00:00"
+ "time": "2024-02-01T13:17:36+00:00"
},
{
- "name": "symfony/validator",
- "version": "v7.0.4",
+ "name": "symfony/uid",
+ "version": "v7.0.3",
"source": {
"type": "git",
- "url": "https://github.com/symfony/validator.git",
- "reference": "104bc3620d0ee4091034cfbcdcf82ed727f15b7d"
+ "url": "https://github.com/symfony/uid.git",
+ "reference": "87cedaf3fabd7b733859d4d77aa4ca598259054b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/validator/zipball/104bc3620d0ee4091034cfbcdcf82ed727f15b7d",
- "reference": "104bc3620d0ee4091034cfbcdcf82ed727f15b7d",
+ "url": "https://api.github.com/repos/symfony/uid/zipball/87cedaf3fabd7b733859d4d77aa4ca598259054b",
+ "reference": "87cedaf3fabd7b733859d4d77aa4ca598259054b",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/polyfill-ctype": "~1.8",
- "symfony/polyfill-mbstring": "~1.0",
- "symfony/polyfill-php83": "^1.27",
- "symfony/translation-contracts": "^2.5|^3"
- },
- "conflict": {
- "doctrine/lexer": "<1.1",
- "symfony/dependency-injection": "<6.4",
- "symfony/doctrine-bridge": "<7.0",
- "symfony/expression-language": "<6.4",
- "symfony/http-kernel": "<6.4",
- "symfony/intl": "<6.4",
- "symfony/property-info": "<6.4",
- "symfony/translation": "<6.4.3|>=7.0,<7.0.3",
- "symfony/yaml": "<6.4"
- },
- "require-dev": {
- "egulias/email-validator": "^2.1.10|^3|^4",
- "symfony/cache": "^6.4|^7.0",
- "symfony/config": "^6.4|^7.0",
- "symfony/console": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/finder": "^6.4|^7.0",
- "symfony/http-client": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/intl": "^6.4|^7.0",
- "symfony/mime": "^6.4|^7.0",
- "symfony/property-access": "^6.4|^7.0",
- "symfony/property-info": "^6.4|^7.0",
- "symfony/translation": "^6.4.3|^7.0.3",
- "symfony/yaml": "^6.4|^7.0"
+ "php": ">=8.2",
+ "symfony/polyfill-uuid": "^1.15"
+ },
+ "require-dev": {
+ "symfony/console": "^6.4|^7.0"
},
"type": "library",
"autoload": {
"psr-4": {
- "Symfony\\Component\\Validator\\": ""
+ "Symfony\\Component\\Uid\\": ""
},
"exclude-from-classmap": [
"/Tests/"
@@ -6881,18 +4877,27 @@
],
"authors": [
{
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
+ "name": "Grégoire Pineau",
+ "email": "lyrixx@lyrixx.info"
+ },
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Provides tools to validate values",
+ "description": "Provides an object-oriented API to generate and represent UIDs",
"homepage": "https://symfony.com",
+ "keywords": [
+ "UID",
+ "ulid",
+ "uuid"
+ ],
"support": {
- "source": "https://github.com/symfony/validator/tree/v7.0.4"
+ "source": "https://github.com/symfony/uid/tree/v7.0.3"
},
"funding": [
{
@@ -6908,7 +4913,7 @@
"type": "tidelift"
}
],
- "time": "2024-02-22T20:27:20+00:00"
+ "time": "2024-01-23T15:02:46+00:00"
},
{
"name": "symfony/var-dumper",
@@ -7067,89 +5072,6 @@
],
"time": "2024-02-26T10:35:24+00:00"
},
- {
- "name": "symfony/web-link",
- "version": "v7.0.3",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/web-link.git",
- "reference": "855a347feb2ecfc1d1a379c739aff956d4cbec00"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/web-link/zipball/855a347feb2ecfc1d1a379c739aff956d4cbec00",
- "reference": "855a347feb2ecfc1d1a379c739aff956d4cbec00",
- "shasum": ""
- },
- "require": {
- "php": ">=8.2",
- "psr/link": "^1.1|^2.0"
- },
- "conflict": {
- "symfony/http-kernel": "<6.4"
- },
- "provide": {
- "psr/link-implementation": "1.0|2.0"
- },
- "require-dev": {
- "symfony/http-kernel": "^6.4|^7.0"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\WebLink\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Kévin Dunglas",
- "email": "dunglas@gmail.com"
- },
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Manages links between resources",
- "homepage": "https://symfony.com",
- "keywords": [
- "dns-prefetch",
- "http",
- "http2",
- "link",
- "performance",
- "prefetch",
- "preload",
- "prerender",
- "psr13",
- "push"
- ],
- "support": {
- "source": "https://github.com/symfony/web-link/tree/v7.0.3"
- },
- "funding": [
- {
- "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": "2024-01-23T15:02:46+00:00"
- },
{
"name": "symfony/yaml",
"version": "v7.0.3",
@@ -7221,242 +5143,40 @@
],
"time": "2024-01-23T15:02:46+00:00"
},
- {
- "name": "twig/extra-bundle",
- "version": "v3.8.0",
- "source": {
- "type": "git",
- "url": "https://github.com/twigphp/twig-extra-bundle.git",
- "reference": "32807183753de0388c8e59f7ac2d13bb47311140"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/32807183753de0388c8e59f7ac2d13bb47311140",
- "reference": "32807183753de0388c8e59f7ac2d13bb47311140",
- "shasum": ""
- },
- "require": {
- "php": ">=7.2.5",
- "symfony/framework-bundle": "^5.4|^6.0|^7.0",
- "symfony/twig-bundle": "^5.4|^6.0|^7.0",
- "twig/twig": "^3.0"
- },
- "require-dev": {
- "league/commonmark": "^1.0|^2.0",
- "symfony/phpunit-bridge": "^6.4|^7.0",
- "twig/cache-extra": "^3.0",
- "twig/cssinliner-extra": "^2.12|^3.0",
- "twig/html-extra": "^2.12|^3.0",
- "twig/inky-extra": "^2.12|^3.0",
- "twig/intl-extra": "^2.12|^3.0",
- "twig/markdown-extra": "^2.12|^3.0",
- "twig/string-extra": "^2.12|^3.0"
- },
- "type": "symfony-bundle",
- "autoload": {
- "psr-4": {
- "Twig\\Extra\\TwigExtraBundle\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com",
- "homepage": "http://fabien.potencier.org",
- "role": "Lead Developer"
- }
- ],
- "description": "A Symfony bundle for extra Twig extensions",
- "homepage": "https://twig.symfony.com",
- "keywords": [
- "bundle",
- "extra",
- "twig"
- ],
- "support": {
- "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.8.0"
- },
- "funding": [
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/twig/twig",
- "type": "tidelift"
- }
- ],
- "time": "2023-11-21T14:02:01+00:00"
- },
- {
- "name": "twig/twig",
- "version": "v3.8.0",
- "source": {
- "type": "git",
- "url": "https://github.com/twigphp/Twig.git",
- "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/twigphp/Twig/zipball/9d15f0ac07f44dc4217883ec6ae02fd555c6f71d",
- "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d",
- "shasum": ""
- },
- "require": {
- "php": ">=7.2.5",
- "symfony/polyfill-ctype": "^1.8",
- "symfony/polyfill-mbstring": "^1.3",
- "symfony/polyfill-php80": "^1.22"
- },
- "require-dev": {
- "psr/container": "^1.0|^2.0",
- "symfony/phpunit-bridge": "^5.4.9|^6.3|^7.0"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Twig\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com",
- "homepage": "http://fabien.potencier.org",
- "role": "Lead Developer"
- },
- {
- "name": "Twig Team",
- "role": "Contributors"
- },
- {
- "name": "Armin Ronacher",
- "email": "armin.ronacher@active-4.com",
- "role": "Project Founder"
- }
- ],
- "description": "Twig, the flexible, fast, and secure template language for PHP",
- "homepage": "https://twig.symfony.com",
- "keywords": [
- "templating"
- ],
- "support": {
- "issues": "https://github.com/twigphp/Twig/issues",
- "source": "https://github.com/twigphp/Twig/tree/v3.8.0"
- },
- "funding": [
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/twig/twig",
- "type": "tidelift"
- }
- ],
- "time": "2023-11-21T18:54:41+00:00"
- },
{
"name": "webmozart/assert",
"version": "1.11.0",
"source": {
"type": "git",
- "url": "https://github.com/webmozarts/assert.git",
- "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
- "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
- "shasum": ""
- },
- "require": {
- "ext-ctype": "*",
- "php": "^7.2 || ^8.0"
- },
- "conflict": {
- "phpstan/phpstan": "<0.12.20",
- "vimeo/psalm": "<4.6.1 || 4.6.2"
- },
- "require-dev": {
- "phpunit/phpunit": "^8.5.13"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.10-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Webmozart\\Assert\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Bernhard Schussek",
- "email": "bschussek@gmail.com"
- }
- ],
- "description": "Assertions to validate method input/output with nice error messages.",
- "keywords": [
- "assert",
- "check",
- "validate"
- ],
- "support": {
- "issues": "https://github.com/webmozarts/assert/issues",
- "source": "https://github.com/webmozarts/assert/tree/1.11.0"
- },
- "time": "2022-06-03T18:03:27+00:00"
- }
- ],
- "packages-dev": [
- {
- "name": "masterminds/html5",
- "version": "2.8.1",
- "source": {
- "type": "git",
- "url": "https://github.com/Masterminds/html5-php.git",
- "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf"
+ "url": "https://github.com/webmozarts/assert.git",
+ "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f47dcf3c70c584de14f21143c55d9939631bc6cf",
- "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf",
+ "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
+ "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
"shasum": ""
},
"require": {
- "ext-dom": "*",
- "php": ">=5.3.0"
+ "ext-ctype": "*",
+ "php": "^7.2 || ^8.0"
+ },
+ "conflict": {
+ "phpstan/phpstan": "<0.12.20",
+ "vimeo/psalm": "<4.6.1 || 4.6.2"
},
"require-dev": {
- "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8"
+ "phpunit/phpunit": "^8.5.13"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.7-dev"
+ "dev-master": "1.10-dev"
}
},
"autoload": {
"psr-4": {
- "Masterminds\\": "src"
+ "Webmozart\\Assert\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -7465,35 +5185,24 @@
],
"authors": [
{
- "name": "Matt Butcher",
- "email": "technosophos@gmail.com"
- },
- {
- "name": "Matt Farina",
- "email": "matt@mattfarina.com"
- },
- {
- "name": "Asmir Mustafic",
- "email": "goetas@gmail.com"
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
}
],
- "description": "An HTML5 parser and serializer.",
- "homepage": "http://masterminds.github.io/html5-php",
+ "description": "Assertions to validate method input/output with nice error messages.",
"keywords": [
- "HTML5",
- "dom",
- "html",
- "parser",
- "querypath",
- "serializer",
- "xml"
+ "assert",
+ "check",
+ "validate"
],
"support": {
- "issues": "https://github.com/Masterminds/html5-php/issues",
- "source": "https://github.com/Masterminds/html5-php/tree/2.8.1"
+ "issues": "https://github.com/webmozarts/assert/issues",
+ "source": "https://github.com/webmozarts/assert/tree/1.11.0"
},
- "time": "2023-05-10T11:58:31+00:00"
- },
+ "time": "2022-06-03T18:03:27+00:00"
+ }
+ ],
+ "packages-dev": [
{
"name": "myclabs/deep-copy",
"version": "1.11.1",
@@ -9109,33 +6818,39 @@
"time": "2020-09-28T06:39:44+00:00"
},
{
- "name": "symfony/browser-kit",
+ "name": "symfony/debug-bundle",
"version": "v7.0.3",
"source": {
"type": "git",
- "url": "https://github.com/symfony/browser-kit.git",
- "reference": "725d5b15681685ac17b20b575254c75639722488"
+ "url": "https://github.com/symfony/debug-bundle.git",
+ "reference": "b0db5c443883ce5c10c2265c77feb9833c3d9d6d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/browser-kit/zipball/725d5b15681685ac17b20b575254c75639722488",
- "reference": "725d5b15681685ac17b20b575254c75639722488",
+ "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/b0db5c443883ce5c10c2265c77feb9833c3d9d6d",
+ "reference": "b0db5c443883ce5c10c2265c77feb9833c3d9d6d",
"shasum": ""
},
"require": {
+ "ext-xml": "*",
"php": ">=8.2",
- "symfony/dom-crawler": "^6.4|^7.0"
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/twig-bridge": "^6.4|^7.0",
+ "symfony/var-dumper": "^6.4|^7.0"
+ },
+ "conflict": {
+ "symfony/config": "<6.4",
+ "symfony/dependency-injection": "<6.4"
},
"require-dev": {
- "symfony/css-selector": "^6.4|^7.0",
- "symfony/http-client": "^6.4|^7.0",
- "symfony/mime": "^6.4|^7.0",
- "symfony/process": "^6.4|^7.0"
+ "symfony/config": "^6.4|^7.0",
+ "symfony/web-profiler-bundle": "^6.4|^7.0"
},
- "type": "library",
+ "type": "symfony-bundle",
"autoload": {
"psr-4": {
- "Symfony\\Component\\BrowserKit\\": ""
+ "Symfony\\Bundle\\DebugBundle\\": ""
},
"exclude-from-classmap": [
"/Tests/"
@@ -9155,10 +6870,10 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically",
+ "description": "Provides a tight integration of the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/browser-kit/tree/v7.0.3"
+ "source": "https://github.com/symfony/debug-bundle/tree/v7.0.3"
},
"funding": [
{
@@ -9177,53 +6892,80 @@
"time": "2024-01-23T15:02:46+00:00"
},
{
- "name": "symfony/css-selector",
- "version": "v7.0.3",
+ "name": "symfony/maker-bundle",
+ "version": "v1.55.1",
"source": {
"type": "git",
- "url": "https://github.com/symfony/css-selector.git",
- "reference": "ec60a4edf94e63b0556b6a0888548bb400a3a3be"
+ "url": "https://github.com/symfony/maker-bundle.git",
+ "reference": "11a9d3125c5b93ab4043f0f2e9927fdc55881c17"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/css-selector/zipball/ec60a4edf94e63b0556b6a0888548bb400a3a3be",
- "reference": "ec60a4edf94e63b0556b6a0888548bb400a3a3be",
+ "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/11a9d3125c5b93ab4043f0f2e9927fdc55881c17",
+ "reference": "11a9d3125c5b93ab4043f0f2e9927fdc55881c17",
"shasum": ""
},
"require": {
- "php": ">=8.2"
+ "doctrine/inflector": "^2.0",
+ "nikic/php-parser": "^4.18|^5.0",
+ "php": ">=8.1",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/console": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/deprecation-contracts": "^2.2|^3",
+ "symfony/filesystem": "^6.4|^7.0",
+ "symfony/finder": "^6.4|^7.0",
+ "symfony/framework-bundle": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/process": "^6.4|^7.0"
+ },
+ "conflict": {
+ "doctrine/doctrine-bundle": "<2.10",
+ "doctrine/orm": "<2.15"
+ },
+ "require-dev": {
+ "composer/semver": "^3.0",
+ "doctrine/doctrine-bundle": "^2.5.0",
+ "doctrine/orm": "^2.15|^3",
+ "symfony/http-client": "^6.4|^7.0",
+ "symfony/phpunit-bridge": "^6.4.1|^7.0",
+ "symfony/security-core": "^6.4|^7.0",
+ "symfony/yaml": "^6.4|^7.0",
+ "twig/twig": "^3.0|^4.x-dev"
+ },
+ "type": "symfony-bundle",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ }
},
- "type": "library",
"autoload": {
"psr-4": {
- "Symfony\\Component\\CssSelector\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
+ "Symfony\\Bundle\\MakerBundle\\": "src/"
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
- },
- {
- "name": "Jean-François Simon",
- "email": "jeanfrancois.simon@sensiolabs.com"
- },
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Converts CSS selectors to XPath expressions",
- "homepage": "https://symfony.com",
+ "description": "Symfony Maker helps you create empty commands, controllers, form classes, tests and more so you can forget about writing boilerplate code.",
+ "homepage": "https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html",
+ "keywords": [
+ "code generator",
+ "dev",
+ "generator",
+ "scaffold",
+ "scaffolding"
+ ],
"support": {
- "source": "https://github.com/symfony/css-selector/tree/v7.0.3"
+ "issues": "https://github.com/symfony/maker-bundle/issues",
+ "source": "https://github.com/symfony/maker-bundle/tree/v1.55.1"
},
"funding": [
{
@@ -9239,42 +6981,49 @@
"type": "tidelift"
}
],
- "time": "2024-01-23T15:02:46+00:00"
+ "time": "2024-02-21T13:41:51+00:00"
},
{
- "name": "symfony/debug-bundle",
- "version": "v7.0.3",
+ "name": "symfony/phpunit-bridge",
+ "version": "v7.0.4",
"source": {
"type": "git",
- "url": "https://github.com/symfony/debug-bundle.git",
- "reference": "b0db5c443883ce5c10c2265c77feb9833c3d9d6d"
+ "url": "https://github.com/symfony/phpunit-bridge.git",
+ "reference": "54ca13ec990a40411ad978e08d994fca6cdd865f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/b0db5c443883ce5c10c2265c77feb9833c3d9d6d",
- "reference": "b0db5c443883ce5c10c2265c77feb9833c3d9d6d",
+ "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/54ca13ec990a40411ad978e08d994fca6cdd865f",
+ "reference": "54ca13ec990a40411ad978e08d994fca6cdd865f",
"shasum": ""
},
"require": {
- "ext-xml": "*",
- "php": ">=8.2",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/twig-bridge": "^6.4|^7.0",
- "symfony/var-dumper": "^6.4|^7.0"
+ "php": ">=7.2.5"
},
"conflict": {
- "symfony/config": "<6.4",
- "symfony/dependency-injection": "<6.4"
+ "phpunit/phpunit": "<7.5|9.1.2"
},
"require-dev": {
- "symfony/config": "^6.4|^7.0",
- "symfony/web-profiler-bundle": "^6.4|^7.0"
+ "symfony/deprecation-contracts": "^2.5|^3.0",
+ "symfony/error-handler": "^5.4|^6.4|^7.0",
+ "symfony/polyfill-php81": "^1.27"
+ },
+ "bin": [
+ "bin/simple-phpunit"
+ ],
+ "type": "symfony-bridge",
+ "extra": {
+ "thanks": {
+ "name": "phpunit/phpunit",
+ "url": "https://github.com/sebastianbergmann/phpunit"
+ }
},
- "type": "symfony-bundle",
"autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
"psr-4": {
- "Symfony\\Bundle\\DebugBundle\\": ""
+ "Symfony\\Bridge\\PhpUnit\\": ""
},
"exclude-from-classmap": [
"/Tests/"
@@ -9286,18 +7035,18 @@
],
"authors": [
{
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Provides a tight integration of the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework",
+ "description": "Provides utilities for PHPUnit, especially user deprecation notices management",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/debug-bundle/tree/v7.0.3"
+ "source": "https://github.com/symfony/phpunit-bridge/tree/v7.0.4"
},
"funding": [
{
@@ -9313,35 +7062,29 @@
"type": "tidelift"
}
],
- "time": "2024-01-23T15:02:46+00:00"
+ "time": "2024-02-08T19:22:56+00:00"
},
{
- "name": "symfony/dom-crawler",
+ "name": "symfony/process",
"version": "v7.0.4",
"source": {
"type": "git",
- "url": "https://github.com/symfony/dom-crawler.git",
- "reference": "6cb272cbec4dc7a30a853d2931766b03bea92dda"
+ "url": "https://github.com/symfony/process.git",
+ "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/6cb272cbec4dc7a30a853d2931766b03bea92dda",
- "reference": "6cb272cbec4dc7a30a853d2931766b03bea92dda",
+ "url": "https://api.github.com/repos/symfony/process/zipball/0e7727191c3b71ebec6d529fa0e50a01ca5679e9",
+ "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9",
"shasum": ""
},
"require": {
- "masterminds/html5": "^2.6",
- "php": ">=8.2",
- "symfony/polyfill-ctype": "~1.8",
- "symfony/polyfill-mbstring": "~1.0"
- },
- "require-dev": {
- "symfony/css-selector": "^6.4|^7.0"
+ "php": ">=8.2"
},
"type": "library",
"autoload": {
"psr-4": {
- "Symfony\\Component\\DomCrawler\\": ""
+ "Symfony\\Component\\Process\\": ""
},
"exclude-from-classmap": [
"/Tests/"
@@ -9361,10 +7104,88 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Eases DOM navigation for HTML and XML documents",
+ "description": "Executes commands in sub-processes",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/process/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-22T20:27:20+00:00"
+ },
+ {
+ "name": "symfony/translation-contracts",
+ "version": "v3.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/translation-contracts.git",
+ "reference": "06450585bf65e978026bda220cdebca3f867fde7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/06450585bf65e978026bda220cdebca3f867fde7",
+ "reference": "06450585bf65e978026bda220cdebca3f867fde7",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Contracts\\Translation\\": ""
+ },
+ "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 translation",
"homepage": "https://symfony.com",
+ "keywords": [
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
+ ],
"support": {
- "source": "https://github.com/symfony/dom-crawler/tree/v7.0.4"
+ "source": "https://github.com/symfony/translation-contracts/tree/v3.4.1"
},
"funding": [
{
@@ -9380,83 +7201,99 @@
"type": "tidelift"
}
],
- "time": "2024-02-12T11:15:03+00:00"
+ "time": "2023-12-26T14:02:43+00:00"
},
{
- "name": "symfony/maker-bundle",
- "version": "v1.55.1",
+ "name": "symfony/twig-bridge",
+ "version": "v7.0.4",
"source": {
"type": "git",
- "url": "https://github.com/symfony/maker-bundle.git",
- "reference": "11a9d3125c5b93ab4043f0f2e9927fdc55881c17"
+ "url": "https://github.com/symfony/twig-bridge.git",
+ "reference": "d16aa4eb5bdaeb6e7407782431dc70530f3b1df5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/11a9d3125c5b93ab4043f0f2e9927fdc55881c17",
- "reference": "11a9d3125c5b93ab4043f0f2e9927fdc55881c17",
+ "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/d16aa4eb5bdaeb6e7407782431dc70530f3b1df5",
+ "reference": "d16aa4eb5bdaeb6e7407782431dc70530f3b1df5",
"shasum": ""
},
"require": {
- "doctrine/inflector": "^2.0",
- "nikic/php-parser": "^4.18|^5.0",
- "php": ">=8.1",
- "symfony/config": "^6.4|^7.0",
- "symfony/console": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/deprecation-contracts": "^2.2|^3",
- "symfony/filesystem": "^6.4|^7.0",
- "symfony/finder": "^6.4|^7.0",
- "symfony/framework-bundle": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/process": "^6.4|^7.0"
+ "php": ">=8.2",
+ "symfony/translation-contracts": "^2.5|^3",
+ "twig/twig": "^3.0.4"
},
"conflict": {
- "doctrine/doctrine-bundle": "<2.10",
- "doctrine/orm": "<2.15"
+ "phpdocumentor/reflection-docblock": "<3.2.2",
+ "phpdocumentor/type-resolver": "<1.4.0",
+ "symfony/console": "<6.4",
+ "symfony/form": "<6.4",
+ "symfony/http-foundation": "<6.4",
+ "symfony/http-kernel": "<6.4",
+ "symfony/mime": "<6.4",
+ "symfony/serializer": "<6.4",
+ "symfony/translation": "<6.4",
+ "symfony/workflow": "<6.4"
},
"require-dev": {
- "composer/semver": "^3.0",
- "doctrine/doctrine-bundle": "^2.5.0",
- "doctrine/orm": "^2.15|^3",
- "symfony/http-client": "^6.4|^7.0",
- "symfony/phpunit-bridge": "^6.4.1|^7.0",
+ "egulias/email-validator": "^2.1.10|^3|^4",
+ "league/html-to-markdown": "^5.0",
+ "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
+ "symfony/asset": "^6.4|^7.0",
+ "symfony/asset-mapper": "^6.4|^7.0",
+ "symfony/console": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/finder": "^6.4|^7.0",
+ "symfony/form": "^6.4|^7.0",
+ "symfony/html-sanitizer": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/intl": "^6.4|^7.0",
+ "symfony/mime": "^6.4|^7.0",
+ "symfony/polyfill-intl-icu": "~1.0",
+ "symfony/property-info": "^6.4|^7.0",
+ "symfony/routing": "^6.4|^7.0",
+ "symfony/security-acl": "^2.8|^3.0",
"symfony/security-core": "^6.4|^7.0",
+ "symfony/security-csrf": "^6.4|^7.0",
+ "symfony/security-http": "^6.4|^7.0",
+ "symfony/serializer": "^6.4.3|^7.0.3",
+ "symfony/stopwatch": "^6.4|^7.0",
+ "symfony/translation": "^6.4|^7.0",
+ "symfony/web-link": "^6.4|^7.0",
+ "symfony/workflow": "^6.4|^7.0",
"symfony/yaml": "^6.4|^7.0",
- "twig/twig": "^3.0|^4.x-dev"
- },
- "type": "symfony-bundle",
- "extra": {
- "branch-alias": {
- "dev-main": "1.x-dev"
- }
+ "twig/cssinliner-extra": "^2.12|^3",
+ "twig/inky-extra": "^2.12|^3",
+ "twig/markdown-extra": "^2.12|^3"
},
+ "type": "symfony-bridge",
"autoload": {
"psr-4": {
- "Symfony\\Bundle\\MakerBundle\\": "src/"
- }
+ "Symfony\\Bridge\\Twig\\": ""
+ },
+ "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": "Symfony Maker helps you create empty commands, controllers, form classes, tests and more so you can forget about writing boilerplate code.",
- "homepage": "https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html",
- "keywords": [
- "code generator",
- "dev",
- "generator",
- "scaffold",
- "scaffolding"
- ],
+ "description": "Provides integration for Twig with various Symfony components",
+ "homepage": "https://symfony.com",
"support": {
- "issues": "https://github.com/symfony/maker-bundle/issues",
- "source": "https://github.com/symfony/maker-bundle/tree/v1.55.1"
+ "source": "https://github.com/symfony/twig-bridge/tree/v7.0.4"
},
"funding": [
{
@@ -9472,49 +7309,52 @@
"type": "tidelift"
}
],
- "time": "2024-02-21T13:41:51+00:00"
+ "time": "2024-02-15T11:33:06+00:00"
},
{
- "name": "symfony/phpunit-bridge",
+ "name": "symfony/twig-bundle",
"version": "v7.0.4",
"source": {
"type": "git",
- "url": "https://github.com/symfony/phpunit-bridge.git",
- "reference": "54ca13ec990a40411ad978e08d994fca6cdd865f"
+ "url": "https://github.com/symfony/twig-bundle.git",
+ "reference": "acab2368f53491e018bf31ef48b39df55a6812ef"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/54ca13ec990a40411ad978e08d994fca6cdd865f",
- "reference": "54ca13ec990a40411ad978e08d994fca6cdd865f",
+ "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/acab2368f53491e018bf31ef48b39df55a6812ef",
+ "reference": "acab2368f53491e018bf31ef48b39df55a6812ef",
"shasum": ""
},
"require": {
- "php": ">=7.2.5"
+ "composer-runtime-api": ">=2.1",
+ "php": ">=8.2",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/twig-bridge": "^6.4|^7.0",
+ "twig/twig": "^3.0.4"
},
"conflict": {
- "phpunit/phpunit": "<7.5|9.1.2"
+ "symfony/framework-bundle": "<6.4",
+ "symfony/translation": "<6.4"
},
"require-dev": {
- "symfony/deprecation-contracts": "^2.5|^3.0",
- "symfony/error-handler": "^5.4|^6.4|^7.0",
- "symfony/polyfill-php81": "^1.27"
- },
- "bin": [
- "bin/simple-phpunit"
- ],
- "type": "symfony-bridge",
- "extra": {
- "thanks": {
- "name": "phpunit/phpunit",
- "url": "https://github.com/sebastianbergmann/phpunit"
- }
+ "symfony/asset": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/finder": "^6.4|^7.0",
+ "symfony/form": "^6.4|^7.0",
+ "symfony/framework-bundle": "^6.4|^7.0",
+ "symfony/routing": "^6.4|^7.0",
+ "symfony/stopwatch": "^6.4|^7.0",
+ "symfony/translation": "^6.4|^7.0",
+ "symfony/web-link": "^6.4|^7.0",
+ "symfony/yaml": "^6.4|^7.0"
},
+ "type": "symfony-bundle",
"autoload": {
- "files": [
- "bootstrap.php"
- ],
"psr-4": {
- "Symfony\\Bridge\\PhpUnit\\": ""
+ "Symfony\\Bundle\\TwigBundle\\": ""
},
"exclude-from-classmap": [
"/Tests/"
@@ -9526,18 +7366,18 @@
],
"authors": [
{
- "name": "Nicolas Grekas",
- "email": "p@tchwork.com"
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Provides utilities for PHPUnit, especially user deprecation notices management",
+ "description": "Provides a tight integration of Twig into the Symfony full-stack framework",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/phpunit-bridge/tree/v7.0.4"
+ "source": "https://github.com/symfony/twig-bundle/tree/v7.0.4"
},
"funding": [
{
@@ -9553,7 +7393,7 @@
"type": "tidelift"
}
],
- "time": "2024-02-08T19:22:56+00:00"
+ "time": "2024-02-15T11:33:06+00:00"
},
{
"name": "symfony/web-profiler-bundle",
@@ -9685,15 +7525,89 @@
}
],
"time": "2023-11-20T00:12:19+00:00"
+ },
+ {
+ "name": "twig/twig",
+ "version": "v3.8.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/twigphp/Twig.git",
+ "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/twigphp/Twig/zipball/9d15f0ac07f44dc4217883ec6ae02fd555c6f71d",
+ "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/polyfill-ctype": "^1.8",
+ "symfony/polyfill-mbstring": "^1.3",
+ "symfony/polyfill-php80": "^1.22"
+ },
+ "require-dev": {
+ "psr/container": "^1.0|^2.0",
+ "symfony/phpunit-bridge": "^5.4.9|^6.3|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Twig\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com",
+ "homepage": "http://fabien.potencier.org",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Twig Team",
+ "role": "Contributors"
+ },
+ {
+ "name": "Armin Ronacher",
+ "email": "armin.ronacher@active-4.com",
+ "role": "Project Founder"
+ }
+ ],
+ "description": "Twig, the flexible, fast, and secure template language for PHP",
+ "homepage": "https://twig.symfony.com",
+ "keywords": [
+ "templating"
+ ],
+ "support": {
+ "issues": "https://github.com/twigphp/Twig/issues",
+ "source": "https://github.com/twigphp/Twig/tree/v3.8.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/twig/twig",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-11-21T18:54:41+00:00"
}
],
"aliases": [],
"minimum-stability": "stable",
- "stability-flags": [],
+ "stability-flags": {
+ "beberlei/metrics": 20
+ },
"prefer-stable": true,
"prefer-lowest": false,
"platform": {
- "php": ">=8.2",
+ "php": ">=8.3",
"ext-ctype": "*",
"ext-iconv": "*"
},
diff --git a/examples/config/bundles.php b/examples/config/bundles.php
index f8df89b..53ad6f5 100644
--- a/examples/config/bundles.php
+++ b/examples/config/bundles.php
@@ -14,10 +14,7 @@
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true],
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
- Symfony\UX\StimulusBundle\StimulusBundle::class => ['all' => true],
- Symfony\UX\Turbo\TurboBundle::class => ['all' => true],
- Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
- Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
+ Beberlei\Bundle\MetricsBundle\BeberleiMetricsBundle::class => ['all' => true],
];
diff --git a/examples/config/packages/asset_mapper.yaml b/examples/config/packages/asset_mapper.yaml
deleted file mode 100644
index d1ac653..0000000
--- a/examples/config/packages/asset_mapper.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
-framework:
- asset_mapper:
- # The paths to make available to the asset mapper.
- paths:
- - assets/
diff --git a/examples/config/packages/mailer.yaml b/examples/config/packages/mailer.yaml
deleted file mode 100644
index 56a650d..0000000
--- a/examples/config/packages/mailer.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-framework:
- mailer:
- dsn: '%env(MAILER_DSN)%'
diff --git a/examples/config/packages/messenger.yaml b/examples/config/packages/messenger.yaml
deleted file mode 100644
index 587083a..0000000
--- a/examples/config/packages/messenger.yaml
+++ /dev/null
@@ -1,24 +0,0 @@
-framework:
- messenger:
- failure_transport: failed
-
- transports:
- # https://symfony.com/doc/current/messenger.html#transport-configuration
- async:
- dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
- options:
- use_notify: true
- check_delayed_interval: 60000
- retry_strategy:
- max_retries: 3
- multiplier: 2
- failed: 'doctrine://default?queue_name=failed'
- # sync: 'sync://'
-
- routing:
- Symfony\Component\Mailer\Messenger\SendEmailMessage: async
- Symfony\Component\Notifier\Message\ChatMessage: async
- Symfony\Component\Notifier\Message\SmsMessage: async
-
- # Route your messages to the transports
- # 'App\Message\YourMessage': async
diff --git a/examples/config/packages/metrics.yaml b/examples/config/packages/metrics.yaml
new file mode 100644
index 0000000..6b5369a
--- /dev/null
+++ b/examples/config/packages/metrics.yaml
@@ -0,0 +1,31 @@
+beberlei_metrics:
+ default: logger
+ collectors:
+ influxdb_v1:
+ type: influxdb_v1
+ host: influxdb1
+ database: app
+ prometheus:
+ type: prometheus
+ host: prometheus
+ service: Prometheus\CollectorRegistry
+ namespace: app
+ graphite:
+ type: graphite
+ host: graphite
+ statsd:
+ type: statsd
+ host: graphite
+ prefix: 'app.statsd.'
+ dogstatsd:
+ type: dogstatsd
+ host: graphite
+ prefix: 'app.dogstatsd.'
+ dbal:
+ type: doctrine_dbal
+ logger:
+ type: logger
+ memory:
+ type: memory
+ 'null':
+ type: 'null'
diff --git a/examples/config/packages/notifier.yaml b/examples/config/packages/notifier.yaml
deleted file mode 100644
index d02f986..0000000
--- a/examples/config/packages/notifier.yaml
+++ /dev/null
@@ -1,12 +0,0 @@
-framework:
- notifier:
- chatter_transports:
- texter_transports:
- channel_policy:
- # use chat/slack, chat/telegram, sms/twilio or sms/nexmo
- urgent: ['email']
- high: ['email']
- medium: ['email']
- low: ['email']
- admin_recipients:
- - { email: admin@example.com }
diff --git a/examples/config/packages/security.yaml b/examples/config/packages/security.yaml
deleted file mode 100644
index 367af25..0000000
--- a/examples/config/packages/security.yaml
+++ /dev/null
@@ -1,39 +0,0 @@
-security:
- # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
- password_hashers:
- Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
- # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
- providers:
- users_in_memory: { memory: null }
- firewalls:
- dev:
- pattern: ^/(_(profiler|wdt)|css|images|js)/
- security: false
- main:
- lazy: true
- provider: users_in_memory
-
- # activate different ways to authenticate
- # https://symfony.com/doc/current/security.html#the-firewall
-
- # https://symfony.com/doc/current/security/impersonating_user.html
- # switch_user: true
-
- # Easy way to control access for large sections of your site
- # Note: Only the *first* access control that matches will be used
- access_control:
- # - { path: ^/admin, roles: ROLE_ADMIN }
- # - { path: ^/profile, roles: ROLE_USER }
-
-when@test:
- security:
- password_hashers:
- # By default, password hashers are resource intensive and take time. This is
- # important to generate secure password hashes. In tests however, secure hashes
- # are not important, waste resources and increase test times. The following
- # reduces the work factor to the lowest possible values.
- Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
- algorithm: auto
- cost: 4 # Lowest possible value for bcrypt
- time_cost: 3 # Lowest possible value for argon
- memory_cost: 10 # Lowest possible value for argon
diff --git a/examples/config/packages/translation.yaml b/examples/config/packages/translation.yaml
deleted file mode 100644
index b3f8f9c..0000000
--- a/examples/config/packages/translation.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-framework:
- default_locale: en
- translator:
- default_path: '%kernel.project_dir%/translations'
- fallbacks:
- - en
- providers:
diff --git a/examples/config/packages/twig.yaml b/examples/config/packages/twig.yaml
index 3f795d9..5d1e199 100644
--- a/examples/config/packages/twig.yaml
+++ b/examples/config/packages/twig.yaml
@@ -1,5 +1,7 @@
twig:
file_name_pattern: '*.twig'
+ globals:
+ project_dir: '%kernel.project_dir%'
when@test:
twig:
diff --git a/examples/config/packages/validator.yaml b/examples/config/packages/validator.yaml
deleted file mode 100644
index dd47a6a..0000000
--- a/examples/config/packages/validator.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-framework:
- validation:
- # Enables validator auto-mapping support.
- # For instance, basic validation constraints will be inferred from Doctrine's metadata.
- #auto_mapping:
- # App\Entity\: []
-
-when@test:
- framework:
- validation:
- not_compromised_password: false
diff --git a/examples/config/routes/security.yaml b/examples/config/routes/security.yaml
deleted file mode 100644
index f853be1..0000000
--- a/examples/config/routes/security.yaml
+++ /dev/null
@@ -1,3 +0,0 @@
-_security_logout:
- resource: security.route_loader.logout
- type: service
diff --git a/examples/config/services.yaml b/examples/config/services.yaml
index 2d6a76f..e3d19ce 100644
--- a/examples/config/services.yaml
+++ b/examples/config/services.yaml
@@ -1,18 +1,10 @@
-# This file is the entry point to configure your own services.
-# Files in the packages/ subdirectory configure your dependencies.
-
-# Put parameters here that don't need to change on each machine where the app is deployed
-# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
parameters:
services:
- # default configuration for services in *this* file
_defaults:
- autowire: true # Automatically injects dependencies in your services.
- autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
+ autowire: true
+ autoconfigure: true
- # makes classes in src/ available to be used as services
- # this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/'
exclude:
@@ -20,5 +12,8 @@ services:
- '../src/Entity/'
- '../src/Kernel.php'
- # add more service definitions when explicit configuration is needed
- # please note that last definitions always *replace* previous ones
+ Prometheus\CollectorRegistry:
+ arguments:
+ $storageAdapter: !service { class: Prometheus\Storage\APCng }
+ $registerDefaultMetrics: false
+ Prometheus\RenderTextFormat: ~
diff --git a/examples/importmap.php b/examples/importmap.php
deleted file mode 100644
index 277f3f6..0000000
--- a/examples/importmap.php
+++ /dev/null
@@ -1,24 +0,0 @@
- [
- 'path' => './assets/app.js',
- 'entrypoint' => true,
- ],
- '@hotwired/stimulus' => [
- 'version' => '3.2.2',
- ],
- '@symfony/stimulus-bundle' => [
- 'path' => './vendor/symfony/stimulus-bundle/assets/dist/loader.js',
- ],
- '@hotwired/turbo' => [
- 'version' => '7.3.0',
- ],
-];
diff --git a/examples/infrastructure/docker/docker-compose.builder.yml b/examples/infrastructure/docker/docker-compose.builder.yml
index f2b4807..ca6fc68 100644
--- a/examples/infrastructure/docker/docker-compose.builder.yml
+++ b/examples/infrastructure/docker/docker-compose.builder.yml
@@ -23,3 +23,4 @@ services:
- "builder-data:/home/app"
- "${COMPOSER_CACHE_DIR}:/home/app/.composer/cache"
- "../..:/var/www:cached"
+ - "../../..:/metrics:cached"
diff --git a/examples/infrastructure/docker/docker-compose.yml b/examples/infrastructure/docker/docker-compose.yml
index 230a21a..7003dca 100644
--- a/examples/infrastructure/docker/docker-compose.yml
+++ b/examples/infrastructure/docker/docker-compose.yml
@@ -1,7 +1,13 @@
version: '3.7'
volumes:
+ grafana-data: {}
+ graphite-data: {}
+ influxdb-data: {}
postgres-data: {}
+ prometheus-data: {}
+ # redis-data: {}
+ # vector-data: {}
services:
router:
@@ -19,6 +25,7 @@ services:
- postgres
volumes:
- "../..:/var/www:cached"
+ - "../../..:/metrics:cached"
environment:
- "PHP_VERSION=${PHP_VERSION}"
labels:
@@ -36,3 +43,101 @@ services:
- POSTGRES_PASSWORD=app
volumes:
- postgres-data:/var/lib/postgresql/data
+
+ grafana:
+ image: grafana/grafana:latest
+ volumes:
+ - grafana-data:/var/lib/grafana
+ environment:
+ - GF_PATHS_PROVISIONING=/etc/grafana/provisioning
+ - GF_AUTH_ANONYMOUS_ENABLED=true
+ - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
+ - GF_INSTALL_PLUGINS=grafana-clickhouse-datasource
+ entrypoint:
+ - sh
+ - -euc
+ - |
+ mkdir -p /etc/grafana/provisioning/datasources
+ cat < /etc/grafana/provisioning/datasources/loki.yaml
+ apiVersion: 1
+ datasources:
+ - name: Loki
+ type: loki
+ access: proxy
+ orgId: 1
+ url: http://loki:3100
+ basicAuth: false
+ isDefault: true
+ version: 1
+ editable: false
+ - name: ClickHouse
+ type: grafana-clickhouse-datasource
+ access: proxy
+ orgId: 1
+ isDefault: false
+ jsonData:
+ host: clickhouse
+ port: 9000
+ defaultDatabase: observability
+ username: observability
+ defaultDatasource: true
+ secureJsonData:
+ password: observability
+ version: 1
+ editable: false
+ EOF
+ /run.sh
+ labels:
+ - "traefik.enable=true"
+ - "traefik.http.routers.${PROJECT_NAME}-grafana.rule=Host(`grafana.${PROJECT_ROOT_DOMAIN}`)"
+ - "traefik.http.routers.${PROJECT_NAME}-grafana.tls=true"
+
+ graphite:
+ image: graphiteapp/graphite-statsd:1.1.10-5
+ volumes:
+ - graphite-data:/opt/graphite/storage
+ expose:
+ - 80
+ labels:
+ - "traefik.enable=true"
+ - "traefik.http.routers.${PROJECT_NAME}-graphite.rule=Host(`graphite.${PROJECT_ROOT_DOMAIN}`)"
+ - "traefik.http.routers.${PROJECT_NAME}-graphite.tls=true"
+
+ influxdb1:
+ image: influxdb:1.8
+ environment:
+ - INFLUXDB_DB=app
+ volumes:
+ - influxdb-data:/var/lib/influxdb
+
+ prometheus:
+ image: prom/prometheus:v2.50.1
+ volumes:
+ - ./services/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:cached
+ - prometheus-data:/var/lib/prometheus
+
+ # redis:
+ # image: redislabs/redistimeseries:1.10.11
+ # volumes:
+ # - "redis-data:/data"
+
+ # redis-insight:
+ # image: redislabs/redisinsight:1.14.0
+ # environment:
+ # RITRUSTEDORIGINS: https://redis.symfony-metrics.test
+ # labels:
+ # - "traefik.enable=true"
+ # - "traefik.http.routers.${PROJECT_NAME}-redis.rule=Host(`redis.${PROJECT_ROOT_DOMAIN}`)"
+ # - "traefik.http.routers.${PROJECT_NAME}-redis.tls=true"
+
+ # vector:
+ # image: timberio/vector:0.36.0-debian
+ # volumes:
+ # - ./services/vector/vector.yaml:/etc/vector/vector.yaml:cached
+ # - vector-data:/var/lib/vector
+ # expose:
+ # - 8686
+ # labels:
+ # - "traefik.enable=true"
+ # - "traefik.http.routers.${PROJECT_NAME}-vector.rule=Host(`vector.${PROJECT_ROOT_DOMAIN}`)"
+ # - "traefik.http.routers.${PROJECT_NAME}-vector.tls=true"
diff --git a/examples/infrastructure/docker/services/php/frontend/etc/nginx/nginx.conf b/examples/infrastructure/docker/services/php/frontend/etc/nginx/nginx.conf
index 8e939f7..64f8c39 100644
--- a/examples/infrastructure/docker/services/php/frontend/etc/nginx/nginx.conf
+++ b/examples/infrastructure/docker/services/php/frontend/etc/nginx/nginx.conf
@@ -29,11 +29,6 @@ http {
listen 0.0.0.0:80;
root /var/www/public;
- location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg)$ {
- access_log off;
- add_header Cache-Control "no-cache";
- }
-
# Remove this block if you want to access to PHP FPM monitoring
# dashboard (on URL: /php-fpm-status). WARNING: on production, you must
# secure this page (by user IP address, with a password, for example)
diff --git a/examples/infrastructure/docker/services/prometheus/prometheus.yml b/examples/infrastructure/docker/services/prometheus/prometheus.yml
new file mode 100644
index 0000000..6936b83
--- /dev/null
+++ b/examples/infrastructure/docker/services/prometheus/prometheus.yml
@@ -0,0 +1,14 @@
+global:
+ scrape_interval: 15s
+ evaluation_interval: 15s
+
+rule_files:
+
+scrape_configs:
+ - job_name: "prometheus"
+ static_configs:
+ - targets: ["localhost:9090"]
+ - job_name: "app"
+ metrics_path: /prometheus
+ static_configs:
+ - targets: ["frontend"]
diff --git a/examples/infrastructure/docker/services/vector/vector.yaml b/examples/infrastructure/docker/services/vector/vector.yaml
new file mode 100644
index 0000000..13e9771
--- /dev/null
+++ b/examples/infrastructure/docker/services/vector/vector.yaml
@@ -0,0 +1,62 @@
+data_dir: /var/lib/vector
+
+api:
+ enabled: true
+ address: '0.0.0.0:8686'
+
+sources:
+ syslog:
+ type: syslog
+ mode: udp
+ address: '0.0.0.0:9000'
+
+transforms:
+ syslog_json:
+ inputs:
+ - syslog
+ type: remap
+ source: |
+ . = parse_json!(.message)
+ .host = get_hostname() ?? "n/a"
+ .environment = get_env_var("VECTOR_ENVIRONMENT") ?? "production"
+ .application = get_env_var("VECTOR_APPLICATION") ?? "symfony"
+
+sinks:
+ elasticsearch:
+ inputs:
+ - syslog_json
+ type: elasticsearch
+ mode: bulk
+ endpoints:
+ - 'http://elasticsearch:9200'
+ bulk:
+ index: vector-%Y.%m.%d
+ action: create
+ loki:
+ inputs:
+ - syslog_json
+ type: loki
+ encoding:
+ codec: json
+ endpoint: 'http://loki:3100'
+ healthcheck: false
+ labels:
+ host: '{{ host }}'
+ environment: '{{ environment }}'
+ application: '{{ application }}'
+ channel: '{{ channel }}'
+ level: '{{ level_name }}'
+ clickhouse:
+ inputs:
+ - syslog_json
+ type: clickhouse
+ # format: json_as_string
+ endpoint: 'http://clickhouse:8123'
+ database: observability
+ table: logs
+ healthcheck: false
+ auth:
+ strategy: basic
+ password: observability
+ user: observability
+ skip_unknown_fields: true
diff --git a/examples/migrations/.gitignore b/examples/migrations/.gitignore
deleted file mode 100644
index e69de29..0000000
diff --git a/examples/migrations/Version20240302012809.php b/examples/migrations/Version20240302012809.php
new file mode 100644
index 0000000..28a9ea0
--- /dev/null
+++ b/examples/migrations/Version20240302012809.php
@@ -0,0 +1,32 @@
+addSql('CREATE TABLE metrics (id UUID DEFAULT gen_random_uuid() NOT NULL, metric VARCHAR(255) NOT NULL, measurement INT NOT NULL, created TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, PRIMARY KEY(id))');
+ $this->addSql('COMMENT ON COLUMN metrics.created IS \'(DC2Type:datetime_immutable)\'');
+ }
+
+ public function down(Schema $schema): void
+ {
+ $this->addSql('DROP TABLE metrics');
+ }
+}
diff --git a/examples/phpstan.neon b/examples/phpstan.neon
index 2db6d86..ff5ad2d 100644
--- a/examples/phpstan.neon
+++ b/examples/phpstan.neon
@@ -11,7 +11,7 @@ parameters:
inferPrivatePropertyTypeFromConstructor: true
symfony:
- container_xml_path: var/cache/dev/App_KernelDevDebugContainer.xml'
+ container_xml_path: var/cache/dev/App_KernelDevDebugContainer.xml
typeAliases:
ContextData: '''
diff --git a/examples/src/Controller/.gitignore b/examples/src/Controller/.gitignore
deleted file mode 100644
index e69de29..0000000
diff --git a/examples/src/Controller/HomepageController.php b/examples/src/Controller/HomepageController.php
index dcec4e1..5dfc53a 100644
--- a/examples/src/Controller/HomepageController.php
+++ b/examples/src/Controller/HomepageController.php
@@ -10,26 +10,55 @@
namespace App\Controller;
use Beberlei\Metrics\Collector\CollectorInterface;
+use Beberlei\Metrics\Collector\GaugeableCollectorInterface;
+use Beberlei\Metrics\Collector\InMemory;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Symfony\Component\DependencyInjection\Attribute\TaggedIterator;
use Symfony\Component\DependencyInjection\Attribute\Target;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class HomepageController extends AbstractController
{
+ private readonly InMemory $memoryCollector;
+
+ /**
+ * @param iterable $collectors
+ */
public function __construct(
- #[Target('null')]
- private CollectorInterface $collector2,
- #[Target('null2')]
- private CollectorInterface $collector,
+ #[TaggedIterator(CollectorInterface::class)]
+ private readonly iterable $collectors,
+ #[Target('memory')]
+ CollectorInterface $memoryCollector,
) {
+ if (!$memoryCollector instanceof InMemory) {
+ throw new \InvalidArgumentException('The memory collector must be an instance of InMemory.');
+ }
+ $this->memoryCollector = $memoryCollector;
}
#[Route('/')]
public function index(): Response
{
+ $random = date('s');
+ $timing = (int) ((microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']) * 1000);
+ $gauges = random_int(0, 100);
+
+ foreach ($this->collectors as $collector) {
+ $collector->measure('homepage.random', $random);
+ $collector->increment('homepage.visits');
+ $collector->timing('homepage.duration', $timing);
+ if ($collector instanceof GaugeableCollectorInterface) {
+ $collector->gauge('homepage.gauge', $gauges);
+ }
+ }
+
return $this->render('homepage/index.html.twig', [
- 'controller_name' => 'HomepageController',
+ 'collectors' => $this->collectors,
+ 'random' => $this->memoryCollector->getMeasure('homepage.random'),
+ 'visits' => $this->memoryCollector->getMeasure('homepage.visits'),
+ 'timing' => $this->memoryCollector->getTiming('homepage.duration'),
+ 'gauge' => $this->memoryCollector->getGauge('homepage.gauge'),
]);
}
}
diff --git a/examples/src/Controller/PrometheusController.php b/examples/src/Controller/PrometheusController.php
new file mode 100644
index 0000000..586b8ff
--- /dev/null
+++ b/examples/src/Controller/PrometheusController.php
@@ -0,0 +1,34 @@
+renderer->render($this->registry->getMetricFamilySamples()),
+ headers: ['Content-Type' => RenderTextFormat::MIME_TYPE],
+ );
+ }
+}
diff --git a/examples/src/Entity/.gitignore b/examples/src/Entity/.gitignore
deleted file mode 100644
index e69de29..0000000
diff --git a/examples/src/Entity/Metrics.php b/examples/src/Entity/Metrics.php
new file mode 100644
index 0000000..28fdad8
--- /dev/null
+++ b/examples/src/Entity/Metrics.php
@@ -0,0 +1,36 @@
+ 'gen_random_uuid()'])]
+ public string $id;
+
+ public function __construct(
+ #[ORM\Column(length: 255)]
+ public string $metric,
+
+ #[ORM\Column]
+ public int $measurement,
+
+ #[ORM\Column(type: Types::DATETIME_IMMUTABLE)]
+ public \DateTimeInterface $created,
+ ) {
+ $this->id = Uuid::v6()->toRfc4122();
+ }
+}
diff --git a/examples/src/Repository/.gitignore b/examples/src/Repository/.gitignore
deleted file mode 100644
index e69de29..0000000
diff --git a/examples/src/Repository/MetricsRepository.php b/examples/src/Repository/MetricsRepository.php
new file mode 100644
index 0000000..2425ec8
--- /dev/null
+++ b/examples/src/Repository/MetricsRepository.php
@@ -0,0 +1,30 @@
+
+ *
+ * @method Metrics|null find($id, $lockMode = null, $lockVersion = null)
+ * @method Metrics|null findOneBy(array $criteria, array $orderBy = null)
+ * @method Metrics[] findAll()
+ * @method Metrics[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
+ */
+class MetricsRepository extends ServiceEntityRepository
+{
+ public function __construct(ManagerRegistry $registry)
+ {
+ parent::__construct($registry, Metrics::class);
+ }
+}
diff --git a/examples/symfony.lock b/examples/symfony.lock
index 2769bd4..feb3c7a 100644
--- a/examples/symfony.lock
+++ b/examples/symfony.lock
@@ -1,4 +1,7 @@
{
+ "beberlei/metrics": {
+ "version": "dev-massive-code-grooming"
+ },
"doctrine/doctrine-bundle": {
"version": "2.11",
"recipe": {
@@ -40,21 +43,6 @@
"tests/bootstrap.php"
]
},
- "symfony/asset-mapper": {
- "version": "7.0",
- "recipe": {
- "repo": "github.com/symfony/recipes",
- "branch": "main",
- "version": "6.4",
- "ref": "6c28c471640cc2c6e60812ebcb961c526ef8997f"
- },
- "files": [
- "assets/app.js",
- "assets/styles/app.css",
- "config/packages/asset_mapper.yaml",
- "importmap.php"
- ]
- },
"symfony/console": {
"version": "7.0",
"recipe": {
@@ -110,18 +98,6 @@
"src/Kernel.php"
]
},
- "symfony/mailer": {
- "version": "7.0",
- "recipe": {
- "repo": "github.com/symfony/recipes",
- "branch": "main",
- "version": "4.3",
- "ref": "df66ee1f226c46f01e85c29c2f7acce0596ba35a"
- },
- "files": [
- "config/packages/mailer.yaml"
- ]
- },
"symfony/maker-bundle": {
"version": "1.55",
"recipe": {
@@ -131,18 +107,6 @@
"ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
}
},
- "symfony/messenger": {
- "version": "7.0",
- "recipe": {
- "repo": "github.com/symfony/recipes",
- "branch": "main",
- "version": "6.0",
- "ref": "ba1ac4e919baba5644d31b57a3284d6ba12d52ee"
- },
- "files": [
- "config/packages/messenger.yaml"
- ]
- },
"symfony/monolog-bundle": {
"version": "3.10",
"recipe": {
@@ -155,18 +119,6 @@
"config/packages/monolog.yaml"
]
},
- "symfony/notifier": {
- "version": "7.0",
- "recipe": {
- "repo": "github.com/symfony/recipes",
- "branch": "main",
- "version": "5.0",
- "ref": "178877daf79d2dbd62129dd03612cb1a2cb407cc"
- },
- "files": [
- "config/packages/notifier.yaml"
- ]
- },
"symfony/phpunit-bridge": {
"version": "7.0",
"recipe": {
@@ -195,46 +147,6 @@
"config/routes.yaml"
]
},
- "symfony/security-bundle": {
- "version": "7.0",
- "recipe": {
- "repo": "github.com/symfony/recipes",
- "branch": "main",
- "version": "6.4",
- "ref": "2ae08430db28c8eb4476605894296c82a642028f"
- },
- "files": [
- "config/packages/security.yaml",
- "config/routes/security.yaml"
- ]
- },
- "symfony/stimulus-bundle": {
- "version": "2.16",
- "recipe": {
- "repo": "github.com/symfony/recipes",
- "branch": "main",
- "version": "2.13",
- "ref": "6acd9ff4f7fd5626d2962109bd4ebab351d43c43"
- },
- "files": [
- "assets/bootstrap.js",
- "assets/controllers.json",
- "assets/controllers/hello_controller.js"
- ]
- },
- "symfony/translation": {
- "version": "7.0",
- "recipe": {
- "repo": "github.com/symfony/recipes",
- "branch": "main",
- "version": "6.3",
- "ref": "e28e27f53663cc34f0be2837aba18e3a1bef8e7b"
- },
- "files": [
- "config/packages/translation.yaml",
- "translations/.gitignore"
- ]
- },
"symfony/twig-bundle": {
"version": "7.0",
"recipe": {
@@ -248,20 +160,14 @@
"templates/base.html.twig"
]
},
- "symfony/ux-turbo": {
- "version": "v2.16.0"
- },
- "symfony/validator": {
+ "symfony/uid": {
"version": "7.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.0",
- "ref": "8c1c4e28d26a124b0bb273f537ca8ce443472bfd"
- },
- "files": [
- "config/packages/validator.yaml"
- ]
+ "ref": "0df5844274d871b37fc3816c57a768ffc60a43a5"
+ }
},
"symfony/web-profiler-bundle": {
"version": "7.0",
@@ -275,8 +181,5 @@
"config/packages/web_profiler.yaml",
"config/routes/web_profiler.yaml"
]
- },
- "twig/extra-bundle": {
- "version": "v3.8.0"
}
}
diff --git a/examples/templates/base.html.twig b/examples/templates/base.html.twig
index 3cda30f..1069c14 100644
--- a/examples/templates/base.html.twig
+++ b/examples/templates/base.html.twig
@@ -8,7 +8,6 @@
{% endblock %}
{% block javascripts %}
- {% block importmap %}{{ importmap('app') }}{% endblock %}
{% endblock %}
diff --git a/examples/templates/homepage/index.html.twig b/examples/templates/homepage/index.html.twig
new file mode 100644
index 0000000..b55483b
--- /dev/null
+++ b/examples/templates/homepage/index.html.twig
@@ -0,0 +1,56 @@
+{% extends 'base.html.twig' %}
+
+{% block title %}Hello{% endblock %}
+
+{% block body %}
+ Metrics demo application
+
+
+ This application demonstrates how to use the
+ beberlei/metrics
library.
+
+ This controller uses all collectors defined in the
+ config/packages/metrics.yaml
:
+
+ {% for collector in collectors %}
+ -
+ {{ constant('class', collector) }}
+ {% endfor %}
+
+
+
+
+ The following applications let you explore the collected metrics:
+
+ - Grafana: application with all database configureds
+ - Graphite: application with graphite, statsd, dogstatsd
+
+
+
+ Current collectors data
+
+ Current collectors collected the following metrics:
+
+
+
+ Mesaure |
+ Value |
+
+
+ random |
+ {{ random }} |
+
+
+ visits |
+ {{ visits }} |
+
+
+ timing |
+ {{ timing }} |
+
+
+ gauge |
+ {{ gauge }} |
+
+
+{% endblock %}
diff --git a/examples/translations/.gitignore b/examples/translations/.gitignore
deleted file mode 100644
index e69de29..0000000
From e533b9807f8b9a32ca8ed051deaca9716e01f8aa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Thu, 29 Feb 2024 18:27:03 +0100
Subject: [PATCH 31/32] doc: create CHANGELOG.md
---
CHANGELOG.md | 43 +++++++++++++++++++++++++++++++++++++++++++
UPGRADE-2.0.md | 17 -----------------
2 files changed, 43 insertions(+), 17 deletions(-)
create mode 100644 CHANGELOG.md
delete mode 100644 UPGRADE-2.0.md
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..dc71083
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,43 @@
+# CHANGELOG
+
+## v3.0.0 (unreleased)
+
+### Breaking changes
+
+* Drop support for PHP < 8.1
+* Drop support for Symfony < 5.4
+* Drop support for zabbix collector
+* Drop support for librato collector
+* Rename InfluxDB collector to InfluxDbV1
+* Change inner dependency of InfluxDbV1
+* Change inner dependency of Prometheus
+* Remove the TaggableCollectorInterface. Tags can be injected in the constructor
+ instead
+
+### New features
+
+* collector:
+ * Ensure all collectors cannot raise error or exception
+* bundle:
+ * All collectors has alias for autowiring. Use
+ `#[Target('name-of-the-collector')]` to inject a collector
+ * All collectors are tagged with `kernel.reset` to reset their state
+ * All collectors are tagged with
+ `Beberlei\Metrics\Collector\CollectorInterface`
+* add a symfony application in the `examples` folder will all collectors enabled
+ and visualisation with Grafana
+
+### Minor changes
+
+* collector:
+ * Fix doctrine dbal deprecations
+* chore:
+ * modernise PHP code, use PHP 8.1 features
+ * add license file, and link it in each PHP files
+* ci:
+ * use symfony/phpunit-bridge instead of phpunit
+ * add php-cs-fixer
+ * add phpstan
+ * replace Travis by GitHub Actions
+* composer:
+ * move tests to it's own folder, and it's own autoloader
diff --git a/UPGRADE-2.0.md b/UPGRADE-2.0.md
deleted file mode 100644
index b1def08..0000000
--- a/UPGRADE-2.0.md
+++ /dev/null
@@ -1,17 +0,0 @@
-Upgrade from 1.x to 2.0
-=======================
-
-* [BC BREAK] Collector `Beberlei\Metrics\Collector\Monolog` is renamed to `Beberlei\Metrics\Collector\Logger`.
-
-* [BC BREAK] Collector `Beberlei\Metrics\Collector\Monolog` takes a `Psr\Log\LoggerInterface`.
-
-* [BC BREAK] The bundle does not rely on `Beberlei\Metrics\Factory` and `Beberlei\Metrics\Registry` anymore.
-
-* [BC BREAK] The bundle configuration has a new "standard" key mapping. The
-`hostname` key for `Librato` is now `source`. The `hostname` key for `Zabbix` is
-now `prefix`. `hostname`, and `servername` are now `host`. `serverport` is now
-`port`.
-
-* [BC BREAK] The `Registry` is removed.
-
-* [BC BREAK] The `functions.php` is removed.
From 4689791f4a261eb66bacd09eea7d9ad77a4eb49c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?=
Date: Sat, 2 Mar 2024 18:51:54 +0100
Subject: [PATCH 32/32] --
---
examples/composer.json | 2 +-
examples/composer.lock | 1106 ++++++++++++++++------------------------
2 files changed, 441 insertions(+), 667 deletions(-)
diff --git a/examples/composer.json b/examples/composer.json
index 1dd83d7..9ccc0a6 100644
--- a/examples/composer.json
+++ b/examples/composer.json
@@ -19,7 +19,6 @@
"doctrine/doctrine-migrations-bundle": "^3.3",
"doctrine/orm": "^3.0",
"influxdb/influxdb-php": "^1.15",
- "phpdocumentor/reflection-docblock": "^5.3",
"phpstan/phpdoc-parser": "^1.26",
"promphp/prometheus_client_php": "^2.10",
"symfony/console": "7.0.*",
@@ -28,6 +27,7 @@
"symfony/framework-bundle": "7.0.*",
"symfony/monolog-bundle": "^3.0",
"symfony/runtime": "7.0.*",
+ "symfony/twig-bundle": "7.0.*",
"symfony/uid": "7.0.*",
"symfony/yaml": "7.0.*"
},
diff --git a/examples/composer.lock b/examples/composer.lock
index be4b0da..91d0b4d 100644
--- a/examples/composer.lock
+++ b/examples/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "8d17d049d9055c18f7e29bb59065459f",
+ "content-hash": "13387979a3a0d1d914b168e3a8ae7c53",
"packages": [
{
"name": "beberlei/metrics",
@@ -12,7 +12,7 @@
"dist": {
"type": "path",
"url": "/metrics",
- "reference": "e27a066968ab3726df32364b8afe679562672783"
+ "reference": "e533b9807f8b9a32ca8ed051deaca9716e01f8aa"
},
"require": {
"psr/log": "^1.0 || ^2.0 || ^3.0"
@@ -1784,174 +1784,6 @@
],
"time": "2023-10-27T15:32:31+00:00"
},
- {
- "name": "phpdocumentor/reflection-common",
- "version": "2.2.0",
- "source": {
- "type": "git",
- "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
- "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b",
- "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b",
- "shasum": ""
- },
- "require": {
- "php": "^7.2 || ^8.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-2.x": "2.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "phpDocumentor\\Reflection\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Jaap van Otterdijk",
- "email": "opensource@ijaap.nl"
- }
- ],
- "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
- "homepage": "http://www.phpdoc.org",
- "keywords": [
- "FQSEN",
- "phpDocumentor",
- "phpdoc",
- "reflection",
- "static analysis"
- ],
- "support": {
- "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues",
- "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x"
- },
- "time": "2020-06-27T09:03:43+00:00"
- },
- {
- "name": "phpdocumentor/reflection-docblock",
- "version": "5.3.0",
- "source": {
- "type": "git",
- "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
- "reference": "622548b623e81ca6d78b721c5e029f4ce664f170"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170",
- "reference": "622548b623e81ca6d78b721c5e029f4ce664f170",
- "shasum": ""
- },
- "require": {
- "ext-filter": "*",
- "php": "^7.2 || ^8.0",
- "phpdocumentor/reflection-common": "^2.2",
- "phpdocumentor/type-resolver": "^1.3",
- "webmozart/assert": "^1.9.1"
- },
- "require-dev": {
- "mockery/mockery": "~1.3.2",
- "psalm/phar": "^4.8"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "5.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "phpDocumentor\\Reflection\\": "src"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Mike van Riel",
- "email": "me@mikevanriel.com"
- },
- {
- "name": "Jaap van Otterdijk",
- "email": "account@ijaap.nl"
- }
- ],
- "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
- "support": {
- "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
- "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0"
- },
- "time": "2021-10-19T17:43:47+00:00"
- },
- {
- "name": "phpdocumentor/type-resolver",
- "version": "1.8.2",
- "source": {
- "type": "git",
- "url": "https://github.com/phpDocumentor/TypeResolver.git",
- "reference": "153ae662783729388a584b4361f2545e4d841e3c"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c",
- "reference": "153ae662783729388a584b4361f2545e4d841e3c",
- "shasum": ""
- },
- "require": {
- "doctrine/deprecations": "^1.0",
- "php": "^7.3 || ^8.0",
- "phpdocumentor/reflection-common": "^2.0",
- "phpstan/phpdoc-parser": "^1.13"
- },
- "require-dev": {
- "ext-tokenizer": "*",
- "phpbench/phpbench": "^1.2",
- "phpstan/extension-installer": "^1.1",
- "phpstan/phpstan": "^1.8",
- "phpstan/phpstan-phpunit": "^1.1",
- "phpunit/phpunit": "^9.5",
- "rector/rector": "^0.13.9",
- "vimeo/psalm": "^4.25"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-1.x": "1.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "phpDocumentor\\Reflection\\": "src"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Mike van Riel",
- "email": "me@mikevanriel.com"
- }
- ],
- "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
- "support": {
- "issues": "https://github.com/phpDocumentor/TypeResolver/issues",
- "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2"
- },
- "time": "2024-02-23T11:10:43+00:00"
- },
{
"name": "phpstan/phpdoc-parser",
"version": "1.26.0",
@@ -4842,33 +4674,38 @@
"time": "2024-02-01T13:17:36+00:00"
},
{
- "name": "symfony/uid",
- "version": "v7.0.3",
+ "name": "symfony/translation-contracts",
+ "version": "v3.4.1",
"source": {
"type": "git",
- "url": "https://github.com/symfony/uid.git",
- "reference": "87cedaf3fabd7b733859d4d77aa4ca598259054b"
+ "url": "https://github.com/symfony/translation-contracts.git",
+ "reference": "06450585bf65e978026bda220cdebca3f867fde7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/uid/zipball/87cedaf3fabd7b733859d4d77aa4ca598259054b",
- "reference": "87cedaf3fabd7b733859d4d77aa4ca598259054b",
+ "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/06450585bf65e978026bda220cdebca3f867fde7",
+ "reference": "06450585bf65e978026bda220cdebca3f867fde7",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/polyfill-uuid": "^1.15"
- },
- "require-dev": {
- "symfony/console": "^6.4|^7.0"
+ "php": ">=8.1"
},
"type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.4-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ },
"autoload": {
"psr-4": {
- "Symfony\\Component\\Uid\\": ""
+ "Symfony\\Contracts\\Translation\\": ""
},
"exclude-from-classmap": [
- "/Tests/"
+ "/Test/"
]
},
"notification-url": "https://packagist.org/downloads/",
@@ -4876,10 +4713,6 @@
"MIT"
],
"authors": [
- {
- "name": "Grégoire Pineau",
- "email": "lyrixx@lyrixx.info"
- },
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
@@ -4889,15 +4722,18 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Provides an object-oriented API to generate and represent UIDs",
+ "description": "Generic abstractions related to translation",
"homepage": "https://symfony.com",
"keywords": [
- "UID",
- "ulid",
- "uuid"
+ "abstractions",
+ "contracts",
+ "decoupling",
+ "interfaces",
+ "interoperability",
+ "standards"
],
"support": {
- "source": "https://github.com/symfony/uid/tree/v7.0.3"
+ "source": "https://github.com/symfony/translation-contracts/tree/v3.4.1"
},
"funding": [
{
@@ -4913,47 +4749,76 @@
"type": "tidelift"
}
],
- "time": "2024-01-23T15:02:46+00:00"
+ "time": "2023-12-26T14:02:43+00:00"
},
{
- "name": "symfony/var-dumper",
+ "name": "symfony/twig-bridge",
"version": "v7.0.4",
"source": {
"type": "git",
- "url": "https://github.com/symfony/var-dumper.git",
- "reference": "e03ad7c1535e623edbb94c22cc42353e488c6670"
+ "url": "https://github.com/symfony/twig-bridge.git",
+ "reference": "d16aa4eb5bdaeb6e7407782431dc70530f3b1df5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e03ad7c1535e623edbb94c22cc42353e488c6670",
- "reference": "e03ad7c1535e623edbb94c22cc42353e488c6670",
+ "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/d16aa4eb5bdaeb6e7407782431dc70530f3b1df5",
+ "reference": "d16aa4eb5bdaeb6e7407782431dc70530f3b1df5",
"shasum": ""
},
"require": {
"php": ">=8.2",
- "symfony/polyfill-mbstring": "~1.0"
+ "symfony/translation-contracts": "^2.5|^3",
+ "twig/twig": "^3.0.4"
},
"conflict": {
- "symfony/console": "<6.4"
+ "phpdocumentor/reflection-docblock": "<3.2.2",
+ "phpdocumentor/type-resolver": "<1.4.0",
+ "symfony/console": "<6.4",
+ "symfony/form": "<6.4",
+ "symfony/http-foundation": "<6.4",
+ "symfony/http-kernel": "<6.4",
+ "symfony/mime": "<6.4",
+ "symfony/serializer": "<6.4",
+ "symfony/translation": "<6.4",
+ "symfony/workflow": "<6.4"
},
"require-dev": {
- "ext-iconv": "*",
+ "egulias/email-validator": "^2.1.10|^3|^4",
+ "league/html-to-markdown": "^5.0",
+ "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
+ "symfony/asset": "^6.4|^7.0",
+ "symfony/asset-mapper": "^6.4|^7.0",
"symfony/console": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/finder": "^6.4|^7.0",
+ "symfony/form": "^6.4|^7.0",
+ "symfony/html-sanitizer": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
"symfony/http-kernel": "^6.4|^7.0",
- "symfony/process": "^6.4|^7.0",
- "symfony/uid": "^6.4|^7.0",
- "twig/twig": "^3.0.4"
+ "symfony/intl": "^6.4|^7.0",
+ "symfony/mime": "^6.4|^7.0",
+ "symfony/polyfill-intl-icu": "~1.0",
+ "symfony/property-info": "^6.4|^7.0",
+ "symfony/routing": "^6.4|^7.0",
+ "symfony/security-acl": "^2.8|^3.0",
+ "symfony/security-core": "^6.4|^7.0",
+ "symfony/security-csrf": "^6.4|^7.0",
+ "symfony/security-http": "^6.4|^7.0",
+ "symfony/serializer": "^6.4.3|^7.0.3",
+ "symfony/stopwatch": "^6.4|^7.0",
+ "symfony/translation": "^6.4|^7.0",
+ "symfony/web-link": "^6.4|^7.0",
+ "symfony/workflow": "^6.4|^7.0",
+ "symfony/yaml": "^6.4|^7.0",
+ "twig/cssinliner-extra": "^2.12|^3",
+ "twig/inky-extra": "^2.12|^3",
+ "twig/markdown-extra": "^2.12|^3"
},
- "bin": [
- "Resources/bin/var-dump-server"
- ],
- "type": "library",
+ "type": "symfony-bridge",
"autoload": {
- "files": [
- "Resources/functions/dump.php"
- ],
"psr-4": {
- "Symfony\\Component\\VarDumper\\": ""
+ "Symfony\\Bridge\\Twig\\": ""
},
"exclude-from-classmap": [
"/Tests/"
@@ -4965,22 +4830,18 @@
],
"authors": [
{
- "name": "Nicolas Grekas",
- "email": "p@tchwork.com"
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Provides mechanisms for walking through any arbitrary PHP variable",
+ "description": "Provides integration for Twig with various Symfony components",
"homepage": "https://symfony.com",
- "keywords": [
- "debug",
- "dump"
- ],
"support": {
- "source": "https://github.com/symfony/var-dumper/tree/v7.0.4"
+ "source": "https://github.com/symfony/twig-bridge/tree/v7.0.4"
},
"funding": [
{
@@ -4999,23 +4860,264 @@
"time": "2024-02-15T11:33:06+00:00"
},
{
- "name": "symfony/var-exporter",
+ "name": "symfony/twig-bundle",
"version": "v7.0.4",
"source": {
"type": "git",
- "url": "https://github.com/symfony/var-exporter.git",
- "reference": "dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41"
+ "url": "https://github.com/symfony/twig-bundle.git",
+ "reference": "acab2368f53491e018bf31ef48b39df55a6812ef"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/var-exporter/zipball/dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41",
- "reference": "dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41",
+ "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/acab2368f53491e018bf31ef48b39df55a6812ef",
+ "reference": "acab2368f53491e018bf31ef48b39df55a6812ef",
"shasum": ""
},
"require": {
- "php": ">=8.2"
+ "composer-runtime-api": ">=2.1",
+ "php": ">=8.2",
+ "symfony/config": "^6.4|^7.0",
+ "symfony/dependency-injection": "^6.4|^7.0",
+ "symfony/http-foundation": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/twig-bridge": "^6.4|^7.0",
+ "twig/twig": "^3.0.4"
},
- "require-dev": {
+ "conflict": {
+ "symfony/framework-bundle": "<6.4",
+ "symfony/translation": "<6.4"
+ },
+ "require-dev": {
+ "symfony/asset": "^6.4|^7.0",
+ "symfony/expression-language": "^6.4|^7.0",
+ "symfony/finder": "^6.4|^7.0",
+ "symfony/form": "^6.4|^7.0",
+ "symfony/framework-bundle": "^6.4|^7.0",
+ "symfony/routing": "^6.4|^7.0",
+ "symfony/stopwatch": "^6.4|^7.0",
+ "symfony/translation": "^6.4|^7.0",
+ "symfony/web-link": "^6.4|^7.0",
+ "symfony/yaml": "^6.4|^7.0"
+ },
+ "type": "symfony-bundle",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Bundle\\TwigBundle\\": ""
+ },
+ "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 a tight integration of Twig into the Symfony full-stack framework",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/twig-bundle/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-15T11:33:06+00:00"
+ },
+ {
+ "name": "symfony/uid",
+ "version": "v7.0.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/uid.git",
+ "reference": "87cedaf3fabd7b733859d4d77aa4ca598259054b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/uid/zipball/87cedaf3fabd7b733859d4d77aa4ca598259054b",
+ "reference": "87cedaf3fabd7b733859d4d77aa4ca598259054b",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-uuid": "^1.15"
+ },
+ "require-dev": {
+ "symfony/console": "^6.4|^7.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Uid\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Grégoire Pineau",
+ "email": "lyrixx@lyrixx.info"
+ },
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides an object-oriented API to generate and represent UIDs",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "UID",
+ "ulid",
+ "uuid"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/uid/tree/v7.0.3"
+ },
+ "funding": [
+ {
+ "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": "2024-01-23T15:02:46+00:00"
+ },
+ {
+ "name": "symfony/var-dumper",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/var-dumper.git",
+ "reference": "e03ad7c1535e623edbb94c22cc42353e488c6670"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e03ad7c1535e623edbb94c22cc42353e488c6670",
+ "reference": "e03ad7c1535e623edbb94c22cc42353e488c6670",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "conflict": {
+ "symfony/console": "<6.4"
+ },
+ "require-dev": {
+ "ext-iconv": "*",
+ "symfony/console": "^6.4|^7.0",
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/process": "^6.4|^7.0",
+ "symfony/uid": "^6.4|^7.0",
+ "twig/twig": "^3.0.4"
+ },
+ "bin": [
+ "Resources/bin/var-dump-server"
+ ],
+ "type": "library",
+ "autoload": {
+ "files": [
+ "Resources/functions/dump.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\VarDumper\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "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": "Provides mechanisms for walking through any arbitrary PHP variable",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "debug",
+ "dump"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/var-dumper/tree/v7.0.4"
+ },
+ "funding": [
+ {
+ "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": "2024-02-15T11:33:06+00:00"
+ },
+ {
+ "name": "symfony/var-exporter",
+ "version": "v7.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/var-exporter.git",
+ "reference": "dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/var-exporter/zipball/dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41",
+ "reference": "dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.2"
+ },
+ "require-dev": {
"symfony/var-dumper": "^6.4|^7.0"
},
"type": "library",
@@ -5144,62 +5246,76 @@
"time": "2024-01-23T15:02:46+00:00"
},
{
- "name": "webmozart/assert",
- "version": "1.11.0",
+ "name": "twig/twig",
+ "version": "v3.8.0",
"source": {
"type": "git",
- "url": "https://github.com/webmozarts/assert.git",
- "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
+ "url": "https://github.com/twigphp/Twig.git",
+ "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
- "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
+ "url": "https://api.github.com/repos/twigphp/Twig/zipball/9d15f0ac07f44dc4217883ec6ae02fd555c6f71d",
+ "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d",
"shasum": ""
},
"require": {
- "ext-ctype": "*",
- "php": "^7.2 || ^8.0"
- },
- "conflict": {
- "phpstan/phpstan": "<0.12.20",
- "vimeo/psalm": "<4.6.1 || 4.6.2"
+ "php": ">=7.2.5",
+ "symfony/polyfill-ctype": "^1.8",
+ "symfony/polyfill-mbstring": "^1.3",
+ "symfony/polyfill-php80": "^1.22"
},
"require-dev": {
- "phpunit/phpunit": "^8.5.13"
+ "psr/container": "^1.0|^2.0",
+ "symfony/phpunit-bridge": "^5.4.9|^6.3|^7.0"
},
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "1.10-dev"
- }
- },
"autoload": {
"psr-4": {
- "Webmozart\\Assert\\": "src/"
+ "Twig\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "MIT"
+ "BSD-3-Clause"
],
"authors": [
{
- "name": "Bernhard Schussek",
- "email": "bschussek@gmail.com"
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com",
+ "homepage": "http://fabien.potencier.org",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Twig Team",
+ "role": "Contributors"
+ },
+ {
+ "name": "Armin Ronacher",
+ "email": "armin.ronacher@active-4.com",
+ "role": "Project Founder"
}
],
- "description": "Assertions to validate method input/output with nice error messages.",
+ "description": "Twig, the flexible, fast, and secure template language for PHP",
+ "homepage": "https://twig.symfony.com",
"keywords": [
- "assert",
- "check",
- "validate"
+ "templating"
],
"support": {
- "issues": "https://github.com/webmozarts/assert/issues",
- "source": "https://github.com/webmozarts/assert/tree/1.11.0"
+ "issues": "https://github.com/twigphp/Twig/issues",
+ "source": "https://github.com/twigphp/Twig/tree/v3.8.0"
},
- "time": "2022-06-03T18:03:27+00:00"
+ "funding": [
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/twig/twig",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2023-11-21T18:54:41+00:00"
}
],
"packages-dev": [
@@ -6916,276 +7032,56 @@
"symfony/filesystem": "^6.4|^7.0",
"symfony/finder": "^6.4|^7.0",
"symfony/framework-bundle": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/process": "^6.4|^7.0"
- },
- "conflict": {
- "doctrine/doctrine-bundle": "<2.10",
- "doctrine/orm": "<2.15"
- },
- "require-dev": {
- "composer/semver": "^3.0",
- "doctrine/doctrine-bundle": "^2.5.0",
- "doctrine/orm": "^2.15|^3",
- "symfony/http-client": "^6.4|^7.0",
- "symfony/phpunit-bridge": "^6.4.1|^7.0",
- "symfony/security-core": "^6.4|^7.0",
- "symfony/yaml": "^6.4|^7.0",
- "twig/twig": "^3.0|^4.x-dev"
- },
- "type": "symfony-bundle",
- "extra": {
- "branch-alias": {
- "dev-main": "1.x-dev"
- }
- },
- "autoload": {
- "psr-4": {
- "Symfony\\Bundle\\MakerBundle\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Symfony Community",
- "homepage": "https://symfony.com/contributors"
- }
- ],
- "description": "Symfony Maker helps you create empty commands, controllers, form classes, tests and more so you can forget about writing boilerplate code.",
- "homepage": "https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html",
- "keywords": [
- "code generator",
- "dev",
- "generator",
- "scaffold",
- "scaffolding"
- ],
- "support": {
- "issues": "https://github.com/symfony/maker-bundle/issues",
- "source": "https://github.com/symfony/maker-bundle/tree/v1.55.1"
- },
- "funding": [
- {
- "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": "2024-02-21T13:41:51+00:00"
- },
- {
- "name": "symfony/phpunit-bridge",
- "version": "v7.0.4",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/phpunit-bridge.git",
- "reference": "54ca13ec990a40411ad978e08d994fca6cdd865f"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/54ca13ec990a40411ad978e08d994fca6cdd865f",
- "reference": "54ca13ec990a40411ad978e08d994fca6cdd865f",
- "shasum": ""
- },
- "require": {
- "php": ">=7.2.5"
- },
- "conflict": {
- "phpunit/phpunit": "<7.5|9.1.2"
- },
- "require-dev": {
- "symfony/deprecation-contracts": "^2.5|^3.0",
- "symfony/error-handler": "^5.4|^6.4|^7.0",
- "symfony/polyfill-php81": "^1.27"
- },
- "bin": [
- "bin/simple-phpunit"
- ],
- "type": "symfony-bridge",
- "extra": {
- "thanks": {
- "name": "phpunit/phpunit",
- "url": "https://github.com/sebastianbergmann/phpunit"
- }
- },
- "autoload": {
- "files": [
- "bootstrap.php"
- ],
- "psr-4": {
- "Symfony\\Bridge\\PhpUnit\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
- },
- "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": "Provides utilities for PHPUnit, especially user deprecation notices management",
- "homepage": "https://symfony.com",
- "support": {
- "source": "https://github.com/symfony/phpunit-bridge/tree/v7.0.4"
- },
- "funding": [
- {
- "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": "2024-02-08T19:22:56+00:00"
- },
- {
- "name": "symfony/process",
- "version": "v7.0.4",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/process.git",
- "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/0e7727191c3b71ebec6d529fa0e50a01ca5679e9",
- "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9",
- "shasum": ""
- },
- "require": {
- "php": ">=8.2"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Symfony\\Component\\Process\\": ""
- },
- "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": "Executes commands in sub-processes",
- "homepage": "https://symfony.com",
- "support": {
- "source": "https://github.com/symfony/process/tree/v7.0.4"
- },
- "funding": [
- {
- "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": "2024-02-22T20:27:20+00:00"
- },
- {
- "name": "symfony/translation-contracts",
- "version": "v3.4.1",
- "source": {
- "type": "git",
- "url": "https://github.com/symfony/translation-contracts.git",
- "reference": "06450585bf65e978026bda220cdebca3f867fde7"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/06450585bf65e978026bda220cdebca3f867fde7",
- "reference": "06450585bf65e978026bda220cdebca3f867fde7",
- "shasum": ""
+ "symfony/http-kernel": "^6.4|^7.0",
+ "symfony/process": "^6.4|^7.0"
},
- "require": {
- "php": ">=8.1"
+ "conflict": {
+ "doctrine/doctrine-bundle": "<2.10",
+ "doctrine/orm": "<2.15"
},
- "type": "library",
+ "require-dev": {
+ "composer/semver": "^3.0",
+ "doctrine/doctrine-bundle": "^2.5.0",
+ "doctrine/orm": "^2.15|^3",
+ "symfony/http-client": "^6.4|^7.0",
+ "symfony/phpunit-bridge": "^6.4.1|^7.0",
+ "symfony/security-core": "^6.4|^7.0",
+ "symfony/yaml": "^6.4|^7.0",
+ "twig/twig": "^3.0|^4.x-dev"
+ },
+ "type": "symfony-bundle",
"extra": {
"branch-alias": {
- "dev-main": "3.4-dev"
- },
- "thanks": {
- "name": "symfony/contracts",
- "url": "https://github.com/symfony/contracts"
+ "dev-main": "1.x-dev"
}
},
"autoload": {
"psr-4": {
- "Symfony\\Contracts\\Translation\\": ""
- },
- "exclude-from-classmap": [
- "/Test/"
- ]
+ "Symfony\\Bundle\\MakerBundle\\": "src/"
+ }
},
"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 translation",
- "homepage": "https://symfony.com",
+ "description": "Symfony Maker helps you create empty commands, controllers, form classes, tests and more so you can forget about writing boilerplate code.",
+ "homepage": "https://symfony.com/doc/current/bundles/SymfonyMakerBundle/index.html",
"keywords": [
- "abstractions",
- "contracts",
- "decoupling",
- "interfaces",
- "interoperability",
- "standards"
+ "code generator",
+ "dev",
+ "generator",
+ "scaffold",
+ "scaffolding"
],
"support": {
- "source": "https://github.com/symfony/translation-contracts/tree/v3.4.1"
+ "issues": "https://github.com/symfony/maker-bundle/issues",
+ "source": "https://github.com/symfony/maker-bundle/tree/v1.55.1"
},
"funding": [
{
@@ -7201,76 +7097,49 @@
"type": "tidelift"
}
],
- "time": "2023-12-26T14:02:43+00:00"
+ "time": "2024-02-21T13:41:51+00:00"
},
{
- "name": "symfony/twig-bridge",
+ "name": "symfony/phpunit-bridge",
"version": "v7.0.4",
"source": {
"type": "git",
- "url": "https://github.com/symfony/twig-bridge.git",
- "reference": "d16aa4eb5bdaeb6e7407782431dc70530f3b1df5"
+ "url": "https://github.com/symfony/phpunit-bridge.git",
+ "reference": "54ca13ec990a40411ad978e08d994fca6cdd865f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/d16aa4eb5bdaeb6e7407782431dc70530f3b1df5",
- "reference": "d16aa4eb5bdaeb6e7407782431dc70530f3b1df5",
+ "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/54ca13ec990a40411ad978e08d994fca6cdd865f",
+ "reference": "54ca13ec990a40411ad978e08d994fca6cdd865f",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/translation-contracts": "^2.5|^3",
- "twig/twig": "^3.0.4"
+ "php": ">=7.2.5"
},
"conflict": {
- "phpdocumentor/reflection-docblock": "<3.2.2",
- "phpdocumentor/type-resolver": "<1.4.0",
- "symfony/console": "<6.4",
- "symfony/form": "<6.4",
- "symfony/http-foundation": "<6.4",
- "symfony/http-kernel": "<6.4",
- "symfony/mime": "<6.4",
- "symfony/serializer": "<6.4",
- "symfony/translation": "<6.4",
- "symfony/workflow": "<6.4"
+ "phpunit/phpunit": "<7.5|9.1.2"
},
"require-dev": {
- "egulias/email-validator": "^2.1.10|^3|^4",
- "league/html-to-markdown": "^5.0",
- "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
- "symfony/asset": "^6.4|^7.0",
- "symfony/asset-mapper": "^6.4|^7.0",
- "symfony/console": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/finder": "^6.4|^7.0",
- "symfony/form": "^6.4|^7.0",
- "symfony/html-sanitizer": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/intl": "^6.4|^7.0",
- "symfony/mime": "^6.4|^7.0",
- "symfony/polyfill-intl-icu": "~1.0",
- "symfony/property-info": "^6.4|^7.0",
- "symfony/routing": "^6.4|^7.0",
- "symfony/security-acl": "^2.8|^3.0",
- "symfony/security-core": "^6.4|^7.0",
- "symfony/security-csrf": "^6.4|^7.0",
- "symfony/security-http": "^6.4|^7.0",
- "symfony/serializer": "^6.4.3|^7.0.3",
- "symfony/stopwatch": "^6.4|^7.0",
- "symfony/translation": "^6.4|^7.0",
- "symfony/web-link": "^6.4|^7.0",
- "symfony/workflow": "^6.4|^7.0",
- "symfony/yaml": "^6.4|^7.0",
- "twig/cssinliner-extra": "^2.12|^3",
- "twig/inky-extra": "^2.12|^3",
- "twig/markdown-extra": "^2.12|^3"
+ "symfony/deprecation-contracts": "^2.5|^3.0",
+ "symfony/error-handler": "^5.4|^6.4|^7.0",
+ "symfony/polyfill-php81": "^1.27"
},
+ "bin": [
+ "bin/simple-phpunit"
+ ],
"type": "symfony-bridge",
+ "extra": {
+ "thanks": {
+ "name": "phpunit/phpunit",
+ "url": "https://github.com/sebastianbergmann/phpunit"
+ }
+ },
"autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
"psr-4": {
- "Symfony\\Bridge\\Twig\\": ""
+ "Symfony\\Bridge\\PhpUnit\\": ""
},
"exclude-from-classmap": [
"/Tests/"
@@ -7282,18 +7151,18 @@
],
"authors": [
{
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Provides integration for Twig with various Symfony components",
+ "description": "Provides utilities for PHPUnit, especially user deprecation notices management",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/twig-bridge/tree/v7.0.4"
+ "source": "https://github.com/symfony/phpunit-bridge/tree/v7.0.4"
},
"funding": [
{
@@ -7309,52 +7178,29 @@
"type": "tidelift"
}
],
- "time": "2024-02-15T11:33:06+00:00"
+ "time": "2024-02-08T19:22:56+00:00"
},
{
- "name": "symfony/twig-bundle",
+ "name": "symfony/process",
"version": "v7.0.4",
"source": {
"type": "git",
- "url": "https://github.com/symfony/twig-bundle.git",
- "reference": "acab2368f53491e018bf31ef48b39df55a6812ef"
+ "url": "https://github.com/symfony/process.git",
+ "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/acab2368f53491e018bf31ef48b39df55a6812ef",
- "reference": "acab2368f53491e018bf31ef48b39df55a6812ef",
+ "url": "https://api.github.com/repos/symfony/process/zipball/0e7727191c3b71ebec6d529fa0e50a01ca5679e9",
+ "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9",
"shasum": ""
},
"require": {
- "composer-runtime-api": ">=2.1",
- "php": ">=8.2",
- "symfony/config": "^6.4|^7.0",
- "symfony/dependency-injection": "^6.4|^7.0",
- "symfony/http-foundation": "^6.4|^7.0",
- "symfony/http-kernel": "^6.4|^7.0",
- "symfony/twig-bridge": "^6.4|^7.0",
- "twig/twig": "^3.0.4"
- },
- "conflict": {
- "symfony/framework-bundle": "<6.4",
- "symfony/translation": "<6.4"
- },
- "require-dev": {
- "symfony/asset": "^6.4|^7.0",
- "symfony/expression-language": "^6.4|^7.0",
- "symfony/finder": "^6.4|^7.0",
- "symfony/form": "^6.4|^7.0",
- "symfony/framework-bundle": "^6.4|^7.0",
- "symfony/routing": "^6.4|^7.0",
- "symfony/stopwatch": "^6.4|^7.0",
- "symfony/translation": "^6.4|^7.0",
- "symfony/web-link": "^6.4|^7.0",
- "symfony/yaml": "^6.4|^7.0"
+ "php": ">=8.2"
},
- "type": "symfony-bundle",
+ "type": "library",
"autoload": {
"psr-4": {
- "Symfony\\Bundle\\TwigBundle\\": ""
+ "Symfony\\Component\\Process\\": ""
},
"exclude-from-classmap": [
"/Tests/"
@@ -7374,10 +7220,10 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Provides a tight integration of Twig into the Symfony full-stack framework",
+ "description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/twig-bundle/tree/v7.0.4"
+ "source": "https://github.com/symfony/process/tree/v7.0.4"
},
"funding": [
{
@@ -7393,7 +7239,7 @@
"type": "tidelift"
}
],
- "time": "2024-02-15T11:33:06+00:00"
+ "time": "2024-02-22T20:27:20+00:00"
},
{
"name": "symfony/web-profiler-bundle",
@@ -7525,78 +7371,6 @@
}
],
"time": "2023-11-20T00:12:19+00:00"
- },
- {
- "name": "twig/twig",
- "version": "v3.8.0",
- "source": {
- "type": "git",
- "url": "https://github.com/twigphp/Twig.git",
- "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/twigphp/Twig/zipball/9d15f0ac07f44dc4217883ec6ae02fd555c6f71d",
- "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d",
- "shasum": ""
- },
- "require": {
- "php": ">=7.2.5",
- "symfony/polyfill-ctype": "^1.8",
- "symfony/polyfill-mbstring": "^1.3",
- "symfony/polyfill-php80": "^1.22"
- },
- "require-dev": {
- "psr/container": "^1.0|^2.0",
- "symfony/phpunit-bridge": "^5.4.9|^6.3|^7.0"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Twig\\": "src/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Fabien Potencier",
- "email": "fabien@symfony.com",
- "homepage": "http://fabien.potencier.org",
- "role": "Lead Developer"
- },
- {
- "name": "Twig Team",
- "role": "Contributors"
- },
- {
- "name": "Armin Ronacher",
- "email": "armin.ronacher@active-4.com",
- "role": "Project Founder"
- }
- ],
- "description": "Twig, the flexible, fast, and secure template language for PHP",
- "homepage": "https://twig.symfony.com",
- "keywords": [
- "templating"
- ],
- "support": {
- "issues": "https://github.com/twigphp/Twig/issues",
- "source": "https://github.com/twigphp/Twig/tree/v3.8.0"
- },
- "funding": [
- {
- "url": "https://github.com/fabpot",
- "type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/twig/twig",
- "type": "tidelift"
- }
- ],
- "time": "2023-11-21T18:54:41+00:00"
}
],
"aliases": [],