From 0c5e513011ecb7e0e782cc8fa44f433b0fd9aef3 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Wed, 17 Jul 2024 21:46:55 +0400 Subject: [PATCH] Add Container, Logger, ConfigInjector; expose Arch, OS and Stability enums --- LICENSE.md | 4 +- README.md | 2 +- bin/{download => dload} | 6 +- bin/{download.bat => dload.bat} | 0 composer-require-checker.json | 2 + composer.json | 3 +- composer.lock | 759 ++++++++++++++++++--- dload.xml | 3 + src/Bootstrap.php | 80 +++ src/Command/Get.php | 88 +++ src/Module/Environment/Architecture.php | 39 ++ src/Module/Environment/OperatingSystem.php | 41 ++ src/Module/Environment/Stability.php | 42 ++ src/Service/Config/ConfigAttribute.php | 10 + src/Service/Config/ConfigLoader.php | 118 ++++ src/Service/Config/Env.php | 16 + src/Service/Config/InputArgument.php | 16 + src/Service/Config/InputOption.php | 16 + src/Service/Config/PhpIni.php | 16 + src/Service/Config/XPath.php | 17 + src/Service/Container.php | 133 ++++ src/Service/Destroyable.php | 15 + src/Service/Factoriable.php | 15 + src/Service/Logger.php | 79 +++ tests/Unit/InfoTest.php | 3 + 25 files changed, 1428 insertions(+), 95 deletions(-) rename bin/{download => dload} (81%) rename bin/{download.bat => dload.bat} (100%) create mode 100644 dload.xml create mode 100644 src/Bootstrap.php create mode 100644 src/Command/Get.php create mode 100644 src/Module/Environment/Architecture.php create mode 100644 src/Module/Environment/OperatingSystem.php create mode 100644 src/Module/Environment/Stability.php create mode 100644 src/Service/Config/ConfigAttribute.php create mode 100644 src/Service/Config/ConfigLoader.php create mode 100644 src/Service/Config/Env.php create mode 100644 src/Service/Config/InputArgument.php create mode 100644 src/Service/Config/InputOption.php create mode 100644 src/Service/Config/PhpIni.php create mode 100644 src/Service/Config/XPath.php create mode 100644 src/Service/Container.php create mode 100644 src/Service/Destroyable.php create mode 100644 src/Service/Factoriable.php create mode 100644 src/Service/Logger.php diff --git a/LICENSE.md b/LICENSE.md index c2d6c22..d89ed75 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ # BSD 3-Clause -Copyright (c) 2024, . +Copyright (c) 2024, [copyright holder]. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -13,7 +13,7 @@ are met: notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -* Neither the name of nor the names of its +* Neither the name of [copyright holder] nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/README.md b/README.md index 9635d77..8e6e013 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -

Simplify any binaries downloading

DLoad

+

Simplify any binaries downloading

