Skip to content

Commit 2698571

Browse files
[Runtime] make GenericRuntime ... generic
1 parent 49d23d4 commit 2698571

File tree

12 files changed

+244
-29
lines changed

12 files changed

+244
-29
lines changed

src/Symfony/Bundle/FrameworkBundle/Resources/config/services.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
use Symfony\Component\HttpKernel\KernelEvents;
3939
use Symfony\Component\HttpKernel\KernelInterface;
4040
use Symfony\Component\HttpKernel\UriSigner;
41+
use Symfony\Component\Runtime\Runner\Symfony\HttpKernelRunner;
42+
use Symfony\Component\Runtime\Runner\Symfony\ResponseRunner;
4143
use Symfony\Component\Runtime\SymfonyRuntime;
4244
use Symfony\Component\String\LazyString;
4345
use Symfony\Component\String\Slugger\AsciiSlugger;
@@ -79,6 +81,8 @@ class_exists(WorkflowEvents::class) ? WorkflowEvents::ALIASES : []
7981
service('argument_resolver'),
8082
])
8183
->tag('container.hot_path')
84+
->tag('container.preload', ['class' => HttpKernelRunner::class])
85+
->tag('container.preload', ['class' => ResponseRunner::class])
8286
->tag('container.preload', ['class' => SymfonyRuntime::class])
8387
->alias(HttpKernelInterface::class, 'http_kernel')
8488

src/Symfony/Component/Runtime/GenericRuntime.php

