From fb29ff29cfd455a0efcbf281befc670a9748ce4e Mon Sep 17 00:00:00 2001 From: Benjamin Dalsass <95754414+bdalsass@users.noreply.github.com> Date: Tue, 12 Dec 2023 16:40:04 +0100 Subject: [PATCH] =?UTF-8?q?N=C2=B07059=20-=20Symfony=206.4=20-=20Applicati?= =?UTF-8?q?on=20skeleton=20(#587)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mise en place d'un squelette temporaire fonctionnel d'application Symfony. - Ajout bundles debug & runtime pour une implémentation standard - Configuration minimale - .env file in specific directory - Frontal application app.php --- app.php | 29 +++ composer.json | 13 +- composer.lock | 155 +++++++++++- lib/autoload_runtime.php | 31 +++ lib/composer/autoload_classmap.php | 31 ++- lib/composer/autoload_psr4.php | 3 + lib/composer/autoload_static.php | 46 +++- lib/composer/installed.json | 160 +++++++++++++ lib/composer/installed.php | 22 +- lib/symfony/debug-bundle/CHANGELOG.md | 8 + .../Command/ServerDumpPlaceholderCommand.php | 54 +++++ lib/symfony/debug-bundle/DebugBundle.php | 72 ++++++ .../Compiler/DumpDataCollectorPass.php | 45 ++++ .../DependencyInjection/Configuration.php | 60 +++++ .../DependencyInjection/DebugExtension.php | 102 ++++++++ lib/symfony/debug-bundle/LICENSE | 19 ++ lib/symfony/debug-bundle/README.md | 13 + .../Resources/config/schema/debug-1.0.xsd | 15 ++ .../Resources/config/services.php | 140 +++++++++++ .../Resources/views/Profiler/dump.html.twig | 83 +++++++ .../Resources/views/Profiler/icon.svg | 9 + lib/symfony/debug-bundle/composer.json | 41 ++++ lib/symfony/runtime/CHANGELOG.md | 19 ++ lib/symfony/runtime/GenericRuntime.php | 223 +++++++++++++++++ .../runtime/Internal/BasicErrorHandler.php | 53 ++++ .../runtime/Internal/ComposerPlugin.php | 119 +++++++++ .../Internal/Console/ApplicationRuntime.php | 21 ++ .../Console/Command/CommandRuntime.php | 21 ++ .../Console/Input/InputInterfaceRuntime.php | 21 ++ .../Console/Output/OutputInterfaceRuntime.php | 21 ++ .../HttpFoundation/RequestRuntime.php | 21 ++ .../HttpFoundation/ResponseRuntime.php | 21 ++ .../HttpKernel/HttpKernelInterfaceRuntime.php | 21 ++ .../runtime/Internal/MissingDotenv.php | 19 ++ .../runtime/Internal/SymfonyErrorHandler.php | 35 +++ .../Internal/autoload_runtime.template | 28 +++ lib/symfony/runtime/LICENSE | 19 ++ lib/symfony/runtime/README.md | 13 + .../runtime/Resolver/ClosureResolver.php | 31 +++ .../runtime/Resolver/DebugClosureResolver.php | 36 +++ lib/symfony/runtime/ResolverInterface.php | 23 ++ lib/symfony/runtime/Runner/ClosureRunner.php | 44 ++++ .../Symfony/ConsoleApplicationRunner.php | 51 ++++ .../Runner/Symfony/HttpKernelRunner.php | 58 +++++ .../runtime/Runner/Symfony/ResponseRunner.php | 33 +++ lib/symfony/runtime/RunnerInterface.php | 20 ++ lib/symfony/runtime/RuntimeInterface.php | 34 +++ lib/symfony/runtime/SymfonyRuntime.php | 226 ++++++++++++++++++ lib/symfony/runtime/composer.json | 45 ++++ sources/Controller/AbstractAppController.php | 32 +++ sources/Kernel.php | 51 ++++ .../SummaryCard/SummaryCardService.php | 3 +- symfony/.env | 20 ++ symfony/config/bundles.php | 8 + symfony/config/packages/cache.yaml | 19 ++ symfony/config/packages/debug.yaml | 5 + symfony/config/packages/framework.yaml | 25 ++ .../packages/itop_configuration_bridge.php | 32 +++ symfony/config/packages/routing.yaml | 12 + symfony/config/packages/twig.yaml | 6 + symfony/config/packages/web_profiler.yaml | 17 ++ symfony/config/preload.php | 5 + symfony/config/routes.yaml | 5 + symfony/config/routes/framework.yaml | 4 + symfony/config/routes/web_profiler.yaml | 8 + symfony/config/services.yaml | 23 ++ 66 files changed, 2694 insertions(+), 8 deletions(-) create mode 100644 app.php create mode 100644 lib/autoload_runtime.php create mode 100644 lib/symfony/debug-bundle/CHANGELOG.md create mode 100644 lib/symfony/debug-bundle/Command/ServerDumpPlaceholderCommand.php create mode 100644 lib/symfony/debug-bundle/DebugBundle.php create mode 100644 lib/symfony/debug-bundle/DependencyInjection/Compiler/DumpDataCollectorPass.php create mode 100644 lib/symfony/debug-bundle/DependencyInjection/Configuration.php create mode 100644 lib/symfony/debug-bundle/DependencyInjection/DebugExtension.php create mode 100644 lib/symfony/debug-bundle/LICENSE create mode 100644 lib/symfony/debug-bundle/README.md create mode 100644 lib/symfony/debug-bundle/Resources/config/schema/debug-1.0.xsd create mode 100644 lib/symfony/debug-bundle/Resources/config/services.php create mode 100644 lib/symfony/debug-bundle/Resources/views/Profiler/dump.html.twig create mode 100644 lib/symfony/debug-bundle/Resources/views/Profiler/icon.svg create mode 100644 lib/symfony/debug-bundle/composer.json create mode 100644 lib/symfony/runtime/CHANGELOG.md create mode 100644 lib/symfony/runtime/GenericRuntime.php create mode 100644 lib/symfony/runtime/Internal/BasicErrorHandler.php create mode 100644 lib/symfony/runtime/Internal/ComposerPlugin.php create mode 100644 lib/symfony/runtime/Internal/Console/ApplicationRuntime.php create mode 100644 lib/symfony/runtime/Internal/Console/Command/CommandRuntime.php create mode 100644 lib/symfony/runtime/Internal/Console/Input/InputInterfaceRuntime.php create mode 100644 lib/symfony/runtime/Internal/Console/Output/OutputInterfaceRuntime.php create mode 100644 lib/symfony/runtime/Internal/HttpFoundation/RequestRuntime.php create mode 100644 lib/symfony/runtime/Internal/HttpFoundation/ResponseRuntime.php create mode 100644 lib/symfony/runtime/Internal/HttpKernel/HttpKernelInterfaceRuntime.php create mode 100644 lib/symfony/runtime/Internal/MissingDotenv.php create mode 100644 lib/symfony/runtime/Internal/SymfonyErrorHandler.php create mode 100644 lib/symfony/runtime/Internal/autoload_runtime.template create mode 100644 lib/symfony/runtime/LICENSE create mode 100644 lib/symfony/runtime/README.md create mode 100644 lib/symfony/runtime/Resolver/ClosureResolver.php create mode 100644 lib/symfony/runtime/Resolver/DebugClosureResolver.php create mode 100644 lib/symfony/runtime/ResolverInterface.php create mode 100644 lib/symfony/runtime/Runner/ClosureRunner.php create mode 100644 lib/symfony/runtime/Runner/Symfony/ConsoleApplicationRunner.php create mode 100644 lib/symfony/runtime/Runner/Symfony/HttpKernelRunner.php create mode 100644 lib/symfony/runtime/Runner/Symfony/ResponseRunner.php create mode 100644 lib/symfony/runtime/RunnerInterface.php create mode 100644 lib/symfony/runtime/RuntimeInterface.php create mode 100644 lib/symfony/runtime/SymfonyRuntime.php create mode 100644 lib/symfony/runtime/composer.json create mode 100644 sources/Controller/AbstractAppController.php create mode 100644 sources/Kernel.php create mode 100644 symfony/.env create mode 100644 symfony/config/bundles.php create mode 100644 symfony/config/packages/cache.yaml create mode 100644 symfony/config/packages/debug.yaml create mode 100644 symfony/config/packages/framework.yaml create mode 100644 symfony/config/packages/itop_configuration_bridge.php create mode 100644 symfony/config/packages/routing.yaml create mode 100644 symfony/config/packages/twig.yaml create mode 100644 symfony/config/packages/web_profiler.yaml create mode 100644 symfony/config/preload.php create mode 100644 symfony/config/routes.yaml create mode 100644 symfony/config/routes/framework.yaml create mode 100644 symfony/config/routes/web_profiler.yaml create mode 100644 symfony/config/services.yaml diff --git a/app.php b/app.php new file mode 100644 index 000000000..6127fbdcb --- /dev/null +++ b/app.php @@ -0,0 +1,29 @@ +=8.1" + }, + "conflict": { + "symfony/dotenv": "<5.4" + }, + "require-dev": { + "composer/composer": "^1.0.2|^2.0", + "symfony/console": "^5.4.9|^6.0.9|^7.0", + "symfony/dotenv": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0" + }, + "type": "composer-plugin", + "extra": { + "class": "Symfony\\Component\\Runtime\\Internal\\ComposerPlugin" + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Runtime\\": "", + "Symfony\\Runtime\\Symfony\\Component\\": "Internal/" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Enables decoupling PHP applications from global state", + "homepage": "https://symfony.com", + "keywords": [ + "runtime" + ], + "support": { + "source": "https://github.com/symfony/runtime/tree/v6.4.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-10-18T09:43:34+00:00" + }, { "name": "symfony/service-contracts", "version": "v2.5.2", @@ -4983,6 +5062,80 @@ } ], "packages-dev": [ + { + "name": "symfony/debug-bundle", + "version": "v6.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug-bundle.git", + "reference": "1e07027423d1d37125b60a50997ada26a9d9d202" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/1e07027423d1d37125b60a50997ada26a9d9d202", + "reference": "1e07027423d1d37125b60a50997ada26a9d9d202", + "shasum": "" + }, + "require": { + "ext-xml": "*", + "php": ">=8.1", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/twig-bridge": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" + }, + "conflict": { + "symfony/config": "<5.4", + "symfony/dependency-injection": "<5.4" + }, + "require-dev": { + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/web-profiler-bundle": "^5.4|^6.0|^7.0" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\DebugBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a tight integration of the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/debug-bundle/tree/v6.4.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-11-01T12:07:38+00:00" + }, { "name": "symfony/stopwatch", "version": "v6.4.0", diff --git a/lib/autoload_runtime.php b/lib/autoload_runtime.php new file mode 100644 index 000000000..f620a1a7a --- /dev/null +++ b/lib/autoload_runtime.php @@ -0,0 +1,31 @@ + 'symfony/.env', + 'project_dir' => dirname(__DIR__, 1), +]); + +[$app, $args] = $runtime + ->getResolver($app) + ->resolve(); + +$app = $app(...$args); + +exit( + $runtime + ->getRunner($app) + ->run() +); diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php index cb832eea6..8e2464f25 100644 --- a/lib/composer/autoload_classmap.php +++ b/lib/composer/autoload_classmap.php @@ -20,6 +20,7 @@ return array( 'ActionNotification' => $baseDir . '/core/action.class.inc.php', 'AjaxPage' => $baseDir . '/sources/Application/WebPage/AjaxPage.php', 'ApcService' => $baseDir . '/core/apc-service.class.inc.php', + 'App\\Kernel' => $baseDir . '/sources/Kernel.php', 'ApplicationContext' => $baseDir . '/application/applicationcontext.class.inc.php', 'ApplicationException' => $baseDir . '/application/exceptions/ApplicationException.php', 'ApplicationMenu' => $baseDir . '/application/menunode.class.inc.php', @@ -369,6 +370,7 @@ return array( 'Combodo\\iTop\\Application\\UI\\Preferences\\BlockShortcuts\\BlockShortcuts' => $baseDir . '/sources/Application/UI/Preferences/BlockShortcuts/BlockShortcuts.php', 'Combodo\\iTop\\Application\\UI\\Printable\\BlockPrintHeader\\BlockPrintHeader' => $baseDir . '/sources/Application/UI/Printable/BlockPrintHeader/BlockPrintHeader.php', 'Combodo\\iTop\\Composer\\iTopComposer' => $baseDir . '/sources/Composer/iTopComposer.php', + 'Combodo\\iTop\\Controller\\AbstractAppController' => $baseDir . '/sources/Controller/AbstractAppController.php', 'Combodo\\iTop\\Controller\\AbstractController' => $baseDir . '/sources/Controller/AbstractController.php', 'Combodo\\iTop\\Controller\\AjaxRenderController' => $baseDir . '/sources/Controller/AjaxRenderController.php', 'Combodo\\iTop\\Controller\\Base\\Layout\\ActivityPanelController' => $baseDir . '/sources/Controller/Base/Layout/ActivityPanelController.php', @@ -471,6 +473,7 @@ return array( 'Combodo\\iTop\\Service\\Router\\Exception\\RouteNotFoundException' => $baseDir . '/sources/Service/Router/Exception/RouteNotFoundException.php', 'Combodo\\iTop\\Service\\Router\\Exception\\RouterException' => $baseDir . '/sources/Service/Router/Exception/RouterException.php', 'Combodo\\iTop\\Service\\Router\\Router' => $baseDir . '/sources/Service/Router/Router.php', + 'Combodo\\iTop\\Service\\SummaryCard\\SummaryCardService' => $baseDir . '/sources/Service/SummaryCard/SummaryCardService.php', 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectConfig' => $baseDir . '/sources/Service/TemporaryObjects/TemporaryObjectConfig.php', 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectGC' => $baseDir . '/sources/Service/TemporaryObjects/TemporaryObjectGC.php', 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectHelper' => $baseDir . '/sources/Service/TemporaryObjects/TemporaryObjectHelper.php', @@ -1592,7 +1595,6 @@ return array( 'StimulusUserAction' => $baseDir . '/core/stimulus.class.inc.php', 'Str' => $baseDir . '/core/MyHelpers.class.inc.php', 'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', - 'SummaryCardService' => $baseDir . '/sources/Service/SummaryCard/SummaryCardService.php', 'Symfony\\Bridge\\Twig\\AppVariable' => $vendorDir . '/symfony/twig-bridge/AppVariable.php', 'Symfony\\Bridge\\Twig\\Attribute\\Template' => $vendorDir . '/symfony/twig-bridge/Attribute/Template.php', 'Symfony\\Bridge\\Twig\\Command\\DebugCommand' => $vendorDir . '/symfony/twig-bridge/Command/DebugCommand.php', @@ -1646,6 +1648,11 @@ return array( 'Symfony\\Bridge\\Twig\\TokenParser\\TransTokenParser' => $vendorDir . '/symfony/twig-bridge/TokenParser/TransTokenParser.php', 'Symfony\\Bridge\\Twig\\Translation\\TwigExtractor' => $vendorDir . '/symfony/twig-bridge/Translation/TwigExtractor.php', 'Symfony\\Bridge\\Twig\\UndefinedCallableHandler' => $vendorDir . '/symfony/twig-bridge/UndefinedCallableHandler.php', + 'Symfony\\Bundle\\DebugBundle\\Command\\ServerDumpPlaceholderCommand' => $vendorDir . '/symfony/debug-bundle/Command/ServerDumpPlaceholderCommand.php', + 'Symfony\\Bundle\\DebugBundle\\DebugBundle' => $vendorDir . '/symfony/debug-bundle/DebugBundle.php', + 'Symfony\\Bundle\\DebugBundle\\DependencyInjection\\Compiler\\DumpDataCollectorPass' => $vendorDir . '/symfony/debug-bundle/DependencyInjection/Compiler/DumpDataCollectorPass.php', + 'Symfony\\Bundle\\DebugBundle\\DependencyInjection\\Configuration' => $vendorDir . '/symfony/debug-bundle/DependencyInjection/Configuration.php', + 'Symfony\\Bundle\\DebugBundle\\DependencyInjection\\DebugExtension' => $vendorDir . '/symfony/debug-bundle/DependencyInjection/DebugExtension.php', 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\AbstractPhpFileCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php', 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\AnnotationsCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php', 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\CachePoolClearerCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/CachePoolClearerCacheWarmer.php', @@ -2655,6 +2662,21 @@ return array( 'Symfony\\Component\\Routing\\RouteCompilerInterface' => $vendorDir . '/symfony/routing/RouteCompilerInterface.php', 'Symfony\\Component\\Routing\\Router' => $vendorDir . '/symfony/routing/Router.php', 'Symfony\\Component\\Routing\\RouterInterface' => $vendorDir . '/symfony/routing/RouterInterface.php', + 'Symfony\\Component\\Runtime\\GenericRuntime' => $vendorDir . '/symfony/runtime/GenericRuntime.php', + 'Symfony\\Component\\Runtime\\Internal\\BasicErrorHandler' => $vendorDir . '/symfony/runtime/Internal/BasicErrorHandler.php', + 'Symfony\\Component\\Runtime\\Internal\\ComposerPlugin' => $vendorDir . '/symfony/runtime/Internal/ComposerPlugin.php', + 'Symfony\\Component\\Runtime\\Internal\\MissingDotenv' => $vendorDir . '/symfony/runtime/Internal/MissingDotenv.php', + 'Symfony\\Component\\Runtime\\Internal\\SymfonyErrorHandler' => $vendorDir . '/symfony/runtime/Internal/SymfonyErrorHandler.php', + 'Symfony\\Component\\Runtime\\ResolverInterface' => $vendorDir . '/symfony/runtime/ResolverInterface.php', + 'Symfony\\Component\\Runtime\\Resolver\\ClosureResolver' => $vendorDir . '/symfony/runtime/Resolver/ClosureResolver.php', + 'Symfony\\Component\\Runtime\\Resolver\\DebugClosureResolver' => $vendorDir . '/symfony/runtime/Resolver/DebugClosureResolver.php', + 'Symfony\\Component\\Runtime\\RunnerInterface' => $vendorDir . '/symfony/runtime/RunnerInterface.php', + 'Symfony\\Component\\Runtime\\Runner\\ClosureRunner' => $vendorDir . '/symfony/runtime/Runner/ClosureRunner.php', + 'Symfony\\Component\\Runtime\\Runner\\Symfony\\ConsoleApplicationRunner' => $vendorDir . '/symfony/runtime/Runner/Symfony/ConsoleApplicationRunner.php', + 'Symfony\\Component\\Runtime\\Runner\\Symfony\\HttpKernelRunner' => $vendorDir . '/symfony/runtime/Runner/Symfony/HttpKernelRunner.php', + 'Symfony\\Component\\Runtime\\Runner\\Symfony\\ResponseRunner' => $vendorDir . '/symfony/runtime/Runner/Symfony/ResponseRunner.php', + 'Symfony\\Component\\Runtime\\RuntimeInterface' => $vendorDir . '/symfony/runtime/RuntimeInterface.php', + 'Symfony\\Component\\Runtime\\SymfonyRuntime' => $vendorDir . '/symfony/runtime/SymfonyRuntime.php', 'Symfony\\Component\\Stopwatch\\Section' => $vendorDir . '/symfony/stopwatch/Section.php', 'Symfony\\Component\\Stopwatch\\Stopwatch' => $vendorDir . '/symfony/stopwatch/Stopwatch.php', 'Symfony\\Component\\Stopwatch\\StopwatchEvent' => $vendorDir . '/symfony/stopwatch/StopwatchEvent.php', @@ -2799,6 +2821,13 @@ return array( 'Symfony\\Polyfill\\Php80\\Php80' => $vendorDir . '/symfony/polyfill-php80/Php80.php', 'Symfony\\Polyfill\\Php80\\PhpToken' => $vendorDir . '/symfony/polyfill-php80/PhpToken.php', 'Symfony\\Polyfill\\Php83\\Php83' => $vendorDir . '/symfony/polyfill-php83/Php83.php', + 'Symfony\\Runtime\\Symfony\\Component\\Console\\ApplicationRuntime' => $vendorDir . '/symfony/runtime/Internal/Console/ApplicationRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\Console\\Command\\CommandRuntime' => $vendorDir . '/symfony/runtime/Internal/Console/Command/CommandRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\Console\\Input\\InputInterfaceRuntime' => $vendorDir . '/symfony/runtime/Internal/Console/Input/InputInterfaceRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\Console\\Output\\OutputInterfaceRuntime' => $vendorDir . '/symfony/runtime/Internal/Console/Output/OutputInterfaceRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\HttpFoundation\\RequestRuntime' => $vendorDir . '/symfony/runtime/Internal/HttpFoundation/RequestRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\HttpFoundation\\ResponseRuntime' => $vendorDir . '/symfony/runtime/Internal/HttpFoundation/ResponseRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\HttpKernel\\HttpKernelInterfaceRuntime' => $vendorDir . '/symfony/runtime/Internal/HttpKernel/HttpKernelInterfaceRuntime.php', 'SynchroExceptionNotStarted' => $baseDir . '/application/exceptions/SynchroExceptionNotStarted.php', 'System' => $vendorDir . '/pear/pear-core-minimal/src/System.php', 'TCPDF' => $vendorDir . '/combodo/tcpdf/tcpdf.php', diff --git a/lib/composer/autoload_psr4.php b/lib/composer/autoload_psr4.php index b7c94ac93..e69498973 100644 --- a/lib/composer/autoload_psr4.php +++ b/lib/composer/autoload_psr4.php @@ -9,6 +9,7 @@ return array( 'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'), 'Twig\\' => array($vendorDir . '/twig/twig/src'), 'TheNetworg\\OAuth2\\Client\\' => array($vendorDir . '/thenetworg/oauth2-azure/src'), + 'Symfony\\Runtime\\Symfony\\Component\\' => array($vendorDir . '/symfony/runtime/Internal'), 'Symfony\\Polyfill\\Php83\\' => array($vendorDir . '/symfony/polyfill-php83'), 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'), 'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'), @@ -26,6 +27,7 @@ return array( 'Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'), 'Symfony\\Component\\String\\' => array($vendorDir . '/symfony/string'), 'Symfony\\Component\\Stopwatch\\' => array($vendorDir . '/symfony/stopwatch'), + 'Symfony\\Component\\Runtime\\' => array($vendorDir . '/symfony/runtime'), 'Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'), 'Symfony\\Component\\HttpKernel\\' => array($vendorDir . '/symfony/http-kernel'), 'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'), @@ -42,6 +44,7 @@ return array( 'Symfony\\Bundle\\WebProfilerBundle\\' => array($vendorDir . '/symfony/web-profiler-bundle'), 'Symfony\\Bundle\\TwigBundle\\' => array($vendorDir . '/symfony/twig-bundle'), 'Symfony\\Bundle\\FrameworkBundle\\' => array($vendorDir . '/symfony/framework-bundle'), + 'Symfony\\Bundle\\DebugBundle\\' => array($vendorDir . '/symfony/debug-bundle'), 'Symfony\\Bridge\\Twig\\' => array($vendorDir . '/symfony/twig-bridge'), 'ScssPhp\\ScssPhp\\' => array($vendorDir . '/scssphp/scssphp/src'), 'Sabberworm\\CSS\\' => array($vendorDir . '/sabberworm/php-css-parser/src'), diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php index da00cbf5b..79d76a21d 100644 --- a/lib/composer/autoload_static.php +++ b/lib/composer/autoload_static.php @@ -35,6 +35,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f ), 'S' => array ( + 'Symfony\\Runtime\\Symfony\\Component\\' => 34, 'Symfony\\Polyfill\\Php83\\' => 23, 'Symfony\\Polyfill\\Php80\\' => 23, 'Symfony\\Polyfill\\Php72\\' => 23, @@ -52,6 +53,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Component\\VarDumper\\' => 28, 'Symfony\\Component\\String\\' => 25, 'Symfony\\Component\\Stopwatch\\' => 28, + 'Symfony\\Component\\Runtime\\' => 26, 'Symfony\\Component\\Routing\\' => 26, 'Symfony\\Component\\HttpKernel\\' => 29, 'Symfony\\Component\\HttpFoundation\\' => 33, @@ -68,6 +70,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Bundle\\WebProfilerBundle\\' => 33, 'Symfony\\Bundle\\TwigBundle\\' => 26, 'Symfony\\Bundle\\FrameworkBundle\\' => 31, + 'Symfony\\Bundle\\DebugBundle\\' => 27, 'Symfony\\Bridge\\Twig\\' => 20, 'ScssPhp\\ScssPhp\\' => 16, 'Sabberworm\\CSS\\' => 15, @@ -118,6 +121,10 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f array ( 0 => __DIR__ . '/..' . '/thenetworg/oauth2-azure/src', ), + 'Symfony\\Runtime\\Symfony\\Component\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/runtime/Internal', + ), 'Symfony\\Polyfill\\Php83\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-php83', @@ -186,6 +193,10 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f array ( 0 => __DIR__ . '/..' . '/symfony/stopwatch', ), + 'Symfony\\Component\\Runtime\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/runtime', + ), 'Symfony\\Component\\Routing\\' => array ( 0 => __DIR__ . '/..' . '/symfony/routing', @@ -250,6 +261,10 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f array ( 0 => __DIR__ . '/..' . '/symfony/framework-bundle', ), + 'Symfony\\Bundle\\DebugBundle\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/debug-bundle', + ), 'Symfony\\Bridge\\Twig\\' => array ( 0 => __DIR__ . '/..' . '/symfony/twig-bridge', @@ -378,6 +393,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'ActionNotification' => __DIR__ . '/../..' . '/core/action.class.inc.php', 'AjaxPage' => __DIR__ . '/../..' . '/sources/Application/WebPage/AjaxPage.php', 'ApcService' => __DIR__ . '/../..' . '/core/apc-service.class.inc.php', + 'App\\Kernel' => __DIR__ . '/../..' . '/sources/Kernel.php', 'ApplicationContext' => __DIR__ . '/../..' . '/application/applicationcontext.class.inc.php', 'ApplicationException' => __DIR__ . '/../..' . '/application/exceptions/ApplicationException.php', 'ApplicationMenu' => __DIR__ . '/../..' . '/application/menunode.class.inc.php', @@ -727,6 +743,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Combodo\\iTop\\Application\\UI\\Preferences\\BlockShortcuts\\BlockShortcuts' => __DIR__ . '/../..' . '/sources/Application/UI/Preferences/BlockShortcuts/BlockShortcuts.php', 'Combodo\\iTop\\Application\\UI\\Printable\\BlockPrintHeader\\BlockPrintHeader' => __DIR__ . '/../..' . '/sources/Application/UI/Printable/BlockPrintHeader/BlockPrintHeader.php', 'Combodo\\iTop\\Composer\\iTopComposer' => __DIR__ . '/../..' . '/sources/Composer/iTopComposer.php', + 'Combodo\\iTop\\Controller\\AbstractAppController' => __DIR__ . '/../..' . '/sources/Controller/AbstractAppController.php', 'Combodo\\iTop\\Controller\\AbstractController' => __DIR__ . '/../..' . '/sources/Controller/AbstractController.php', 'Combodo\\iTop\\Controller\\AjaxRenderController' => __DIR__ . '/../..' . '/sources/Controller/AjaxRenderController.php', 'Combodo\\iTop\\Controller\\Base\\Layout\\ActivityPanelController' => __DIR__ . '/../..' . '/sources/Controller/Base/Layout/ActivityPanelController.php', @@ -829,6 +846,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Combodo\\iTop\\Service\\Router\\Exception\\RouteNotFoundException' => __DIR__ . '/../..' . '/sources/Service/Router/Exception/RouteNotFoundException.php', 'Combodo\\iTop\\Service\\Router\\Exception\\RouterException' => __DIR__ . '/../..' . '/sources/Service/Router/Exception/RouterException.php', 'Combodo\\iTop\\Service\\Router\\Router' => __DIR__ . '/../..' . '/sources/Service/Router/Router.php', + 'Combodo\\iTop\\Service\\SummaryCard\\SummaryCardService' => __DIR__ . '/../..' . '/sources/Service/SummaryCard/SummaryCardService.php', 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectConfig' => __DIR__ . '/../..' . '/sources/Service/TemporaryObjects/TemporaryObjectConfig.php', 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectGC' => __DIR__ . '/../..' . '/sources/Service/TemporaryObjects/TemporaryObjectGC.php', 'Combodo\\iTop\\Service\\TemporaryObjects\\TemporaryObjectHelper' => __DIR__ . '/../..' . '/sources/Service/TemporaryObjects/TemporaryObjectHelper.php', @@ -1950,7 +1968,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'StimulusUserAction' => __DIR__ . '/../..' . '/core/stimulus.class.inc.php', 'Str' => __DIR__ . '/../..' . '/core/MyHelpers.class.inc.php', 'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', - 'SummaryCardService' => __DIR__ . '/../..' . '/sources/Service/SummaryCard/SummaryCardService.php', 'Symfony\\Bridge\\Twig\\AppVariable' => __DIR__ . '/..' . '/symfony/twig-bridge/AppVariable.php', 'Symfony\\Bridge\\Twig\\Attribute\\Template' => __DIR__ . '/..' . '/symfony/twig-bridge/Attribute/Template.php', 'Symfony\\Bridge\\Twig\\Command\\DebugCommand' => __DIR__ . '/..' . '/symfony/twig-bridge/Command/DebugCommand.php', @@ -2004,6 +2021,11 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Bridge\\Twig\\TokenParser\\TransTokenParser' => __DIR__ . '/..' . '/symfony/twig-bridge/TokenParser/TransTokenParser.php', 'Symfony\\Bridge\\Twig\\Translation\\TwigExtractor' => __DIR__ . '/..' . '/symfony/twig-bridge/Translation/TwigExtractor.php', 'Symfony\\Bridge\\Twig\\UndefinedCallableHandler' => __DIR__ . '/..' . '/symfony/twig-bridge/UndefinedCallableHandler.php', + 'Symfony\\Bundle\\DebugBundle\\Command\\ServerDumpPlaceholderCommand' => __DIR__ . '/..' . '/symfony/debug-bundle/Command/ServerDumpPlaceholderCommand.php', + 'Symfony\\Bundle\\DebugBundle\\DebugBundle' => __DIR__ . '/..' . '/symfony/debug-bundle/DebugBundle.php', + 'Symfony\\Bundle\\DebugBundle\\DependencyInjection\\Compiler\\DumpDataCollectorPass' => __DIR__ . '/..' . '/symfony/debug-bundle/DependencyInjection/Compiler/DumpDataCollectorPass.php', + 'Symfony\\Bundle\\DebugBundle\\DependencyInjection\\Configuration' => __DIR__ . '/..' . '/symfony/debug-bundle/DependencyInjection/Configuration.php', + 'Symfony\\Bundle\\DebugBundle\\DependencyInjection\\DebugExtension' => __DIR__ . '/..' . '/symfony/debug-bundle/DependencyInjection/DebugExtension.php', 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\AbstractPhpFileCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php', 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\AnnotationsCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php', 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\CachePoolClearerCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/CachePoolClearerCacheWarmer.php', @@ -3013,6 +3035,21 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Component\\Routing\\RouteCompilerInterface' => __DIR__ . '/..' . '/symfony/routing/RouteCompilerInterface.php', 'Symfony\\Component\\Routing\\Router' => __DIR__ . '/..' . '/symfony/routing/Router.php', 'Symfony\\Component\\Routing\\RouterInterface' => __DIR__ . '/..' . '/symfony/routing/RouterInterface.php', + 'Symfony\\Component\\Runtime\\GenericRuntime' => __DIR__ . '/..' . '/symfony/runtime/GenericRuntime.php', + 'Symfony\\Component\\Runtime\\Internal\\BasicErrorHandler' => __DIR__ . '/..' . '/symfony/runtime/Internal/BasicErrorHandler.php', + 'Symfony\\Component\\Runtime\\Internal\\ComposerPlugin' => __DIR__ . '/..' . '/symfony/runtime/Internal/ComposerPlugin.php', + 'Symfony\\Component\\Runtime\\Internal\\MissingDotenv' => __DIR__ . '/..' . '/symfony/runtime/Internal/MissingDotenv.php', + 'Symfony\\Component\\Runtime\\Internal\\SymfonyErrorHandler' => __DIR__ . '/..' . '/symfony/runtime/Internal/SymfonyErrorHandler.php', + 'Symfony\\Component\\Runtime\\ResolverInterface' => __DIR__ . '/..' . '/symfony/runtime/ResolverInterface.php', + 'Symfony\\Component\\Runtime\\Resolver\\ClosureResolver' => __DIR__ . '/..' . '/symfony/runtime/Resolver/ClosureResolver.php', + 'Symfony\\Component\\Runtime\\Resolver\\DebugClosureResolver' => __DIR__ . '/..' . '/symfony/runtime/Resolver/DebugClosureResolver.php', + 'Symfony\\Component\\Runtime\\RunnerInterface' => __DIR__ . '/..' . '/symfony/runtime/RunnerInterface.php', + 'Symfony\\Component\\Runtime\\Runner\\ClosureRunner' => __DIR__ . '/..' . '/symfony/runtime/Runner/ClosureRunner.php', + 'Symfony\\Component\\Runtime\\Runner\\Symfony\\ConsoleApplicationRunner' => __DIR__ . '/..' . '/symfony/runtime/Runner/Symfony/ConsoleApplicationRunner.php', + 'Symfony\\Component\\Runtime\\Runner\\Symfony\\HttpKernelRunner' => __DIR__ . '/..' . '/symfony/runtime/Runner/Symfony/HttpKernelRunner.php', + 'Symfony\\Component\\Runtime\\Runner\\Symfony\\ResponseRunner' => __DIR__ . '/..' . '/symfony/runtime/Runner/Symfony/ResponseRunner.php', + 'Symfony\\Component\\Runtime\\RuntimeInterface' => __DIR__ . '/..' . '/symfony/runtime/RuntimeInterface.php', + 'Symfony\\Component\\Runtime\\SymfonyRuntime' => __DIR__ . '/..' . '/symfony/runtime/SymfonyRuntime.php', 'Symfony\\Component\\Stopwatch\\Section' => __DIR__ . '/..' . '/symfony/stopwatch/Section.php', 'Symfony\\Component\\Stopwatch\\Stopwatch' => __DIR__ . '/..' . '/symfony/stopwatch/Stopwatch.php', 'Symfony\\Component\\Stopwatch\\StopwatchEvent' => __DIR__ . '/..' . '/symfony/stopwatch/StopwatchEvent.php', @@ -3157,6 +3194,13 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Polyfill\\Php80\\Php80' => __DIR__ . '/..' . '/symfony/polyfill-php80/Php80.php', 'Symfony\\Polyfill\\Php80\\PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/PhpToken.php', 'Symfony\\Polyfill\\Php83\\Php83' => __DIR__ . '/..' . '/symfony/polyfill-php83/Php83.php', + 'Symfony\\Runtime\\Symfony\\Component\\Console\\ApplicationRuntime' => __DIR__ . '/..' . '/symfony/runtime/Internal/Console/ApplicationRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\Console\\Command\\CommandRuntime' => __DIR__ . '/..' . '/symfony/runtime/Internal/Console/Command/CommandRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\Console\\Input\\InputInterfaceRuntime' => __DIR__ . '/..' . '/symfony/runtime/Internal/Console/Input/InputInterfaceRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\Console\\Output\\OutputInterfaceRuntime' => __DIR__ . '/..' . '/symfony/runtime/Internal/Console/Output/OutputInterfaceRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\HttpFoundation\\RequestRuntime' => __DIR__ . '/..' . '/symfony/runtime/Internal/HttpFoundation/RequestRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\HttpFoundation\\ResponseRuntime' => __DIR__ . '/..' . '/symfony/runtime/Internal/HttpFoundation/ResponseRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\HttpKernel\\HttpKernelInterfaceRuntime' => __DIR__ . '/..' . '/symfony/runtime/Internal/HttpKernel/HttpKernelInterfaceRuntime.php', 'SynchroExceptionNotStarted' => __DIR__ . '/../..' . '/application/exceptions/SynchroExceptionNotStarted.php', 'System' => __DIR__ . '/..' . '/pear/pear-core-minimal/src/System.php', 'TCPDF' => __DIR__ . '/..' . '/combodo/tcpdf/tcpdf.php', diff --git a/lib/composer/installed.json b/lib/composer/installed.json index dde14fa73..4acaa78fb 100644 --- a/lib/composer/installed.json +++ b/lib/composer/installed.json @@ -2563,6 +2563,83 @@ ], "install-path": "../symfony/css-selector" }, + { + "name": "symfony/debug-bundle", + "version": "v6.4.0", + "version_normalized": "6.4.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug-bundle.git", + "reference": "1e07027423d1d37125b60a50997ada26a9d9d202" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/1e07027423d1d37125b60a50997ada26a9d9d202", + "reference": "1e07027423d1d37125b60a50997ada26a9d9d202", + "shasum": "" + }, + "require": { + "ext-xml": "*", + "php": ">=8.1", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/twig-bridge": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" + }, + "conflict": { + "symfony/config": "<5.4", + "symfony/dependency-injection": "<5.4" + }, + "require-dev": { + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/web-profiler-bundle": "^5.4|^6.0|^7.0" + }, + "time": "2023-11-01T12:07:38+00:00", + "type": "symfony-bundle", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\DebugBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a tight integration of the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/debug-bundle/tree/v6.4.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/debug-bundle" + }, { "name": "symfony/dependency-injection", "version": "v6.4.0", @@ -4280,6 +4357,88 @@ ], "install-path": "../symfony/routing" }, + { + "name": "symfony/runtime", + "version": "v6.4.0", + "version_normalized": "6.4.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/runtime.git", + "reference": "86539231fadfdc7f7e9911d6fa7ed84a606e7d34" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/runtime/zipball/86539231fadfdc7f7e9911d6fa7ed84a606e7d34", + "reference": "86539231fadfdc7f7e9911d6fa7ed84a606e7d34", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0|^2.0", + "php": ">=8.1" + }, + "conflict": { + "symfony/dotenv": "<5.4" + }, + "require-dev": { + "composer/composer": "^1.0.2|^2.0", + "symfony/console": "^5.4.9|^6.0.9|^7.0", + "symfony/dotenv": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0" + }, + "time": "2023-10-18T09:43:34+00:00", + "type": "composer-plugin", + "extra": { + "class": "Symfony\\Component\\Runtime\\Internal\\ComposerPlugin" + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Runtime\\": "", + "Symfony\\Runtime\\Symfony\\Component\\": "Internal/" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Enables decoupling PHP applications from global state", + "homepage": "https://symfony.com", + "keywords": [ + "runtime" + ], + "support": { + "source": "https://github.com/symfony/runtime/tree/v6.4.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/runtime" + }, { "name": "symfony/service-contracts", "version": "v2.5.2", @@ -5329,6 +5488,7 @@ ], "dev": true, "dev-package-names": [ + "symfony/debug-bundle", "symfony/stopwatch", "symfony/web-profiler-bundle" ] diff --git a/lib/composer/installed.php b/lib/composer/installed.php index dce3a9bdb..0f0acba03 100644 --- a/lib/composer/installed.php +++ b/lib/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'combodo/itop', 'pretty_version' => 'dev-develop', 'version' => 'dev-develop', - 'reference' => '7d3ff60eb26aec3f18c9cd88dc7e7ebcd1f93a52', + 'reference' => '62d7e10257f88b1de89da257859f8280cab77689', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -22,7 +22,7 @@ 'combodo/itop' => array( 'pretty_version' => 'dev-develop', 'version' => 'dev-develop', - 'reference' => '7d3ff60eb26aec3f18c9cd88dc7e7ebcd1f93a52', + 'reference' => '62d7e10257f88b1de89da257859f8280cab77689', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -410,6 +410,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'symfony/debug-bundle' => array( + 'pretty_version' => 'v6.4.0', + 'version' => '6.4.0.0', + 'reference' => '1e07027423d1d37125b60a50997ada26a9d9d202', + 'type' => 'symfony-bundle', + 'install_path' => __DIR__ . '/../symfony/debug-bundle', + 'aliases' => array(), + 'dev_requirement' => true, + ), 'symfony/dependency-injection' => array( 'pretty_version' => 'v6.4.0', 'version' => '6.4.0.0', @@ -596,6 +605,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'symfony/runtime' => array( + 'pretty_version' => 'v6.4.0', + 'version' => '6.4.0.0', + 'reference' => '86539231fadfdc7f7e9911d6fa7ed84a606e7d34', + 'type' => 'composer-plugin', + 'install_path' => __DIR__ . '/../symfony/runtime', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'symfony/service-contracts' => array( 'pretty_version' => 'v2.5.2', 'version' => '2.5.2.0', diff --git a/lib/symfony/debug-bundle/CHANGELOG.md b/lib/symfony/debug-bundle/CHANGELOG.md new file mode 100644 index 000000000..685dd1d07 --- /dev/null +++ b/lib/symfony/debug-bundle/CHANGELOG.md @@ -0,0 +1,8 @@ +CHANGELOG +========= + +4.1.0 +----- + + * Added the `server:dump` command to run a server collecting and displaying + dumps on a single place with multiple formats support diff --git a/lib/symfony/debug-bundle/Command/ServerDumpPlaceholderCommand.php b/lib/symfony/debug-bundle/Command/ServerDumpPlaceholderCommand.php new file mode 100644 index 000000000..44023876f --- /dev/null +++ b/lib/symfony/debug-bundle/Command/ServerDumpPlaceholderCommand.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\DebugBundle\Command; + +use Symfony\Component\Console\Attribute\AsCommand; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\VarDumper\Command\ServerDumpCommand; +use Symfony\Component\VarDumper\Server\DumpServer; + +/** + * A placeholder command easing VarDumper server discovery. + * + * @author Maxime Steinhausser + * + * @internal + */ +#[AsCommand(name: 'server:dump', description: 'Start a dump server that collects and displays dumps in a single place')] +class ServerDumpPlaceholderCommand extends Command +{ + private ServerDumpCommand $replacedCommand; + + public function __construct(DumpServer $server = null, array $descriptors = []) + { + $this->replacedCommand = new ServerDumpCommand((new \ReflectionClass(DumpServer::class))->newInstanceWithoutConstructor(), $descriptors); + + parent::__construct(); + } + + protected function configure(): void + { + $this->setDefinition($this->replacedCommand->getDefinition()); + $this->setHelp($this->replacedCommand->getHelp()); + $this->setDescription($this->replacedCommand->getDescription()); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + (new SymfonyStyle($input, $output))->getErrorStyle()->warning('In order to use the VarDumper server, set the "debug.dump_destination" config option to "tcp://%env(VAR_DUMPER_SERVER)%"'); + + return 8; + } +} diff --git a/lib/symfony/debug-bundle/DebugBundle.php b/lib/symfony/debug-bundle/DebugBundle.php new file mode 100644 index 000000000..9782bf8e3 --- /dev/null +++ b/lib/symfony/debug-bundle/DebugBundle.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\DebugBundle; + +use Symfony\Bundle\DebugBundle\DependencyInjection\Compiler\DumpDataCollectorPass; +use Symfony\Component\Console\Application; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HttpKernel\Bundle\Bundle; +use Symfony\Component\VarDumper\VarDumper; + +/** + * @author Nicolas Grekas + */ +class DebugBundle extends Bundle +{ + /** + * @return void + */ + public function boot() + { + if ($this->container->getParameter('kernel.debug')) { + $container = $this->container; + + // This code is here to lazy load the dump stack. This default + // configuration is overridden in CLI mode on 'console.command' event. + // The dump data collector is used by default, so dump output is sent to + // the WDT. In a CLI context, if dump is used too soon, the data collector + // will buffer it, and release it at the end of the script. + VarDumper::setHandler(function ($var, string $label = null) use ($container) { + $dumper = $container->get('data_collector.dump'); + $cloner = $container->get('var_dumper.cloner'); + $handler = function ($var, string $label = null) use ($dumper, $cloner) { + $var = $cloner->cloneVar($var); + if (null !== $label) { + $var = $var->withContext(['label' => $label]); + } + + $dumper->dump($var); + }; + VarDumper::setHandler($handler); + $handler($var, $label); + }); + } + } + + /** + * @return void + */ + public function build(ContainerBuilder $container) + { + parent::build($container); + + $container->addCompilerPass(new DumpDataCollectorPass()); + } + + /** + * @return void + */ + public function registerCommands(Application $application) + { + // noop + } +} diff --git a/lib/symfony/debug-bundle/DependencyInjection/Compiler/DumpDataCollectorPass.php b/lib/symfony/debug-bundle/DependencyInjection/Compiler/DumpDataCollectorPass.php new file mode 100644 index 000000000..568107f2f --- /dev/null +++ b/lib/symfony/debug-bundle/DependencyInjection/Compiler/DumpDataCollectorPass.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\DebugBundle\DependencyInjection\Compiler; + +use Symfony\Bundle\WebProfilerBundle\EventListener\WebDebugToolbarListener; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Registers the file link format for the {@link \Symfony\Component\HttpKernel\DataCollector\DumpDataCollector}. + * + * @author Christian Flothmann + */ +class DumpDataCollectorPass implements CompilerPassInterface +{ + /** + * @return void + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('data_collector.dump')) { + return; + } + + $definition = $container->getDefinition('data_collector.dump'); + + if (!$container->has('.virtual_request_stack')) { + $definition->replaceArgument(3, new Reference('request_stack')); + } + + if (!$container->hasParameter('web_profiler.debug_toolbar.mode') || WebDebugToolbarListener::DISABLED === $container->getParameter('web_profiler.debug_toolbar.mode')) { + $definition->replaceArgument(3, null); + } + } +} diff --git a/lib/symfony/debug-bundle/DependencyInjection/Configuration.php b/lib/symfony/debug-bundle/DependencyInjection/Configuration.php new file mode 100644 index 000000000..caf735969 --- /dev/null +++ b/lib/symfony/debug-bundle/DependencyInjection/Configuration.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\DebugBundle\DependencyInjection; + +use Symfony\Component\Config\Definition\Builder\TreeBuilder; +use Symfony\Component\Config\Definition\ConfigurationInterface; + +/** + * DebugExtension configuration structure. + * + * @author Nicolas Grekas + */ +class Configuration implements ConfigurationInterface +{ + public function getConfigTreeBuilder(): TreeBuilder + { + $treeBuilder = new TreeBuilder('debug'); + + $rootNode = $treeBuilder->getRootNode(); + $rootNode->children() + ->integerNode('max_items') + ->info('Max number of displayed items past the first level, -1 means no limit') + ->min(-1) + ->defaultValue(2500) + ->end() + ->integerNode('min_depth') + ->info('Minimum tree depth to clone all the items, 1 is default') + ->min(0) + ->defaultValue(1) + ->end() + ->integerNode('max_string_length') + ->info('Max length of displayed strings, -1 means no limit') + ->min(-1) + ->defaultValue(-1) + ->end() + ->scalarNode('dump_destination') + ->info('A stream URL where dumps should be written to') + ->example('php://stderr, or tcp://%env(VAR_DUMPER_SERVER)% when using the "server:dump" command') + ->defaultNull() + ->end() + ->enumNode('theme') + ->info('Changes the color of the dump() output when rendered directly on the templating. "dark" (default) or "light"') + ->example('dark') + ->values(['dark', 'light']) + ->defaultValue('dark') + ->end() + ; + + return $treeBuilder; + } +} diff --git a/lib/symfony/debug-bundle/DependencyInjection/DebugExtension.php b/lib/symfony/debug-bundle/DependencyInjection/DebugExtension.php new file mode 100644 index 000000000..d00d6111c --- /dev/null +++ b/lib/symfony/debug-bundle/DependencyInjection/DebugExtension.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\DebugBundle\DependencyInjection; + +use Symfony\Bridge\Monolog\Command\ServerLogCommand; +use Symfony\Bundle\DebugBundle\Command\ServerDumpPlaceholderCommand; +use Symfony\Component\Config\FileLocator; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\Extension; +use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\VarDumper\Caster\ReflectionCaster; + +/** + * DebugExtension. + * + * @author Nicolas Grekas + */ +class DebugExtension extends Extension +{ + /** + * @return void + */ + public function load(array $configs, ContainerBuilder $container) + { + $configuration = new Configuration(); + $config = $this->processConfiguration($configuration, $configs); + + $loader = new PhpFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); + $loader->load('services.php'); + + $container->getDefinition('var_dumper.cloner') + ->addMethodCall('setMaxItems', [$config['max_items']]) + ->addMethodCall('setMinDepth', [$config['min_depth']]) + ->addMethodCall('setMaxString', [$config['max_string_length']]) + ->addMethodCall('addCasters', [ReflectionCaster::UNSET_CLOSURE_FILE_INFO]); + + if ('dark' !== $config['theme']) { + $container->getDefinition('var_dumper.html_dumper') + ->addMethodCall('setTheme', [$config['theme']]); + } + + if (null === $config['dump_destination']) { + $container->getDefinition('var_dumper.command.server_dump') + ->setClass(ServerDumpPlaceholderCommand::class) + ; + } elseif (str_starts_with($config['dump_destination'], 'tcp://')) { + $container->getDefinition('debug.dump_listener') + ->replaceArgument(2, new Reference('var_dumper.server_connection')) + ; + $container->getDefinition('data_collector.dump') + ->replaceArgument(4, new Reference('var_dumper.server_connection')) + ; + $container->getDefinition('var_dumper.dump_server') + ->replaceArgument(0, $config['dump_destination']) + ; + $container->getDefinition('var_dumper.server_connection') + ->replaceArgument(0, $config['dump_destination']) + ; + } else { + $container->getDefinition('var_dumper.cli_dumper') + ->replaceArgument(0, $config['dump_destination']) + ; + $container->getDefinition('data_collector.dump') + ->replaceArgument(4, new Reference('var_dumper.cli_dumper')) + ; + $container->getDefinition('var_dumper.command.server_dump') + ->setClass(ServerDumpPlaceholderCommand::class) + ; + } + + $container->getDefinition('var_dumper.cli_dumper') + ->addMethodCall('setDisplayOptions', [[ + 'fileLinkFormat' => new Reference('debug.file_link_formatter', ContainerBuilder::IGNORE_ON_INVALID_REFERENCE), + ]]) + ; + + if (!class_exists(Command::class) || !class_exists(ServerLogCommand::class)) { + $container->removeDefinition('monolog.command.server_log'); + } + } + + public function getXsdValidationBasePath(): string|false + { + return __DIR__.'/../Resources/config/schema'; + } + + public function getNamespace(): string + { + return 'http://symfony.com/schema/dic/debug'; + } +} diff --git a/lib/symfony/debug-bundle/LICENSE b/lib/symfony/debug-bundle/LICENSE new file mode 100644 index 000000000..29f72d5e9 --- /dev/null +++ b/lib/symfony/debug-bundle/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014-present Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/lib/symfony/debug-bundle/README.md b/lib/symfony/debug-bundle/README.md new file mode 100644 index 000000000..bed2f5b6d --- /dev/null +++ b/lib/symfony/debug-bundle/README.md @@ -0,0 +1,13 @@ +DebugBundle +=========== + +DebugBundle provides a tight integration of the Symfony VarDumper component and +the ServerLogCommand from MonologBridge into the Symfony full-stack framework. + +Resources +--------- + + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/lib/symfony/debug-bundle/Resources/config/schema/debug-1.0.xsd b/lib/symfony/debug-bundle/Resources/config/schema/debug-1.0.xsd new file mode 100644 index 000000000..323068860 --- /dev/null +++ b/lib/symfony/debug-bundle/Resources/config/schema/debug-1.0.xsd @@ -0,0 +1,15 @@ + + + + + + + + + + + + diff --git a/lib/symfony/debug-bundle/Resources/config/services.php b/lib/symfony/debug-bundle/Resources/config/services.php new file mode 100644 index 000000000..ea2d05731 --- /dev/null +++ b/lib/symfony/debug-bundle/Resources/config/services.php @@ -0,0 +1,140 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Monolog\Formatter\FormatterInterface; +use Symfony\Bridge\Monolog\Command\ServerLogCommand; +use Symfony\Bridge\Monolog\Formatter\ConsoleFormatter; +use Symfony\Bridge\Twig\Extension\DumpExtension; +use Symfony\Component\HttpKernel\DataCollector\DumpDataCollector; +use Symfony\Component\HttpKernel\EventListener\DumpListener; +use Symfony\Component\VarDumper\Cloner\VarCloner; +use Symfony\Component\VarDumper\Command\Descriptor\CliDescriptor; +use Symfony\Component\VarDumper\Command\Descriptor\HtmlDescriptor; +use Symfony\Component\VarDumper\Command\ServerDumpCommand; +use Symfony\Component\VarDumper\Dumper\CliDumper; +use Symfony\Component\VarDumper\Dumper\ContextProvider\CliContextProvider; +use Symfony\Component\VarDumper\Dumper\ContextProvider\RequestContextProvider; +use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider; +use Symfony\Component\VarDumper\Dumper\ContextualizedDumper; +use Symfony\Component\VarDumper\Dumper\HtmlDumper; +use Symfony\Component\VarDumper\Server\Connection; +use Symfony\Component\VarDumper\Server\DumpServer; + +return static function (ContainerConfigurator $container) { + $container->parameters() + ->set('env(VAR_DUMPER_SERVER)', '127.0.0.1:9912') + ; + + $container->services() + + ->set('twig.extension.dump', DumpExtension::class) + ->args([ + service('var_dumper.cloner'), + service('var_dumper.html_dumper'), + ]) + ->tag('twig.extension') + + ->set('data_collector.dump', DumpDataCollector::class) + ->public() + ->args([ + service('debug.stopwatch')->ignoreOnInvalid(), + service('debug.file_link_formatter')->ignoreOnInvalid(), + param('kernel.charset'), + service('.virtual_request_stack'), + null, // var_dumper.cli_dumper or var_dumper.server_connection when debug.dump_destination is set + ]) + ->tag('data_collector', [ + 'id' => 'dump', + 'template' => '@Debug/Profiler/dump.html.twig', + 'priority' => 240, + ]) + + ->set('debug.dump_listener', DumpListener::class) + ->args([ + service('var_dumper.cloner'), + service('var_dumper.cli_dumper'), + null, + ]) + ->tag('kernel.event_subscriber') + + ->set('var_dumper.cloner', VarCloner::class) + ->public() + + ->set('var_dumper.cli_dumper', CliDumper::class) + ->args([ + null, // debug.dump_destination, + param('kernel.charset'), + 0, // flags + ]) + + ->set('var_dumper.contextualized_cli_dumper', ContextualizedDumper::class) + ->decorate('var_dumper.cli_dumper') + ->args([ + service('var_dumper.contextualized_cli_dumper.inner'), + [ + 'source' => inline_service(SourceContextProvider::class)->args([ + param('kernel.charset'), + param('kernel.project_dir'), + service('debug.file_link_formatter')->nullOnInvalid(), + ]), + ], + ]) + + ->set('var_dumper.html_dumper', HtmlDumper::class) + ->args([ + null, + param('kernel.charset'), + 0, // flags + ]) + ->call('setDisplayOptions', [ + ['fileLinkFormat' => service('debug.file_link_formatter')->ignoreOnInvalid()], + ]) + + ->set('var_dumper.server_connection', Connection::class) + ->args([ + '', // server host + [ + 'source' => inline_service(SourceContextProvider::class)->args([ + param('kernel.charset'), + param('kernel.project_dir'), + service('debug.file_link_formatter')->nullOnInvalid(), + ]), + 'request' => inline_service(RequestContextProvider::class)->args([service('request_stack')]), + 'cli' => inline_service(CliContextProvider::class), + ], + ]) + + ->set('var_dumper.dump_server', DumpServer::class) + ->args([ + '', // server host + service('logger')->nullOnInvalid(), + ]) + ->tag('monolog.logger', ['channel' => 'debug']) + + ->set('var_dumper.command.server_dump', ServerDumpCommand::class) + ->args([ + service('var_dumper.dump_server'), + [ + 'cli' => inline_service(CliDescriptor::class)->args([service('var_dumper.contextualized_cli_dumper.inner')]), + 'html' => inline_service(HtmlDescriptor::class)->args([service('var_dumper.html_dumper')]), + ], + ]) + ->tag('console.command') + + ->set('monolog.command.server_log', ServerLogCommand::class) + ; + + if (class_exists(ConsoleFormatter::class) && interface_exists(FormatterInterface::class)) { + $container->services()->get('monolog.command.server_log')->tag('console.command'); + } +}; diff --git a/lib/symfony/debug-bundle/Resources/views/Profiler/dump.html.twig b/lib/symfony/debug-bundle/Resources/views/Profiler/dump.html.twig new file mode 100644 index 000000000..e98e52474 --- /dev/null +++ b/lib/symfony/debug-bundle/Resources/views/Profiler/dump.html.twig @@ -0,0 +1,83 @@ +{% extends '@WebProfiler/Profiler/layout.html.twig' %} + +{% block toolbar %} + {% if collector.dumpsCount %} + {% set icon %} + {{ source('@Debug/Profiler/icon.svg') }} + {{ collector.dumpsCount }} + {% endset %} + + {% set text %} + {% for dump in collector.getDumps('html') %} +
+ + {% if dump.label is defined and '' != dump.label %} + {{ dump.label }} in + {% endif %} + {% if dump.file %} + {% set link = dump.file|file_link(dump.line) %} + {% if link %} + {{ dump.name }} + {% else %} + {{ dump.name }} + {% endif %} + {% else %} + {{ dump.name }} + {% endif %} + + line {{ dump.line }} + + {{ dump.data|raw }} +
+ {% endfor %} + {% endset %} + + {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { 'link': true }) }} + {% endif %} +{% endblock %} + +{% block menu %} + + {{ source('@Debug/Profiler/icon.svg') }} + Debug + +{% endblock %} + +{% block panel %} +