diff --git a/bin/download b/bin/dload similarity index 81% rename from bin/download rename to bin/dload index 0ca4376..10507bc 100644 --- a/bin/download +++ b/bin/dload @@ -44,11 +44,9 @@ if ('cli' !== PHP_SAPI) { $application = new Application(); $application->setCommandLoader( new FactoryCommandLoader([ - Command\Run::getDefaultName() => static fn() => new Command\Run(), - Command\Joke::getDefaultName() => static fn() => new Command\Joke(), - Command\Test::getDefaultName() => static fn() => new Command\Test(), + Command\Get::getDefaultName() => static fn() => new Command\Get(), ]), ); - $application->setDefaultCommand(Command\Run::getDefaultName(), false); + $application->setDefaultCommand(Command\Get::getDefaultName(), true); $application->run(); })(); diff --git a/bin/download.bat b/bin/dload.bat similarity index 100% rename from bin/download.bat rename to bin/dload.bat diff --git a/composer-require-checker.json b/composer-require-checker.json index 7e76d9a..cd89462 100644 --- a/composer-require-checker.json +++ b/composer-require-checker.json @@ -1,4 +1,6 @@ { "symbol-whitelist": [ + "SIGINT", + "SIGTERM" ] } diff --git a/composer.json b/composer.json index 60e0831..af30940 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,8 @@ } ], "require": { - "php": ">=8.1" + "php": ">=8.1", + "yiisoft/injector": "^1.2" }, "require-dev": { "buggregator/trap": "^1.10", diff --git a/composer.lock b/composer.lock index b66da6c..1802b56 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": "5c2d968f8cffc9fbddd3a1e8c50fae96", + "content-hash": "d9955f7a2ec56a6b172516321ba6982d", "packages": [], "packages-dev": [ { @@ -48,7 +48,7 @@ "Amp\\": "lib" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -131,7 +131,7 @@ "Amp\\ByteStream\\": "lib" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -222,7 +222,7 @@ ] } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -262,6 +262,115 @@ ], "time": "2023-10-31T09:24:17+00:00" }, + { + "name": "buggregator/trap", + "version": "1.10.1", + "source": { + "type": "git", + "url": "https://github.com/buggregator/trap.git", + "reference": "156ac1e0386a40454e71f1282f3b10bed6e34a12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/buggregator/trap/zipball/156ac1e0386a40454e71f1282f3b10bed6e34a12", + "reference": "156ac1e0386a40454e71f1282f3b10bed6e34a12", + "shasum": "" + }, + "require": { + "clue/stream-filter": "^1.6", + "ext-filter": "*", + "ext-sockets": "*", + "nunomaduro/termwind": "^1.15 || ^2", + "nyholm/psr7": "^1.8", + "php": ">=8.1", + "php-http/message": "^1.15", + "psr/container": "^1.1 || ^2.0", + "psr/http-message": "^1.1 || ^2", + "symfony/console": "^6.4 || ^7", + "symfony/var-dumper": "^6.3 || ^7", + "yiisoft/injector": "^1.2" + }, + "require-dev": { + "dereuromark/composer-prefer-lowest": "^0.1.10", + "ergebnis/phpunit-slow-test-detector": "^2.14", + "friendsofphp/php-cs-fixer": "^3.54", + "google/protobuf": "^3.23", + "pestphp/pest": "^2.34", + "phpstan/extension-installer": "^1.3", + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-deprecation-rules": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "phpstan/phpstan-strict-rules": "^1.5", + "phpunit/phpunit": "^10.5", + "roxblnfk/unpoly": "^1.8.1", + "vimeo/psalm": "^5.11", + "wayofdev/cs-fixer-config": "^1.4" + }, + "suggest": { + "ext-simplexml": "To load trap.xml", + "roxblnfk/unpoly": "If you want to remove unnecessary PHP polyfills depend on PHP version." + }, + "bin": [ + "bin/trap" + ], + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Buggregator\\Trap\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Aleksei Gagarin (roxblnfk)", + "homepage": "https://github.com/roxblnfk" + }, + { + "name": "Pavel Buchnev (butschster)", + "homepage": "https://github.com/butschster" + } + ], + "description": "A simple and powerful tool for debugging PHP applications.", + "homepage": "https://buggregator.dev/", + "keywords": [ + "WebSockets", + "binary dump", + "cli", + "console", + "debug", + "dev", + "dump", + "helper", + "sentry", + "server", + "smtp" + ], + "support": { + "issues": "https://github.com/buggregator/trap/issues", + "source": "https://github.com/buggregator/trap/tree/1.10.1" + }, + "funding": [ + { + "url": "https://github.com/sponsors/buggregator", + "type": "github" + }, + { + "url": "https://patreon.com/butschster", + "type": "patreon" + }, + { + "url": "https://patreon.com/roxblnfk", + "type": "patreon" + } + ], + "time": "2024-06-23T14:24:42+00:00" + }, { "name": "clue/ndjson-react", "version": "v1.3.0", @@ -290,7 +399,7 @@ "Clue\\React\\NDJson\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -326,6 +435,72 @@ ], "time": "2022-12-23T10:58:28+00:00" }, + { + "name": "clue/stream-filter", + "version": "v1.7.0", + "source": { + "type": "git", + "url": "https://github.com/clue/stream-filter.git", + "reference": "049509fef80032cb3f051595029ab75b49a3c2f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/clue/stream-filter/zipball/049509fef80032cb3f051595029ab75b49a3c2f7", + "reference": "049509fef80032cb3f051595029ab75b49a3c2f7", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "Clue\\StreamFilter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + } + ], + "description": "A simple and modern approach to stream filtering in PHP", + "homepage": "https://github.com/clue/stream-filter", + "keywords": [ + "bucket brigade", + "callback", + "filter", + "php_user_filter", + "stream", + "stream_filter_append", + "stream_filter_register" + ], + "support": { + "issues": "https://github.com/clue/stream-filter/issues", + "source": "https://github.com/clue/stream-filter/tree/v1.7.0" + }, + "funding": [ + { + "url": "https://clue.engineering/support", + "type": "custom" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2023-12-20T15:40:13+00:00" + }, { "name": "composer/pcre", "version": "3.1.4", @@ -359,7 +534,7 @@ "Composer\\Pcre\\": "src" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -429,7 +604,7 @@ "Composer\\Semver\\": "src" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -508,7 +683,7 @@ "Composer\\XdebugHandler\\": "src" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -576,7 +751,7 @@ "ComposerPreferLowest\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -619,7 +794,7 @@ "XdgBaseDir\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -665,7 +840,7 @@ "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -717,7 +892,7 @@ "Ergebnis\\PHPUnit\\SlowTestDetector\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -770,7 +945,7 @@ "Evenement\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -819,7 +994,7 @@ "AdvancedJsonRpc\\": "lib/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "ISC" ], @@ -869,7 +1044,7 @@ "LanguageServerProtocol\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "ISC" ], @@ -926,7 +1101,7 @@ "Fidry\\CpuCoreCounter\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -991,7 +1166,7 @@ "Whoops\\": "src/Whoops/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -1094,7 +1269,7 @@ "src/Fixer/Internal/*" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -1163,7 +1338,7 @@ "Jean85\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -1222,7 +1397,7 @@ "DeepCopy\\": "src/DeepCopy/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -1277,7 +1452,7 @@ "JsonMapper": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "OSL-3.0" ], @@ -1333,7 +1508,7 @@ "PhpParser\\": "lib/PhpParser" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -1406,7 +1581,7 @@ "NunoMaduro\\Collision\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -1496,7 +1671,7 @@ "Termwind\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -1535,6 +1710,84 @@ ], "time": "2023-02-08T01:06:31+00:00" }, + { + "name": "nyholm/psr7", + "version": "1.8.1", + "source": { + "type": "git", + "url": "https://github.com/Nyholm/psr7.git", + "reference": "aa5fc277a4f5508013d571341ade0c3886d4d00e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Nyholm/psr7/zipball/aa5fc277a4f5508013d571341ade0c3886d4d00e", + "reference": "aa5fc277a4f5508013d571341ade0c3886d4d00e", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0" + }, + "provide": { + "php-http/message-factory-implementation": "1.0", + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "http-interop/http-factory-tests": "^0.9", + "php-http/message-factory": "^1.0", + "php-http/psr7-integration-tests": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.4", + "symfony/error-handler": "^4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Nyholm\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + }, + { + "name": "Martijn van der Ven", + "email": "martijn@vanderven.se" + } + ], + "description": "A fast PHP7 implementation of PSR-7", + "homepage": "https://tnyholm.se", + "keywords": [ + "psr-17", + "psr-7" + ], + "support": { + "issues": "https://github.com/Nyholm/psr7/issues", + "source": "https://github.com/Nyholm/psr7/tree/1.8.1" + }, + "funding": [ + { + "url": "https://github.com/Zegnat", + "type": "github" + }, + { + "url": "https://github.com/nyholm", + "type": "github" + } + ], + "time": "2023-11-13T09:31:12+00:00" + }, { "name": "pestphp/pest", "version": "v2.34.9", @@ -1608,7 +1861,7 @@ "Pest\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -1679,7 +1932,7 @@ "Pest\\Plugin\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -1753,7 +2006,7 @@ "Pest\\Arch\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -1817,7 +2070,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -1874,7 +2127,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -1902,6 +2155,75 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "php-http/message", + "version": "1.16.1", + "source": { + "type": "git", + "url": "https://github.com/php-http/message.git", + "reference": "5997f3289332c699fa2545c427826272498a2088" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/message/zipball/5997f3289332c699fa2545c427826272498a2088", + "reference": "5997f3289332c699fa2545c427826272498a2088", + "shasum": "" + }, + "require": { + "clue/stream-filter": "^1.5", + "php": "^7.2 || ^8.0", + "psr/http-message": "^1.1 || ^2.0" + }, + "provide": { + "php-http/message-factory-implementation": "1.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.6", + "ext-zlib": "*", + "guzzlehttp/psr7": "^1.0 || ^2.0", + "laminas/laminas-diactoros": "^2.0 || ^3.0", + "php-http/message-factory": "^1.0.2", + "phpspec/phpspec": "^5.1 || ^6.3 || ^7.1", + "slim/slim": "^3.0" + }, + "suggest": { + "ext-zlib": "Used with compressor/decompressor streams", + "guzzlehttp/psr7": "Used with Guzzle PSR-7 Factories", + "laminas/laminas-diactoros": "Used with Diactoros Factories", + "slim/slim": "Used with Slim Framework PSR-7 implementation" + }, + "type": "library", + "autoload": { + "files": [ + "src/filters.php" + ], + "psr-4": { + "Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "HTTP Message related tools", + "homepage": "http://php-http.org", + "keywords": [ + "http", + "message", + "psr-7" + ], + "support": { + "issues": "https://github.com/php-http/message/issues", + "source": "https://github.com/php-http/message/tree/1.16.1" + }, + "time": "2024-03-07T13:22:09+00:00" + }, { "name": "phpdocumentor/reflection-common", "version": "2.2.0", @@ -1930,7 +2252,7 @@ "phpDocumentor\\Reflection\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -1998,7 +2320,7 @@ "phpDocumentor\\Reflection\\": "src" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -2060,7 +2382,7 @@ "phpDocumentor\\Reflection\\": "src" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -2113,7 +2435,7 @@ ] } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -2171,7 +2493,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -2233,7 +2555,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -2298,7 +2620,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -2357,7 +2679,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -2417,7 +2739,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -2507,7 +2829,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -2574,7 +2896,7 @@ "Psr\\Container\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -2627,7 +2949,7 @@ "Psr\\EventDispatcher\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -2649,6 +2971,114 @@ }, "time": "2019-01-08T18:20:26+00:00" }, + { + "name": "psr/http-factory", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, { "name": "psr/log", "version": "3.0.0", @@ -2677,7 +3107,7 @@ "Psr\\Log\\": "src" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -2726,7 +3156,7 @@ "React\\Cache\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -2802,7 +3232,7 @@ "React\\ChildProcess\\": "src" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -2881,7 +3311,7 @@ "React\\Dns\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -2955,7 +3385,7 @@ "React\\EventLoop\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -3028,7 +3458,7 @@ "React\\Promise\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -3105,7 +3535,7 @@ "React\\Socket\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -3180,7 +3610,7 @@ "React\\Stream\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -3260,7 +3690,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -3317,7 +3747,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -3373,7 +3803,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -3432,7 +3862,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -3506,7 +3936,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -3564,7 +3994,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -3633,7 +4063,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -3696,7 +4126,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -3775,7 +4205,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -3835,7 +4265,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -3894,7 +4324,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -3949,7 +4379,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -4004,7 +4434,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -4067,7 +4497,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -4120,7 +4550,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -4179,7 +4609,7 @@ "Spatie\\ArrayToXml\\": "src" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -4266,7 +4696,7 @@ "/Tests/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -4339,7 +4769,7 @@ "function.php" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -4419,7 +4849,7 @@ "/Tests/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -4487,7 +4917,7 @@ "Symfony\\Contracts\\EventDispatcher\\": "" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -4561,7 +4991,7 @@ "/Tests/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -4625,7 +5055,7 @@ "/Tests/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -4687,7 +5117,7 @@ "/Tests/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -4765,7 +5195,7 @@ "Symfony\\Polyfill\\Ctype\\": "" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -4841,7 +5271,7 @@ "Symfony\\Polyfill\\Intl\\Grapheme\\": "" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -4922,7 +5352,7 @@ "Resources/stubs" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -5003,7 +5433,7 @@ "Symfony\\Polyfill\\Mbstring\\": "" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -5080,7 +5510,7 @@ "Resources/stubs" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -5160,7 +5590,7 @@ "Resources/stubs" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -5227,7 +5657,7 @@ "/Tests/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -5302,7 +5732,7 @@ "/Test/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -5372,7 +5802,7 @@ "/Tests/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -5450,7 +5880,7 @@ "/Tests/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -5493,6 +5923,91 @@ ], "time": "2024-06-28T09:25:38+00:00" }, + { + "name": "symfony/var-dumper", + "version": "v6.4.9", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "c31566e4ca944271cc8d8ac6887cbf31b8c6a172" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c31566e4ca944271cc8d8ac6887cbf31b8c6a172", + "reference": "c31566e4ca944271cc8d8ac6887cbf31b8c6a172", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/console": "<5.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^6.3|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/uid": "^5.4|^6.0|^7.0", + "twig/twig": "^2.13|^3.0.4" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v6.4.9" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-06-27T13:23:14+00:00" + }, { "name": "ta-tikoma/phpunit-architecture-test", "version": "0.8.4", @@ -5524,7 +6039,7 @@ "PHPUnit\\Architecture\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -5578,7 +6093,7 @@ "src/" ] }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], @@ -5689,7 +6204,7 @@ "Psalm\\": "src/Psalm/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -5756,7 +6271,7 @@ "WayOfDev\\PhpCsFixer\\Config\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -5828,7 +6343,7 @@ "Webmozart\\Assert\\": "src/" } }, - "notification-url": "https://packagist.org/dloads/", + "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -5849,6 +6364,76 @@ "source": "https://github.com/webmozarts/assert/tree/1.11.0" }, "time": "2022-06-03T18:03:27+00:00" + }, + { + "name": "yiisoft/injector", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/yiisoft/injector.git", + "reference": "0dc0127a7542341bdaabda7b85204e992938b83e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yiisoft/injector/zipball/0dc0127a7542341bdaabda7b85204e992938b83e", + "reference": "0dc0127a7542341bdaabda7b85204e992938b83e", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "require-dev": { + "maglnet/composer-require-checker": "^3.8|^4.2", + "phpbench/phpbench": "^1.1", + "phpunit/phpunit": "^9.5", + "psr/container": "^1.0|^2.0", + "rector/rector": "^0.18.12", + "roave/infection-static-analysis-plugin": "^1.16", + "spatie/phpunit-watcher": "^1.23", + "vimeo/psalm": "^4.30|^5.7", + "yiisoft/test-support": "^1.2" + }, + "suggest": { + "psr/container": "For automatic resolving of dependencies" + }, + "type": "library", + "autoload": { + "psr-4": { + "Yiisoft\\Injector\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "PSR-11 compatible injector. Executes a callable and makes an instances by injecting dependencies from a given DI container.", + "homepage": "https://www.yiiframework.com/", + "keywords": [ + "PSR-11", + "dependency injection", + "di", + "injector", + "reflection" + ], + "support": { + "chat": "https://t.me/yii3en", + "forum": "https://www.yiiframework.com/forum/", + "irc": "irc://irc.freenode.net/yii", + "issues": "https://github.com/yiisoft/injector/issues?state=open", + "source": "https://github.com/yiisoft/injector", + "wiki": "https://www.yiiframework.com/wiki/" + }, + "funding": [ + { + "url": "https://github.com/yiisoft", + "type": "github" + }, + { + "url": "https://opencollective.com/yiisoft", + "type": "open_collective" + } + ], + "time": "2023-12-20T09:39:03+00:00" } ], "aliases": [], diff --git a/dload.xml b/dload.xml new file mode 100644 index 0000000..280f686 --- /dev/null +++ b/dload.xml @@ -0,0 +1,3 @@ + + + diff --git a/src/Bootstrap.php b/src/Bootstrap.php new file mode 100644 index 0000000..c9eef55 --- /dev/null +++ b/src/Bootstrap.php @@ -0,0 +1,80 @@ +container; + unset($this->container); + + return $c; + } + + /** + * @param non-empty-string|null $xml File or XML content + */ + public function withConfig( + ?string $xml = null, + array $inputOptions = [], + array $inputArguments = [], + array $environment = [], + ): self { + $args = [ + 'env' => $environment, + 'inputArguments' => $inputArguments, + 'inputOptions' => $inputOptions, + ]; + + // XML config file + $xml === null or $args['xml'] = $this->readXml($xml); + + // Register bindings + $this->container->bind(ConfigLoader::class, $args); + $this->container->bind(Architecture::class); + $this->container->bind(OperatingSystem::class); + $this->container->bind(Stability::class); + + return $this; + } + + private function readXml(string $fileOrContent): string + { + // Load content + if (\str_starts_with($fileOrContent, 'addArgument( + 'binary', + InputArgument::REQUIRED, + 'Binary name, e.g. "rr", "dolt", "temporal" etc.', + ); + $this->addArgument( + 'path', + InputArgument::OPTIONAL, + 'Path to store the binary, e.g. "./bin"', + ".", + ); + } + + public function handleSignal(int $signal, int|false $previousExitCode = 0): int|false + { + if (\defined('SIGINT') && $signal === \SIGINT) { + $this->cancelling = true; + } + + if (\defined('SIGTERM') && $signal === \SIGTERM) { + return $signal; + } + + return false; + } + + public function getSubscribedSignals(): array + { + $result = []; + /** @psalm-suppress MixedAssignment */ + \defined('SIGINT') and $result[] = \SIGINT; + /** @psalm-suppress MixedAssignment */ + \defined('SIGTERM') and $result[] = \SIGTERM; + + return $result; + } + + protected function execute( + InputInterface $input, + OutputInterface $output, + ): int { + $output->writeln('Binary to load: ' . $input->getArgument('binary')); + $output->writeln('Path to store the binary: ' . $input->getArgument('path')); + + $container = Bootstrap::init()->withConfig( + xml: \dirname(__DIR__, 2) . '/dload.xml', + inputOptions: $input->getOptions(), + inputArguments: $input->getArguments(), + environment: \getenv(), + )->finish(); + + $output->writeln('Architecture: ' . $container->get(Architecture::class)->name); + $output->writeln('Operating system: ' . $container->get(OperatingSystem::class)->name); + $output->writeln('Stability: ' . $container->get(Stability::class)->name); + + return Command::SUCCESS; + } +} diff --git a/src/Module/Environment/Architecture.php b/src/Module/Environment/Architecture.php new file mode 100644 index 0000000..2522b9e --- /dev/null +++ b/src/Module/Environment/Architecture.php @@ -0,0 +1,39 @@ + self::X86_64, + 'arm64', 'aarch64' => self::ARM_64, + default => throw new \OutOfRangeException( + \sprintf( + self::ERROR_UNKNOWN_ARCH, + \php_uname('m'), + ), + ), + }; + } +} diff --git a/src/Module/Environment/OperatingSystem.php b/src/Module/Environment/OperatingSystem.php new file mode 100644 index 0000000..c0d5bd8 --- /dev/null +++ b/src/Module/Environment/OperatingSystem.php @@ -0,0 +1,41 @@ + self::Windows, + 'BSD' => self::BSD, + 'Darwin' => self::Darwin, + 'Linux' => \str_contains(\PHP_OS, 'Alpine') + ? self::Alpine + : self::Linux, + default => throw new \OutOfRangeException(\sprintf(self::ERROR_UNKNOWN_OS, \PHP_OS_FAMILY)), + }; + } +} diff --git a/src/Module/Environment/Stability.php b/src/Module/Environment/Stability.php new file mode 100644 index 0000000..0caaf4c --- /dev/null +++ b/src/Module/Environment/Stability.php @@ -0,0 +1,42 @@ + 4, + self::RC => 3, + self::Beta => 2, + self::Alpha => 1, + self::Dev => 0, + }; + } +} diff --git a/src/Service/Config/ConfigAttribute.php b/src/Service/Config/ConfigAttribute.php new file mode 100644 index 0000000..e2d1a40 --- /dev/null +++ b/src/Service/Config/ConfigAttribute.php @@ -0,0 +1,10 @@ +info('SimpleXML extension is not loaded.'); + } else { + $this->xml = \simplexml_load_string($xml, options: \LIBXML_NOERROR) ?: null; + } + } + } + + public function hydrate(object $config): void + { + // Read class properties + $reflection = new \ReflectionObject($config); + foreach ($reflection->getProperties() as $property) { + $attributes = $property->getAttributes(ConfigAttribute::class, \ReflectionAttribute::IS_INSTANCEOF); + if (\count($attributes) === 0) { + continue; + } + + $this->injectValue($config, $property, $attributes); + } + } + + /** + * @param \ReflectionProperty $property + * @param list<\ReflectionAttribute> $attributes + */ + private function injectValue(object $config, \ReflectionProperty $property, array $attributes): void + { + foreach ($attributes as $attribute) { + try { + $attribute = $attribute->newInstance(); + + /** @var mixed $value */ + $value = match (true) { + $attribute instanceof XPath => $this->getXPath($attribute), + $attribute instanceof Env => $this->env[$attribute->name] ?? null, + $attribute instanceof InputOption => $this->inputOptions[$attribute->name] ?? null, + $attribute instanceof InputArgument => $this->inputArguments[$attribute->name] ?? null, + $attribute instanceof PhpIni => (static fn(string|false $value): ?string => match ($value) { + // Option does not exist or set to null + '', false => null, + default => $value, + })(\ini_get($attribute->option)), + default => null, + }; + + if (\in_array($value, [null, []], true)) { + continue; + } + + // Cast value to the property type + $type = $property->getType(); + + /** @var mixed $result */ + $result = match (true) { + !$type instanceof \ReflectionNamedType => $value, + $type->allowsNull() && $value === '' => null, + $type->isBuiltin() => match ($type->getName()) { + 'int' => (int) $value, + 'float' => (float) $value, + 'bool' => \filter_var($value, FILTER_VALIDATE_BOOLEAN), + 'array' => match (true) { + \is_array($value) => $value, + \is_string($value) => \explode(',', $value), + default => [$value], + }, + default => $value, + }, + default => $value, + }; + + // todo Validation + + // Set the property value + $property->setValue($config, $result); + return; + } catch (\Throwable $e) { + $this->logger->exception($e, important: true); + } + } + } + + private function getXPath(XPath $attribute): mixed + { + $value = $this->xml?->xpath($attribute->path); + + return \is_array($value) && \array_key_exists($attribute->key, $value) + ? $value[$attribute->key] + : null; + } +} diff --git a/src/Service/Config/Env.php b/src/Service/Config/Env.php new file mode 100644 index 0000000..82a0548 --- /dev/null +++ b/src/Service/Config/Env.php @@ -0,0 +1,16 @@ + */ + private array $cache = []; + + /** @var array */ + private array $factory = []; + + private readonly Injector $injector; + + /** + * @psalm-suppress PropertyTypeCoercion + */ + public function __construct() + { + $this->injector = (new Injector($this))->withCacheReflections(false); + $this->cache[Injector::class] = $this->injector; + $this->cache[self::class] = $this; + $this->cache[ContainerInterface::class] = $this; + } + + /** + * @template T of object + * @param class-string $id + * @param array $arguments Will be used if the object is created for the first time. + * @return T + * + * @psalm-suppress MoreSpecificImplementedParamType, InvalidReturnType + */ + public function get(string $id, array $arguments = []): object + { + /** @psalm-suppress InvalidReturnStatement */ + return $this->cache[$id] ??= $this->make($id, $arguments); + } + + /** + * @param class-string $id + * + * @psalm-suppress MoreSpecificImplementedParamType + */ + public function has(string $id): bool + { + return \array_key_exists($id, $this->cache) || \array_key_exists($id, $this->factory); + } + + /** + * @template T of object + * @param T $service + * @param class-string|null $id + */ + public function set(object $service, ?string $id = null): void + { + \assert($id === null || $service instanceof $id, "Service must be instance of {$id}."); + $this->cache[$id ?? \get_class($service)] = $service; + } + + /** + * Create an object of the specified class without caching. + * + * @template T + * @param class-string $class + * @return T + */ + public function make(string $class, array $arguments = []): object + { + $binding = $this->factory[$class] ?? null; + + if ($binding instanceof \Closure) { + $result = $binding($this); + } else { + try { + $result = $this->injector->make($class, \array_merge((array) $binding, $arguments)); + } catch (\Throwable $e) { + throw new class("Unable to create object of class $class.", previous: $e) extends \RuntimeException implements NotFoundExceptionInterface {}; + } + } + + \assert($result instanceof $class, "Created object must be instance of {$class}."); + + // Detect related types + // Configs + if (\str_starts_with($class, 'Internal\\DLoad\\Config\\')) { + // Hydrate config + /** @var ConfigLoader $configLoader */ + $configLoader = $this->get(ConfigLoader::class); + $configLoader->hydrate($result); + } + + return $result; + } + + /** + * Declare a factory or predefined arguments for the specified class. + * + * @template T of object + * @param class-string $id + * @param array|\Closure(Container): T $binding + */ + public function bind(string $id, \Closure|array|null $binding = null): void + { + if ($binding !== null) { + $this->factory[$id] = $binding; + return; + } + + (\class_exists($id) && \is_a($id, Factoriable::class, true)) or throw new \InvalidArgumentException( + "Class `$id` must have a factory or be a factory itself and implement `Factoriable`.", + ); + + $this->factory[$id] = $id::create(...); + } + + public function destroy(): void + { + unset($this->cache, $this->factory, $this->injector); + } +} diff --git a/src/Service/Destroyable.php b/src/Service/Destroyable.php new file mode 100644 index 0000000..4e70e34 --- /dev/null +++ b/src/Service/Destroyable.php @@ -0,0 +1,15 @@ +debug = $output?->isVeryVerbose() ?? false; + $this->verbose = $output?->isVerbose() ?? false; + } + + public function print(string $message): void + { + $this->echo($message . "\n", false); + } + + public function status(string $sender, string $message, string|int|float|bool ...$values): void + { + $this->echo("\033[47;1;30m " . $sender . " \033[0m " . \sprintf($message, ...$values) . "\n\n", false); + } + + public function info(string $message, string|int|float|bool ...$values): void + { + $this->echo("\033[32m" . \sprintf($message, ...$values) . "\033[0m\n", !$this->verbose); + } + + public function debug(string $message, string|int|float|bool ...$values): void + { + $this->echo("\033[34m" . \sprintf($message, ...$values) . "\033[0m\n"); + } + + public function error(string $message, string|int|float|bool ...$values): void + { + $this->echo("\033[31m" . \sprintf($message, ...$values) . "\033[0m\n"); + } + + public function exception(\Throwable $e, ?string $header = null, bool $important = false): void + { + $r = "----------------------\n"; + // Print bold yellow header if exists + if ($header !== null) { + $r .= "\033[1;33m" . $header . "\033[0m\n"; + } + // Print exception message + $r .= $e->getMessage() . "\n"; + // Print file and line using green color and italic font + $r .= "In \033[3;32m" . $e->getFile() . ':' . $e->getLine() . "\033[0m\n"; + // Print stack trace using gray + $r .= "Stack trace:\n"; + // Limit stacktrace to 5 lines + $stack = \explode("\n", $e->getTraceAsString()); + $r .= "\033[90m" . \implode("\n", \array_slice($stack, 0, \min(5, \count($stack)))) . "\033[0m\n"; + $r .= "\n"; + $this->echo($r, !$important); + } + + private function echo(string $message, bool $debug = true): void + { + if ($debug && !$this->debug) { + return; + } + $this->output?->write($message); + } +} diff --git a/tests/Unit/InfoTest.php b/tests/Unit/InfoTest.php index cc4dd3c..bece496 100644 --- a/tests/Unit/InfoTest.php +++ b/tests/Unit/InfoTest.php @@ -4,9 +4,12 @@ namespace Internal\DLoad\Tests\Unit; +use PHPUnit\Framework\TestCase; + final class InfoTest extends TestCase { public function testTest(): void { + self::assertTrue(true); } }