From bae45b1cc1c4f139a0d22733996b5bf4328b31de Mon Sep 17 00:00:00 2001 From: "Nikola Svitlica a.k.a TheCelavi" Date: Tue, 23 Dec 2025 16:08:10 +0100 Subject: [PATCH 01/13] prepare release --- .../Bundle/MetadataBundle/composer.json | 41 +------------------ .../Bundle/QueryBundle/composer.json | 41 +------------------ .../Component/Bitmask/composer.json | 39 +----------------- .../Component/Dataset/composer.json | 39 +----------------- .../Component/Metadata/composer.json | 39 +----------------- src/RunOpenCode/Component/Query/composer.json | 41 +------------------ 6 files changed, 9 insertions(+), 231 deletions(-) diff --git a/src/RunOpenCode/Bundle/MetadataBundle/composer.json b/src/RunOpenCode/Bundle/MetadataBundle/composer.json index e3ccb93..5f5d17d 100644 --- a/src/RunOpenCode/Bundle/MetadataBundle/composer.json +++ b/src/RunOpenCode/Bundle/MetadataBundle/composer.json @@ -11,7 +11,7 @@ "require": { "php": ">=8.4", "psr/cache": "^3.0", - "runopencode/metadata": "^0.2", + "runopencode/metadata": "^0.1.37", "symfony/cache": "^7.0", "symfony/config": "^7.0", "symfony/dependency-injection": "^7.0", @@ -22,47 +22,10 @@ "RunOpenCode\\Bundle\\MetadataBundle\\": "src/" } }, - "repositories": [ - { - "type": "path", - "url": "../../Component/Dataset", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Bitmask", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Query", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Metadata", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/QueryBundle", - "options": { - "symlink": false - } - } - ], "config": { "sort-packages": true }, - "version": "0.2", + "version": "0.1.37", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Bundle/QueryBundle/composer.json b/src/RunOpenCode/Bundle/QueryBundle/composer.json index d253b73..247b1e4 100644 --- a/src/RunOpenCode/Bundle/QueryBundle/composer.json +++ b/src/RunOpenCode/Bundle/QueryBundle/composer.json @@ -13,7 +13,7 @@ "psr/cache": "^3.0", "psr/container": "^2.0", "psr/log": "^2.0|^3.0", - "runopencode/query": "^0.2", + "runopencode/query": "^0.1.37", "symfony/config": "^7.0", "symfony/dependency-injection": "^7.0", "symfony/finder": "^7.0", @@ -26,47 +26,10 @@ "RunOpenCode\\Bundle\\QueryBundle\\": "src/" } }, - "repositories": [ - { - "type": "path", - "url": "../../Component/Dataset", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Bitmask", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Query", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Metadata", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/MetadataBundle", - "options": { - "symlink": false - } - } - ], "config": { "sort-packages": true }, - "version": "0.2", + "version": "0.1.37", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Bitmask/composer.json b/src/RunOpenCode/Component/Bitmask/composer.json index e501d51..ccf43fc 100644 --- a/src/RunOpenCode/Component/Bitmask/composer.json +++ b/src/RunOpenCode/Component/Bitmask/composer.json @@ -19,47 +19,10 @@ "RunOpenCode\\Component\\Bitmask\\": "src" } }, - "repositories": [ - { - "type": "path", - "url": "../../Component/Dataset", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Query", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Metadata", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/MetadataBundle", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/QueryBundle", - "options": { - "symlink": false - } - } - ], "config": { "sort-packages": true }, - "version": "0.2", + "version": "0.1.37", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Dataset/composer.json b/src/RunOpenCode/Component/Dataset/composer.json index 549600b..cdefc80 100644 --- a/src/RunOpenCode/Component/Dataset/composer.json +++ b/src/RunOpenCode/Component/Dataset/composer.json @@ -23,47 +23,10 @@ "src/functions.php" ] }, - "repositories": [ - { - "type": "path", - "url": "../../Component/Bitmask", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Query", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Metadata", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/MetadataBundle", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/QueryBundle", - "options": { - "symlink": false - } - } - ], "config": { "sort-packages": true }, - "version": "0.2", + "version": "0.1.37", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Metadata/composer.json b/src/RunOpenCode/Component/Metadata/composer.json index a38f5f6..6215d13 100644 --- a/src/RunOpenCode/Component/Metadata/composer.json +++ b/src/RunOpenCode/Component/Metadata/composer.json @@ -18,47 +18,10 @@ "RunOpenCode\\Component\\Metadata\\": "src/" } }, - "repositories": [ - { - "type": "path", - "url": "../../Component/Dataset", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Bitmask", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Query", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/MetadataBundle", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/QueryBundle", - "options": { - "symlink": false - } - } - ], "config": { "sort-packages": true }, - "version": "0.2", + "version": "0.1.37", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Query/composer.json b/src/RunOpenCode/Component/Query/composer.json index 1376c4c..3b8518a 100644 --- a/src/RunOpenCode/Component/Query/composer.json +++ b/src/RunOpenCode/Component/Query/composer.json @@ -14,7 +14,7 @@ "doctrine/dbal": "^4.0", "psr/cache": "^3.0", "psr/log": "^2.0|^3.0", - "runopencode/dataset": "^0.2", + "runopencode/dataset": "^0.1.37", "symfony/cache": "^7.0", "symfony/finder": "^7.0", "thecodingmachine/safe": "^3.3", @@ -28,47 +28,10 @@ "src/functions.php" ] }, - "repositories": [ - { - "type": "path", - "url": "../../Component/Dataset", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Bitmask", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Metadata", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/MetadataBundle", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/QueryBundle", - "options": { - "symlink": false - } - } - ], "config": { "sort-packages": true }, - "version": "0.2", + "version": "0.1.37", "minimum-stability": "dev", "prefer-stable": true } From 5467fbd91cc5a7de0e9b1d027a80dc3cd5c45eda Mon Sep 17 00:00:00 2001 From: "Nikola Svitlica a.k.a TheCelavi" Date: Tue, 23 Dec 2025 16:08:14 +0100 Subject: [PATCH 02/13] open 0.2-dev --- .../Bundle/MetadataBundle/composer.json | 41 ++++++++++++++++++- .../Bundle/QueryBundle/composer.json | 41 ++++++++++++++++++- .../Component/Bitmask/composer.json | 39 +++++++++++++++++- .../Component/Dataset/composer.json | 39 +++++++++++++++++- .../Component/Metadata/composer.json | 39 +++++++++++++++++- src/RunOpenCode/Component/Query/composer.json | 41 ++++++++++++++++++- 6 files changed, 231 insertions(+), 9 deletions(-) diff --git a/src/RunOpenCode/Bundle/MetadataBundle/composer.json b/src/RunOpenCode/Bundle/MetadataBundle/composer.json index 5f5d17d..e3ccb93 100644 --- a/src/RunOpenCode/Bundle/MetadataBundle/composer.json +++ b/src/RunOpenCode/Bundle/MetadataBundle/composer.json @@ -11,7 +11,7 @@ "require": { "php": ">=8.4", "psr/cache": "^3.0", - "runopencode/metadata": "^0.1.37", + "runopencode/metadata": "^0.2", "symfony/cache": "^7.0", "symfony/config": "^7.0", "symfony/dependency-injection": "^7.0", @@ -22,10 +22,47 @@ "RunOpenCode\\Bundle\\MetadataBundle\\": "src/" } }, + "repositories": [ + { + "type": "path", + "url": "../../Component/Dataset", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Bitmask", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Query", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Metadata", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/QueryBundle", + "options": { + "symlink": false + } + } + ], "config": { "sort-packages": true }, - "version": "0.1.37", + "version": "0.2", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Bundle/QueryBundle/composer.json b/src/RunOpenCode/Bundle/QueryBundle/composer.json index 247b1e4..d253b73 100644 --- a/src/RunOpenCode/Bundle/QueryBundle/composer.json +++ b/src/RunOpenCode/Bundle/QueryBundle/composer.json @@ -13,7 +13,7 @@ "psr/cache": "^3.0", "psr/container": "^2.0", "psr/log": "^2.0|^3.0", - "runopencode/query": "^0.1.37", + "runopencode/query": "^0.2", "symfony/config": "^7.0", "symfony/dependency-injection": "^7.0", "symfony/finder": "^7.0", @@ -26,10 +26,47 @@ "RunOpenCode\\Bundle\\QueryBundle\\": "src/" } }, + "repositories": [ + { + "type": "path", + "url": "../../Component/Dataset", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Bitmask", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Query", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Metadata", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/MetadataBundle", + "options": { + "symlink": false + } + } + ], "config": { "sort-packages": true }, - "version": "0.1.37", + "version": "0.2", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Bitmask/composer.json b/src/RunOpenCode/Component/Bitmask/composer.json index ccf43fc..e501d51 100644 --- a/src/RunOpenCode/Component/Bitmask/composer.json +++ b/src/RunOpenCode/Component/Bitmask/composer.json @@ -19,10 +19,47 @@ "RunOpenCode\\Component\\Bitmask\\": "src" } }, + "repositories": [ + { + "type": "path", + "url": "../../Component/Dataset", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Query", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Metadata", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/MetadataBundle", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/QueryBundle", + "options": { + "symlink": false + } + } + ], "config": { "sort-packages": true }, - "version": "0.1.37", + "version": "0.2", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Dataset/composer.json b/src/RunOpenCode/Component/Dataset/composer.json index cdefc80..549600b 100644 --- a/src/RunOpenCode/Component/Dataset/composer.json +++ b/src/RunOpenCode/Component/Dataset/composer.json @@ -23,10 +23,47 @@ "src/functions.php" ] }, + "repositories": [ + { + "type": "path", + "url": "../../Component/Bitmask", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Query", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Metadata", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/MetadataBundle", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/QueryBundle", + "options": { + "symlink": false + } + } + ], "config": { "sort-packages": true }, - "version": "0.1.37", + "version": "0.2", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Metadata/composer.json b/src/RunOpenCode/Component/Metadata/composer.json index 6215d13..a38f5f6 100644 --- a/src/RunOpenCode/Component/Metadata/composer.json +++ b/src/RunOpenCode/Component/Metadata/composer.json @@ -18,10 +18,47 @@ "RunOpenCode\\Component\\Metadata\\": "src/" } }, + "repositories": [ + { + "type": "path", + "url": "../../Component/Dataset", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Bitmask", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Query", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/MetadataBundle", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/QueryBundle", + "options": { + "symlink": false + } + } + ], "config": { "sort-packages": true }, - "version": "0.1.37", + "version": "0.2", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Query/composer.json b/src/RunOpenCode/Component/Query/composer.json index 3b8518a..1376c4c 100644 --- a/src/RunOpenCode/Component/Query/composer.json +++ b/src/RunOpenCode/Component/Query/composer.json @@ -14,7 +14,7 @@ "doctrine/dbal": "^4.0", "psr/cache": "^3.0", "psr/log": "^2.0|^3.0", - "runopencode/dataset": "^0.1.37", + "runopencode/dataset": "^0.2", "symfony/cache": "^7.0", "symfony/finder": "^7.0", "thecodingmachine/safe": "^3.3", @@ -28,10 +28,47 @@ "src/functions.php" ] }, + "repositories": [ + { + "type": "path", + "url": "../../Component/Dataset", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Bitmask", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Metadata", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/MetadataBundle", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/QueryBundle", + "options": { + "symlink": false + } + } + ], "config": { "sort-packages": true }, - "version": "0.1.37", + "version": "0.2", "minimum-stability": "dev", "prefer-stable": true } From 63455d198b467a34057097519af2097234be42cb Mon Sep 17 00:00:00 2001 From: "Nikola Svitlica a.k.a TheCelavi" Date: Tue, 23 Dec 2025 16:09:48 +0100 Subject: [PATCH 03/13] prepare release --- .../Bundle/MetadataBundle/composer.json | 41 +------------------ .../Bundle/QueryBundle/composer.json | 41 +------------------ .../Component/Bitmask/composer.json | 39 +----------------- .../Component/Dataset/composer.json | 39 +----------------- .../Component/Metadata/composer.json | 39 +----------------- src/RunOpenCode/Component/Query/composer.json | 41 +------------------ 6 files changed, 9 insertions(+), 231 deletions(-) diff --git a/src/RunOpenCode/Bundle/MetadataBundle/composer.json b/src/RunOpenCode/Bundle/MetadataBundle/composer.json index e3ccb93..4e29f12 100644 --- a/src/RunOpenCode/Bundle/MetadataBundle/composer.json +++ b/src/RunOpenCode/Bundle/MetadataBundle/composer.json @@ -11,7 +11,7 @@ "require": { "php": ">=8.4", "psr/cache": "^3.0", - "runopencode/metadata": "^0.2", + "runopencode/metadata": "^0.1.38", "symfony/cache": "^7.0", "symfony/config": "^7.0", "symfony/dependency-injection": "^7.0", @@ -22,47 +22,10 @@ "RunOpenCode\\Bundle\\MetadataBundle\\": "src/" } }, - "repositories": [ - { - "type": "path", - "url": "../../Component/Dataset", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Bitmask", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Query", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Metadata", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/QueryBundle", - "options": { - "symlink": false - } - } - ], "config": { "sort-packages": true }, - "version": "0.2", + "version": "0.1.38", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Bundle/QueryBundle/composer.json b/src/RunOpenCode/Bundle/QueryBundle/composer.json index d253b73..af8a298 100644 --- a/src/RunOpenCode/Bundle/QueryBundle/composer.json +++ b/src/RunOpenCode/Bundle/QueryBundle/composer.json @@ -13,7 +13,7 @@ "psr/cache": "^3.0", "psr/container": "^2.0", "psr/log": "^2.0|^3.0", - "runopencode/query": "^0.2", + "runopencode/query": "^0.1.38", "symfony/config": "^7.0", "symfony/dependency-injection": "^7.0", "symfony/finder": "^7.0", @@ -26,47 +26,10 @@ "RunOpenCode\\Bundle\\QueryBundle\\": "src/" } }, - "repositories": [ - { - "type": "path", - "url": "../../Component/Dataset", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Bitmask", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Query", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Metadata", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/MetadataBundle", - "options": { - "symlink": false - } - } - ], "config": { "sort-packages": true }, - "version": "0.2", + "version": "0.1.38", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Bitmask/composer.json b/src/RunOpenCode/Component/Bitmask/composer.json index e501d51..d5890ee 100644 --- a/src/RunOpenCode/Component/Bitmask/composer.json +++ b/src/RunOpenCode/Component/Bitmask/composer.json @@ -19,47 +19,10 @@ "RunOpenCode\\Component\\Bitmask\\": "src" } }, - "repositories": [ - { - "type": "path", - "url": "../../Component/Dataset", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Query", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Metadata", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/MetadataBundle", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/QueryBundle", - "options": { - "symlink": false - } - } - ], "config": { "sort-packages": true }, - "version": "0.2", + "version": "0.1.38", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Dataset/composer.json b/src/RunOpenCode/Component/Dataset/composer.json index 549600b..bde0310 100644 --- a/src/RunOpenCode/Component/Dataset/composer.json +++ b/src/RunOpenCode/Component/Dataset/composer.json @@ -23,47 +23,10 @@ "src/functions.php" ] }, - "repositories": [ - { - "type": "path", - "url": "../../Component/Bitmask", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Query", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Metadata", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/MetadataBundle", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/QueryBundle", - "options": { - "symlink": false - } - } - ], "config": { "sort-packages": true }, - "version": "0.2", + "version": "0.1.38", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Metadata/composer.json b/src/RunOpenCode/Component/Metadata/composer.json index a38f5f6..5cfe77a 100644 --- a/src/RunOpenCode/Component/Metadata/composer.json +++ b/src/RunOpenCode/Component/Metadata/composer.json @@ -18,47 +18,10 @@ "RunOpenCode\\Component\\Metadata\\": "src/" } }, - "repositories": [ - { - "type": "path", - "url": "../../Component/Dataset", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Bitmask", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Query", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/MetadataBundle", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/QueryBundle", - "options": { - "symlink": false - } - } - ], "config": { "sort-packages": true }, - "version": "0.2", + "version": "0.1.38", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Query/composer.json b/src/RunOpenCode/Component/Query/composer.json index 1376c4c..8c83f90 100644 --- a/src/RunOpenCode/Component/Query/composer.json +++ b/src/RunOpenCode/Component/Query/composer.json @@ -14,7 +14,7 @@ "doctrine/dbal": "^4.0", "psr/cache": "^3.0", "psr/log": "^2.0|^3.0", - "runopencode/dataset": "^0.2", + "runopencode/dataset": "^0.1.38", "symfony/cache": "^7.0", "symfony/finder": "^7.0", "thecodingmachine/safe": "^3.3", @@ -28,47 +28,10 @@ "src/functions.php" ] }, - "repositories": [ - { - "type": "path", - "url": "../../Component/Dataset", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Bitmask", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Metadata", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/MetadataBundle", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/QueryBundle", - "options": { - "symlink": false - } - } - ], "config": { "sort-packages": true }, - "version": "0.2", + "version": "0.1.38", "minimum-stability": "dev", "prefer-stable": true } From 08734a772507fc6157d4bf7c2fa03f880e42684c Mon Sep 17 00:00:00 2001 From: "Nikola Svitlica a.k.a TheCelavi" Date: Tue, 23 Dec 2025 16:09:53 +0100 Subject: [PATCH 04/13] open 0.2-dev --- .../Bundle/MetadataBundle/composer.json | 41 ++++++++++++++++++- .../Bundle/QueryBundle/composer.json | 41 ++++++++++++++++++- .../Component/Bitmask/composer.json | 39 +++++++++++++++++- .../Component/Dataset/composer.json | 39 +++++++++++++++++- .../Component/Metadata/composer.json | 39 +++++++++++++++++- src/RunOpenCode/Component/Query/composer.json | 41 ++++++++++++++++++- 6 files changed, 231 insertions(+), 9 deletions(-) diff --git a/src/RunOpenCode/Bundle/MetadataBundle/composer.json b/src/RunOpenCode/Bundle/MetadataBundle/composer.json index 4e29f12..e3ccb93 100644 --- a/src/RunOpenCode/Bundle/MetadataBundle/composer.json +++ b/src/RunOpenCode/Bundle/MetadataBundle/composer.json @@ -11,7 +11,7 @@ "require": { "php": ">=8.4", "psr/cache": "^3.0", - "runopencode/metadata": "^0.1.38", + "runopencode/metadata": "^0.2", "symfony/cache": "^7.0", "symfony/config": "^7.0", "symfony/dependency-injection": "^7.0", @@ -22,10 +22,47 @@ "RunOpenCode\\Bundle\\MetadataBundle\\": "src/" } }, + "repositories": [ + { + "type": "path", + "url": "../../Component/Dataset", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Bitmask", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Query", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Metadata", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/QueryBundle", + "options": { + "symlink": false + } + } + ], "config": { "sort-packages": true }, - "version": "0.1.38", + "version": "0.2", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Bundle/QueryBundle/composer.json b/src/RunOpenCode/Bundle/QueryBundle/composer.json index af8a298..d253b73 100644 --- a/src/RunOpenCode/Bundle/QueryBundle/composer.json +++ b/src/RunOpenCode/Bundle/QueryBundle/composer.json @@ -13,7 +13,7 @@ "psr/cache": "^3.0", "psr/container": "^2.0", "psr/log": "^2.0|^3.0", - "runopencode/query": "^0.1.38", + "runopencode/query": "^0.2", "symfony/config": "^7.0", "symfony/dependency-injection": "^7.0", "symfony/finder": "^7.0", @@ -26,10 +26,47 @@ "RunOpenCode\\Bundle\\QueryBundle\\": "src/" } }, + "repositories": [ + { + "type": "path", + "url": "../../Component/Dataset", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Bitmask", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Query", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Metadata", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/MetadataBundle", + "options": { + "symlink": false + } + } + ], "config": { "sort-packages": true }, - "version": "0.1.38", + "version": "0.2", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Bitmask/composer.json b/src/RunOpenCode/Component/Bitmask/composer.json index d5890ee..e501d51 100644 --- a/src/RunOpenCode/Component/Bitmask/composer.json +++ b/src/RunOpenCode/Component/Bitmask/composer.json @@ -19,10 +19,47 @@ "RunOpenCode\\Component\\Bitmask\\": "src" } }, + "repositories": [ + { + "type": "path", + "url": "../../Component/Dataset", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Query", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Metadata", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/MetadataBundle", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/QueryBundle", + "options": { + "symlink": false + } + } + ], "config": { "sort-packages": true }, - "version": "0.1.38", + "version": "0.2", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Dataset/composer.json b/src/RunOpenCode/Component/Dataset/composer.json index bde0310..549600b 100644 --- a/src/RunOpenCode/Component/Dataset/composer.json +++ b/src/RunOpenCode/Component/Dataset/composer.json @@ -23,10 +23,47 @@ "src/functions.php" ] }, + "repositories": [ + { + "type": "path", + "url": "../../Component/Bitmask", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Query", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Metadata", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/MetadataBundle", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/QueryBundle", + "options": { + "symlink": false + } + } + ], "config": { "sort-packages": true }, - "version": "0.1.38", + "version": "0.2", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Metadata/composer.json b/src/RunOpenCode/Component/Metadata/composer.json index 5cfe77a..a38f5f6 100644 --- a/src/RunOpenCode/Component/Metadata/composer.json +++ b/src/RunOpenCode/Component/Metadata/composer.json @@ -18,10 +18,47 @@ "RunOpenCode\\Component\\Metadata\\": "src/" } }, + "repositories": [ + { + "type": "path", + "url": "../../Component/Dataset", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Bitmask", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Query", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/MetadataBundle", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/QueryBundle", + "options": { + "symlink": false + } + } + ], "config": { "sort-packages": true }, - "version": "0.1.38", + "version": "0.2", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Query/composer.json b/src/RunOpenCode/Component/Query/composer.json index 8c83f90..1376c4c 100644 --- a/src/RunOpenCode/Component/Query/composer.json +++ b/src/RunOpenCode/Component/Query/composer.json @@ -14,7 +14,7 @@ "doctrine/dbal": "^4.0", "psr/cache": "^3.0", "psr/log": "^2.0|^3.0", - "runopencode/dataset": "^0.1.38", + "runopencode/dataset": "^0.2", "symfony/cache": "^7.0", "symfony/finder": "^7.0", "thecodingmachine/safe": "^3.3", @@ -28,10 +28,47 @@ "src/functions.php" ] }, + "repositories": [ + { + "type": "path", + "url": "../../Component/Dataset", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Bitmask", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Metadata", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/MetadataBundle", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/QueryBundle", + "options": { + "symlink": false + } + } + ], "config": { "sort-packages": true }, - "version": "0.1.38", + "version": "0.2", "minimum-stability": "dev", "prefer-stable": true } From c51eb89f60220ebeb921071ee5a58d1d29837333 Mon Sep 17 00:00:00 2001 From: "Nikola Svitlica a.k.a TheCelavi" Date: Tue, 23 Dec 2025 17:12:57 +0100 Subject: [PATCH 05/13] Minor docblock fixes --- .../Component/Dataset/src/Collector/IndexedCollector.php | 6 +++--- src/RunOpenCode/Component/Dataset/tests/StreamTest.php | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/RunOpenCode/Component/Dataset/src/Collector/IndexedCollector.php b/src/RunOpenCode/Component/Dataset/src/Collector/IndexedCollector.php index e1605cc..859bd1c 100644 --- a/src/RunOpenCode/Component/Dataset/src/Collector/IndexedCollector.php +++ b/src/RunOpenCode/Component/Dataset/src/Collector/IndexedCollector.php @@ -95,7 +95,7 @@ public function __construct( continue; } - throw new UnsupportedException('Only object, string and integer keys are supported.'); + throw new UnsupportedException('Only object and scalar keys are supported.'); } } @@ -117,7 +117,7 @@ public function offsetExists(mixed $offset): bool return match (true) { \is_string($offset) || \is_int($offset) => \array_key_exists($offset, $this->scalarIndex), \is_object($offset) => $this->objectIndex->contains($offset), - default => throw new UnsupportedException('Only object, string and integer keys are supported.'), + default => throw new UnsupportedException('Only object and scalar keys are supported.'), }; } @@ -137,7 +137,7 @@ public function offsetGet(mixed $offset): mixed return match (true) { \is_string($offset) || \is_int($offset) => $this->scalarIndex[$offset], \is_object($offset) => $this->objectIndex[$offset], - default => throw new UnsupportedException('Only object, string and integer keys are supported.'), + default => throw new UnsupportedException('Only object and scalar keys are supported.'), }; } diff --git a/src/RunOpenCode/Component/Dataset/tests/StreamTest.php b/src/RunOpenCode/Component/Dataset/tests/StreamTest.php index 44f8027..8a71e48 100644 --- a/src/RunOpenCode/Component/Dataset/tests/StreamTest.php +++ b/src/RunOpenCode/Component/Dataset/tests/StreamTest.php @@ -160,6 +160,7 @@ public function flatten(): void ], $data); } + #[Test] public function left_join(): void { $left = [1 => 'a', 2 => 'b', 3 => 'c']; @@ -317,7 +318,7 @@ public function take(): void } #[Test] - public function takeUntil(): void + public function take_until(): void { $dataset = [ 'a' => 2, From 83f9c23458de02ecd32846723f2da064786e7f14 Mon Sep 17 00:00:00 2001 From: "Nikola Svitlica a.k.a TheCelavi" Date: Wed, 24 Dec 2025 14:06:53 +0100 Subject: [PATCH 06/13] Working on documentation --- docs/source/components/dataset/index.rst | 29 +++--- .../dataset/operators/list/index.rst | 60 +++++------- .../components/dataset/reducers/extend.rst | 85 +++++++++++++++++ .../components/dataset/reducers/index.rst | 17 ++++ .../dataset/reducers/list/average.rst | 6 ++ .../dataset/reducers/list/count.rst | 6 ++ .../dataset/reducers/list/index.rst | 13 +++ .../components/dataset/reducers/list/max.rst | 6 ++ .../components/dataset/reducers/list/min.rst | 6 ++ .../dataset/reducers/list/reduce.rst | 6 ++ .../components/dataset/reducers/list/sum.rst | 6 ++ docs/source/contributing.rst | 7 +- .../Component/Dataset/src/Reducer/Average.php | 2 +- .../Component/Dataset/src/Reducer/Max.php | 3 +- .../Component/Dataset/src/Stream.php | 82 +++++++++++++++- .../Component/Dataset/src/functions.php | 93 ++++++++++++++++++- 16 files changed, 372 insertions(+), 55 deletions(-) create mode 100644 docs/source/components/dataset/reducers/extend.rst create mode 100644 docs/source/components/dataset/reducers/list/average.rst create mode 100644 docs/source/components/dataset/reducers/list/count.rst create mode 100644 docs/source/components/dataset/reducers/list/index.rst create mode 100644 docs/source/components/dataset/reducers/list/max.rst create mode 100644 docs/source/components/dataset/reducers/list/min.rst create mode 100644 docs/source/components/dataset/reducers/list/reduce.rst create mode 100644 docs/source/components/dataset/reducers/list/sum.rst diff --git a/docs/source/components/dataset/index.rst b/docs/source/components/dataset/index.rst index 142d9e3..4246c14 100644 --- a/docs/source/components/dataset/index.rst +++ b/docs/source/components/dataset/index.rst @@ -7,6 +7,22 @@ collections in a functional(ish), declarative way. In some aspects, it is also inspired by `ReactiveX`_, but with a much simpler approach and far fewer features. +Table of Contents +----------------- + +.. toctree:: + :maxdepth: 1 + + installation + concepts + stream/index + operators/index + reducers/index + collectors/index + +Introduction +------------ + If your problem can be described as: I have a data stream from some source (file, database query result, etc.), @@ -43,19 +59,6 @@ Features and reduce (aggregate) values simultaneously without interrupting the data stream. -Table of Contents ------------------ - -.. toctree:: - :maxdepth: 1 - - installation - concepts - stream/index - operators/index - reducers/index - collectors/index - Quick example ------------- diff --git a/docs/source/components/dataset/operators/list/index.rst b/docs/source/components/dataset/operators/list/index.rst index 1e20cdf..d013d19 100644 --- a/docs/source/components/dataset/operators/list/index.rst +++ b/docs/source/components/dataset/operators/list/index.rst @@ -2,66 +2,56 @@ Available operators =================== +Transformation operators +------------------------ + .. toctree:: :maxdepth: 1 - :hidden: buffer_count buffer_while - distinct - filter - finalize flatten - if_empty left_join map merge - overflow reverse - skip sort - take - take_until - tap - -Transformation operators ------------------------- - -* ``bufferCount()`` -* ``bufferWhile()`` -* ``flatten()`` -* ``map()`` -* ``merge()`` -* ``reverse()`` -* ``sort()`` Filtering operators ------------------- -* ``distinct()`` -* ``filter()`` -* ``skip()`` -* ``take()`` -* ``takeUntil()`` +.. toctree:: + :maxdepth: 1 + + distinct + filter + skip + take + takeUntil Asserting operators ------------------- -* ``ifEmpty()`` -* ``overflow()`` +.. toctree:: + :maxdepth: 1 + + if_empty + overflow Error handling operators ------------------------ -* ``finalize()`` - -Aggregate operators -------------------- - -* ``reduce()`` +.. toctree:: + :maxdepth: 1 + + finalize Utility operators ----------------- -* ``tap()`` +.. toctree:: + :maxdepth: 1 + + tap + diff --git a/docs/source/components/dataset/reducers/extend.rst b/docs/source/components/dataset/reducers/extend.rst new file mode 100644 index 0000000..5cc6310 --- /dev/null +++ b/docs/source/components/dataset/reducers/extend.rst @@ -0,0 +1,85 @@ +====================== +Write your own reducer +====================== + + +Typically, a reducer function has the following signature: + +.. code-block:: php + :linenos: + + */ diff --git a/src/RunOpenCode/Component/Dataset/src/Stream.php b/src/RunOpenCode/Component/Dataset/src/Stream.php index 153ef43..9a2755a 100644 --- a/src/RunOpenCode/Component/Dataset/src/Stream.php +++ b/src/RunOpenCode/Component/Dataset/src/Stream.php @@ -31,6 +31,11 @@ use function RunOpenCode\Component\Dataset\overflow as dataset_overflow; use function RunOpenCode\Component\Dataset\operator as dataset_operator; use function RunOpenCode\Component\Dataset\left_join as dataset_left_join; +use function RunOpenCode\Component\Dataset\average as dataset_average; +use function RunOpenCode\Component\Dataset\count as dataset_count; +use function RunOpenCode\Component\Dataset\max as dataset_max; +use function RunOpenCode\Component\Dataset\min as dataset_min; +use function RunOpenCode\Component\Dataset\sum as dataset_sum; /** * Iterable data stream. @@ -342,6 +347,8 @@ public function operator(string $operator, mixed ...$arguments): self } /** + * Attaches aggregation to the current stream. + * * @template TReducedValue * @template TReducer of ReducerInterface * @@ -357,7 +364,7 @@ public function aggregate(string $name, callable|string $reducer, mixed ...$args } /** - * Collect values from dataset using specified collector. + * Collect values from current stream using specified collector. * * @template TCollectedValue * @template TCollector of CollectorInterface @@ -375,7 +382,7 @@ public function collect(string $collector, mixed ...$args): CollectorInterface } /** - * Reduce values from dataset using specified reducer. + * Reduce values of current stream to single value using specified reducer. * * @template TReducedValue * @template TReducer of ReducerInterface @@ -392,6 +399,77 @@ public function reduce(callable|string $reducer, mixed ...$args): mixed return dataset_reduce($this, $reducer, ...$args); } + /** + * Reduces values from the current stream to their average. + * + * @param int|float|null $initial Initial value to start with. + * @param callable(TValue, TKey): (int|float|null)|null $extractor Optional function to extract reducible value. + * @param bool $countNull Should `null` values be accounted for, `false` by default. + * + * @return float|null Average of values. + */ + public function average(int|float|null $initial = null, ?callable $extractor = null, bool $countNull = false): float|null + { + return dataset_average($this, $initial, $extractor, $countNull); + } + + /** + * Reduces values from the current streams to their count. + * + * @param (callable(TValue, TKey): bool)|null $filter Optional filter callback to count only items that match the filter. + * + * @return int Number of items in the stream. + */ + public function count(?callable $filter = null): int + { + return dataset_count($this, $filter); + } + + /** + * Reduces values from stream source to their maximum value. + * + * @template TReducedValue + * + * @param TReducedValue|null $initial Initial value to start with. + * @param (callable(TValue, TKey): TReducedValue|null)|null $extractor Optional function to extract reducible value. + * @param (callable(TReducedValue, TReducedValue): int)|null $comparator Optional comparator. + * + * @return TReducedValue + */ + public function max(mixed $initial = null, ?callable $extractor = null, ?callable $comparator = null): mixed + { + return dataset_max($this, $initial, $extractor, $comparator); + } + + /** + * Reduces values from stream source to their minimum value. + * + * @template TReducedValue + * + * @param TReducedValue|null $initial Initial value to start with. + * @param (callable(TValue, TKey): TReducedValue|null)|null $extractor Optional function to extract reducible value. + * @param (callable(TReducedValue, TReducedValue): int)|null $comparator Optional comparator. + * + * @return TReducedValue + */ + public function min(mixed $initial = null, ?callable $extractor = null, ?callable $comparator = null): mixed + { + return dataset_min($this, $initial, $extractor, $comparator); + } + + /** + * Reduces values from stream source to their sum. + * + * @param int|float|null $initial Initial value to start with. + * @param (callable(TValue, TKey): (int|float|null))|null $extractor Optional function to extract reducible value. + * + * @return int|float|null Sum of values. + */ + public function sum(int|float|null $initial = null, ?callable $extractor = null): int|float|null + { + return dataset_sum($this, $initial, $extractor); + } + /** * {@inheritdoc} */ diff --git a/src/RunOpenCode/Component/Dataset/src/functions.php b/src/RunOpenCode/Component/Dataset/src/functions.php index 60f5452..25791ee 100644 --- a/src/RunOpenCode/Component/Dataset/src/functions.php +++ b/src/RunOpenCode/Component/Dataset/src/functions.php @@ -461,7 +461,7 @@ function operator(iterable $source, string $operator, mixed ...$arguments): Stre } /** - * Attach reducer as an aggregator. + * Attach reducer as an aggregator to stream source. * * @template TKey * @template TValue @@ -488,7 +488,7 @@ function aggregate(string $name, iterable $source, callable|string $reducer, mix } /** - * Collect values from dataset using specified collector. + * Collect values from given stream source using specified collector. * * @template TKey * @template TValue @@ -540,3 +540,92 @@ function reduce(iterable $source, callable|string $reducer, mixed ...$args): mix return $operator->value; } + +/** + * Reduces values from stream source to their average. + * + * @template TKey + * @template TValue + * + * @param iterable $source Stream source to reduce. + * @param int|float|null $initial Initial value to start with. + * @param callable(TValue, TKey): (int|float|null)|null $extractor Optional function to extract reducible value. + * @param bool $countNull Should `null` values be accounted for, `false` by default. + * + * @return float|null Average of values. + */ +function average(iterable $source, int|float|null $initial = null, ?callable $extractor = null, bool $countNull = false): float|null +{ + return reduce($source, Reducer\Average::class, $initial, $extractor, $countNull); +} + +/** + * Reduces values from stream source to their count. + * + * @template TKey + * @template TValue + * + * @param iterable $source Stream source to reduce. + * @param (callable(TValue, TKey): bool)|null $filter Optional filter callback to count only items that match the filter. + * + * @return int Number of items in the stream. + */ +function count(iterable $source, ?callable $filter = null): int +{ + return reduce($source, Reducer\Count::class, $filter); +} + +/** + * Reduces values from stream source to their maximum value. + * + * @template TKey + * @template TValue + * @template TReducedValue + * + * @param iterable $source Stream source to reduce. + * @param TReducedValue|null $initial Initial value to start with. + * @param (callable(TValue, TKey): (TReducedValue|null))|null $extractor Optional function to extract reducible value. + * @param (callable(TReducedValue, TReducedValue): int)|null $comparator Optional comparator. + * + * @return TReducedValue Maximum value. + */ +function max(iterable $source, mixed $initial = null, ?callable $extractor = null, ?callable $comparator = null): mixed +{ + return reduce($source, Reducer\Max::class, $initial, $extractor, $comparator); +} + +/** + * Reduces values from stream source to their minimum value. + * + * @template TKey + * @template TValue + * @template TReducedValue + * + * @param iterable $source Stream source to reduce. + * @param TReducedValue|null $initial Initial value to start with. + * @param (callable(TValue, TKey): (TReducedValue|null))|null $extractor Optional function to extract reducible value. + * @param (callable(TReducedValue, TReducedValue): int)|null $comparator Optional comparator. + * + * @return TReducedValue Minimum value. + */ +function min(iterable $source, mixed $initial = null, ?callable $extractor = null, ?callable $comparator = null): mixed +{ + return reduce($source, Reducer\Min::class, $initial, $extractor, $comparator); +} + +/** + * Reduces values from stream source to their sum. + * + * @template TKey + * @template TValue + * + * @param iterable $source Stream source to reduce. + * @param int|float|null $initial Initial value to start with. + * @param (callable(TValue, TKey): (int|float|null))|null $extractor Optional function to extract reducible value. + * + * @return int|float|null Sum of values. + */ +function sum(iterable $source, int|float|null $initial = null, ?callable $extractor = null): int|float|null +{ + return reduce($source, Reducer\Sum::class, $initial, $extractor); +} From e3c8d1277db05ce5be0fbb0eb85e5a40ebd8dc56 Mon Sep 17 00:00:00 2001 From: "Nikola Svitlica a.k.a TheCelavi" Date: Wed, 24 Dec 2025 14:07:41 +0100 Subject: [PATCH 07/13] prepare release --- .../Bundle/MetadataBundle/composer.json | 41 +------------------ .../Bundle/QueryBundle/composer.json | 41 +------------------ .../Component/Bitmask/composer.json | 39 +----------------- .../Component/Dataset/composer.json | 39 +----------------- .../Component/Metadata/composer.json | 39 +----------------- src/RunOpenCode/Component/Query/composer.json | 41 +------------------ 6 files changed, 9 insertions(+), 231 deletions(-) diff --git a/src/RunOpenCode/Bundle/MetadataBundle/composer.json b/src/RunOpenCode/Bundle/MetadataBundle/composer.json index e3ccb93..e6a3457 100644 --- a/src/RunOpenCode/Bundle/MetadataBundle/composer.json +++ b/src/RunOpenCode/Bundle/MetadataBundle/composer.json @@ -11,7 +11,7 @@ "require": { "php": ">=8.4", "psr/cache": "^3.0", - "runopencode/metadata": "^0.2", + "runopencode/metadata": "^0.1.39", "symfony/cache": "^7.0", "symfony/config": "^7.0", "symfony/dependency-injection": "^7.0", @@ -22,47 +22,10 @@ "RunOpenCode\\Bundle\\MetadataBundle\\": "src/" } }, - "repositories": [ - { - "type": "path", - "url": "../../Component/Dataset", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Bitmask", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Query", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Metadata", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/QueryBundle", - "options": { - "symlink": false - } - } - ], "config": { "sort-packages": true }, - "version": "0.2", + "version": "0.1.39", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Bundle/QueryBundle/composer.json b/src/RunOpenCode/Bundle/QueryBundle/composer.json index d253b73..426e811 100644 --- a/src/RunOpenCode/Bundle/QueryBundle/composer.json +++ b/src/RunOpenCode/Bundle/QueryBundle/composer.json @@ -13,7 +13,7 @@ "psr/cache": "^3.0", "psr/container": "^2.0", "psr/log": "^2.0|^3.0", - "runopencode/query": "^0.2", + "runopencode/query": "^0.1.39", "symfony/config": "^7.0", "symfony/dependency-injection": "^7.0", "symfony/finder": "^7.0", @@ -26,47 +26,10 @@ "RunOpenCode\\Bundle\\QueryBundle\\": "src/" } }, - "repositories": [ - { - "type": "path", - "url": "../../Component/Dataset", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Bitmask", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Query", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Metadata", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/MetadataBundle", - "options": { - "symlink": false - } - } - ], "config": { "sort-packages": true }, - "version": "0.2", + "version": "0.1.39", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Bitmask/composer.json b/src/RunOpenCode/Component/Bitmask/composer.json index e501d51..c1a45c2 100644 --- a/src/RunOpenCode/Component/Bitmask/composer.json +++ b/src/RunOpenCode/Component/Bitmask/composer.json @@ -19,47 +19,10 @@ "RunOpenCode\\Component\\Bitmask\\": "src" } }, - "repositories": [ - { - "type": "path", - "url": "../../Component/Dataset", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Query", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Metadata", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/MetadataBundle", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/QueryBundle", - "options": { - "symlink": false - } - } - ], "config": { "sort-packages": true }, - "version": "0.2", + "version": "0.1.39", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Dataset/composer.json b/src/RunOpenCode/Component/Dataset/composer.json index 549600b..455b95e 100644 --- a/src/RunOpenCode/Component/Dataset/composer.json +++ b/src/RunOpenCode/Component/Dataset/composer.json @@ -23,47 +23,10 @@ "src/functions.php" ] }, - "repositories": [ - { - "type": "path", - "url": "../../Component/Bitmask", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Query", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Metadata", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/MetadataBundle", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/QueryBundle", - "options": { - "symlink": false - } - } - ], "config": { "sort-packages": true }, - "version": "0.2", + "version": "0.1.39", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Metadata/composer.json b/src/RunOpenCode/Component/Metadata/composer.json index a38f5f6..4fdb600 100644 --- a/src/RunOpenCode/Component/Metadata/composer.json +++ b/src/RunOpenCode/Component/Metadata/composer.json @@ -18,47 +18,10 @@ "RunOpenCode\\Component\\Metadata\\": "src/" } }, - "repositories": [ - { - "type": "path", - "url": "../../Component/Dataset", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Bitmask", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Query", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/MetadataBundle", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/QueryBundle", - "options": { - "symlink": false - } - } - ], "config": { "sort-packages": true }, - "version": "0.2", + "version": "0.1.39", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Query/composer.json b/src/RunOpenCode/Component/Query/composer.json index 1376c4c..7178eb2 100644 --- a/src/RunOpenCode/Component/Query/composer.json +++ b/src/RunOpenCode/Component/Query/composer.json @@ -14,7 +14,7 @@ "doctrine/dbal": "^4.0", "psr/cache": "^3.0", "psr/log": "^2.0|^3.0", - "runopencode/dataset": "^0.2", + "runopencode/dataset": "^0.1.39", "symfony/cache": "^7.0", "symfony/finder": "^7.0", "thecodingmachine/safe": "^3.3", @@ -28,47 +28,10 @@ "src/functions.php" ] }, - "repositories": [ - { - "type": "path", - "url": "../../Component/Dataset", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Bitmask", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Component/Metadata", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/MetadataBundle", - "options": { - "symlink": false - } - }, - { - "type": "path", - "url": "../../Bundle/QueryBundle", - "options": { - "symlink": false - } - } - ], "config": { "sort-packages": true }, - "version": "0.2", + "version": "0.1.39", "minimum-stability": "dev", "prefer-stable": true } From c5ef0c456d75008169f165be11b722601bd26c03 Mon Sep 17 00:00:00 2001 From: "Nikola Svitlica a.k.a TheCelavi" Date: Wed, 24 Dec 2025 14:07:44 +0100 Subject: [PATCH 08/13] open 0.2-dev --- .../Bundle/MetadataBundle/composer.json | 41 ++++++++++++++++++- .../Bundle/QueryBundle/composer.json | 41 ++++++++++++++++++- .../Component/Bitmask/composer.json | 39 +++++++++++++++++- .../Component/Dataset/composer.json | 39 +++++++++++++++++- .../Component/Metadata/composer.json | 39 +++++++++++++++++- src/RunOpenCode/Component/Query/composer.json | 41 ++++++++++++++++++- 6 files changed, 231 insertions(+), 9 deletions(-) diff --git a/src/RunOpenCode/Bundle/MetadataBundle/composer.json b/src/RunOpenCode/Bundle/MetadataBundle/composer.json index e6a3457..e3ccb93 100644 --- a/src/RunOpenCode/Bundle/MetadataBundle/composer.json +++ b/src/RunOpenCode/Bundle/MetadataBundle/composer.json @@ -11,7 +11,7 @@ "require": { "php": ">=8.4", "psr/cache": "^3.0", - "runopencode/metadata": "^0.1.39", + "runopencode/metadata": "^0.2", "symfony/cache": "^7.0", "symfony/config": "^7.0", "symfony/dependency-injection": "^7.0", @@ -22,10 +22,47 @@ "RunOpenCode\\Bundle\\MetadataBundle\\": "src/" } }, + "repositories": [ + { + "type": "path", + "url": "../../Component/Dataset", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Bitmask", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Query", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Metadata", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/QueryBundle", + "options": { + "symlink": false + } + } + ], "config": { "sort-packages": true }, - "version": "0.1.39", + "version": "0.2", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Bundle/QueryBundle/composer.json b/src/RunOpenCode/Bundle/QueryBundle/composer.json index 426e811..d253b73 100644 --- a/src/RunOpenCode/Bundle/QueryBundle/composer.json +++ b/src/RunOpenCode/Bundle/QueryBundle/composer.json @@ -13,7 +13,7 @@ "psr/cache": "^3.0", "psr/container": "^2.0", "psr/log": "^2.0|^3.0", - "runopencode/query": "^0.1.39", + "runopencode/query": "^0.2", "symfony/config": "^7.0", "symfony/dependency-injection": "^7.0", "symfony/finder": "^7.0", @@ -26,10 +26,47 @@ "RunOpenCode\\Bundle\\QueryBundle\\": "src/" } }, + "repositories": [ + { + "type": "path", + "url": "../../Component/Dataset", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Bitmask", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Query", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Metadata", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/MetadataBundle", + "options": { + "symlink": false + } + } + ], "config": { "sort-packages": true }, - "version": "0.1.39", + "version": "0.2", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Bitmask/composer.json b/src/RunOpenCode/Component/Bitmask/composer.json index c1a45c2..e501d51 100644 --- a/src/RunOpenCode/Component/Bitmask/composer.json +++ b/src/RunOpenCode/Component/Bitmask/composer.json @@ -19,10 +19,47 @@ "RunOpenCode\\Component\\Bitmask\\": "src" } }, + "repositories": [ + { + "type": "path", + "url": "../../Component/Dataset", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Query", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Metadata", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/MetadataBundle", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/QueryBundle", + "options": { + "symlink": false + } + } + ], "config": { "sort-packages": true }, - "version": "0.1.39", + "version": "0.2", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Dataset/composer.json b/src/RunOpenCode/Component/Dataset/composer.json index 455b95e..549600b 100644 --- a/src/RunOpenCode/Component/Dataset/composer.json +++ b/src/RunOpenCode/Component/Dataset/composer.json @@ -23,10 +23,47 @@ "src/functions.php" ] }, + "repositories": [ + { + "type": "path", + "url": "../../Component/Bitmask", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Query", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Metadata", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/MetadataBundle", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/QueryBundle", + "options": { + "symlink": false + } + } + ], "config": { "sort-packages": true }, - "version": "0.1.39", + "version": "0.2", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Metadata/composer.json b/src/RunOpenCode/Component/Metadata/composer.json index 4fdb600..a38f5f6 100644 --- a/src/RunOpenCode/Component/Metadata/composer.json +++ b/src/RunOpenCode/Component/Metadata/composer.json @@ -18,10 +18,47 @@ "RunOpenCode\\Component\\Metadata\\": "src/" } }, + "repositories": [ + { + "type": "path", + "url": "../../Component/Dataset", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Bitmask", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Query", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/MetadataBundle", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/QueryBundle", + "options": { + "symlink": false + } + } + ], "config": { "sort-packages": true }, - "version": "0.1.39", + "version": "0.2", "minimum-stability": "dev", "prefer-stable": true } diff --git a/src/RunOpenCode/Component/Query/composer.json b/src/RunOpenCode/Component/Query/composer.json index 7178eb2..1376c4c 100644 --- a/src/RunOpenCode/Component/Query/composer.json +++ b/src/RunOpenCode/Component/Query/composer.json @@ -14,7 +14,7 @@ "doctrine/dbal": "^4.0", "psr/cache": "^3.0", "psr/log": "^2.0|^3.0", - "runopencode/dataset": "^0.1.39", + "runopencode/dataset": "^0.2", "symfony/cache": "^7.0", "symfony/finder": "^7.0", "thecodingmachine/safe": "^3.3", @@ -28,10 +28,47 @@ "src/functions.php" ] }, + "repositories": [ + { + "type": "path", + "url": "../../Component/Dataset", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Bitmask", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Component/Metadata", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/MetadataBundle", + "options": { + "symlink": false + } + }, + { + "type": "path", + "url": "../../Bundle/QueryBundle", + "options": { + "symlink": false + } + } + ], "config": { "sort-packages": true }, - "version": "0.1.39", + "version": "0.2", "minimum-stability": "dev", "prefer-stable": true } From 965941e30abd3df5ce0b6a603c9c2c0a05938239 Mon Sep 17 00:00:00 2001 From: "Nikola Svitlica a.k.a TheCelavi" Date: Wed, 24 Dec 2025 15:01:28 +0100 Subject: [PATCH 09/13] Updated api docs --- .../Component/Dataset/src/Collector/ArrayCollector.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/RunOpenCode/Component/Dataset/src/Collector/ArrayCollector.php b/src/RunOpenCode/Component/Dataset/src/Collector/ArrayCollector.php index 32aea76..572982d 100644 --- a/src/RunOpenCode/Component/Dataset/src/Collector/ArrayCollector.php +++ b/src/RunOpenCode/Component/Dataset/src/Collector/ArrayCollector.php @@ -52,6 +52,8 @@ public function __construct( } /** + * Get collected keys. + * * @return list */ public function keys(): array @@ -60,6 +62,8 @@ public function keys(): array } /** + * Get collected values. + * * @return list */ public function values(): array From 5f8ea00668d824a27012f242a690efeb0c79236f Mon Sep 17 00:00:00 2001 From: "Nikola Svitlica a.k.a TheCelavi" Date: Wed, 28 Jan 2026 10:58:56 +0100 Subject: [PATCH 10/13] Minor fixes --- .../config/definition/middleware.php | 2 +- .../src/Collector/IndexedCollector.php | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/RunOpenCode/Bundle/QueryBundle/config/definition/middleware.php b/src/RunOpenCode/Bundle/QueryBundle/config/definition/middleware.php index db055e5..5302335 100644 --- a/src/RunOpenCode/Bundle/QueryBundle/config/definition/middleware.php +++ b/src/RunOpenCode/Bundle/QueryBundle/config/definition/middleware.php @@ -37,7 +37,7 @@ 'parser', 'convert', 'retry', - 'slow' + 'slow', ]) ->scalarPrototype()->end() ->end() diff --git a/src/RunOpenCode/Component/Dataset/src/Collector/IndexedCollector.php b/src/RunOpenCode/Component/Dataset/src/Collector/IndexedCollector.php index 5e79793..846ff77 100644 --- a/src/RunOpenCode/Component/Dataset/src/Collector/IndexedCollector.php +++ b/src/RunOpenCode/Component/Dataset/src/Collector/IndexedCollector.php @@ -99,6 +99,30 @@ public function __construct( } } + /** + * Get collected keys. + * + * @return iterable + */ + public function keys(): iterable + { + foreach ($this->source as [$key,]) { + yield $key; + } + } + + /** + * Get collected values. + * + * @return iterable + */ + public function values(): iterable + { + foreach ($this->source as [,$value]) { + yield $value; + } + } + /** * {@inheritdoc} */ From aab433485f9bb509405122f8a89e1300888576b9 Mon Sep 17 00:00:00 2001 From: "Nikola Svitlica a.k.a TheCelavi" Date: Wed, 28 Jan 2026 11:03:31 +0100 Subject: [PATCH 11/13] Minor fixes --- docker/php/Dockerfile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/docker/php/Dockerfile b/docker/php/Dockerfile index d11de5c..5d4ccc5 100644 --- a/docker/php/Dockerfile +++ b/docker/php/Dockerfile @@ -87,10 +87,7 @@ ENV PHP_EXTENSION_DIR=/usr/local/lib/php/extensions/no-debug-non-zts-20240924 ##################################################################################### RUN composer global config --no-plugins allow-plugins.infection/extension-installer true && \ - composer global require infection/infection && \ - composer global require maglnet/composer-require-checker && \ - composer global require icanhazstring/composer-unused && \ - composer global require phpmetrics/phpmetrics && \ + composer global require infection/infection maglnet/composer-require-checker icanhazstring/composer-unused phpmetrics/phpmetrics && \ export PATH=~/.config/composer/vendor/bin:$PATH ##################################################################################### From b5a00a3d0bb7002b05bf226a511a3300ae274411 Mon Sep 17 00:00:00 2001 From: "Nikola Svitlica a.k.a TheCelavi" Date: Wed, 28 Jan 2026 11:12:51 +0100 Subject: [PATCH 12/13] Minor fixes --- .../Component/Dataset/composer-require-checker.json | 3 +++ .../Component/Dataset/src/Collector/ArrayCollector.php | 4 ++-- .../Component/Dataset/src/Collector/IndexedCollector.php | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) create mode 100644 src/RunOpenCode/Component/Dataset/composer-require-checker.json diff --git a/src/RunOpenCode/Component/Dataset/composer-require-checker.json b/src/RunOpenCode/Component/Dataset/composer-require-checker.json new file mode 100644 index 0000000..208f518 --- /dev/null +++ b/src/RunOpenCode/Component/Dataset/composer-require-checker.json @@ -0,0 +1,3 @@ +{ + "symbol-whitelist" : ["reduce"] +} \ No newline at end of file diff --git a/src/RunOpenCode/Component/Dataset/src/Collector/ArrayCollector.php b/src/RunOpenCode/Component/Dataset/src/Collector/ArrayCollector.php index 572982d..9bfc61e 100644 --- a/src/RunOpenCode/Component/Dataset/src/Collector/ArrayCollector.php +++ b/src/RunOpenCode/Component/Dataset/src/Collector/ArrayCollector.php @@ -53,7 +53,7 @@ public function __construct( /** * Get collected keys. - * + * * @return list */ public function keys(): array @@ -63,7 +63,7 @@ public function keys(): array /** * Get collected values. - * + * * @return list */ public function values(): array diff --git a/src/RunOpenCode/Component/Dataset/src/Collector/IndexedCollector.php b/src/RunOpenCode/Component/Dataset/src/Collector/IndexedCollector.php index 846ff77..6a17541 100644 --- a/src/RunOpenCode/Component/Dataset/src/Collector/IndexedCollector.php +++ b/src/RunOpenCode/Component/Dataset/src/Collector/IndexedCollector.php @@ -101,7 +101,7 @@ public function __construct( /** * Get collected keys. - * + * * @return iterable */ public function keys(): iterable @@ -110,10 +110,10 @@ public function keys(): iterable yield $key; } } - + /** * Get collected values. - * + * * @return iterable */ public function values(): iterable From 1358129566a5b9ea1cfeeb66feeab2e829859ba9 Mon Sep 17 00:00:00 2001 From: Stefan Veljancic Date: Mon, 26 Jan 2026 13:55:17 +0100 Subject: [PATCH 13/13] Created logger bundle Fixed performances --- composer.json | 4 + composer.lock | 283 ++++++++--------- docs/source/bundles/index.rst | 1 + docs/source/bundles/logger-bundle/index.rst | 177 +++++++++++ docs/source/components/index.rst | 1 + .../components/logger/context-providers.rst | 238 +++++++++++++++ docs/source/components/logger/index.rst | 120 ++++++++ .../source/components/logger/installation.rst | 156 ++++++++++ docs/source/components/logger/usage.rst | 285 ++++++++++++++++++ src/RunOpenCode/Bundle/LoggerBundle/LICENSE | 21 ++ src/RunOpenCode/Bundle/LoggerBundle/README.md | 0 .../Bundle/LoggerBundle/composer.json | 44 +++ .../Bundle/LoggerBundle/src/LoggerBundle.php | 71 +++++ .../LoggerBundle/tests/LoggerBundleTest.php | 68 +++++ src/RunOpenCode/Component/Logger/README.md | 0 .../Component/Logger/composer.json | 30 ++ .../src/Contract/LoggerContextInterface.php | 24 ++ .../Logger/src/Contract/LoggerInterface.php | 48 +++ .../Component/Logger/src/Logger.php | 195 ++++++++++++ .../Component/Logger/tests/LoggerTest.php | 168 +++++++++++ .../Query/tests/Functions/ToRegexTest.php | 11 +- 21 files changed, 1795 insertions(+), 150 deletions(-) create mode 100644 docs/source/bundles/logger-bundle/index.rst create mode 100644 docs/source/components/logger/context-providers.rst create mode 100644 docs/source/components/logger/index.rst create mode 100644 docs/source/components/logger/installation.rst create mode 100644 docs/source/components/logger/usage.rst create mode 100644 src/RunOpenCode/Bundle/LoggerBundle/LICENSE create mode 100644 src/RunOpenCode/Bundle/LoggerBundle/README.md create mode 100644 src/RunOpenCode/Bundle/LoggerBundle/composer.json create mode 100644 src/RunOpenCode/Bundle/LoggerBundle/src/LoggerBundle.php create mode 100644 src/RunOpenCode/Bundle/LoggerBundle/tests/LoggerBundleTest.php create mode 100644 src/RunOpenCode/Component/Logger/README.md create mode 100644 src/RunOpenCode/Component/Logger/composer.json create mode 100644 src/RunOpenCode/Component/Logger/src/Contract/LoggerContextInterface.php create mode 100644 src/RunOpenCode/Component/Logger/src/Contract/LoggerInterface.php create mode 100644 src/RunOpenCode/Component/Logger/src/Logger.php create mode 100644 src/RunOpenCode/Component/Logger/tests/LoggerTest.php diff --git a/composer.json b/composer.json index fb38cb0..c6b6246 100644 --- a/composer.json +++ b/composer.json @@ -39,8 +39,10 @@ "psr-4": { "RunOpenCode\\Component\\Bitmask\\": "src/RunOpenCode/Component/Bitmask/src/", "RunOpenCode\\Component\\Dataset\\": "src/RunOpenCode/Component/Dataset/src/", + "RunOpenCode\\Component\\Logger\\": "src/RunOpenCode/Component/Logger/src/", "RunOpenCode\\Component\\Metadata\\": "src/RunOpenCode/Component/Metadata/src/", "RunOpenCode\\Component\\Query\\": "src/RunOpenCode/Component/Query/src/", + "RunOpenCode\\Bundle\\LoggerBundle\\": "src/RunOpenCode/Bundle/LoggerBundle/src/", "RunOpenCode\\Bundle\\QueryBundle\\": "src/RunOpenCode/Bundle/QueryBundle/src/", "RunOpenCode\\Bundle\\MetadataBundle\\": "src/RunOpenCode/Bundle/MetadataBundle/src/", "Monorepo\\": "monorepo/" @@ -54,8 +56,10 @@ "psr-4": { "RunOpenCode\\Component\\Bitmask\\Tests\\": "src/RunOpenCode/Component/Bitmask/tests/", "RunOpenCode\\Component\\Dataset\\Tests\\": "src/RunOpenCode/Component/Dataset/tests/", + "RunOpenCode\\Component\\Logger\\Tests\\": "src/RunOpenCode/Component/Logger/tests/", "RunOpenCode\\Component\\Metadata\\Tests\\": "src/RunOpenCode/Component/Metadata/tests/", "RunOpenCode\\Component\\Query\\Tests\\": "src/RunOpenCode/Component/Query/tests/", + "RunOpenCode\\Bundle\\LoggerBundle\\Tests\\": "src/RunOpenCode/Bundle/LoggerBundle/tests/", "RunOpenCode\\Bundle\\QueryBundle\\Tests\\": "src/RunOpenCode/Bundle/QueryBundle/tests/", "RunOpenCode\\Bundle\\MetadataBundle\\Tests\\": "src/RunOpenCode/Bundle/MetadataBundle/tests/" } diff --git a/composer.lock b/composer.lock index 41ced96..62bd9e5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "adb62d230ff60ef99c1b35dbb063ce86", + "content-hash": "5b298102263fd2401569b725dae99cb1", "packages": [ { "name": "doctrine/dbal", @@ -364,16 +364,16 @@ }, { "name": "symfony/cache", - "version": "v7.4.1", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "21e0755783bbbab58f2bb6a7a57896d21d27a366" + "reference": "67ca35eaa52dd9c1f07a42d459b5a2544dd29b34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/21e0755783bbbab58f2bb6a7a57896d21d27a366", - "reference": "21e0755783bbbab58f2bb6a7a57896d21d27a366", + "url": "https://api.github.com/repos/symfony/cache/zipball/67ca35eaa52dd9c1f07a42d459b5a2544dd29b34", + "reference": "67ca35eaa52dd9c1f07a42d459b5a2544dd29b34", "shasum": "" }, "require": { @@ -444,7 +444,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v7.4.1" + "source": "https://github.com/symfony/cache/tree/v7.4.4" }, "funding": [ { @@ -464,7 +464,7 @@ "type": "tidelift" } ], - "time": "2025-12-04T18:11:45+00:00" + "time": "2026-01-23T12:59:19+00:00" }, { "name": "symfony/cache-contracts", @@ -544,16 +544,16 @@ }, { "name": "symfony/config", - "version": "v7.4.1", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "2c323304c354a43a48b61c5fa760fc4ed60ce495" + "reference": "4275b53b8ab0cf37f48bf273dc2285c8178efdfb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/2c323304c354a43a48b61c5fa760fc4ed60ce495", - "reference": "2c323304c354a43a48b61c5fa760fc4ed60ce495", + "url": "https://api.github.com/repos/symfony/config/zipball/4275b53b8ab0cf37f48bf273dc2285c8178efdfb", + "reference": "4275b53b8ab0cf37f48bf273dc2285c8178efdfb", "shasum": "" }, "require": { @@ -599,7 +599,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v7.4.1" + "source": "https://github.com/symfony/config/tree/v7.4.4" }, "funding": [ { @@ -619,20 +619,20 @@ "type": "tidelift" } ], - "time": "2025-12-05T07:52:08+00:00" + "time": "2026-01-13T11:36:38+00:00" }, { "name": "symfony/dependency-injection", - "version": "v7.4.2", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "baf614f7c15b30ba6762d4b1ddabdf83dbf0d29b" + "reference": "dbbaba1cc65ccfa29106e931f68b51cd2f4b32bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/baf614f7c15b30ba6762d4b1ddabdf83dbf0d29b", - "reference": "baf614f7c15b30ba6762d4b1ddabdf83dbf0d29b", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/dbbaba1cc65ccfa29106e931f68b51cd2f4b32bb", + "reference": "dbbaba1cc65ccfa29106e931f68b51cd2f4b32bb", "shasum": "" }, "require": { @@ -683,7 +683,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v7.4.2" + "source": "https://github.com/symfony/dependency-injection/tree/v7.4.4" }, "funding": [ { @@ -703,7 +703,7 @@ "type": "tidelift" } ], - "time": "2025-12-08T06:57:04+00:00" + "time": "2026-01-23T12:59:19+00:00" }, { "name": "symfony/deprecation-contracts", @@ -774,16 +774,16 @@ }, { "name": "symfony/error-handler", - "version": "v8.0.0", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "d77ec7dda0c274178745d152e82baf7ea827fd73" + "reference": "7620b97ec0ab1d2d6c7fb737aa55da411bea776a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/d77ec7dda0c274178745d152e82baf7ea827fd73", - "reference": "d77ec7dda0c274178745d152e82baf7ea827fd73", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/7620b97ec0ab1d2d6c7fb737aa55da411bea776a", + "reference": "7620b97ec0ab1d2d6c7fb737aa55da411bea776a", "shasum": "" }, "require": { @@ -831,7 +831,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v8.0.0" + "source": "https://github.com/symfony/error-handler/tree/v8.0.4" }, "funding": [ { @@ -851,20 +851,20 @@ "type": "tidelift" } ], - "time": "2025-11-05T14:36:47+00:00" + "time": "2026-01-23T11:07:10+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v8.0.0", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "573f95783a2ec6e38752979db139f09fec033f03" + "reference": "99301401da182b6cfaa4700dbe9987bb75474b47" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/573f95783a2ec6e38752979db139f09fec033f03", - "reference": "573f95783a2ec6e38752979db139f09fec033f03", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/99301401da182b6cfaa4700dbe9987bb75474b47", + "reference": "99301401da182b6cfaa4700dbe9987bb75474b47", "shasum": "" }, "require": { @@ -916,7 +916,7 @@ "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/v8.0.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v8.0.4" }, "funding": [ { @@ -936,7 +936,7 @@ "type": "tidelift" } ], - "time": "2025-10-30T14:17:19+00:00" + "time": "2026-01-05T11:45:55+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -1086,16 +1086,16 @@ }, { "name": "symfony/finder", - "version": "v7.4.0", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "340b9ed7320570f319028a2cbec46d40535e94bd" + "reference": "01b24a145bbeaa7141e75887ec904c34a6728a5f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/340b9ed7320570f319028a2cbec46d40535e94bd", - "reference": "340b9ed7320570f319028a2cbec46d40535e94bd", + "url": "https://api.github.com/repos/symfony/finder/zipball/01b24a145bbeaa7141e75887ec904c34a6728a5f", + "reference": "01b24a145bbeaa7141e75887ec904c34a6728a5f", "shasum": "" }, "require": { @@ -1130,7 +1130,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.4.0" + "source": "https://github.com/symfony/finder/tree/v7.4.4" }, "funding": [ { @@ -1150,20 +1150,20 @@ "type": "tidelift" } ], - "time": "2025-11-05T05:42:40+00:00" + "time": "2026-01-12T12:19:02+00:00" }, { "name": "symfony/http-foundation", - "version": "v8.0.1", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "3690740e2e8b19d877f20d4f10b7a489cddf0fe2" + "reference": "e33ba71e674a1bb16eb251688bd27c2ff67e0dc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/3690740e2e8b19d877f20d4f10b7a489cddf0fe2", - "reference": "3690740e2e8b19d877f20d4f10b7a489cddf0fe2", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e33ba71e674a1bb16eb251688bd27c2ff67e0dc1", + "reference": "e33ba71e674a1bb16eb251688bd27c2ff67e0dc1", "shasum": "" }, "require": { @@ -1210,7 +1210,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v8.0.1" + "source": "https://github.com/symfony/http-foundation/tree/v8.0.4" }, "funding": [ { @@ -1230,20 +1230,20 @@ "type": "tidelift" } ], - "time": "2025-12-07T11:23:24+00:00" + "time": "2026-01-09T12:15:10+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.4.2", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "f6e6f0a5fa8763f75a504b930163785fb6dd055f" + "reference": "48b067768859f7b68acf41dfb857a5a4be00acdd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/f6e6f0a5fa8763f75a504b930163785fb6dd055f", - "reference": "f6e6f0a5fa8763f75a504b930163785fb6dd055f", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/48b067768859f7b68acf41dfb857a5a4be00acdd", + "reference": "48b067768859f7b68acf41dfb857a5a4be00acdd", "shasum": "" }, "require": { @@ -1329,7 +1329,7 @@ "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.4.2" + "source": "https://github.com/symfony/http-kernel/tree/v7.4.4" }, "funding": [ { @@ -1349,7 +1349,7 @@ "type": "tidelift" } ], - "time": "2025-12-08T07:43:37+00:00" + "time": "2026-01-24T22:13:01+00:00" }, { "name": "symfony/polyfill-ctype", @@ -1768,16 +1768,16 @@ }, { "name": "symfony/process", - "version": "v7.4.0", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "7ca8dc2d0dcf4882658313aba8be5d9fd01026c8" + "reference": "626f07a53f4b4e2f00e11824cc29f928d797783b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/7ca8dc2d0dcf4882658313aba8be5d9fd01026c8", - "reference": "7ca8dc2d0dcf4882658313aba8be5d9fd01026c8", + "url": "https://api.github.com/repos/symfony/process/zipball/626f07a53f4b4e2f00e11824cc29f928d797783b", + "reference": "626f07a53f4b4e2f00e11824cc29f928d797783b", "shasum": "" }, "require": { @@ -1809,7 +1809,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.4.0" + "source": "https://github.com/symfony/process/tree/v7.4.4" }, "funding": [ { @@ -1829,7 +1829,7 @@ "type": "tidelift" } ], - "time": "2025-10-16T11:21:06+00:00" + "time": "2026-01-20T09:23:51+00:00" }, { "name": "symfony/service-contracts", @@ -1920,16 +1920,16 @@ }, { "name": "symfony/string", - "version": "v7.4.0", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "d50e862cb0a0e0886f73ca1f31b865efbb795003" + "reference": "1c4b10461bf2ec27537b5f36105337262f5f5d6f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/d50e862cb0a0e0886f73ca1f31b865efbb795003", - "reference": "d50e862cb0a0e0886f73ca1f31b865efbb795003", + "url": "https://api.github.com/repos/symfony/string/zipball/1c4b10461bf2ec27537b5f36105337262f5f5d6f", + "reference": "1c4b10461bf2ec27537b5f36105337262f5f5d6f", "shasum": "" }, "require": { @@ -1987,7 +1987,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.4.0" + "source": "https://github.com/symfony/string/tree/v7.4.4" }, "funding": [ { @@ -2007,20 +2007,20 @@ "type": "tidelift" } ], - "time": "2025-11-27T13:27:24+00:00" + "time": "2026-01-12T10:54:30+00:00" }, { "name": "symfony/var-dumper", - "version": "v8.0.0", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "d2a2476c93b58ac5292145e9fac1ff76a21d1ce2" + "reference": "326e0406fc315eca57ef5740fa4a280b7a068c82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/d2a2476c93b58ac5292145e9fac1ff76a21d1ce2", - "reference": "d2a2476c93b58ac5292145e9fac1ff76a21d1ce2", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/326e0406fc315eca57ef5740fa4a280b7a068c82", + "reference": "326e0406fc315eca57ef5740fa4a280b7a068c82", "shasum": "" }, "require": { @@ -2074,7 +2074,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v8.0.0" + "source": "https://github.com/symfony/var-dumper/tree/v8.0.4" }, "funding": [ { @@ -2094,7 +2094,7 @@ "type": "tidelift" } ], - "time": "2025-10-28T09:34:19+00:00" + "time": "2026-01-01T23:07:29+00:00" }, { "name": "symfony/var-exporter", @@ -2317,16 +2317,16 @@ }, { "name": "twig/twig", - "version": "v3.22.1", + "version": "v3.23.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "1de2ec1fc43ab58a4b7e80b214b96bfc895750f3" + "reference": "a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/1de2ec1fc43ab58a4b7e80b214b96bfc895750f3", - "reference": "1de2ec1fc43ab58a4b7e80b214b96bfc895750f3", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9", + "reference": "a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9", "shasum": "" }, "require": { @@ -2380,7 +2380,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.22.1" + "source": "https://github.com/twigphp/Twig/tree/v3.23.0" }, "funding": [ { @@ -2392,7 +2392,7 @@ "type": "tidelift" } ], - "time": "2025-11-16T16:01:12+00:00" + "time": "2026-01-23T21:00:41+00:00" } ], "packages-dev": [ @@ -2792,16 +2792,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.91.3", + "version": "v3.93.0", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "9f10aa6390cea91da175ea608880e942d7c0226e" + "reference": "50895a07cface1385082e4caa6a6786c4e033468" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/9f10aa6390cea91da175ea608880e942d7c0226e", - "reference": "9f10aa6390cea91da175ea608880e942d7c0226e", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/50895a07cface1385082e4caa6a6786c4e033468", + "reference": "50895a07cface1385082e4caa6a6786c4e033468", "shasum": "" }, "require": { @@ -2833,16 +2833,17 @@ }, "require-dev": { "facile-it/paraunit": "^1.3.1 || ^2.7", - "infection/infection": "^0.31.0", - "justinrainbow/json-schema": "^6.5", - "keradus/cli-executor": "^2.2", + "infection/infection": "^0.32", + "justinrainbow/json-schema": "^6.6", + "keradus/cli-executor": "^2.3", "mikey179/vfsstream": "^1.6.12", "php-coveralls/php-coveralls": "^2.9", "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6", "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6", - "phpunit/phpunit": "^9.6.25 || ^10.5.53 || ^11.5.34", - "symfony/var-dumper": "^5.4.48 || ^6.4.24 || ^7.3.2 || ^8.0", - "symfony/yaml": "^5.4.45 || ^6.4.24 || ^7.3.2 || ^8.0" + "phpunit/phpunit": "^9.6.31 || ^10.5.60 || ^11.5.48", + "symfony/polyfill-php85": "^1.33", + "symfony/var-dumper": "^5.4.48 || ^6.4.26 || ^7.4.0 || ^8.0", + "symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0" }, "suggest": { "ext-dom": "For handling output formats in XML", @@ -2883,7 +2884,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.91.3" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.93.0" }, "funding": [ { @@ -2891,7 +2892,7 @@ "type": "github" } ], - "time": "2025-12-05T19:45:37+00:00" + "time": "2026-01-23T17:33:21+00:00" }, { "name": "matthiasnoback/symfony-config-test", @@ -3075,16 +3076,16 @@ }, { "name": "nette/utils", - "version": "v4.1.0", + "version": "v4.1.1", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "fa1f0b8261ed150447979eb22e373b7b7ad5a8e0" + "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/fa1f0b8261ed150447979eb22e373b7b7ad5a8e0", - "reference": "fa1f0b8261ed150447979eb22e373b7b7ad5a8e0", + "url": "https://api.github.com/repos/nette/utils/zipball/c99059c0315591f1a0db7ad6002000288ab8dc72", + "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72", "shasum": "" }, "require": { @@ -3158,9 +3159,9 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.1.0" + "source": "https://github.com/nette/utils/tree/v4.1.1" }, - "time": "2025-12-01T17:49:23+00:00" + "time": "2025-12-22T12:14:32+00:00" }, { "name": "nikic/php-parser", @@ -3388,11 +3389,11 @@ }, { "name": "phpstan/phpstan", - "version": "2.1.33", + "version": "2.1.37", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9e800e6bee7d5bd02784d4c6069b48032d16224f", - "reference": "9e800e6bee7d5bd02784d4c6069b48032d16224f", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/28cd424c5ea984128c95cfa7ea658808e8954e49", + "reference": "28cd424c5ea984128c95cfa7ea658808e8954e49", "shasum": "" }, "require": { @@ -3437,20 +3438,20 @@ "type": "github" } ], - "time": "2025-12-05T10:24:31+00:00" + "time": "2026-01-24T08:21:55+00:00" }, { "name": "phpstan/phpstan-phpunit", - "version": "2.0.10", + "version": "2.0.12", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-phpunit.git", - "reference": "8d61a5854e7497d95bc85188e13537e99bd7aae7" + "reference": "e4c5a22bf43d3d2bd5a780ad261a622ff62c49a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/8d61a5854e7497d95bc85188e13537e99bd7aae7", - "reference": "8d61a5854e7497d95bc85188e13537e99bd7aae7", + "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/e4c5a22bf43d3d2bd5a780ad261a622ff62c49a4", + "reference": "e4c5a22bf43d3d2bd5a780ad261a622ff62c49a4", "shasum": "" }, "require": { @@ -3488,22 +3489,22 @@ "description": "PHPUnit extensions and rules for PHPStan", "support": { "issues": "https://github.com/phpstan/phpstan-phpunit/issues", - "source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.10" + "source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.12" }, - "time": "2025-12-06T11:15:39+00:00" + "time": "2026-01-22T13:40:00+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "12.5.1", + "version": "12.5.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "c467c59a4f6e04b942be422844e7a6352fa01b57" + "reference": "4a9739b51cbcb355f6e95659612f92e282a7077b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c467c59a4f6e04b942be422844e7a6352fa01b57", - "reference": "c467c59a4f6e04b942be422844e7a6352fa01b57", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/4a9739b51cbcb355f6e95659612f92e282a7077b", + "reference": "4a9739b51cbcb355f6e95659612f92e282a7077b", "shasum": "" }, "require": { @@ -3518,7 +3519,7 @@ "sebastian/environment": "^8.0.3", "sebastian/lines-of-code": "^4.0", "sebastian/version": "^6.0", - "theseer/tokenizer": "^2.0" + "theseer/tokenizer": "^2.0.1" }, "require-dev": { "phpunit/phpunit": "^12.5.1" @@ -3559,7 +3560,7 @@ "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/12.5.1" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.2" }, "funding": [ { @@ -3579,7 +3580,7 @@ "type": "tidelift" } ], - "time": "2025-12-08T07:17:58+00:00" + "time": "2025-12-24T07:03:04+00:00" }, { "name": "phpunit/php-file-iterator", @@ -3828,16 +3829,16 @@ }, { "name": "phpunit/phpunit", - "version": "12.5.2", + "version": "12.5.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "06713c2633d6d832f2fe98a70511ecaa7cb92c1a" + "reference": "37ddb96c14bfee10304825edbb7e66d341ec6889" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/06713c2633d6d832f2fe98a70511ecaa7cb92c1a", - "reference": "06713c2633d6d832f2fe98a70511ecaa7cb92c1a", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/37ddb96c14bfee10304825edbb7e66d341ec6889", + "reference": "37ddb96c14bfee10304825edbb7e66d341ec6889", "shasum": "" }, "require": { @@ -3851,13 +3852,13 @@ "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.3", - "phpunit/php-code-coverage": "^12.5.1", + "phpunit/php-code-coverage": "^12.5.2", "phpunit/php-file-iterator": "^6.0.0", "phpunit/php-invoker": "^6.0.0", "phpunit/php-text-template": "^5.0.0", "phpunit/php-timer": "^8.0.0", "sebastian/cli-parser": "^4.2.0", - "sebastian/comparator": "^7.1.3", + "sebastian/comparator": "^7.1.4", "sebastian/diff": "^7.0.0", "sebastian/environment": "^8.0.3", "sebastian/exporter": "^7.0.2", @@ -3905,7 +3906,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.2" + "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.8" }, "funding": [ { @@ -3929,7 +3930,7 @@ "type": "tidelift" } ], - "time": "2025-12-08T07:22:32+00:00" + "time": "2026-01-27T06:12:29+00:00" }, { "name": "react/cache", @@ -4005,16 +4006,16 @@ }, { "name": "react/child-process", - "version": "v0.6.6", + "version": "v0.6.7", "source": { "type": "git", "url": "https://github.com/reactphp/child-process.git", - "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159" + "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/child-process/zipball/1721e2b93d89b745664353b9cfc8f155ba8a6159", - "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159", + "url": "https://api.github.com/repos/reactphp/child-process/zipball/970f0e71945556422ee4570ccbabaedc3cf04ad3", + "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3", "shasum": "" }, "require": { @@ -4068,7 +4069,7 @@ ], "support": { "issues": "https://github.com/reactphp/child-process/issues", - "source": "https://github.com/reactphp/child-process/tree/v0.6.6" + "source": "https://github.com/reactphp/child-process/tree/v0.6.7" }, "funding": [ { @@ -4076,7 +4077,7 @@ "type": "open_collective" } ], - "time": "2025-01-01T16:37:48+00:00" + "time": "2025-12-23T15:25:20+00:00" }, { "name": "react/dns", @@ -4459,21 +4460,21 @@ }, { "name": "rector/rector", - "version": "2.2.14", + "version": "2.3.4", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", - "reference": "6d56bb0e94d4df4f57a78610550ac76ab403657d" + "reference": "9227d7a24b0f23ae941057509364f948d5da9ab2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/6d56bb0e94d4df4f57a78610550ac76ab403657d", - "reference": "6d56bb0e94d4df4f57a78610550ac76ab403657d", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/9227d7a24b0f23ae941057509364f948d5da9ab2", + "reference": "9227d7a24b0f23ae941057509364f948d5da9ab2", "shasum": "" }, "require": { "php": "^7.4|^8.0", - "phpstan/phpstan": "^2.1.33" + "phpstan/phpstan": "^2.1.36" }, "conflict": { "rector/rector-doctrine": "*", @@ -4507,7 +4508,7 @@ ], "support": { "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/2.2.14" + "source": "https://github.com/rectorphp/rector/tree/2.3.4" }, "funding": [ { @@ -4515,7 +4516,7 @@ "type": "github" } ], - "time": "2025-12-09T10:57:55+00:00" + "time": "2026-01-21T14:49:03+00:00" }, { "name": "sebastian/cli-parser", @@ -4588,16 +4589,16 @@ }, { "name": "sebastian/comparator", - "version": "7.1.3", + "version": "7.1.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "dc904b4bb3ab070865fa4068cd84f3da8b945148" + "reference": "6a7de5df2e094f9a80b40a522391a7e6022df5f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/dc904b4bb3ab070865fa4068cd84f3da8b945148", - "reference": "dc904b4bb3ab070865fa4068cd84f3da8b945148", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6a7de5df2e094f9a80b40a522391a7e6022df5f6", + "reference": "6a7de5df2e094f9a80b40a522391a7e6022df5f6", "shasum": "" }, "require": { @@ -4656,7 +4657,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/7.1.3" + "source": "https://github.com/sebastianbergmann/comparator/tree/7.1.4" }, "funding": [ { @@ -4676,7 +4677,7 @@ "type": "tidelift" } ], - "time": "2025-08-20T11:27:00+00:00" + "time": "2026-01-24T09:28:48+00:00" }, { "name": "sebastian/complexity", @@ -5468,16 +5469,16 @@ }, { "name": "symfony/console", - "version": "v7.4.1", + "version": "v7.4.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "6d9f0fbf2ec2e9785880096e3abd0ca0c88b506e" + "reference": "41e38717ac1dd7a46b6bda7d6a82af2d98a78894" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/6d9f0fbf2ec2e9785880096e3abd0ca0c88b506e", - "reference": "6d9f0fbf2ec2e9785880096e3abd0ca0c88b506e", + "url": "https://api.github.com/repos/symfony/console/zipball/41e38717ac1dd7a46b6bda7d6a82af2d98a78894", + "reference": "41e38717ac1dd7a46b6bda7d6a82af2d98a78894", "shasum": "" }, "require": { @@ -5542,7 +5543,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.4.1" + "source": "https://github.com/symfony/console/tree/v7.4.4" }, "funding": [ { @@ -5562,7 +5563,7 @@ "type": "tidelift" } ], - "time": "2025-12-05T15:23:39+00:00" + "time": "2026-01-13T11:36:38+00:00" }, { "name": "symfony/options-resolver", diff --git a/docs/source/bundles/index.rst b/docs/source/bundles/index.rst index 22ed985..ba34460 100644 --- a/docs/source/bundles/index.rst +++ b/docs/source/bundles/index.rst @@ -14,5 +14,6 @@ Table of Contents :maxdepth: 2 :titlesonly: + logger-bundle/index metadata-bundle/index diff --git a/docs/source/bundles/logger-bundle/index.rst b/docs/source/bundles/logger-bundle/index.rst new file mode 100644 index 0000000..86124c8 --- /dev/null +++ b/docs/source/bundles/logger-bundle/index.rst @@ -0,0 +1,177 @@ +============= +Logger Bundle +============= + +The Logger Bundle provides seamless integration of the Logger component with +the Symfony framework. This bundle automatically configures the Logger as a +service and provides configuration options for customizing its behavior. + +The Logger component is a decorator for PSR-3 logger implementations that adds +convenience methods for exception logging and context enrichment. See the +:doc:`../../components/logger/index` for details about the Logger component +itself. + +Installation +------------ + +To use the Logger component in a Symfony application, install the bundle: + +.. code-block:: console + + composer require runopencode/logger-bundle + +The bundle will be automatically registered in your ``config/bundles.php`` if +you're using Symfony Flex. + +Configuration +------------- + +The bundle provides several configuration options that can be set in your +``config/packages/runopencode_logger.yaml`` file: + +.. code-block:: yaml + + runopencode_logger: + debug: '%kernel.debug%' + default_log_level: 'error' + +Configuration options +~~~~~~~~~~~~~~~~~~~~~ + +* ``debug`` (boolean, default: ``false``): Enable debug mode. When enabled, the + ``exception()`` method will throw exceptions after logging them. This is + useful during development. Typically set to ``%kernel.debug%`` to match + Symfony's debug mode. + +* ``default_log_level`` (string, default: ``'critical'``): The default log level + used for exception logging when no level is explicitly specified. Valid values + are: ``emergency``, ``alert``, ``critical``, ``error``, ``warning``, + ``notice``, ``info``, ``debug``. + +Using the Logger service +------------------------- + +Once the bundle is installed and configured, the Logger service is automatically +available for dependency injection. Inject it using the interface: + +.. code-block:: php + :linenos: + + repository->create($userData); + $this->mailer->sendWelcomeEmail($user); + + return $user; + } catch (\Throwable $exception) { + $this->logger->exception( + $exception, + 'User registration failed', + ['email' => $userData['email'] ?? 'unknown'] + ); + // ... + } + } + } + +The Logger is automatically configured with Symfony's default logger (the +``logger`` service). + +Automatic context provider registration +---------------------------------------- + +One of the most powerful features of the bundle is automatic registration of +context providers. Any service that implements ``LoggerContextInterface`` is +automatically detected and injected into the Logger. + +Creating a context provider +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Simply create a service that implements the interface: + +.. code-block:: php + :linenos: + + requestStack->getCurrentRequest(); + + if (null === $request) { + return []; + } + + return [ + 'request_id' => $request->headers->get('X-Request-ID') ?? uniqid(), + 'request_uri' => $request->getRequestUri(), + 'request_method' => $request->getMethod(), + 'user_agent' => $request->headers->get('User-Agent'), + ]; + } + } + +If you have services autoconfiguration enabled (which is the default in Symfony), +this service will be automatically registered and tagged with +``runopencode.logger.context_provider``. No additional configuration is needed! + +Manual registration +~~~~~~~~~~~~~~~~~~~ + +If you're not using autoconfiguration or want to explicitly register a context +provider, you can do so in your services configuration: + +.. code-block:: yaml + + services: + App\Logger\Context\RequestContextProvider: + tags: + - { name: 'runopencode.logger.context_provider' } + +Best practices +-------------- + +1. **Use the interface**: Always inject ``LoggerInterface`` from the Logger + component, not the concrete ``Logger`` class or PSR-3's ``LoggerInterface``. + +2. **Configure per environment**: Use different configuration files for dev, + test, and prod environments to adjust debug mode and log levels. + +3. **Create focused context providers**: Each context provider should have a + single responsibility (e.g., one for request data, one for user data, etc.). + +4. **Keep providers lightweight**: Context providers are called on every log + entry, so avoid expensive operations. + +See the :doc:`../../components/logger/context-providers` documentation for more +information about creating and using context providers. diff --git a/docs/source/components/index.rst b/docs/source/components/index.rst index 5a112c3..d8ffd88 100644 --- a/docs/source/components/index.rst +++ b/docs/source/components/index.rst @@ -18,5 +18,6 @@ Table of Contents :titlesonly: dataset/index + logger/index metadata/index query/index diff --git a/docs/source/components/logger/context-providers.rst b/docs/source/components/logger/context-providers.rst new file mode 100644 index 0000000..0ee7fff --- /dev/null +++ b/docs/source/components/logger/context-providers.rst @@ -0,0 +1,238 @@ +================= +Context providers +================= + +Context providers allow you to automatically enrich all log entries with +additional context information from various sources. This is useful for adding +consistent metadata to all logs, such as request IDs, user information, +environment details, etc. + +What are context providers? +---------------------------- + +A context provider is a class that implements the ``LoggerContextInterface`` +and provides additional context data to be merged with the context passed to +any log method. This allows you to inject contextual information into all log +entries without having to manually pass it every time you log something. + +Common use cases include: + +* Adding request ID to all logs for request tracing +* Including authenticated user information +* Adding environment details (hostname, instance ID, etc.) +* Including application version or build number +* Adding correlation IDs for distributed systems + +The LoggerContextInterface +--------------------------- + +To create a context provider, implement the ``LoggerContextInterface``: + +.. code-block:: php + :linenos: + + $current Current context passed to the logger method. + * + * @return array Context data to append to the current context. + */ + public function get(array $current): array; + } + +The ``get()`` method receives the current context (the context that was passed +to the log method) and returns additional context data to be merged with it. + +Creating a context provider +---------------------------- + +Here's an example of a simple context provider that adds request ID to all logs: + +.. code-block:: php + :linenos: + + $this->requestId]; + } + } + +Using context providers +----------------------- + +To use context providers, pass them to the Logger constructor: + +.. code-block:: php + :linenos: + + info('User action performed'); + + // Resulting context will be something like: + // [ + // 'request_id' => '96a101dd-c49a-4fea-aee2-a76510f32190', + // ] + +Context merging +--------------- + +Context from providers is merged with the context passed to log methods. The +merge happens in this order: + +1. Context from each provider is collected (in the order they were registered) +2. Each provider's context is merged with the accumulated context +3. The final context is merged with the context passed to the log method + +If there are duplicate keys, later values override earlier ones: + +.. code-block:: php + :linenos: + + 'abc', 'env' => 'prod'] + // Provider 2 returns: ['user_id' => 42, 'env' => 'staging'] + // Passed context: ['env' => 'dev', 'action' => 'create'] + + // Final context will be: + // [ + // 'request_id' => 'abc', + // 'env' => 'dev', // From passed context (overrides providers) + // 'user_id' => 42, + // 'action' => 'create', + // ] + +This means that the context passed directly to the log method always has the +highest priority. + +Access to current context +------------------------- + +Context providers have access to the current context (including context from +previous providers) through the ``$current`` parameter. This allows you to make +decisions based on what's already in the context: + +.. code-block:: php + :linenos: + + memory_get_usage(true), + 'peak_memory' => memory_get_peak_usage(true), + 'time' => microtime(true), + ]; + } + + return []; + } + } + +Performance considerations +-------------------------- + +Context providers are called for every log entry, so keep their implementation +lightweight. Avoid expensive operations like database queries or external API +calls in context providers. + +If you need to include data that's expensive to compute, consider: + +* Caching the data in the provider instance +* Making the computation lazy (only when actually needed) +* Using a different approach for expensive context data + +Good example (lightweight): + +.. code-block:: php + :linenos: + + $_ENV['APP_ENV'] ?? 'unknown', + 'hostname' => gethostname(), + ]; + } + } + +Bad example (expensive - avoid this): + +.. code-block:: php + :linenos: + + $this->db->query('SELECT COUNT(*) FROM users WHERE active = 1'), + ]; + } + } + +See the :doc:`Logger Bundle documentation <../../bundles/logger-bundle/index>` +for details on Symfony integration. diff --git a/docs/source/components/logger/index.rst b/docs/source/components/logger/index.rst new file mode 100644 index 0000000..7060ecb --- /dev/null +++ b/docs/source/components/logger/index.rst @@ -0,0 +1,120 @@ +================ +Logger component +================ + +The Logger component is a decorator for PSR-3 logger implementations that adds +convenience methods for exception logging and context enrichment. It wraps any +PSR-3 compatible logger and extends its functionality with exception-specific +logging methods and the ability to automatically enrich log context from +multiple sources. + +When working with exceptions, you often need to log them with proper context +before either throwing them or suppressing them based on the environment (e.g., +development vs. production). This component provides a clean API for these +common scenarios while maintaining full compatibility with PSR-3. + +Features +-------- + +* **Exception logging methods**: dedicated ``exception()`` and ``throw()`` + methods for logging exceptions with automatic context enrichment. +* **Debug mode support**: toggle between logging and throwing exceptions + depending on the environment. +* **Context providers**: automatically enrich log entries with additional + context from multiple sources (e.g., request ID, user information, etc.). +* **PSR-3 compatible**: fully implements PSR-3 ``LoggerInterface`` and can wrap + any PSR-3 logger. +* **Configurable default log level**: set the default severity level for + exception logging. +* **Symfony ready**: via dedicated ``runopencode/logger-bundle`` package, + see :doc:`../../bundles/logger-bundle/index` for integration details. + +Table of Contents +----------------- + +.. toctree:: + :maxdepth: 1 + + installation + usage + context-providers + +Quick example +------------- + +Basic usage of the Logger component to log exceptions with custom context: + +.. code-block:: php + :linenos: + + gateway->charge($payment); + } catch (\Throwable $exception) { + // Log the exception with additional context + $this->logger->exception( + $exception, + 'Payment processing failed', + [ + 'payment_id' => $payment->getId(), + 'amount' => $payment->getAmount(), + 'currency' => $payment->getCurrency(), + ] + ); + // ... + } + } + } + +In the example above, if an exception occurs during payment processing, it will +be logged with the custom message and context, including payment details. The +``exception()`` method logs the exception but does not re-throw it (unless debug +mode is enabled), allowing you to handle the error yourself. + +For cases where you want to both log and throw the exception, use the +``throw()`` method instead: + +.. code-block:: php + :linenos: + + performOperation(); + } catch (\Throwable $exception) { + // Log and re-throw the exception + $this->logger->throw( + $exception, + 'Critical operation failed', + ['operation' => 'critical'] + ); + } + } + +See :doc:`usage` for more detailed examples and :doc:`context-providers` to +learn how to automatically enrich all log entries with additional context. + +For Symfony framework integration, see the +:doc:`Logger Bundle documentation <../../bundles/logger-bundle/index>`. + diff --git a/docs/source/components/logger/installation.rst b/docs/source/components/logger/installation.rst new file mode 100644 index 0000000..c3b1760 --- /dev/null +++ b/docs/source/components/logger/installation.rst @@ -0,0 +1,156 @@ +============ +Installation +============ + +To install the Logger component, you will need to use Composer. Run the +following command in your terminal: + +.. code-block:: console + + composer require runopencode/logger + +This will download and install the Logger component along with its dependencies. + +Basic setup +----------- + +In your project, you will need to initialize the Logger by wrapping an existing +PSR-3 logger implementation: + +.. code-block:: php + :linenos: + + pushHandler(new StreamHandler('/path/to/logs/app.log', LogLevel::DEBUG)); + + // Wrap it with RunOpenCode Logger + $logger = new Logger( + decorated: $psrLogger, + contextProviders: [], // Optional: context providers + debug: false, // Optional: debug mode (default: false) + defaultLevel: LogLevel::CRITICAL // Optional: default log level (default: CRITICAL) + ); + +The Logger component is a decorator that wraps any PSR-3 logger implementation +and adds additional functionality on top of it. + +Using the interface +------------------- + +It is highly recommended to use the ``LoggerInterface`` from this component +as a dependency in your classes, rather than the concrete implementation: + +.. code-block:: php + :linenos: + + repository->delete($userId); + } catch (\Throwable $exception) { + $this->logger->exception( + $exception, + 'Failed to delete user', + ['user_id' => $userId] + ); + // ... + } + } + } + +The ``LoggerInterface`` extends PSR-3's ``LoggerInterface`` and adds the +``exception()`` and ``throw()`` methods for convenient exception logging. + +Debug mode +---------- + +When creating a Logger instance, you can enable debug mode. In debug mode, the +``exception()`` method will throw the exception after logging it, which is +useful during development: + +.. code-block:: php + :linenos: + + exception($exception); + + // You can still override it per-call + $logger->exception($exception, level: LogLevel::CRITICAL); + +The default log level is ``LogLevel::CRITICAL`` if not specified. + +Symfony integration +------------------- + +If you are using Symfony framework, you should use the +``runopencode/logger-bundle`` package which automatically registers the Logger +as a service in your container and provides configuration options. + +See the :doc:`Logger Bundle documentation <../../bundles/logger-bundle/index>` +for more information about Symfony integration. diff --git a/docs/source/components/logger/usage.rst b/docs/source/components/logger/usage.rst new file mode 100644 index 0000000..433d494 --- /dev/null +++ b/docs/source/components/logger/usage.rst @@ -0,0 +1,285 @@ +===== +Usage +===== + +The Logger component provides a decorator for PSR-3 loggers with additional +methods specifically designed for exception handling. This document covers the +main usage patterns and features. + +Exception logging +----------------- + +The primary feature of this component is the ability to log exceptions with +a clean API. The component provides two methods for exception logging: + +* ``exception()`` - Logs the exception but does not throw it (unless in debug mode) +* ``throw()`` - Logs the exception and always throws it + +exception() method +~~~~~~~~~~~~~~~~~~ + +Use the ``exception()`` method when you want to log an exception and handle it +gracefully without re-throwing it: + +.. code-block:: php + :linenos: + + validateOrder($order); + $this->processPayment($order); + $this->notifyCustomer($order); + + return OrderResult::success($order); + } catch (\Throwable $exception) { + // Log the exception with context + $this->logger->exception( + $exception, + 'Order placement failed', + [ + 'order_id' => $order->getId(), + 'customer_id' => $order->getCustomerId(), + 'total' => $order->getTotal(), + ] + ); + + return OrderResult::failure($exception->getMessage()); + } + } + } + +In the example above, when an exception occurs, it is logged with additional +context, but the method returns a failure result instead of crashing. This is +useful for non-critical operations where you want to continue execution. + +throw() method +~~~~~~~~~~~~~~ + +Use the ``throw()`` method when you want to log an exception and then re-throw +it: + +.. code-block:: php + :linenos: + + database->execute('CRITICAL_OPERATION'); + } catch (\Exception $exception) { + // Log and re-throw + $this->logger->throw( + $exception, + 'Critical database operation failed', + ['operation' => 'CRITICAL_OPERATION'] + ); + } + } + +This is useful when you need to log the exception with context but still want +the exception to propagate up the call stack. + +Custom messages +~~~~~~~~~~~~~~~ + +Both methods accept an optional custom message parameter. If provided, this +message will be used for logging instead of the exception's message: + +.. code-block:: php + :linenos: + + externalApi->call(); + } catch (\Throwable $exception) { + // Use a custom message for logging + $this->logger->exception( + $exception, + 'External API call failed - retrying later' + ); + } + +If no custom message is provided, the exception's message will be used. + +Log levels +~~~~~~~~~~ + +You can specify the log level for each exception: + +.. code-block:: php + :linenos: + + cache->clear(); + } catch (\Throwable $exception) { + // Log at WARNING level instead of the default CRITICAL + $this->logger->exception( + $exception, + 'Cache clear failed', + level: LogLevel::WARNING + ); + } + +If no level is specified, the logger will use the default level configured +during initialization (which defaults to ``LogLevel::CRITICAL``). + +Context enrichment +~~~~~~~~~~~~~~~~~~ + +The ``exception()`` and ``throw()`` methods automatically add the exception +object to the log context under the ``exception`` key: + +.. code-block:: php + :linenos: + + logger->exception( + $exception, + 'Operation failed', + ['user_id' => 123] + ); + + // The actual context passed to the underlying PSR-3 logger will be: + // [ + // 'user_id' => 123, + // 'exception' => $exception - Automatically added + // ] + +This ensures that the exception object is always available in the log context +for further processing by your logging infrastructure (e.g., Sentry, error +tracking services, etc.). + +Additionally, if you have configured context providers (see +:doc:`context-providers`), they will automatically enrich the context with +additional information. + +PSR-3 compatibility +------------------- + +The Logger component fully implements PSR-3's ``LoggerInterface``, so you can +use all standard PSR-3 methods: + +.. code-block:: php + :linenos: + + emergency('System is down'); + $logger->alert('Database connection lost'); + $logger->critical('Critical error occurred'); + $logger->error('An error occurred'); + $logger->warning('Warning: deprecated method used'); + $logger->notice('User logged in'); + $logger->info('Operation completed successfully'); + $logger->debug('Debug information'); + + // Generic log method + $logger->log(LogLevel::INFO, 'Custom log message', ['key' => 'value']); + +All these methods are forwarded to the underlying PSR-3 logger that was passed +to the Logger constructor. If context providers are configured, they will also +enrich the context for these standard PSR-3 methods. + +Debug mode behavior +------------------- + +The behavior of the ``exception()`` method changes based on the debug mode: + +.. code-block:: php + :linenos: + + exception($exception); + + // Execution continues here + echo "Exception was logged, continuing execution..."; + } + + // Development mode (debug = true) + $logger = new Logger($psrLogger, debug: true); + + try { + throw new \RuntimeException('Test exception'); + } catch (\Throwable $exception) { + // This will log the exception AND throw it again + $logger->exception($exception); + + // This line will NOT be reached + echo "This will never be printed"; + } + +This allows you to use the same code in both environments, with different +behavior based on the debug flag. In production, you can log exceptions and +handle them gracefully, while in development, exceptions are still thrown so +you can see stack traces and debug issues. + +Note that the ``throw()`` method always re-throws the exception regardless of +the debug mode. + +Working with context +-------------------- + +You can pass any additional context data when logging exceptions: + +.. code-block:: php + :linenos: + + api->updateUser($userId, $data); + } catch (\Throwable $exception) { + $this->logger->exception( + $exception, + 'User update failed', + [ + 'user_id' => $userId, + 'request_data' => $data, + 'timestamp' => time(), + 'ip_address' => $_SERVER['REMOTE_ADDR'] ?? 'unknown', + ] + ); + } + +The context array can contain any data that will help you debug the issue. This +data is passed to the underlying PSR-3 logger and can be processed by your log +handlers (e.g., written to files, sent to log aggregation services, etc.). + +For automatically enriching context across all log calls, see +:doc:`context-providers`. diff --git a/src/RunOpenCode/Bundle/LoggerBundle/LICENSE b/src/RunOpenCode/Bundle/LoggerBundle/LICENSE new file mode 100644 index 0000000..e8b6ed7 --- /dev/null +++ b/src/RunOpenCode/Bundle/LoggerBundle/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 RunOpenCode + +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/src/RunOpenCode/Bundle/LoggerBundle/README.md b/src/RunOpenCode/Bundle/LoggerBundle/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/RunOpenCode/Bundle/LoggerBundle/composer.json b/src/RunOpenCode/Bundle/LoggerBundle/composer.json new file mode 100644 index 0000000..94f03b0 --- /dev/null +++ b/src/RunOpenCode/Bundle/LoggerBundle/composer.json @@ -0,0 +1,44 @@ +{ + "name": "runopencode/logger-bundle", + "description": "Symfony integration with runopencode/logger component.", + "license": "MIT", + "authors": [ + { + "name": "Nikola Svitlica a.k.a TheCelavi", + "email": "thecelavi@runopencode.com" + }, + { + "name": "Stefan Veljancic", + "email": "veljancicstefan@gmail.com" + } + ], + "require": { + "php": ">=8.4", + "psr/log": "^3.0", + "runopencode/logger": "^0.2", + "symfony/cache": "^7.0", + "symfony/config": "^7.0", + "symfony/http-kernel": "^7.0", + "symfony/dependency-injection": "^7.0" + }, + "autoload": { + "psr-4": { + "RunOpenCode\\Bundle\\LoggerBundle\\": "src/" + } + }, + "repositories": [ + { + "type": "path", + "url": "../../Component/Logger", + "options": { + "symlink": false + } + } + ], + "config": { + "sort-packages": true + }, + "version": "0.2", + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/src/RunOpenCode/Bundle/LoggerBundle/src/LoggerBundle.php b/src/RunOpenCode/Bundle/LoggerBundle/src/LoggerBundle.php new file mode 100644 index 0000000..bec19f1 --- /dev/null +++ b/src/RunOpenCode/Bundle/LoggerBundle/src/LoggerBundle.php @@ -0,0 +1,71 @@ +rootNode() + ->addDefaultsIfNotSet() + ->children() + ->booleanNode('debug') + ->defaultFalse() + ->info('Set to "true" if exception should be thrown instead of logged (useful for development purposes).') + ->end() + ->enumNode('default_log_level') + ->defaultValue(LogLevel::CRITICAL) + ->values(Logger::getLogLevels()) + ->info('Set default log level for exceptions.') + ->end() + ->end() + ->end(); + } + + /** + * {@inheritdoc} + * + * @param array{ + * debug: bool, + * default_log_level: string + * } $config + */ + public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void + { + $builder->registerForAutoconfiguration(LoggerContextInterface::class) + ->addTag('runopencode.logger.context_provider'); + + $services = $container->services(); + + $services + ->set(Logger::class) + ->args([ + '$decorated' => service('monolog.logger'), + '$contextProviders' => tagged_iterator('runopencode.logger.context_provider'), + '$debug' => $config['debug'], + '$defaultLevel' => $config['default_log_level'], + ]); + + $services->alias(LoggerInterface::class, Logger::class); + } +} diff --git a/src/RunOpenCode/Bundle/LoggerBundle/tests/LoggerBundleTest.php b/src/RunOpenCode/Bundle/LoggerBundle/tests/LoggerBundleTest.php new file mode 100644 index 0000000..d5f2ef8 --- /dev/null +++ b/src/RunOpenCode/Bundle/LoggerBundle/tests/LoggerBundleTest.php @@ -0,0 +1,68 @@ +container->setParameter('kernel.environment', 'test'); + $this->container->setParameter('kernel.build_dir', 'tmp'); + } + + #[Test] + public function load_extension_with_default_configuration(): void + { + $this->load(); + + $this->assertContainerBuilderHasService(Logger::class); + $this->assertContainerBuilderHasAlias(LoggerInterface::class, Logger::class); + + $this->assertContainerBuilderHasServiceDefinitionWithArgument(Logger::class, '$decorated'); + $this->assertContainerBuilderHasServiceDefinitionWithArgument(Logger::class, '$contextProviders'); + $this->assertContainerBuilderHasServiceDefinitionWithArgument(Logger::class, '$debug', false); + $this->assertContainerBuilderHasServiceDefinitionWithArgument(Logger::class, '$defaultLevel', LogLevel::CRITICAL); + } + + #[Test] + public function load_extension_with_custom_configuration(): void + { + $this->load([ + 'debug' => true, + 'default_log_level' => 'warning', + ]); + + $this->assertContainerBuilderHasService(Logger::class); + $this->assertContainerBuilderHasAlias(LoggerInterface::class, Logger::class); + + $this->assertContainerBuilderHasServiceDefinitionWithArgument(Logger::class, '$debug', true); + $this->assertContainerBuilderHasServiceDefinitionWithArgument(Logger::class, '$defaultLevel', 'warning'); + } + + /** + * {@inheritdoc} + */ + protected function getContainerExtensions(): array + { + $bundle = new LoggerBundle(); + $extension = $bundle->getContainerExtension(); + + if (null === $extension) { + throw new \RuntimeException('Failed to get container extension from LoggerBundle.'); + } + + return [$extension]; + } +} diff --git a/src/RunOpenCode/Component/Logger/README.md b/src/RunOpenCode/Component/Logger/README.md new file mode 100644 index 0000000..e69de29 diff --git a/src/RunOpenCode/Component/Logger/composer.json b/src/RunOpenCode/Component/Logger/composer.json new file mode 100644 index 0000000..ffef5d5 --- /dev/null +++ b/src/RunOpenCode/Component/Logger/composer.json @@ -0,0 +1,30 @@ +{ + "name": "runopencode/logger", + "description": "Wrapper for psr/logger with additional method to log exceptions.", + "license": "MIT", + "authors": [ + { + "name": "Nikola Svitlica a.k.a TheCelavi", + "email": "thecelavi@runopencode.com" + }, + { + "name": "Stefan Veljancic", + "email": "veljancicstefan@gmail.com" + } + ], + "require": { + "php": ">=8.4", + "psr/log": "^2.0|^3.0" + }, + "autoload": { + "psr-4": { + "RunOpenCode\\Component\\Logger\\": "src/" + } + }, + "config": { + "sort-packages": true + }, + "version": "0.2", + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/src/RunOpenCode/Component/Logger/src/Contract/LoggerContextInterface.php b/src/RunOpenCode/Component/Logger/src/Contract/LoggerContextInterface.php new file mode 100644 index 0000000..db3579e --- /dev/null +++ b/src/RunOpenCode/Component/Logger/src/Contract/LoggerContextInterface.php @@ -0,0 +1,24 @@ + $contextProviders Context providers to enrich log context. + */ + public function __construct( + private PsrLoggerInterface $decorated, + private iterable $contextProviders = [], + private bool $debug = false, + private string $defaultLevel = LogLevel::CRITICAL + ) { + if (!$this->isValidLogLevel($defaultLevel)) { + throw new \InvalidArgumentException(\sprintf( + 'Provided value "%s" for default log level is not known (known values are "%s").', + $defaultLevel, + \implode('", "', self::getLogLevels()) + )); + } + } + + /** + * {@inheritdoc} + */ + public function exception(\Throwable $exception, \Stringable|string|null $message = null, array $context = [], ?string $level = null): void + { + $this->logException($exception, $message, $context, $level); + + if ($this->debug) { + throw $exception; + } + } + + /** + * {@inheritdoc} + */ + public function throw(\Throwable $exception, \Stringable|string|null $message = null, array $context = [], ?string $level = null): void + { + $this->logException($exception, $message, $context, $level); + + throw $exception; + } + + /** + * {@inheritdoc} + */ + public function emergency(\Stringable|string $message, array $context = []): void + { + $this->log(LogLevel::EMERGENCY, $message, $context); + } + + /** + * {@inheritdoc} + */ + public function alert(\Stringable|string $message, array $context = []): void + { + $this->log(LogLevel::ALERT, $message, $context); + } + + /** + * {@inheritdoc} + */ + public function critical(\Stringable|string $message, array $context = []): void + { + $this->log(LogLevel::CRITICAL, $message, $context); + } + + /** + * {@inheritdoc} + */ + public function error(\Stringable|string $message, array $context = []): void + { + $this->log(LogLevel::ERROR, $message, $context); + } + + /** + * {@inheritdoc} + */ + public function warning(\Stringable|string $message, array $context = []): void + { + $this->log(LogLevel::WARNING, $message, $context); + } + + /** + * {@inheritdoc} + */ + public function notice(\Stringable|string $message, array $context = []): void + { + $this->log(LogLevel::NOTICE, $message, $context); + } + + /** + * {@inheritdoc} + */ + public function info(\Stringable|string $message, array $context = []): void + { + $this->log(LogLevel::INFO, $message, $context); + } + + /** + * {@inheritdoc} + */ + public function debug(\Stringable|string $message, array $context = []): void + { + $this->log(LogLevel::DEBUG, $message, $context); + } + + /** + * {@inheritdoc} + */ + public function log($level, \Stringable|string $message, array $context = []): void + { + $collected = []; + + foreach ($this->contextProviders as $provider) { + $collected[] = $provider->get($context); + } + + $this->decorated->log($level, $message, \array_merge($context, ...$collected)); + } + + /** + * Get known log levels defined by psr/log. + * + * @return list + */ + public static function getLogLevels(): array + { + /** @var list|null $levels */ + static $levels; + + if (!isset($levels)) { + /** @var list $levels */ + $levels = \array_values(new \ReflectionClass(LogLevel::class)->getConstants(\ReflectionClassConstant::IS_PUBLIC)); + } + + return $levels; + } + + /** + * @param mixed[] $context + * + * @throws \Throwable + */ + private function logException(\Throwable $exception, \Stringable|string|null $message = null, array $context = [], ?string $level = null): void + { + $message = $message ? (string)$message : $exception->getMessage(); + $level = $level ?? $this->defaultLevel; + + if (!$this->isValidLogLevel($level)) { + throw new \InvalidArgumentException(\sprintf( + 'Provided value "%s" for log level is not in known (known values are "%s").', + $level, + \implode('", "', self::getLogLevels()) + )); + } + + $this->{$level}($message, \array_merge( + $context, + ['exception' => $exception] + )); + } + + /** + * Check if provided log level is defined by psr/log. + */ + private function isValidLogLevel(string $level): bool + { + /** @var array|null $levels */ + static $levels; + + if (!isset($levels)) { + /** @var array $levels */ + $levels = \array_combine(self::getLogLevels(), self::getLogLevels()); + } + + return isset($levels[$level]); + } +} diff --git a/src/RunOpenCode/Component/Logger/tests/LoggerTest.php b/src/RunOpenCode/Component/Logger/tests/LoggerTest.php new file mode 100644 index 0000000..7726231 --- /dev/null +++ b/src/RunOpenCode/Component/Logger/tests/LoggerTest.php @@ -0,0 +1,168 @@ +decorated = $this->createMock(LoggerInterface::class); + } + + protected function tearDown(): void + { + parent::tearDown(); + unset($this->decorated); + } + + /** + * @param non-empty-string $exceptionMessage + * @param non-empty-string|null $loggerMessage + * @param LogLevel::*|null $logLevel + */ + #[Test] + #[DataProvider('get_data_for_exception')] + public function exception( + string $exceptionMessage, + ?string $loggerMessage, + ?string $logLevel, + string $expectedMessage, + ): void { + $exception = new \RuntimeException($exceptionMessage); + + $this + ->decorated + ->expects($this->once()) + ->method('log') + ->with( + $logLevel ?? LogLevel::CRITICAL, + $this->stringContains($expectedMessage), + ['exception' => $exception] + ); + + new Logger($this->decorated)->exception($exception, $loggerMessage, [], $logLevel); + } + + /** + * @return iterable + */ + public static function get_data_for_exception(): iterable + { + yield 'It logs exception with default message and default log level.' => ['Test exception', null, null, 'Test exception']; + yield 'It logs exception with custom message and default log level.' => ['Test exception', 'Custom message', null, 'Custom message']; + yield 'It logs exception with custom message and custom alert level.' => ['Test exception', 'Custom message', LogLevel::ALERT, 'Custom message']; + } + + #[Test] + public function exception_with_context(): void + { + $exception = new \RuntimeException('Test exception'); + $this + ->decorated + ->expects($this->once()) + ->method('log') + ->with( + LogLevel::CRITICAL, + 'Test exception', + ['foo' => 'bar', 'exception' => $exception], + ); + + new Logger($this->decorated)->exception($exception, null, ['foo' => 'bar']); + } + + #[Test] + public function exception_throws_in_debug_mode(): void + { + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Test exception'); + + $exception = new \RuntimeException('Test exception'); + + $this + ->decorated + ->expects($this->once()) + ->method('log') + ->with( + LogLevel::CRITICAL, + 'Test exception', + ['exception' => $exception] + ); + + new Logger($this->decorated, [], true)->exception($exception); + } + + #[Test] + public function throw(): void + { + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Test exception'); + + $exception = new \RuntimeException('Test exception'); + + $this + ->decorated + ->expects($this->once()) + ->method('log') + ->with( + LogLevel::CRITICAL, + 'Test exception', + ['exception' => $exception] + ); + + new Logger($this->decorated, [], true)->throw($exception); + } + + /** + * @param LogLevel::* $method + */ + #[Test] + #[DataProvider('get_data_for_level_methods')] + public function level_methods(string $method): void + { + $this + ->decorated + ->expects($this->once()) + ->method('log') + ->with($method, \sprintf('Message for "%s".', $method), []); + + new Logger($this->decorated)->{$method}(\sprintf('Message for "%s".', $method)); + } + + /** + * @return iterable + */ + public static function get_data_for_level_methods(): iterable + { + /** @var list $levels */ + $levels = new \ReflectionClass(LogLevel::class)->getConstants(); + + foreach ($levels as $level) { + yield \sprintf('Method %s()', $level) => [$level]; + } + } + + #[Test] + public function log(): void + { + $this->decorated->expects($this->once()) + ->method('log') + ->with(LogLevel::INFO, 'Log message'); + + $logger = new Logger($this->decorated); + + $logger->log(LogLevel::INFO, 'Log message'); + } +} diff --git a/src/RunOpenCode/Component/Query/tests/Functions/ToRegexTest.php b/src/RunOpenCode/Component/Query/tests/Functions/ToRegexTest.php index 7320cdc..8c7a725 100644 --- a/src/RunOpenCode/Component/Query/tests/Functions/ToRegexTest.php +++ b/src/RunOpenCode/Component/Query/tests/Functions/ToRegexTest.php @@ -30,14 +30,7 @@ public static function get_data_for_glob_matches(): iterable yield '*.twig, @foo/bar.sql.twig' => ['*.twig', '@foo/bar.sql.twig', false]; yield '*.twig, foo.sql.twig' => ['*.twig', 'foo.sql.twig', true]; yield '**/*.twig, @foo/bar.sql.twig' => ['**/*.twig', '@foo/bar.sql.twig', true]; - } - - /** - * @see https://github.com/symfony/symfony/issues/62737 - */ - #[Test] - public function monitor_fix(): void - { - $this->assertDoesNotMatchRegularExpression(to_regex('**/*.twig'), 'foo.sql.twig'); + // Fixed in @see https://github.com/symfony/symfony/issues/62737 + yield '**/*.twig, foo.sql.twig' => ['**/*.twig', 'foo.sql.twig', true]; } }