From 12b6c4b3008c2df545c537943d4e38323cfc174e Mon Sep 17 00:00:00 2001 From: Asko Nõmm Date: Sun, 10 Nov 2024 22:28:03 +0200 Subject: Initial commit --- .gitignore | 2 + README.md | 72 ++ composer.json | 31 + composer.lock | 1651 ++++++++++++++++++++++++++++++++ src/Driver.php | 11 + src/Drivers/FileSystemDriver.php | 53 + src/Drivers/OutputDriver.php | 19 + src/Format.php | 135 +++ src/Level.php | 18 + src/Loggr.php | 151 +++ src/Message.php | 15 + tests/Drivers/FileSystemDriverTest.php | 155 +++ tests/Drivers/OutputDriverTest.php | 99 ++ tests/LoggrTest.php | 31 + 14 files changed, 2443 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 src/Driver.php create mode 100644 src/Drivers/FileSystemDriver.php create mode 100644 src/Drivers/OutputDriver.php create mode 100644 src/Format.php create mode 100644 src/Level.php create mode 100644 src/Loggr.php create mode 100644 src/Message.php create mode 100644 tests/Drivers/FileSystemDriverTest.php create mode 100644 tests/Drivers/OutputDriverTest.php create mode 100644 tests/LoggrTest.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e0caea8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea/ +vendor/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..0be05dd --- /dev/null +++ b/README.md @@ -0,0 +1,72 @@ +# Loggr + +An extendable logging utility class brought to you by the frustration of every logging class always having its own unique format, +which makes using log viewing tools difficult. Instead of having its own yet-another-format that no tool supports, Loggr attempts to match +many already existing formats, allowing you to use whichever you prefer most. + +## Requirements + +- PHP 8.3+ + +## Installation + +```bash +composer require asko/loggr +``` + +## Usage + +Loggr is very simple to use, and looks like this: + +```php +$loggr = new Loggr(new FileSystemDriver('path-to-logs')); +$loggr->info('context'); +``` + +All you have to do is instantiate Loggr with the appropriate driver for your use case and then simply +log away with any data you want to give it. It takes scalar values, as well as arrays and objects. + +### Methods + +Loggr supports all of these logging methods: + +- `emergency(mixed $context = null)` +- `alert(mixed $context = null)` +- `critical( mixed $context = null)` +- `error(mixed $context = null)` +- `warning(mixed $context = null)` +- `notice(mixed $context = null)` +- `info(mixed $context = null)` +- `debug(mixed $context = null)` + +### Setting log format + +You can change the logging format by setting the `format` variable in Loggr constructor to a value of `Format` enum, like so: + +```php +$loggr = new Loggr(new FileSystemDriver('path-to-logs'), format: Format::JSON); +``` + +Or, if that gets a bit too long for just one line, you can also do: + +```php +$loggr = new Loggr(new FileSystemDriver('path-to-logs')); +$loggr->format = Format::JSON; +``` + +Loggr supports the following log formats: + +- `Format::JSON` - Entries are JSON objects. +- `Format::Laravel` - Entries correspond to the Laravel log format. +- `Format::Symfony` - Entries correspond to the Symfony log format. +- `Format::IntelliJ` - Entries correspond to the IntelliJ log format. + +## Extending + +You can extend Loggr with your own custom drivers. A driver is a class that implements the `Driver` interface and is +responsible for making sure that the serialized log entry would end up in the right place. + +### Built-in drivers + +- [FileSystemDriver](#) +- [StdoutDriver](#) \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..4ee9199 --- /dev/null +++ b/composer.json @@ -0,0 +1,31 @@ +{ + "name": "asko/loggr", + "description": "An extendable logging utility class with built-in support for various logging formats.", + "type": "library", + "license": "MIT", + "autoload": { + "psr-4": { + "Asko\\Loggr\\": "src/" + }, + "classmap": [ + "src/" + ] + }, + "autoload-dev": { + "psr-4": { + "Asko\\Loggr\\Tests\\": "tests/" + } + }, + "authors": [ + { + "name": "Asko Nomm", + "email": "asko@faultd.com" + } + ], + "require": { + "php": "^8.3" + }, + "require-dev": { + "phpunit/phpunit": "11" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..b3438f6 --- /dev/null +++ b/composer.lock @@ -0,0 +1,1651 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "a72050425367efbe00504e8bd2e37500", + "packages": [], + "packages-dev": [ + { + "name": "myclabs/deep-copy", + "version": "1.12.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2024-11-08T17:47:46+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.3.1", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1" + }, + "time": "2024-10-08T18:51:32+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:33:53+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "11.0.7", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f7f08030e8811582cc459871d28d6f5a1a4d35ca", + "reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^5.3.1", + "php": ">=8.2", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-text-template": "^4.0.1", + "sebastian/code-unit-reverse-lookup": "^4.0.1", + "sebastian/complexity": "^4.0.1", + "sebastian/environment": "^7.2.0", + "sebastian/lines-of-code": "^3.0.1", + "sebastian/version": "^5.0.2", + "theseer/tokenizer": "^1.2.3" + }, + "require-dev": { + "phpunit/phpunit": "^11.4.1" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "11.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.7" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-10-09T06:21:38+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "5.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/118cfaaa8bc5aef3287bf315b6060b1174754af6", + "reference": "118cfaaa8bc5aef3287bf315b6060b1174754af6", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/5.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-08-27T05:02:59+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/c1ca3814734c07492b3d4c5f794f4b0995333da2", + "reference": "c1ca3814734c07492b3d4c5f794f4b0995333da2", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "security": "https://github.com/sebastianbergmann/php-invoker/security/policy", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:07:44+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "reference": "3e0404dc6b300e6bf56415467ebcb3fe4f33e964", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:08:43+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "7.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "reference": "3b415def83fbcb41f991d9ebf16ae4ad8b7837b3", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "security": "https://github.com/sebastianbergmann/php-timer/security/policy", + "source": "https://github.com/sebastianbergmann/php-timer/tree/7.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:09:35+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "11.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "ece3536c22fc5113906a42e7e82de00baaef36d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/ece3536c22fc5113906a42e7e82de00baaef36d0", + "reference": "ece3536c22fc5113906a42e7e82de00baaef36d0", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=8.2", + "phpunit/php-code-coverage": "^11.0", + "phpunit/php-file-iterator": "^5.0", + "phpunit/php-invoker": "^5.0", + "phpunit/php-text-template": "^4.0", + "phpunit/php-timer": "^7.0", + "sebastian/cli-parser": "^3.0", + "sebastian/code-unit": "^3.0", + "sebastian/comparator": "^6.0", + "sebastian/diff": "^6.0", + "sebastian/environment": "^7.0", + "sebastian/exporter": "^6.0", + "sebastian/global-state": "^7.0", + "sebastian/object-enumerator": "^6.0", + "sebastian/type": "^5.0", + "sebastian/version": "^5.0" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "11.0-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.0.0" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2024-02-02T06:12:57+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/15c5dd40dc4f38794d383bb95465193f5e0ae180", + "reference": "15c5dd40dc4f38794d383bb95465193f5e0ae180", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:41:36+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "6bb7d09d6623567178cf54126afa9c2310114268" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/6bb7d09d6623567178cf54126afa9c2310114268", + "reference": "6bb7d09d6623567178cf54126afa9c2310114268", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "security": "https://github.com/sebastianbergmann/code-unit/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:44:28+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/183a9b2632194febd219bb9246eee421dad8d45e", + "reference": "183a9b2632194febd219bb9246eee421dad8d45e", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "security": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/security/policy", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:45:54+00:00" + }, + { + "name": "sebastian/comparator", + "version": "6.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "43d129d6a0f81c78bee378b46688293eb7ea3739" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/43d129d6a0f81c78bee378b46688293eb7ea3739", + "reference": "43d129d6a0f81c78bee378b46688293eb7ea3739", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/diff": "^6.0", + "sebastian/exporter": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/6.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-10-31T05:30:08+00:00" + }, + { + "name": "sebastian/complexity", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/ee41d384ab1906c68852636b6de493846e13e5a0", + "reference": "ee41d384ab1906c68852636b6de493846e13e5a0", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:49:50+00:00" + }, + { + "name": "sebastian/diff", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/b4ccd857127db5d41a5b676f24b51371d76d8544", + "reference": "b4ccd857127db5d41a5b676f24b51371d76d8544", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:53:05+00:00" + }, + { + "name": "sebastian/environment", + "version": "7.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", + "reference": "855f3ae0ab316bbafe1ba4e16e9f3c078d24a0c5", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/7.2.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:54:44+00:00" + }, + { + "name": "sebastian/exporter", + "version": "6.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", + "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.2", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/6.1.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:56:19+00:00" + }, + { + "name": "sebastian/global-state", + "version": "7.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/3be331570a721f9a4b5917f4209773de17f747d7", + "reference": "3be331570a721f9a4b5917f4209773de17f747d7", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "7.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/7.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:57:36+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "reference": "d36ad0d782e5756913e42ad87cb2890f4ffe467a", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^5.0", + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T04:58:38+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "6.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/f5b498e631a74204185071eb41f33f38d64608aa", + "reference": "f5b498e631a74204185071eb41f33f38d64608aa", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "sebastian/object-reflector": "^4.0", + "sebastian/recursion-context": "^6.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "security": "https://github.com/sebastianbergmann/object-enumerator/security/policy", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/6.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:00:13+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "reference": "6e1a43b411b2ad34146dee7524cb13a068bb35f9", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "security": "https://github.com/sebastianbergmann/object-reflector/security/policy", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:01:32+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "6.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/694d156164372abbd149a4b85ccda2e4670c0e16", + "reference": "694d156164372abbd149a4b85ccda2e4670c0e16", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/6.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-07-03T05:10:34+00:00" + }, + { + "name": "sebastian/type", + "version": "5.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/461b9c5da241511a2a0e8f240814fb23ce5c0aac", + "reference": "461b9c5da241511a2a0e8f240814fb23ce5c0aac", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "phpunit/phpunit": "^11.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "security": "https://github.com/sebastianbergmann/type/security/policy", + "source": "https://github.com/sebastianbergmann/type/tree/5.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-09-17T13:12:04+00:00" + }, + { + "name": "sebastian/version", + "version": "5.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "security": "https://github.com/sebastianbergmann/version/security/policy", + "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-10-09T05:16:32+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:36:25+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.6.0" +} diff --git a/src/Driver.php b/src/Driver.php new file mode 100644 index 0000000..2bc6cb8 --- /dev/null +++ b/src/Driver.php @@ -0,0 +1,11 @@ + + */ +interface Driver +{ + public function log(string $serializedMessage): void; +} \ No newline at end of file diff --git a/src/Drivers/FileSystemDriver.php b/src/Drivers/FileSystemDriver.php new file mode 100644 index 0000000..16c1461 --- /dev/null +++ b/src/Drivers/FileSystemDriver.php @@ -0,0 +1,53 @@ + + */ +readonly class FileSystemDriver implements Driver +{ + public function __construct( + private string $directory, + ) {} + + /** + * Logs a serialized message to a file. The log file is created on a daily basis. + * If the required directory or log file does not exist, they are created. + * Ensures that the log file is writable before attempting to write the message. + * + * @param string $serializedMessage The message to be logged, serialized as a string. + * @return void + * @throws \RuntimeException If the log file or directory cannot be created, or if the log file is not writable. + */ + public function log(string $serializedMessage): void + { + // If there's no parent directory, try creating one + if (!is_dir($this->directory)) { + mkdir($this->directory, 0600, true); + } + + $date = new DateTime(); + $file_name = "{$date->format('Y-m-d')}.log"; + $path = $this->directory . DIRECTORY_SEPARATOR . $file_name; + + // If the log file does not exist, try creating one + if (!file_exists($path) && !touch($path)) { + throw new \RuntimeException('Log file could not be created'); + } + + // We managed to get this far, but still can't write to the log file + if (!is_writeable($path)) { + throw new \RuntimeException('Log file is not writeable'); + } + + file_put_contents( + filename: $path, + data: $serializedMessage . PHP_EOL, + flags: FILE_APPEND + ); + } +} \ No newline at end of file diff --git a/src/Drivers/OutputDriver.php b/src/Drivers/OutputDriver.php new file mode 100644 index 0000000..93c97ba --- /dev/null +++ b/src/Drivers/OutputDriver.php @@ -0,0 +1,19 @@ + + */ +enum Format +{ + case JSON; + case IntelliJ; + case Laravel; + case Symfony; + + /** + * Serializes the given message into a format based on the type of serialization. + * + * @param Message $message The message to be serialized. + * @return string The serialized message. + */ + public function serialize(Message $message): string + { + return match($this) { + self::JSON => $this->serializeJson($message), + self::IntelliJ => $this->serializeIntelliJ($message), + self::Laravel => $this->serializeLaravel($message), + self::Symfony => $this->serializeSymfony($message), + }; + } + + /** + * Serializes the given message into JSON format. + * + * @param Message $message The message to be serialized. + * @return string The JSON-encoded message. + */ + private function serializeJson(Message $message): string + { + return json_encode([ + 'date' => (new DateTime)->format('Y-m-d H:i:s'), + 'level' => $message->level->value, + 'context' => $message->context, + 'trace' => [ + 'file' => $message->trace['file'], + 'line' => $message->trace['line'], + ], + ]); + } + + /** + * Serializes the given message into a Laravel log format. + * + * @param Message $message The message to be serialized. + * @return string The serialized message. + */ + private function serializeLaravel(Message $message): string + { + // Date + $date = (new DateTime)->format('Y-m-d H:i:s'); + $line = "[$date] "; + + // File name and level + $filename = pathinfo($message->trace['file'], PATHINFO_FILENAME); + $line .= "{$filename}.{$message->level->value}: "; + + // Context + if (is_array($message->context) || is_object($message->context)) { + $line .= json_encode($message->context); + } else { + $line .= $message->context; + } + + return $line; + } + + /** + * Serialized the given message into a Symfony log format. + * + * @param Message $message The message object that contains log details. + * @return string The formatted log string. + */ + private function serializeSymfony(Message $message): string + { + // Date + $date = (new DateTime)->format('Y-m-d\TH:i:s.uP'); + $line = "[$date] "; + + // File name and level + $filename = pathinfo($message->trace['file'], PATHINFO_FILENAME); + $line .= "{$filename}.{$message->level->value}: "; + + // Context + if (is_array($message->context) || is_object($message->context)) { + $line .= json_encode($message->context); + } else { + $line .= $message->context; + } + + return $line; + } + + /** + * Serializes the given message into a IntelliJ log format. + * + * @param Message $message The message object that contains log details. + * @return string The formatted log string. + */ + private function serializeIntelliJ(Message $message): string + { + // Date + $date = (new DateTime)->format('Y-m-d H:i:s'); + $line = "{$date} "; + + // Line number + $line .= "[{$message->trace['line']}] "; + + // Level + $line .= "{$message->level->value} "; + + // Filename + $filename = pathinfo($message->trace['file'], PATHINFO_FILENAME); + $line .= "- {$filename} - "; + + // Context + if (is_array($message->context) || is_object($message->context)) { + $line .= json_encode($message->context); + } else { + $line .= $message->context; + } + + return $line; + } +} diff --git a/src/Level.php b/src/Level.php new file mode 100644 index 0000000..5e573bc --- /dev/null +++ b/src/Level.php @@ -0,0 +1,18 @@ + + */ +enum Level: string +{ + case Emergency = "EMERGENCY"; + case Alert = "ALERT"; + case Critical = "CRITICAL"; + case Error = "ERROR"; + case Warning = "WARNING"; + case Notice = "NOTICE"; + case Info = "INFO"; + case Debug = "DEBUG"; +} diff --git a/src/Loggr.php b/src/Loggr.php new file mode 100644 index 0000000..9b52f1d --- /dev/null +++ b/src/Loggr.php @@ -0,0 +1,151 @@ + + */ +class Loggr +{ + private array $trace; + + public function __construct( + public ?Driver $driver = null, + public ?Format $format = Format::Laravel, + ){} + + /** + * Logs a message at a specified level with optional context. + * + * @param Level $level The severity level of the log message. Defaults to Level::Info. + * @param mixed $context Additional data or context to include with the log message. Optional. + * @return void + * @throws \Exception + */ + private function log(Level $level = Level::Info, mixed $context = null): void + { + if (!$this->driver) { + throw new \Exception("No driver has been set."); + } + + if (!$this->format) { + throw new \Exception("No format has been set."); + } + + $this->driver->log($this->format->serialize(new Message( + level: $level, + trace: $this->trace, + context: $context, + ))); + } + + /** + * Logs an emergency level message with optional context. + * + * @param mixed $context Additional data or context to include with the emergency message. Optional. + * @return void + * @throws \Exception + */ + public function emergency(mixed $context = null): void + { + $this->trace = debug_backtrace()[0]; + $this->log(Level::Emergency, $context); + } + + /** + * Sends an alert-level log message with optional context. + * + * @param mixed $context Additional data or context to include with the log message. Optional. + * @return void + * @throws \Exception + */ + public function alert(mixed $context = null): void + { + $this->trace = debug_backtrace()[0]; + $this->log(Level::Alert, $context); + } + + /** + * Logs a critical level message with optional context. + * + * @param mixed $context Additional data or context to include with the log message. Optional. + * @return void + * @throws \Exception + */ + public function critical( mixed $context = null): void + { + $this->trace = debug_backtrace()[0]; + $this->log(Level::Critical, $context); + } + + /** + * Logs an error message with optional context. + * + * @param mixed $context Additional data or context to include with the error message. Optional. + * @return void + * @throws \Exception + */ + public function error(mixed $context = null): void + { + $this->trace = debug_backtrace()[0]; + $this->log(Level::Error, $context); + } + + /** + * Logs a warning message with the specified context. + * + * @param mixed $context Optional context information to include in the log. + * @return void + * @throws \Exception + */ + public function warning(mixed $context = null): void + { + $this->trace = debug_backtrace()[0]; + $this->log(Level::Warning, $context); + } + + /** + * Logs a notice message with the specified context. + * + * @param mixed $context Optional context information to include in the log. + * @return void + * @throws \Exception + */ + public function notice(mixed $context = null): void + { + $this->trace = debug_backtrace()[0]; + $this->log(Level::Notice, $context); + } + + /** + * Logs an informational message with the specified context. + * + * @param mixed $context Optional context information to include in the log. + * @return void + * @throws \Exception + */ + public function info(mixed $context = null): void + { + $this->trace = debug_backtrace()[0]; + $this->log(Level::Info, $context); + } + + /** + * Logs a debug message with the specified context. + * + * @param mixed $context Optional context information to include in the log. + * @return void + * @throws \Exception + */ + public function debug(mixed $context = null): void + { + $this->trace = debug_backtrace()[0]; + $this->log(Level::Debug, $context); + } +} \ No newline at end of file diff --git a/src/Message.php b/src/Message.php new file mode 100644 index 0000000..4af49e7 --- /dev/null +++ b/src/Message.php @@ -0,0 +1,15 @@ + + */ +readonly class Message +{ + public function __construct( + public Level $level, + public array $trace = [], + public mixed $context = null, + ) {} +} \ No newline at end of file diff --git a/tests/Drivers/FileSystemDriverTest.php b/tests/Drivers/FileSystemDriverTest.php new file mode 100644 index 0000000..bb49042 --- /dev/null +++ b/tests/Drivers/FileSystemDriverTest.php @@ -0,0 +1,155 @@ +emergency('test'); + $lines = file(__DIR__ . '/logs/' . $date->format('Y-m-d') . '.log'); + $last_line = end($lines); + $full_date = $date->format('Y-m-d H:i:s'); + $this->assertStringContainsString("[{$full_date}] FileSystemDriverTest.EMERGENCY: test", $last_line); + } + + /** + * @throws \Exception + */ + public function testAlert(): void + { + $date = new DateTime(); + $loggr = new Loggr(new FileSystemDriver(__DIR__ . '/logs')); + $loggr->alert('test'); + $lines = file(__DIR__ . '/logs/' . $date->format('Y-m-d') . '.log'); + $last_line = end($lines); + $full_date = $date->format('Y-m-d H:i:s'); + $this->assertStringContainsString("[{$full_date}] FileSystemDriverTest.ALERT: test", $last_line); + } + + /** + * @throws \Exception + */ + public function testCritical(): void + { + $date = new DateTime(); + $loggr = new Loggr(new FileSystemDriver(__DIR__ . '/logs')); + $loggr->critical('test'); + $lines = file(__DIR__ . '/logs/' . $date->format('Y-m-d') . '.log'); + $last_line = end($lines); + $full_date = $date->format('Y-m-d H:i:s'); + $this->assertStringContainsString("[{$full_date}] FileSystemDriverTest.CRITICAL: test", $last_line); + } + + /** + * @throws \Exception + */ + public function testError(): void + { + $date = new DateTime(); + $loggr = new Loggr(new FileSystemDriver(__DIR__ . '/logs')); + $loggr->error('test'); + $lines = file(__DIR__ . '/logs/' . $date->format('Y-m-d') . '.log'); + $last_line = end($lines); + $full_date = $date->format('Y-m-d H:i:s'); + $this->assertStringContainsString("[{$full_date}] FileSystemDriverTest.ERROR: test", $last_line); + } + + /** + * @throws \Exception + */ + public function testWarning(): void + { + $date = new DateTime(); + $loggr = new Loggr(new FileSystemDriver(__DIR__ . '/logs')); + $loggr->warning('test'); + $lines = file(__DIR__ . '/logs/' . $date->format('Y-m-d') . '.log'); + $last_line = end($lines); + $full_date = $date->format('Y-m-d H:i:s'); + $this->assertStringContainsString("[{$full_date}] FileSystemDriverTest.WARNING: test", $last_line); + } + + /** + * @throws \Exception + */ + public function testNotice(): void + { + $date = new DateTime(); + $loggr = new Loggr(new FileSystemDriver(__DIR__ . '/logs')); + $loggr->notice('test'); + $lines = file(__DIR__ . '/logs/' . $date->format('Y-m-d') . '.log'); + $last_line = end($lines); + $full_date = $date->format('Y-m-d H:i:s'); + $this->assertStringContainsString("[{$full_date}] FileSystemDriverTest.NOTICE: test", $last_line); + } + + /** + * @throws \Exception + */ + public function testInfo(): void + { + $date = new DateTime(); + $loggr = new Loggr(new FileSystemDriver(__DIR__ . '/logs')); + $loggr->info('test'); + $lines = file(__DIR__ . '/logs/' . $date->format('Y-m-d') . '.log'); + $last_line = end($lines); + $full_date = $date->format('Y-m-d H:i:s'); + $this->assertStringContainsString("[{$full_date}] FileSystemDriverTest.INFO: test", $last_line); + } + + /** + * @throws \Exception + */ + public function testDebug(): void + { + $date = new DateTime(); + $loggr = new Loggr(new FileSystemDriver(__DIR__ . '/logs')); + $loggr->debug('test'); + $lines = file(__DIR__ . '/logs/' . $date->format('Y-m-d') . '.log'); + $last_line = end($lines); + $full_date = $date->format('Y-m-d H:i:s'); + $this->assertStringContainsString("[{$full_date}] FileSystemDriverTest.DEBUG: test", $last_line); + } + + /** + * @throws \Exception + */ + public function testMultipleEntries(): void + { + $date = new DateTime(); + $loggr = new Loggr(new FileSystemDriver(__DIR__ . '/logs')); + $loggr->emergency('test'); + $loggr->alert('test'); + $loggr->critical('test'); + $loggr->error('test'); + $loggr->warning('test'); + $loggr->notice('test'); + $loggr->info('test'); + $loggr->debug('test'); + + $lines = file(__DIR__ . '/logs/' . $date->format('Y-m-d') . '.log'); + $this->assertCount(8, $lines); + + $first_line = $lines[0]; + $last_line = end($lines); + $full_date = $date->format('Y-m-d H:i:s'); + $this->assertStringContainsString("[{$full_date}] FileSystemDriverTest.EMERGENCY: test", $first_line); + $this->assertStringContainsString("[{$full_date}] FileSystemDriverTest.DEBUG: test", $last_line); + } + + public function tearDown(): void + { + array_map('unlink', glob(__DIR__ . '/logs/*')); + rmdir(__DIR__ . '/logs'); + } +} \ No newline at end of file diff --git a/tests/Drivers/OutputDriverTest.php b/tests/Drivers/OutputDriverTest.php new file mode 100644 index 0000000..9f023ae --- /dev/null +++ b/tests/Drivers/OutputDriverTest.php @@ -0,0 +1,99 @@ +format('Y-m-d H:i:s'); + $this->expectOutputString("[{$date}] OutputDriverTest.EMERGENCY: test"); + $loggr = new Loggr(new OutputDriver()); + $loggr->emergency('test'); + } + + /** + * @throws \Exception + */ + public function testAlert(): void + { + $date = (new DateTime)->format('Y-m-d H:i:s'); + $this->expectOutputString("[{$date}] OutputDriverTest.ALERT: test"); + $loggr = new Loggr(new OutputDriver()); + $loggr->alert('test'); + } + + /** + * @throws \Exception + */ + public function testCritical(): void + { + $date = (new DateTime)->format('Y-m-d H:i:s'); + $this->expectOutputString("[{$date}] OutputDriverTest.CRITICAL: test"); + $loggr = new Loggr(new OutputDriver()); + $loggr->critical('test'); + } + + /** + * @throws \Exception + */ + public function testError(): void + { + $date = (new DateTime)->format('Y-m-d H:i:s'); + $this->expectOutputString("[{$date}] OutputDriverTest.ERROR: test"); + $loggr = new Loggr(new OutputDriver()); + $loggr->error('test'); + } + + /** + * @throws \Exception + */ + public function testWarning(): void + { + $date = (new DateTime)->format('Y-m-d H:i:s'); + $this->expectOutputString("[{$date}] OutputDriverTest.WARNING: test"); + $loggr = new Loggr(new OutputDriver()); + $loggr->warning('test'); + } + + /** + * @throws \Exception + */ + public function testNotice(): void + { + $date = (new DateTime)->format('Y-m-d H:i:s'); + $this->expectOutputString("[{$date}] OutputDriverTest.NOTICE: test"); + $loggr = new Loggr(new OutputDriver()); + $loggr->notice('test'); + } + + /** + * @throws \Exception + */ + public function testInfo(): void + { + $date = (new DateTime)->format('Y-m-d H:i:s'); + $this->expectOutputString("[{$date}] OutputDriverTest.INFO: test"); + $loggr = new Loggr(new OutputDriver()); + $loggr->info('test'); + } + + /** + * @throws \Exception + */ + public function testDebug(): void + { + $date = (new DateTime)->format('Y-m-d H:i:s'); + $this->expectOutputString("[{$date}] OutputDriverTest.DEBUG: test"); + $loggr = new Loggr(new OutputDriver()); + $loggr->debug('test'); + } +} \ No newline at end of file diff --git a/tests/LoggrTest.php b/tests/LoggrTest.php new file mode 100644 index 0000000..4abae86 --- /dev/null +++ b/tests/LoggrTest.php @@ -0,0 +1,31 @@ +expectExceptionMessage('No driver has been set.'); + $loggr = new Loggr(); + $loggr->info('test'); + } + + /** + * @throws \Exception + */ + public function testNoFormat(): void + { + $this->expectExceptionMessage('No format has been set.'); + $loggr = new Loggr(new OutputDriver()); + $loggr->format = null; + $loggr->info('test'); + } +} \ No newline at end of file -- cgit v1.2.3