Dumped Contents

+ + {% for dump in collector.getDumps('html') %} +
+ + + + + {{ dump.data|raw }} +
+ {% else %} +
+

No content was dumped.

+
+ {% endfor %} +{% endblock %} diff --git a/lib/symfony/debug-bundle/Resources/views/Profiler/icon.svg b/lib/symfony/debug-bundle/Resources/views/Profiler/icon.svg new file mode 100644 index 000000000..9ba3a7d94 --- /dev/null +++ b/lib/symfony/debug-bundle/Resources/views/Profiler/icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/lib/symfony/debug-bundle/composer.json b/lib/symfony/debug-bundle/composer.json new file mode 100644 index 000000000..1d058228f --- /dev/null +++ b/lib/symfony/debug-bundle/composer.json @@ -0,0 +1,41 @@ +{ + "name": "symfony/debug-bundle", + "type": "symfony-bundle", + "description": "Provides a tight integration of the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=8.1", + "ext-xml": "*", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/twig-bridge": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" + }, + "require-dev": { + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/web-profiler-bundle": "^5.4|^6.0|^7.0" + }, + "conflict": { + "symfony/config": "<5.4", + "symfony/dependency-injection": "<5.4" + }, + "autoload": { + "psr-4": { "Symfony\\Bundle\\DebugBundle\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev" +} diff --git a/lib/symfony/runtime/CHANGELOG.md b/lib/symfony/runtime/CHANGELOG.md new file mode 100644 index 000000000..1a608b4cf --- /dev/null +++ b/lib/symfony/runtime/CHANGELOG.md @@ -0,0 +1,19 @@ +CHANGELOG +========= + +6.4 +--- + + * Add argument `bool $debug = false` to `HttpKernelRunner::__construct()` + +5.4 +--- + + * The component is not experimental anymore + * Add options "env_var_name" and "debug_var_name" to `GenericRuntime` and `SymfonyRuntime` + * Add option "dotenv_overload" to `SymfonyRuntime` + +5.3.0 +----- + + * Add the component diff --git a/lib/symfony/runtime/GenericRuntime.php b/lib/symfony/runtime/GenericRuntime.php new file mode 100644 index 000000000..f1b3254ad --- /dev/null +++ b/lib/symfony/runtime/GenericRuntime.php @@ -0,0 +1,223 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime; + +use Symfony\Component\Runtime\Internal\BasicErrorHandler; +use Symfony\Component\Runtime\Resolver\ClosureResolver; +use Symfony\Component\Runtime\Resolver\DebugClosureResolver; +use Symfony\Component\Runtime\Runner\ClosureRunner; + +// Help opcache.preload discover always-needed symbols +class_exists(ClosureResolver::class); + +/** + * A runtime to do bare-metal PHP without using superglobals. + * + * It supports the following options: + * - "debug" toggles displaying errors and defaults + * to the "APP_DEBUG" environment variable; + * - "runtimes" maps types to a GenericRuntime implementation + * that knows how to deal with each of them; + * - "error_handler" defines the class to use to handle PHP errors; + * - "env_var_name" and "debug_var_name" define the name of the env + * vars that hold the Symfony env and the debug flag respectively. + * + * The app-callable can declare arguments among either: + * - "array $context" to get a local array similar to $_SERVER; + * - "array $argv" to get the command line arguments when running on the CLI; + * - "array $request" to get a local array with keys "query", "body", "files" and + * "session", which map to $_GET, $_POST, $FILES and &$_SESSION respectively. + * + * It should return a Closure():int|string|null or an instance of RunnerInterface. + * + * In debug mode, the runtime registers a strict error handler + * that throws exceptions when a PHP warning/notice is raised. + * + * @author Nicolas Grekas + */ +class GenericRuntime implements RuntimeInterface +{ + protected $options; + + /** + * @param array { + * debug?: ?bool, + * runtimes?: ?array, + * error_handler?: string|false, + * env_var_name?: string, + * debug_var_name?: string, + * } $options + */ + public function __construct(array $options = []) + { + $options['env_var_name'] ??= 'APP_ENV'; + $debugKey = $options['debug_var_name'] ??= 'APP_DEBUG'; + + $debug = $options['debug'] ?? $_SERVER[$debugKey] ?? $_ENV[$debugKey] ?? true; + + if (!\is_bool($debug)) { + $debug = filter_var($debug, \FILTER_VALIDATE_BOOL); + } + + if ($debug) { + umask(0000); + $_SERVER[$debugKey] = $_ENV[$debugKey] = '1'; + + if (false !== $errorHandler = ($options['error_handler'] ?? BasicErrorHandler::class)) { + $errorHandler::register($debug); + $options['error_handler'] = false; + } + } else { + $_SERVER[$debugKey] = $_ENV[$debugKey] = '0'; + } + + $this->options = $options; + } + + public function getResolver(callable $callable, \ReflectionFunction $reflector = null): ResolverInterface + { + $callable = $callable(...); + $parameters = ($reflector ?? new \ReflectionFunction($callable))->getParameters(); + $arguments = function () use ($parameters) { + $arguments = []; + + try { + foreach ($parameters as $parameter) { + $type = $parameter->getType(); + $arguments[] = $this->getArgument($parameter, $type instanceof \ReflectionNamedType ? $type->getName() : null); + } + } catch (\InvalidArgumentException $e) { + if (!$parameter->isOptional()) { + throw $e; + } + } + + return $arguments; + }; + + if ($_SERVER[$this->options['debug_var_name']]) { + return new DebugClosureResolver($callable, $arguments); + } + + return new ClosureResolver($callable, $arguments); + } + + public function getRunner(?object $application): RunnerInterface + { + $application ??= static fn () => 0; + + if ($application instanceof RunnerInterface) { + return $application; + } + + if (!$application instanceof \Closure) { + if ($runtime = $this->resolveRuntime($application::class)) { + return $runtime->getRunner($application); + } + + if (!\is_callable($application)) { + throw new \LogicException(sprintf('"%s" doesn\'t know how to handle apps of type "%s".', get_debug_type($this), get_debug_type($application))); + } + + $application = $application(...); + } + + if ($_SERVER[$this->options['debug_var_name']] && ($r = new \ReflectionFunction($application)) && $r->getNumberOfRequiredParameters()) { + throw new \ArgumentCountError(sprintf('Zero argument should be required by the runner callable, but at least one is in "%s" on line "%d.', $r->getFileName(), $r->getStartLine())); + } + + return new ClosureRunner($application); + } + + protected function getArgument(\ReflectionParameter $parameter, ?string $type): mixed + { + if ('array' === $type) { + switch ($parameter->name) { + case 'context': + $context = $_SERVER; + + if ($_ENV && !isset($_SERVER['PATH']) && !isset($_SERVER['Path'])) { + $context += $_ENV; + } + + return $context; + + case 'argv': + return $_SERVER['argv'] ?? []; + + case 'request': + return [ + 'query' => $_GET, + 'body' => $_POST, + 'files' => $_FILES, + 'session' => &$_SESSION, + ]; + } + } + + if (RuntimeInterface::class === $type) { + return $this; + } + + if (!$runtime = $this->getRuntime($type)) { + $r = $parameter->getDeclaringFunction(); + + throw new \InvalidArgumentException(sprintf('Cannot resolve argument "%s $%s" in "%s" on line "%d": "%s" supports only arguments "array $context", "array $argv" and "array $request", or a runtime named "Symfony\Runtime\%1$sRuntime".', $type, $parameter->name, $r->getFileName(), $r->getStartLine(), get_debug_type($this))); + } + + return $runtime->getArgument($parameter, $type); + } + + protected static function register(self $runtime): self + { + return $runtime; + } + + private function getRuntime(string $type): ?self + { + if (null === $runtime = ($this->options['runtimes'][$type] ?? null)) { + $runtime = 'Symfony\Runtime\\'.$type.'Runtime'; + $runtime = class_exists($runtime) ? $runtime : $this->options['runtimes'][$type] = false; + } + + if (\is_string($runtime)) { + $runtime = $runtime::register($this); + } + + if ($this === $runtime) { + return null; + } + + return $runtime ?: null; + } + + private function resolveRuntime(string $class): ?self + { + if ($runtime = $this->getRuntime($class)) { + return $runtime; + } + + foreach (class_parents($class) as $type) { + if ($runtime = $this->getRuntime($type)) { + return $runtime; + } + } + + foreach (class_implements($class) as $type) { + if ($runtime = $this->getRuntime($type)) { + return $runtime; + } + } + + return null; + } +} diff --git a/lib/symfony/runtime/Internal/BasicErrorHandler.php b/lib/symfony/runtime/Internal/BasicErrorHandler.php new file mode 100644 index 000000000..3567c99ea --- /dev/null +++ b/lib/symfony/runtime/Internal/BasicErrorHandler.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime\Internal; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class BasicErrorHandler +{ + public static function register(bool $debug): void + { + error_reporting(-1); + + if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) { + ini_set('display_errors', $debug); + } elseif (!filter_var(\ini_get('log_errors'), \FILTER_VALIDATE_BOOL) || \ini_get('error_log')) { + // CLI - display errors only if they're not already logged to STDERR + ini_set('display_errors', 1); + } + + if (0 <= \ini_get('zend.assertions')) { + ini_set('zend.assertions', 1); + ini_set('assert.active', $debug); + ini_set('assert.exception', 1); + } + + set_error_handler(new self()); + } + + public function __invoke(int $type, string $message, string $file, int $line): bool + { + if ((\E_DEPRECATED | \E_USER_DEPRECATED) & $type) { + return true; + } + + if ((error_reporting() | \E_ERROR | \E_RECOVERABLE_ERROR | \E_PARSE | \E_CORE_ERROR | \E_COMPILE_ERROR | \E_USER_ERROR) & $type) { + throw new \ErrorException($message, 0, $type, $file, $line); + } + + return false; + } +} diff --git a/lib/symfony/runtime/Internal/ComposerPlugin.php b/lib/symfony/runtime/Internal/ComposerPlugin.php new file mode 100644 index 000000000..4f49e2bf2 --- /dev/null +++ b/lib/symfony/runtime/Internal/ComposerPlugin.php @@ -0,0 +1,119 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime\Internal; + +use Composer\Composer; +use Composer\EventDispatcher\EventSubscriberInterface; +use Composer\Factory; +use Composer\IO\IOInterface; +use Composer\Plugin\PluginInterface; +use Composer\Script\ScriptEvents; +use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\Runtime\SymfonyRuntime; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class ComposerPlugin implements PluginInterface, EventSubscriberInterface +{ + private Composer $composer; + private IOInterface $io; + + private static bool $activated = false; + + public function activate(Composer $composer, IOInterface $io): void + { + self::$activated = true; + $this->composer = $composer; + $this->io = $io; + } + + public function deactivate(Composer $composer, IOInterface $io): void + { + self::$activated = false; + } + + public function uninstall(Composer $composer, IOInterface $io): void + { + @unlink($composer->getConfig()->get('vendor-dir').'/autoload_runtime.php'); + } + + public function updateAutoloadFile(): void + { + $vendorDir = realpath($this->composer->getConfig()->get('vendor-dir')); + + if (!is_file($autoloadFile = $vendorDir.'/autoload.php') + || false === $extra = $this->composer->getPackage()->getExtra()['runtime'] ?? [] + ) { + return; + } + + $fs = new Filesystem(); + $projectDir = \dirname(realpath(Factory::getComposerFile())); + + if (null === $autoloadTemplate = $extra['autoload_template'] ?? null) { + $autoloadTemplate = __DIR__.'/autoload_runtime.template'; + } else { + if (!$fs->isAbsolutePath($autoloadTemplate)) { + $autoloadTemplate = $projectDir.'/'.$autoloadTemplate; + } + + if (!is_file($autoloadTemplate)) { + throw new \InvalidArgumentException(sprintf('File "%s" defined under "extra.runtime.autoload_template" in your composer.json file not found.', $this->composer->getPackage()->getExtra()['runtime']['autoload_template'])); + } + } + + $projectDir = $fs->makePathRelative($projectDir, $vendorDir); + $nestingLevel = 0; + + while (str_starts_with($projectDir, '../')) { + ++$nestingLevel; + $projectDir = substr($projectDir, 3); + } + + if (!$nestingLevel) { + $projectDir = '__'.'DIR__.'.var_export('/'.$projectDir, true); + } else { + $projectDir = 'dirname(__'."DIR__, $nestingLevel)".('' !== $projectDir ? '.'.var_export('/'.$projectDir, true) : ''); + } + + $runtimeClass = $extra['class'] ?? SymfonyRuntime::class; + + unset($extra['class'], $extra['autoload_template']); + + $code = strtr(file_get_contents($autoloadTemplate), [ + '%project_dir%' => $projectDir, + '%runtime_class%' => var_export($runtimeClass, true), + '%runtime_options%' => '['.substr(var_export($extra, true), 7, -1)." 'project_dir' => {$projectDir},\n]", + ]); + + // could use Composer\Util\Filesystem::filePutContentsIfModified once Composer 1.x support is dropped for this plugin + $path = substr_replace($autoloadFile, '_runtime', -4, 0); + $currentContent = @file_exists($path) ? @file_get_contents($path) : false; + if (false === $currentContent || $currentContent !== $code) { + file_put_contents($path, $code); + } + } + + public static function getSubscribedEvents(): array + { + if (!self::$activated) { + return []; + } + + return [ + ScriptEvents::POST_AUTOLOAD_DUMP => 'updateAutoloadFile', + ]; + } +} diff --git a/lib/symfony/runtime/Internal/Console/ApplicationRuntime.php b/lib/symfony/runtime/Internal/Console/ApplicationRuntime.php new file mode 100644 index 000000000..de6b1d974 --- /dev/null +++ b/lib/symfony/runtime/Internal/Console/ApplicationRuntime.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Runtime\Symfony\Component\Console; + +use Symfony\Component\Runtime\SymfonyRuntime; + +/** + * @internal + */ +class ApplicationRuntime extends SymfonyRuntime +{ +} diff --git a/lib/symfony/runtime/Internal/Console/Command/CommandRuntime.php b/lib/symfony/runtime/Internal/Console/Command/CommandRuntime.php new file mode 100644 index 000000000..9cc198ea1 --- /dev/null +++ b/lib/symfony/runtime/Internal/Console/Command/CommandRuntime.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Runtime\Symfony\Component\Console\Command; + +use Symfony\Component\Runtime\SymfonyRuntime; + +/** + * @internal + */ +class CommandRuntime extends SymfonyRuntime +{ +} diff --git a/lib/symfony/runtime/Internal/Console/Input/InputInterfaceRuntime.php b/lib/symfony/runtime/Internal/Console/Input/InputInterfaceRuntime.php new file mode 100644 index 000000000..44360bf50 --- /dev/null +++ b/lib/symfony/runtime/Internal/Console/Input/InputInterfaceRuntime.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Runtime\Symfony\Component\Console\Input; + +use Symfony\Component\Runtime\SymfonyRuntime; + +/** + * @internal + */ +class InputInterfaceRuntime extends SymfonyRuntime +{ +} diff --git a/lib/symfony/runtime/Internal/Console/Output/OutputInterfaceRuntime.php b/lib/symfony/runtime/Internal/Console/Output/OutputInterfaceRuntime.php new file mode 100644 index 000000000..7c59186ad --- /dev/null +++ b/lib/symfony/runtime/Internal/Console/Output/OutputInterfaceRuntime.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Runtime\Symfony\Component\Console\Output; + +use Symfony\Component\Runtime\SymfonyRuntime; + +/** + * @internal + */ +class OutputInterfaceRuntime extends SymfonyRuntime +{ +} diff --git a/lib/symfony/runtime/Internal/HttpFoundation/RequestRuntime.php b/lib/symfony/runtime/Internal/HttpFoundation/RequestRuntime.php new file mode 100644 index 000000000..2a3a0bb82 --- /dev/null +++ b/lib/symfony/runtime/Internal/HttpFoundation/RequestRuntime.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Runtime\Symfony\Component\HttpFoundation; + +use Symfony\Component\Runtime\SymfonyRuntime; + +/** + * @internal + */ +class RequestRuntime extends SymfonyRuntime +{ +} diff --git a/lib/symfony/runtime/Internal/HttpFoundation/ResponseRuntime.php b/lib/symfony/runtime/Internal/HttpFoundation/ResponseRuntime.php new file mode 100644 index 000000000..c70fbfff5 --- /dev/null +++ b/lib/symfony/runtime/Internal/HttpFoundation/ResponseRuntime.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Runtime\Symfony\Component\HttpFoundation; + +use Symfony\Component\Runtime\SymfonyRuntime; + +/** + * @internal + */ +class ResponseRuntime extends SymfonyRuntime +{ +} diff --git a/lib/symfony/runtime/Internal/HttpKernel/HttpKernelInterfaceRuntime.php b/lib/symfony/runtime/Internal/HttpKernel/HttpKernelInterfaceRuntime.php new file mode 100644 index 000000000..08601abff --- /dev/null +++ b/lib/symfony/runtime/Internal/HttpKernel/HttpKernelInterfaceRuntime.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Runtime\Symfony\Component\HttpKernel; + +use Symfony\Component\Runtime\SymfonyRuntime; + +/** + * @internal + */ +class HttpKernelInterfaceRuntime extends SymfonyRuntime +{ +} diff --git a/lib/symfony/runtime/Internal/MissingDotenv.php b/lib/symfony/runtime/Internal/MissingDotenv.php new file mode 100644 index 000000000..896865653 --- /dev/null +++ b/lib/symfony/runtime/Internal/MissingDotenv.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime\Internal; + +/** + * @internal class that should be loaded only when symfony/dotenv is not installed + */ +class MissingDotenv +{ +} diff --git a/lib/symfony/runtime/Internal/SymfonyErrorHandler.php b/lib/symfony/runtime/Internal/SymfonyErrorHandler.php new file mode 100644 index 000000000..40c125a91 --- /dev/null +++ b/lib/symfony/runtime/Internal/SymfonyErrorHandler.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime\Internal; + +use Symfony\Component\ErrorHandler\BufferingLogger; +use Symfony\Component\ErrorHandler\DebugClassLoader; +use Symfony\Component\ErrorHandler\ErrorHandler; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class SymfonyErrorHandler +{ + public static function register(bool $debug): void + { + BasicErrorHandler::register($debug); + + if (class_exists(ErrorHandler::class)) { + DebugClassLoader::enable(); + restore_error_handler(); + ErrorHandler::register(new ErrorHandler(new BufferingLogger(), $debug)); + } + } +} diff --git a/lib/symfony/runtime/Internal/autoload_runtime.template b/lib/symfony/runtime/Internal/autoload_runtime.template new file mode 100644 index 000000000..68af94593 --- /dev/null +++ b/lib/symfony/runtime/Internal/autoload_runtime.template @@ -0,0 +1,28 @@ +getResolver($app) + ->resolve(); + +$app = $app(...$args); + +exit( + $runtime + ->getRunner($app) + ->run() +); diff --git a/lib/symfony/runtime/LICENSE b/lib/symfony/runtime/LICENSE new file mode 100644 index 000000000..99c6bdf35 --- /dev/null +++ b/lib/symfony/runtime/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2021-present Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/lib/symfony/runtime/README.md b/lib/symfony/runtime/README.md new file mode 100644 index 000000000..006e7a22c --- /dev/null +++ b/lib/symfony/runtime/README.md @@ -0,0 +1,13 @@ +Runtime Component +================= + +Symfony Runtime enables decoupling applications from global state. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/runtime.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/lib/symfony/runtime/Resolver/ClosureResolver.php b/lib/symfony/runtime/Resolver/ClosureResolver.php new file mode 100644 index 000000000..c58cf2fbf --- /dev/null +++ b/lib/symfony/runtime/Resolver/ClosureResolver.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime\Resolver; + +use Symfony\Component\Runtime\ResolverInterface; + +/** + * @author Nicolas Grekas + */ +class ClosureResolver implements ResolverInterface +{ + public function __construct( + private readonly \Closure $closure, + private readonly \Closure $arguments, + ) { + } + + public function resolve(): array + { + return [$this->closure, ($this->arguments)()]; + } +} diff --git a/lib/symfony/runtime/Resolver/DebugClosureResolver.php b/lib/symfony/runtime/Resolver/DebugClosureResolver.php new file mode 100644 index 000000000..923ae905b --- /dev/null +++ b/lib/symfony/runtime/Resolver/DebugClosureResolver.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime\Resolver; + +/** + * @author Nicolas Grekas + */ +class DebugClosureResolver extends ClosureResolver +{ + public function resolve(): array + { + [$closure, $arguments] = parent::resolve(); + + return [ + static function (...$arguments) use ($closure) { + if (\is_object($app = $closure(...$arguments)) || null === $app) { + return $app; + } + + $r = new \ReflectionFunction($closure); + + throw new \TypeError(sprintf('Unexpected value of type "%s" returned, "object" expected from "%s" on line "%d".', get_debug_type($app), $r->getFileName(), $r->getStartLine())); + }, + $arguments, + ]; + } +} diff --git a/lib/symfony/runtime/ResolverInterface.php b/lib/symfony/runtime/ResolverInterface.php new file mode 100644 index 000000000..f6fa5980e --- /dev/null +++ b/lib/symfony/runtime/ResolverInterface.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime; + +/** + * @author Nicolas Grekas + */ +interface ResolverInterface +{ + /** + * @return array{0: callable, 1: mixed[]} + */ + public function resolve(): array; +} diff --git a/lib/symfony/runtime/Runner/ClosureRunner.php b/lib/symfony/runtime/Runner/ClosureRunner.php new file mode 100644 index 000000000..4b12ff1e3 --- /dev/null +++ b/lib/symfony/runtime/Runner/ClosureRunner.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime\Runner; + +use Symfony\Component\Runtime\RunnerInterface; + +/** + * @author Nicolas Grekas + */ +class ClosureRunner implements RunnerInterface +{ + public function __construct( + private readonly \Closure $closure, + ) { + } + + public function run(): int + { + $exitStatus = ($this->closure)(); + + if (\is_string($exitStatus)) { + echo $exitStatus; + + return 0; + } + + if (null !== $exitStatus && !\is_int($exitStatus)) { + $r = new \ReflectionFunction($this->closure); + + throw new \TypeError(sprintf('Unexpected value of type "%s" returned, "string|int|null" expected from "%s" on line "%d".', get_debug_type($exitStatus), $r->getFileName(), $r->getStartLine())); + } + + return $exitStatus ?? 0; + } +} diff --git a/lib/symfony/runtime/Runner/Symfony/ConsoleApplicationRunner.php b/lib/symfony/runtime/Runner/Symfony/ConsoleApplicationRunner.php new file mode 100644 index 000000000..d64bc1c77 --- /dev/null +++ b/lib/symfony/runtime/Runner/Symfony/ConsoleApplicationRunner.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime\Runner\Symfony; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Runtime\RunnerInterface; + +/** + * @author Nicolas Grekas + */ +class ConsoleApplicationRunner implements RunnerInterface +{ + public function __construct( + private readonly Application $application, + private readonly ?string $defaultEnv, + private readonly InputInterface $input, + private readonly ?OutputInterface $output = null, + ) { + } + + public function run(): int + { + if (null === $this->defaultEnv) { + return $this->application->run($this->input, $this->output); + } + + $definition = $this->application->getDefinition(); + + if (!$definition->hasOption('env') && !$definition->hasOption('e') && !$definition->hasShortcut('e')) { + $definition->addOption(new InputOption('--env', '-e', InputOption::VALUE_REQUIRED, 'The Environment name.', $this->defaultEnv)); + } + + if (!$definition->hasOption('no-debug')) { + $definition->addOption(new InputOption('--no-debug', null, InputOption::VALUE_NONE, 'Switches off debug mode.')); + } + + return $this->application->run($this->input, $this->output); + } +} diff --git a/lib/symfony/runtime/Runner/Symfony/HttpKernelRunner.php b/lib/symfony/runtime/Runner/Symfony/HttpKernelRunner.php new file mode 100644 index 000000000..13c9037ca --- /dev/null +++ b/lib/symfony/runtime/Runner/Symfony/HttpKernelRunner.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime\Runner\Symfony; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\HttpKernel\TerminableInterface; +use Symfony\Component\Runtime\RunnerInterface; + +/** + * @author Nicolas Grekas + */ +class HttpKernelRunner implements RunnerInterface +{ + public function __construct( + private readonly HttpKernelInterface $kernel, + private readonly Request $request, + private readonly bool $debug = false, + ) { + } + + public function run(): int + { + $response = $this->kernel->handle($this->request); + + if (Kernel::VERSION_ID >= 60400) { + $response->send(false); + + if (\function_exists('fastcgi_finish_request') && !$this->debug) { + fastcgi_finish_request(); + } elseif (\function_exists('litespeed_finish_request') && !$this->debug) { + litespeed_finish_request(); + } else { + Response::closeOutputBuffers(0, true); + flush(); + } + } else { + $response->send(); + } + + if ($this->kernel instanceof TerminableInterface) { + $this->kernel->terminate($this->request, $response); + } + + return 0; + } +} diff --git a/lib/symfony/runtime/Runner/Symfony/ResponseRunner.php b/lib/symfony/runtime/Runner/Symfony/ResponseRunner.php new file mode 100644 index 000000000..04e5a3fa1 --- /dev/null +++ b/lib/symfony/runtime/Runner/Symfony/ResponseRunner.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime\Runner\Symfony; + +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Runtime\RunnerInterface; + +/** + * @author Nicolas Grekas + */ +class ResponseRunner implements RunnerInterface +{ + public function __construct( + private readonly Response $response, + ) { + } + + public function run(): int + { + $this->response->send(); + + return 0; + } +} diff --git a/lib/symfony/runtime/RunnerInterface.php b/lib/symfony/runtime/RunnerInterface.php new file mode 100644 index 000000000..9001ff435 --- /dev/null +++ b/lib/symfony/runtime/RunnerInterface.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime; + +/** + * @author Nicolas Grekas + */ +interface RunnerInterface +{ + public function run(): int; +} diff --git a/lib/symfony/runtime/RuntimeInterface.php b/lib/symfony/runtime/RuntimeInterface.php new file mode 100644 index 000000000..757468c74 --- /dev/null +++ b/lib/symfony/runtime/RuntimeInterface.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime; + +/** + * Enables decoupling applications from global state. + * + * @author Nicolas Grekas + */ +interface RuntimeInterface +{ + /** + * Returns a resolver that should compute the arguments of a callable. + * + * The callable itself should return an object that represents the application to pass to the getRunner() method. + */ + public function getResolver(callable $callable, \ReflectionFunction $reflector = null): ResolverInterface; + + /** + * Returns a callable that knows how to run the passed object and that returns its exit status as int. + * + * The passed object is typically created by calling ResolverInterface::resolve(). + */ + public function getRunner(?object $application): RunnerInterface; +} diff --git a/lib/symfony/runtime/SymfonyRuntime.php b/lib/symfony/runtime/SymfonyRuntime.php new file mode 100644 index 000000000..e88e1e089 --- /dev/null +++ b/lib/symfony/runtime/SymfonyRuntime.php @@ -0,0 +1,226 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\ArgvInput; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\ConsoleOutput; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Dotenv\Dotenv; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\Runtime\Internal\MissingDotenv; +use Symfony\Component\Runtime\Internal\SymfonyErrorHandler; +use Symfony\Component\Runtime\Runner\Symfony\ConsoleApplicationRunner; +use Symfony\Component\Runtime\Runner\Symfony\HttpKernelRunner; +use Symfony\Component\Runtime\Runner\Symfony\ResponseRunner; + +// Help opcache.preload discover always-needed symbols +class_exists(MissingDotenv::class, false) || class_exists(Dotenv::class) || class_exists(MissingDotenv::class); + +/** + * Knows the basic conventions to run Symfony apps. + * + * In addition to the options managed by GenericRuntime, it accepts the following options: + * - "env" to define the name of the environment the app runs in; + * - "disable_dotenv" to disable looking for .env files; + * - "dotenv_path" to define the path of dot-env files - defaults to ".env"; + * - "prod_envs" to define the names of the production envs - defaults to ["prod"]; + * - "test_envs" to define the names of the test envs - defaults to ["test"]; + * - "use_putenv" to tell Dotenv to set env vars using putenv() (NOT RECOMMENDED.) + * - "dotenv_overload" to tell Dotenv to override existing vars + * + * When the "debug" / "env" options are not defined, they will fallback to the + * "APP_DEBUG" / "APP_ENV" environment variables, and to the "--env|-e" / "--no-debug" + * command line arguments if "symfony/console" is installed. + * + * When the "symfony/dotenv" component is installed, .env files are loaded. + * When "symfony/error-handler" is installed, it is registered in debug mode. + * + * On top of the base arguments provided by GenericRuntime, + * this runtime can feed the app-callable with arguments of type: + * - Request from "symfony/http-foundation" if the component is installed; + * - Application, Command, InputInterface and/or OutputInterface + * from "symfony/console" if the component is installed. + * + * This runtime can handle app-callables that return instances of either: + * - HttpKernelInterface, + * - Response, + * - Application, + * - Command, + * - int|string|null as handled by GenericRuntime. + * + * @author Nicolas Grekas + */ +class SymfonyRuntime extends GenericRuntime +{ + private readonly ArgvInput $input; + private readonly ConsoleOutput $output; + private readonly Application $console; + private readonly Command $command; + + /** + * @param array { + * debug?: ?bool, + * env?: ?string, + * disable_dotenv?: ?bool, + * project_dir?: ?string, + * prod_envs?: ?string[], + * dotenv_path?: ?string, + * test_envs?: ?string[], + * use_putenv?: ?bool, + * runtimes?: ?array, + * error_handler?: string|false, + * env_var_name?: string, + * debug_var_name?: string, + * dotenv_overload?: ?bool, + * } $options + */ + public function __construct(array $options = []) + { + $envKey = $options['env_var_name'] ??= 'APP_ENV'; + $debugKey = $options['debug_var_name'] ??= 'APP_DEBUG'; + + if (isset($options['env'])) { + $_SERVER[$envKey] = $options['env']; + } elseif (isset($_SERVER['argv']) && class_exists(ArgvInput::class)) { + $this->options = $options; + $this->getInput(); + } + + if (!($options['disable_dotenv'] ?? false) && isset($options['project_dir']) && !class_exists(MissingDotenv::class, false)) { + (new Dotenv($envKey, $debugKey)) + ->setProdEnvs((array) ($options['prod_envs'] ?? ['prod'])) + ->usePutenv($options['use_putenv'] ?? false) + ->bootEnv($options['project_dir'].'/'.($options['dotenv_path'] ?? '.env'), 'dev', (array) ($options['test_envs'] ?? ['test']), $options['dotenv_overload'] ?? false); + + if (isset($this->input) && ($options['dotenv_overload'] ?? false)) { + if ($this->input->getParameterOption(['--env', '-e'], $_SERVER[$envKey], true) !== $_SERVER[$envKey]) { + throw new \LogicException(sprintf('Cannot use "--env" or "-e" when the "%s" file defines "%s" and the "dotenv_overload" runtime option is true.', $options['dotenv_path'] ?? '.env', $envKey)); + } + + if ($_SERVER[$debugKey] && $this->input->hasParameterOption('--no-debug', true)) { + putenv($debugKey.'='.$_SERVER[$debugKey] = $_ENV[$debugKey] = '0'); + } + } + + $options['debug'] ??= '1' === $_SERVER[$debugKey]; + $options['disable_dotenv'] = true; + } else { + $_SERVER[$envKey] ??= $_ENV[$envKey] ?? 'dev'; + $_SERVER[$debugKey] ??= $_ENV[$debugKey] ?? !\in_array($_SERVER[$envKey], (array) ($options['prod_envs'] ?? ['prod']), true); + } + + $options['error_handler'] ??= SymfonyErrorHandler::class; + + parent::__construct($options); + } + + public function getRunner(?object $application): RunnerInterface + { + if ($application instanceof HttpKernelInterface) { + return new HttpKernelRunner($application, Request::createFromGlobals(), $this->options['debug'] ?? false); + } + + if ($application instanceof Response) { + return new ResponseRunner($application); + } + + if ($application instanceof Command) { + $console = $this->console ??= new Application(); + $console->setName($application->getName() ?: $console->getName()); + + if (!$application->getName() || !$console->has($application->getName())) { + $application->setName($_SERVER['argv'][0]); + $console->add($application); + } + + $console->setDefaultCommand($application->getName(), true); + $console->getDefinition()->addOptions($application->getDefinition()->getOptions()); + + return $this->getRunner($console); + } + + if ($application instanceof Application) { + if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) { + echo 'Warning: The console should be invoked via the CLI version of PHP, not the '.\PHP_SAPI.' SAPI'.\PHP_EOL; + } + + set_time_limit(0); + $defaultEnv = !isset($this->options['env']) ? ($_SERVER[$this->options['env_var_name']] ?? 'dev') : null; + $output = $this->output ??= new ConsoleOutput(); + + return new ConsoleApplicationRunner($application, $defaultEnv, $this->getInput(), $output); + } + + if (isset($this->command)) { + $this->getInput()->bind($this->command->getDefinition()); + } + + return parent::getRunner($application); + } + + protected function getArgument(\ReflectionParameter $parameter, ?string $type): mixed + { + return match ($type) { + Request::class => Request::createFromGlobals(), + InputInterface::class => $this->getInput(), + OutputInterface::class => $this->output ??= new ConsoleOutput(), + Application::class => $this->console ??= new Application(), + Command::class => $this->command ??= new Command(), + default => parent::getArgument($parameter, $type), + }; + } + + protected static function register(GenericRuntime $runtime): GenericRuntime + { + $self = new self($runtime->options + ['runtimes' => []]); + $self->options['runtimes'] += [ + HttpKernelInterface::class => $self, + Request::class => $self, + Response::class => $self, + Application::class => $self, + Command::class => $self, + InputInterface::class => $self, + OutputInterface::class => $self, + ]; + $runtime->options = $self->options; + + return $self; + } + + private function getInput(): ArgvInput + { + if (isset($this->input)) { + return $this->input; + } + + $input = new ArgvInput(); + + if (isset($this->options['env'])) { + return $this->input = $input; + } + + if (null !== $env = $input->getParameterOption(['--env', '-e'], null, true)) { + putenv($this->options['env_var_name'].'='.$_SERVER[$this->options['env_var_name']] = $_ENV[$this->options['env_var_name']] = $env); + } + + if ($input->hasParameterOption('--no-debug', true)) { + putenv($this->options['debug_var_name'].'='.$_SERVER[$this->options['debug_var_name']] = $_ENV[$this->options['debug_var_name']] = '0'); + } + + return $this->input = $input; + } +} diff --git a/lib/symfony/runtime/composer.json b/lib/symfony/runtime/composer.json new file mode 100644 index 000000000..4241bae48 --- /dev/null +++ b/lib/symfony/runtime/composer.json @@ -0,0 +1,45 @@ +{ + "name": "symfony/runtime", + "type": "composer-plugin", + "description": "Enables decoupling PHP applications from global state", + "keywords": ["runtime"], + "homepage": "https://symfony.com", + "license" : "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=8.1", + "composer-plugin-api": "^1.0|^2.0" + }, + "require-dev": { + "composer/composer": "^1.0.2|^2.0", + "symfony/console": "^5.4.9|^6.0.9|^7.0", + "symfony/dotenv": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0" + }, + "conflict": { + "symfony/dotenv": "<5.4" + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Runtime\\": "", + "Symfony\\Runtime\\Symfony\\Component\\": "Internal/" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "class": "Symfony\\Component\\Runtime\\Internal\\ComposerPlugin" + } +} diff --git a/sources/Controller/AbstractAppController.php b/sources/Controller/AbstractAppController.php new file mode 100644 index 000000000..42da16f75 --- /dev/null +++ b/sources/Controller/AbstractAppController.php @@ -0,0 +1,32 @@ +getProjectDir() . '/symfony/config'; + } + + public function getCacheDir(): string + { + $sEnv = Session::Get('itop_env', 'production'); + return $this->getProjectDir() . "/data/cache-$sEnv/symfony"; + } + + public function getLogDir(): string + { + return $this->getProjectDir() . 'log/symfony'; + } +} diff --git a/sources/Service/SummaryCard/SummaryCardService.php b/sources/Service/SummaryCard/SummaryCardService.php index bf507df09..c5d49bab4 100644 --- a/sources/Service/SummaryCard/SummaryCardService.php +++ b/sources/Service/SummaryCard/SummaryCardService.php @@ -4,7 +4,8 @@ * @license http://opensource.org/licenses/AGPL-3.0 */ -use Combodo\iTop\Controller\AbstractController; +namespace Combodo\iTop\Service\SummaryCard; + use Combodo\iTop\Core\MetaModel\FriendlyNameType; use Combodo\iTop\Service\Router\Router; diff --git a/symfony/.env b/symfony/.env new file mode 100644 index 000000000..c4cb030ca --- /dev/null +++ b/symfony/.env @@ -0,0 +1,20 @@ +# In all environments, the following files are loaded if they exist, +# the latter taking precedence over the former: +# +# * .env contains default values for the environment variables needed by the app +# * .env.local uncommitted file with local overrides +# * .env.$APP_ENV committed environment-specific defaults +# * .env.$APP_ENV.local uncommitted environment-specific overrides +# +# Real environment variables win over .env files. +# +# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES. +# https://symfony.com/doc/current/configuration/secrets.html +# +# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2). +# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration + +###> symfony/framework-bundle ### +#APP_ENV=dev +#APP_SECRET=extracted from iTop general configuration in ./symfony/packages/itop_configuration_bridge.php +###< symfony/framework-bundle ### diff --git a/symfony/config/bundles.php b/symfony/config/bundles.php new file mode 100644 index 000000000..e60880154 --- /dev/null +++ b/symfony/config/bundles.php @@ -0,0 +1,8 @@ + ['all' => true], + Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], + Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], + Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true], +]; diff --git a/symfony/config/packages/cache.yaml b/symfony/config/packages/cache.yaml new file mode 100644 index 000000000..6899b7200 --- /dev/null +++ b/symfony/config/packages/cache.yaml @@ -0,0 +1,19 @@ +framework: + cache: + # Unique name of your app: used to compute stable namespaces for cache keys. + #prefix_seed: your_vendor_name/app_name + + # The "app" cache stores to the filesystem by default. + # The data in this cache should persist between deploys. + # Other options include: + + # Redis + #app: cache.adapter.redis + #default_redis_provider: redis://localhost + + # APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues) + #app: cache.adapter.apcu + + # Namespaced pools use the above "app" backend by default + #pools: + #my.dedicated.cache: null diff --git a/symfony/config/packages/debug.yaml b/symfony/config/packages/debug.yaml new file mode 100644 index 000000000..ad874afdd --- /dev/null +++ b/symfony/config/packages/debug.yaml @@ -0,0 +1,5 @@ +when@dev: + debug: + # Forwards VarDumper Data clones to a centralized server allowing to inspect dumps on CLI or in your browser. + # See the "server:dump" command to start a new server. + dump_destination: "tcp://%env(VAR_DUMPER_SERVER)%" diff --git a/symfony/config/packages/framework.yaml b/symfony/config/packages/framework.yaml new file mode 100644 index 000000000..cf3c0d694 --- /dev/null +++ b/symfony/config/packages/framework.yaml @@ -0,0 +1,25 @@ +# see https://symfony.com/doc/current/reference/configuration/framework.html +framework: + #secret: '%env(APP_SECRET)%' will be set by itop general configuration bridge + #csrf_protection: true + annotations: false + http_method_override: false + handle_all_throwables: true + + # Enables session support. Note that the session will ONLY be started if you read or write from it. + # Remove or comment this section to explicitly disable session support. + session: + handler_id: null + cookie_secure: auto + cookie_samesite: lax + + #esi: true + #fragments: true + php_errors: + log: true + +when@test: + framework: + test: true + session: + storage_factory_id: session.storage.factory.mock_file diff --git a/symfony/config/packages/itop_configuration_bridge.php b/symfony/config/packages/itop_configuration_bridge.php new file mode 100644 index 000000000..a76c6830f --- /dev/null +++ b/symfony/config/packages/itop_configuration_bridge.php @@ -0,0 +1,32 @@ +parameters()->set('kernel.secret', $oConfig->Get('application.secret')); + +}; \ No newline at end of file diff --git a/symfony/config/packages/routing.yaml b/symfony/config/packages/routing.yaml new file mode 100644 index 000000000..4b766ce57 --- /dev/null +++ b/symfony/config/packages/routing.yaml @@ -0,0 +1,12 @@ +framework: + router: + utf8: true + + # Configure how to generate URLs in non-HTTP contexts, such as CLI commands. + # See https://symfony.com/doc/current/routing.html#generating-urls-in-commands + #default_uri: http://localhost + +when@prod: + framework: + router: + strict_requirements: null diff --git a/symfony/config/packages/twig.yaml b/symfony/config/packages/twig.yaml new file mode 100644 index 000000000..f9f4cc539 --- /dev/null +++ b/symfony/config/packages/twig.yaml @@ -0,0 +1,6 @@ +twig: + default_path: '%kernel.project_dir%/templates' + +when@test: + twig: + strict_variables: true diff --git a/symfony/config/packages/web_profiler.yaml b/symfony/config/packages/web_profiler.yaml new file mode 100644 index 000000000..b94611102 --- /dev/null +++ b/symfony/config/packages/web_profiler.yaml @@ -0,0 +1,17 @@ +when@dev: + web_profiler: + toolbar: true + intercept_redirects: false + + framework: + profiler: + only_exceptions: false + collect_serializer_data: true + +when@test: + web_profiler: + toolbar: false + intercept_redirects: false + + framework: + profiler: { collect: false } diff --git a/symfony/config/preload.php b/symfony/config/preload.php new file mode 100644 index 000000000..5ebcdb215 --- /dev/null +++ b/symfony/config/preload.php @@ -0,0 +1,5 @@ +