Lines changed: 64 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@ class_exists(ClosureResolver::class);
2222
/**
2323
* A runtime to do bare-metal PHP without using superglobals.
2424
*
25-
* One option named "debug" is supported; it toggles displaying errors
26-
* and defaults to the "APP_ENV" environment variable.
25+
* It supports two options:
26+
* - "debug" toggles displaying errors and defaults
27+
* to the "APP_ENV" environment variable
28+
* - "runtimes" maps types to a GenericRuntime implementation
29+
* that knows how to deal with each of them
2730
*
2831
* The app-callable can declare arguments among either:
2932
* - "array $context" to get a local array similar to $_SERVER;
@@ -42,28 +45,31 @@ class_exists(ClosureResolver::class);
4245
*/
4346
class GenericRuntime implements RuntimeInterface
4447
{
45-
private $debug;
48+
protected $options;
4649

4750
/**
4851
* @param array {
4952
* debug?: ?bool,
53+
* runtimes?: ?array
5054
* } $options
5155
*/
5256
public function __construct(array $options = [])
5357
{
54-
$this->debug = $options['debug'] ?? $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? true;
58+
$debug = $options['debug'] ?? $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? true;
5559

56-
if (!\is_bool($this->debug)) {
57-
$this->debug = filter_var($this->debug, \FILTER_VALIDATE_BOOLEAN);
60+
if (!\is_bool($debug)) {
61+
$debug = filter_var($debug, \FILTER_VALIDATE_BOOLEAN);
5862
}
5963

60-
if ($this->debug) {
64+
if ($debug) {
65+
umask(0000);
6166
$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '1';
62-
$errorHandler = new BasicErrorHandler($this->debug);
63-
set_error_handler($errorHandler);
67+
set_error_handler(new BasicErrorHandler($debug));
6468
} else {
6569
$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0';
6670
}
71+
72+
$this->options = $options;
6773
}
6874

6975
/**
@@ -95,7 +101,7 @@ public function getResolver(callable $callable): ResolverInterface
95101
return $arguments;
96102
};
97103

98-
if ($this->debug) {
104+
if ($_SERVER['APP_DEBUG']) {
99105
return new DebugClosureResolver($callable, $arguments);
100106
}
101107

@@ -115,15 +121,33 @@ public function getRunner(?object $application): RunnerInterface
115121
return $application;
116122
}
117123

118-
if (!\is_callable($application)) {
119-
throw new \LogicException(sprintf('"%s" doesn\'t know how to handle apps of type "%s".', get_debug_type($this), get_debug_type($application)));
120-
}
121-
122124
if (!$application instanceof \Closure) {
125+
$class = \get_class($application);
126+
127+
if ($runtime = $this->getRuntime($class)) {
128+
return $runtime->getRunner($application);
129+
}
130+
131+
foreach (class_parents($class) as $type) {
132+
if ($runtime = $this->getRuntime($type)) {
133+
return $runtime->getRunner($application);
134+
}
135+
}
136+
137+
foreach (class_implements($class) as $type) {
138+
if ($runtime = $this->getRuntime($type)) {
139+
return $runtime->getRunner($application);
140+
}
141+
}
142+
143+
if (!\is_callable($application)) {
144+
throw new \LogicException(sprintf('"%s" doesn\'t know how to handle apps of type "%s".', get_debug_type($this), get_debug_type($application)));
145+
}
146+
123147
$application = \Closure::fromCallable($application);
124148
}
125149

126-
if ($this->debug && ($r = new \ReflectionFunction($application)) && $r->getNumberOfRequiredParameters()) {
150+
if ($_SERVER['APP_DEBUG'] && ($r = new \ReflectionFunction($application)) && $r->getNumberOfRequiredParameters()) {
127151
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()));
128152
}
129153

@@ -163,8 +187,31 @@ protected function getArgument(\ReflectionParameter $parameter, ?string $type)
163187
return $this;
164188
}
165189

166-
$r = $parameter->getDeclaringFunction();
190+
if (!$runtime = $this->getRuntime($type)) {
191+
$r = $parameter->getDeclaringFunction();
192+
193+
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)));
194+
}
195+
196+
return $runtime->getArgument($parameter, $type);
197+
}
198+
199+
protected static function register(self $runtime): self
200+
{
201+
return $runtime;
202+
}
203+
204+
private function getRuntime(string $type): ?self
205+
{
206+
if (null === $runtime = ($this->options['runtimes'][$type] ?? null)) {
207+
$runtime = 'Symfony\Runtime\\'.$type.'Runtime';
208+
$runtime = class_exists($runtime) ? $runtime : $this->options['runtimes'][$type] = false;
209+
}
210+
211+
if (\is_string($runtime)) {
212+
$runtime = $runtime::register($this);
213+
}
167214

168-
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".', $type, $parameter->name, $r->getFileName(), $r->getStartLine(), get_debug_type($this)));
215+
return $runtime ?: null;
169216
}
170217
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Runtime\Symfony\Component\Console;
13+
14+
use Symfony\Component\Runtime\SymfonyRuntime;
15+
16+
/**
17+
* @internal
18+
*/
19+
class ApplicationRuntime extends SymfonyRuntime
20+
{
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Runtime\Symfony\Component\Console\Command;
13+
14+
use Symfony\Component\Runtime\SymfonyRuntime;
15+
16+
/**
17+
* @internal
18+
*/
19+
class CommandRuntime extends SymfonyRuntime
20+
{
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Runtime\Symfony\Component\Console\Input;
13+
14+
use Symfony\Component\Runtime\SymfonyRuntime;
15+
16+
/**
17+
* @internal
18+
*/
19+
class InputInterfaceRuntime extends SymfonyRuntime
20+
{
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Runtime\Symfony\Component\Console\Output;
13+
14+
use Symfony\Component\Runtime\SymfonyRuntime;
15+
16+
/**
17+
* @internal
18+
*/
19+
class OutputInterfaceRuntime extends SymfonyRuntime
20+
{
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Runtime\Symfony\Component\HttpFoundation;
13+
14+
use Symfony\Component\Runtime\SymfonyRuntime;
15+
16+
/**
17+
* @internal
18+
*/
19+
class RequestRuntime extends SymfonyRuntime
20+
{
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Runtime\Symfony\Component\HttpFoundation;
13+
14+
use Symfony\Component\Runtime\SymfonyRuntime;
15+
16+
/**
17+
* @internal
18+
*/
19+
class ResponseRuntime extends SymfonyRuntime
20+
{
21+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Runtime\Symfony\Component\HttKernel;
13+
14+
use Symfony\Component\Runtime\SymfonyRuntime;
15+
16+
/**
17+
* @internal
18+
*/
19+
class HttpKernelInterfaceRuntime extends SymfonyRuntime
20+
{
21+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy