mirror of
https://gitlab.com/TheGamecraft/c-cms.git
synced 2026-04-23 19:39:10 -04:00
ALPHA 3.0.2
This commit is contained in:
@@ -12,10 +12,12 @@
|
||||
namespace Symfony\Component\Console\Tests\DependencyInjection;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\CommandLoader\ContainerCommandLoader;
|
||||
use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
|
||||
use Symfony\Component\DependencyInjection\ChildDefinition;
|
||||
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\TypedReference;
|
||||
@@ -28,7 +30,7 @@ class AddConsoleCommandPassTest extends TestCase
|
||||
public function testProcess($public)
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->addCompilerPass(new AddConsoleCommandPass());
|
||||
$container->addCompilerPass(new AddConsoleCommandPass(), PassConfig::TYPE_BEFORE_REMOVING);
|
||||
$container->setParameter('my-command.class', 'Symfony\Component\Console\Tests\DependencyInjection\MyCommand');
|
||||
|
||||
$id = 'my-command';
|
||||
@@ -124,7 +126,7 @@ class AddConsoleCommandPassTest extends TestCase
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->setResourceTracking(false);
|
||||
$container->addCompilerPass(new AddConsoleCommandPass());
|
||||
$container->addCompilerPass(new AddConsoleCommandPass(), PassConfig::TYPE_BEFORE_REMOVING);
|
||||
|
||||
$definition = new Definition('Symfony\Component\Console\Tests\DependencyInjection\MyCommand');
|
||||
$definition->addTag('console.command');
|
||||
@@ -142,7 +144,7 @@ class AddConsoleCommandPassTest extends TestCase
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->setResourceTracking(false);
|
||||
$container->addCompilerPass(new AddConsoleCommandPass());
|
||||
$container->addCompilerPass(new AddConsoleCommandPass(), PassConfig::TYPE_BEFORE_REMOVING);
|
||||
|
||||
$definition = new Definition('SplObjectStorage');
|
||||
$definition->addTag('console.command');
|
||||
@@ -171,6 +173,79 @@ class AddConsoleCommandPassTest extends TestCase
|
||||
$this->assertTrue($container->hasAlias($aliasPrefix.'my-command1'));
|
||||
$this->assertTrue($container->hasAlias($aliasPrefix.'my-command2'));
|
||||
}
|
||||
|
||||
public function testProcessOnChildDefinitionWithClass()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->addCompilerPass(new AddConsoleCommandPass(), PassConfig::TYPE_BEFORE_REMOVING);
|
||||
$className = 'Symfony\Component\Console\Tests\DependencyInjection\MyCommand';
|
||||
|
||||
$parentId = 'my-parent-command';
|
||||
$childId = 'my-child-command';
|
||||
|
||||
$parentDefinition = new Definition(/* no class */);
|
||||
$parentDefinition->setAbstract(true)->setPublic(false);
|
||||
|
||||
$childDefinition = new ChildDefinition($parentId);
|
||||
$childDefinition->addTag('console.command')->setPublic(true);
|
||||
$childDefinition->setClass($className);
|
||||
|
||||
$container->setDefinition($parentId, $parentDefinition);
|
||||
$container->setDefinition($childId, $childDefinition);
|
||||
|
||||
$container->compile();
|
||||
$command = $container->get($childId);
|
||||
|
||||
$this->assertInstanceOf($className, $command);
|
||||
}
|
||||
|
||||
public function testProcessOnChildDefinitionWithParentClass()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->addCompilerPass(new AddConsoleCommandPass(), PassConfig::TYPE_BEFORE_REMOVING);
|
||||
$className = 'Symfony\Component\Console\Tests\DependencyInjection\MyCommand';
|
||||
|
||||
$parentId = 'my-parent-command';
|
||||
$childId = 'my-child-command';
|
||||
|
||||
$parentDefinition = new Definition($className);
|
||||
$parentDefinition->setAbstract(true)->setPublic(false);
|
||||
|
||||
$childDefinition = new ChildDefinition($parentId);
|
||||
$childDefinition->addTag('console.command')->setPublic(true);
|
||||
|
||||
$container->setDefinition($parentId, $parentDefinition);
|
||||
$container->setDefinition($childId, $childDefinition);
|
||||
|
||||
$container->compile();
|
||||
$command = $container->get($childId);
|
||||
|
||||
$this->assertInstanceOf($className, $command);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
* @expectedExceptionMessage The definition for "my-child-command" has no class.
|
||||
*/
|
||||
public function testProcessOnChildDefinitionWithoutClass()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->addCompilerPass(new AddConsoleCommandPass(), PassConfig::TYPE_BEFORE_REMOVING);
|
||||
|
||||
$parentId = 'my-parent-command';
|
||||
$childId = 'my-child-command';
|
||||
|
||||
$parentDefinition = new Definition();
|
||||
$parentDefinition->setAbstract(true)->setPublic(false);
|
||||
|
||||
$childDefinition = new ChildDefinition($parentId);
|
||||
$childDefinition->addTag('console.command')->setPublic(true);
|
||||
|
||||
$container->setDefinition($parentId, $parentDefinition);
|
||||
$container->setDefinition($childId, $childDefinition);
|
||||
|
||||
$container->compile();
|
||||
}
|
||||
}
|
||||
|
||||
class MyCommand extends Command
|
||||
|
||||
@@ -26,6 +26,9 @@ class ClassNotFoundException extends FatalErrorException
|
||||
$previous->getSeverity(),
|
||||
$previous->getFile(),
|
||||
$previous->getLine(),
|
||||
null,
|
||||
true,
|
||||
null,
|
||||
$previous->getPrevious()
|
||||
);
|
||||
$this->setTrace($previous->getTrace());
|
||||
|
||||
@@ -18,9 +18,9 @@ namespace Symfony\Component\Debug\Exception;
|
||||
*/
|
||||
class FatalErrorException extends \ErrorException
|
||||
{
|
||||
public function __construct(string $message, int $code, int $severity, string $filename, int $lineno, int $traceOffset = null, bool $traceArgs = true, array $trace = null)
|
||||
public function __construct(string $message, int $code, int $severity, string $filename, int $lineno, int $traceOffset = null, bool $traceArgs = true, array $trace = null, \Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message, $code, $severity, $filename, $lineno);
|
||||
parent::__construct($message, $code, $severity, $filename, $lineno, $previous);
|
||||
|
||||
if (null !== $trace) {
|
||||
if (!$traceArgs) {
|
||||
|
||||
@@ -26,6 +26,9 @@ class UndefinedFunctionException extends FatalErrorException
|
||||
$previous->getSeverity(),
|
||||
$previous->getFile(),
|
||||
$previous->getLine(),
|
||||
null,
|
||||
true,
|
||||
null,
|
||||
$previous->getPrevious()
|
||||
);
|
||||
$this->setTrace($previous->getTrace());
|
||||
|
||||
@@ -26,6 +26,9 @@ class UndefinedMethodException extends FatalErrorException
|
||||
$previous->getSeverity(),
|
||||
$previous->getFile(),
|
||||
$previous->getLine(),
|
||||
null,
|
||||
true,
|
||||
null,
|
||||
$previous->getPrevious()
|
||||
);
|
||||
$this->setTrace($previous->getTrace());
|
||||
|
||||
@@ -60,11 +60,20 @@ abstract class RealIteratorTestCase extends IteratorTestCase
|
||||
|
||||
public static function tearDownAfterClass()
|
||||
{
|
||||
foreach (array_reverse(self::$files) as $file) {
|
||||
if (DIRECTORY_SEPARATOR === $file[strlen($file) - 1]) {
|
||||
@rmdir($file);
|
||||
$paths = new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator(self::$tmpDir, \RecursiveDirectoryIterator::SKIP_DOTS),
|
||||
\RecursiveIteratorIterator::CHILD_FIRST
|
||||
);
|
||||
|
||||
foreach ($paths as $path) {
|
||||
if ($path->isDir()) {
|
||||
if ($path->isLink()) {
|
||||
@unlink($path);
|
||||
} else {
|
||||
@rmdir($path);
|
||||
}
|
||||
} else {
|
||||
@unlink($file);
|
||||
@unlink($path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ class ResponseHeaderBag extends HeaderBag
|
||||
*
|
||||
* @param string $format
|
||||
*
|
||||
* @return array
|
||||
* @return Cookie[]
|
||||
*
|
||||
* @throws \InvalidArgumentException When the $format is invalid
|
||||
*/
|
||||
|
||||
@@ -29,7 +29,7 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
|
||||
private $flashName;
|
||||
private $attributeName;
|
||||
private $data = array();
|
||||
private $hasBeenStarted;
|
||||
private $usageIndex = 0;
|
||||
|
||||
/**
|
||||
* @param SessionStorageInterface $storage A SessionStorageInterface instance
|
||||
@@ -54,6 +54,8 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
|
||||
*/
|
||||
public function start()
|
||||
{
|
||||
++$this->usageIndex;
|
||||
|
||||
return $this->storage->start();
|
||||
}
|
||||
|
||||
@@ -142,13 +144,13 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @return int
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function hasBeenStarted()
|
||||
public function getUsageIndex()
|
||||
{
|
||||
return $this->hasBeenStarted;
|
||||
return $this->usageIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,6 +160,7 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
|
||||
*/
|
||||
public function isEmpty()
|
||||
{
|
||||
++$this->usageIndex;
|
||||
foreach ($this->data as &$data) {
|
||||
if (!empty($data)) {
|
||||
return false;
|
||||
@@ -182,6 +185,8 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
|
||||
*/
|
||||
public function migrate($destroy = false, $lifetime = null)
|
||||
{
|
||||
++$this->usageIndex;
|
||||
|
||||
return $this->storage->regenerate($destroy, $lifetime);
|
||||
}
|
||||
|
||||
@@ -190,6 +195,8 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
++$this->usageIndex;
|
||||
|
||||
$this->storage->save();
|
||||
}
|
||||
|
||||
@@ -230,6 +237,8 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
|
||||
*/
|
||||
public function getMetadataBag()
|
||||
{
|
||||
++$this->usageIndex;
|
||||
|
||||
return $this->storage->getMetadataBag();
|
||||
}
|
||||
|
||||
@@ -238,7 +247,7 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
|
||||
*/
|
||||
public function registerBag(SessionBagInterface $bag)
|
||||
{
|
||||
$this->storage->registerBag(new SessionBagProxy($bag, $this->data, $this->hasBeenStarted));
|
||||
$this->storage->registerBag(new SessionBagProxy($bag, $this->data, $this->usageIndex));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,13 +20,13 @@ final class SessionBagProxy implements SessionBagInterface
|
||||
{
|
||||
private $bag;
|
||||
private $data;
|
||||
private $hasBeenStarted;
|
||||
private $usageIndex;
|
||||
|
||||
public function __construct(SessionBagInterface $bag, array &$data, &$hasBeenStarted)
|
||||
public function __construct(SessionBagInterface $bag, array &$data, &$usageIndex)
|
||||
{
|
||||
$this->bag = $bag;
|
||||
$this->data = &$data;
|
||||
$this->hasBeenStarted = &$hasBeenStarted;
|
||||
$this->usageIndex = &$usageIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,6 +34,8 @@ final class SessionBagProxy implements SessionBagInterface
|
||||
*/
|
||||
public function getBag()
|
||||
{
|
||||
++$this->usageIndex;
|
||||
|
||||
return $this->bag;
|
||||
}
|
||||
|
||||
@@ -42,6 +44,8 @@ final class SessionBagProxy implements SessionBagInterface
|
||||
*/
|
||||
public function isEmpty()
|
||||
{
|
||||
++$this->usageIndex;
|
||||
|
||||
return empty($this->data[$this->bag->getStorageKey()]);
|
||||
}
|
||||
|
||||
@@ -58,7 +62,7 @@ final class SessionBagProxy implements SessionBagInterface
|
||||
*/
|
||||
public function initialize(array &$array)
|
||||
{
|
||||
$this->hasBeenStarted = true;
|
||||
++$this->usageIndex;
|
||||
$this->data[$this->bag->getStorageKey()] = &$array;
|
||||
|
||||
$this->bag->initialize($array);
|
||||
@@ -77,6 +81,8 @@ final class SessionBagProxy implements SessionBagInterface
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
++$this->usageIndex;
|
||||
|
||||
return $this->bag->clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +100,6 @@ class RedisSessionHandler extends AbstractSessionHandler
|
||||
*/
|
||||
public function updateTimestamp($sessionId, $data)
|
||||
{
|
||||
return $this->redis->expire($this->prefix.$sessionId, (int) ini_get('session.gc_maxlifetime'));
|
||||
return (bool) $this->redis->expire($this->prefix.$sessionId, (int) ini_get('session.gc_maxlifetime'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ class RequestTest extends TestCase
|
||||
{
|
||||
protected function tearDown()
|
||||
{
|
||||
// reset
|
||||
Request::setTrustedProxies(array(), -1);
|
||||
Request::setTrustedHosts(array());
|
||||
}
|
||||
|
||||
2
vendor/symfony/http-kernel/CHANGELOG.md
vendored
2
vendor/symfony/http-kernel/CHANGELOG.md
vendored
@@ -5,7 +5,7 @@ CHANGELOG
|
||||
-----
|
||||
|
||||
* added orphaned events support to `EventDataCollector`
|
||||
* `ExceptionListener` now logs and collects exceptions at priority `2048` (previously logged at `-128` and collected at `0`)
|
||||
* `ExceptionListener` now logs exceptions at priority `0` (previously logged at `-128`)
|
||||
* Deprecated `service:action` syntax with a single colon to reference controllers. Use `service::method` instead.
|
||||
* Added the ability to profile individual argument value resolvers via the
|
||||
`Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver`
|
||||
|
||||
@@ -68,7 +68,7 @@ final class ServiceValueResolver implements ArgumentValueResolverInterface
|
||||
yield $this->container->get($controller)->get($argument->getName());
|
||||
} catch (RuntimeException $e) {
|
||||
$what = sprintf('argument $%s of "%s()"', $argument->getName(), $controller);
|
||||
$message = preg_replace('/service "service_locator\.[^"]++"/', $what, $e->getMessage());
|
||||
$message = preg_replace('/service "\.service_locator\.[^"]++"/', $what, $e->getMessage());
|
||||
|
||||
if ($e->getMessage() === $message) {
|
||||
$message = sprintf('Cannot resolve %s: %s', $what, $message);
|
||||
|
||||
@@ -21,7 +21,7 @@ use Symfony\Component\VarDumper\Dumper\CliDumper;
|
||||
use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider;
|
||||
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
|
||||
use Symfony\Component\VarDumper\Dumper\DataDumperInterface;
|
||||
use Symfony\Component\VarDumper\Dumper\ServerDumper;
|
||||
use Symfony\Component\VarDumper\Server\Connection;
|
||||
|
||||
/**
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
@@ -38,17 +38,18 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
private $charset;
|
||||
private $requestStack;
|
||||
private $dumper;
|
||||
private $dumperIsInjected;
|
||||
private $sourceContextProvider;
|
||||
|
||||
public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, string $charset = null, RequestStack $requestStack = null, DataDumperInterface $dumper = null)
|
||||
/**
|
||||
* @param DataDumperInterface|Connection|null $dumper
|
||||
*/
|
||||
public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, string $charset = null, RequestStack $requestStack = null, $dumper = null)
|
||||
{
|
||||
$this->stopwatch = $stopwatch;
|
||||
$this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
|
||||
$this->charset = $charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8';
|
||||
$this->requestStack = $requestStack;
|
||||
$this->dumper = $dumper;
|
||||
$this->dumperIsInjected = null !== $dumper;
|
||||
|
||||
// All clones share these properties by reference:
|
||||
$this->rootRefs = array(
|
||||
@@ -58,7 +59,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
&$this->clonesCount,
|
||||
);
|
||||
|
||||
$this->sourceContextProvider = $dumper instanceof ServerDumper && isset($dumper->getContextProviders()['source']) ? $dumper->getContextProviders()['source'] : new SourceContextProvider($this->charset);
|
||||
$this->sourceContextProvider = $dumper instanceof Connection && isset($dumper->getContextProviders()['source']) ? $dumper->getContextProviders()['source'] : new SourceContextProvider($this->charset);
|
||||
}
|
||||
|
||||
public function __clone()
|
||||
@@ -71,14 +72,17 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
if ($this->stopwatch) {
|
||||
$this->stopwatch->start('dump');
|
||||
}
|
||||
if ($this->isCollected && !$this->dumper) {
|
||||
$this->isCollected = false;
|
||||
}
|
||||
|
||||
list('name' => $name, 'file' => $file, 'line' => $line, 'file_excerpt' => $fileExcerpt) = $this->sourceContextProvider->getContext();
|
||||
|
||||
if ($this->dumper) {
|
||||
if ($this->dumper instanceof Connection) {
|
||||
if (!$this->dumper->write($data)) {
|
||||
$this->isCollected = false;
|
||||
}
|
||||
} elseif ($this->dumper) {
|
||||
$this->doDump($this->dumper, $data, $name, $file, $line);
|
||||
} else {
|
||||
$this->isCollected = false;
|
||||
}
|
||||
|
||||
$this->data[] = compact('data', 'name', 'file', 'line', 'fileExcerpt');
|
||||
@@ -124,7 +128,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
}
|
||||
$this->data = array();
|
||||
$this->dataCount = 0;
|
||||
$this->isCollected = false;
|
||||
$this->isCollected = true;
|
||||
$this->clonesCount = 0;
|
||||
$this->clonesIndex = 0;
|
||||
}
|
||||
@@ -141,9 +145,6 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
$this->data = array();
|
||||
$this->dataCount = 0;
|
||||
$this->isCollected = true;
|
||||
if (!$this->dumperIsInjected) {
|
||||
$this->dumper = null;
|
||||
}
|
||||
|
||||
return $ser;
|
||||
}
|
||||
@@ -245,7 +246,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface
|
||||
};
|
||||
$contextDumper = $contextDumper->bindTo($dumper, $dumper);
|
||||
$contextDumper($name, $file, $line, $this->fileLinkFormat);
|
||||
} elseif (!$dumper instanceof ServerDumper) {
|
||||
} else {
|
||||
$cloner = new VarCloner();
|
||||
$dumper->dump($cloner->cloneVar($name.' on line '.$line.':'));
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ use Psr\Container\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
@@ -37,6 +38,7 @@ abstract class AbstractSessionListener implements EventSubscriberInterface
|
||||
const NO_AUTO_CACHE_CONTROL_HEADER = 'Symfony-Session-NoAutoCacheControl';
|
||||
|
||||
protected $container;
|
||||
private $sessionUsageStack = array();
|
||||
|
||||
public function __construct(ContainerInterface $container = null)
|
||||
{
|
||||
@@ -49,6 +51,7 @@ abstract class AbstractSessionListener implements EventSubscriberInterface
|
||||
return;
|
||||
}
|
||||
|
||||
$session = null;
|
||||
$request = $event->getRequest();
|
||||
if ($request->hasSession()) {
|
||||
// no-op
|
||||
@@ -57,6 +60,9 @@ abstract class AbstractSessionListener implements EventSubscriberInterface
|
||||
} elseif ($session = $this->getSession()) {
|
||||
$request->setSession($session);
|
||||
}
|
||||
|
||||
$session = $session ?? ($this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : null);
|
||||
$this->sessionUsageStack[] = $session instanceof Session ? $session->getUsageIndex() : null;
|
||||
}
|
||||
|
||||
public function onKernelResponse(FilterResponseEvent $event)
|
||||
@@ -71,7 +77,7 @@ abstract class AbstractSessionListener implements EventSubscriberInterface
|
||||
|
||||
$response = $event->getResponse();
|
||||
|
||||
if ($session->isStarted() || ($session instanceof Session && $session->hasBeenStarted())) {
|
||||
if ($session instanceof Session ? $session->getUsageIndex() !== end($this->sessionUsageStack) : $session->isStarted()) {
|
||||
if (!$response->headers->has(self::NO_AUTO_CACHE_CONTROL_HEADER)) {
|
||||
$response
|
||||
->setPrivate()
|
||||
@@ -113,12 +119,23 @@ abstract class AbstractSessionListener implements EventSubscriberInterface
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function onFinishRequest(FinishRequestEvent $event)
|
||||
{
|
||||
if ($event->isMasterRequest()) {
|
||||
array_pop($this->sessionUsageStack);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
KernelEvents::REQUEST => array('onKernelRequest', 128),
|
||||
// low priority to come after regular response listeners, but higher than StreamedResponseListener
|
||||
KernelEvents::RESPONSE => array('onKernelResponse', -1000),
|
||||
KernelEvents::FINISH_REQUEST => array('onFinishRequest'),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ use Symfony\Component\Console\ConsoleEvents;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\VarDumper\Cloner\ClonerInterface;
|
||||
use Symfony\Component\VarDumper\Dumper\DataDumperInterface;
|
||||
use Symfony\Component\VarDumper\Server\Connection;
|
||||
use Symfony\Component\VarDumper\VarDumper;
|
||||
|
||||
/**
|
||||
@@ -26,20 +27,27 @@ class DumpListener implements EventSubscriberInterface
|
||||
{
|
||||
private $cloner;
|
||||
private $dumper;
|
||||
private $connection;
|
||||
|
||||
public function __construct(ClonerInterface $cloner, DataDumperInterface $dumper)
|
||||
public function __construct(ClonerInterface $cloner, DataDumperInterface $dumper, Connection $connection = null)
|
||||
{
|
||||
$this->cloner = $cloner;
|
||||
$this->dumper = $dumper;
|
||||
$this->connection = $connection;
|
||||
}
|
||||
|
||||
public function configure()
|
||||
{
|
||||
$cloner = $this->cloner;
|
||||
$dumper = $this->dumper;
|
||||
$connection = $this->connection;
|
||||
|
||||
VarDumper::setHandler(function ($var) use ($cloner, $dumper) {
|
||||
$dumper->dump($cloner->cloneVar($var));
|
||||
VarDumper::setHandler(static function ($var) use ($cloner, $dumper, $connection) {
|
||||
$data = $cloner->cloneVar($var);
|
||||
|
||||
if (!$connection || !$connection->write($data)) {
|
||||
$dumper->dump($data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -12,11 +12,9 @@
|
||||
namespace Symfony\Component\HttpKernel\EventListener;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Debug\ExceptionHandler;
|
||||
use Symfony\Component\Debug\Exception\FlattenException;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
|
||||
@@ -35,20 +33,17 @@ class ExceptionListener implements EventSubscriberInterface
|
||||
protected $controller;
|
||||
protected $logger;
|
||||
protected $debug;
|
||||
private $charset;
|
||||
|
||||
public function __construct($controller, LoggerInterface $logger = null, $debug = false, $charset = null)
|
||||
public function __construct($controller, LoggerInterface $logger = null, $debug = false)
|
||||
{
|
||||
$this->controller = $controller;
|
||||
$this->logger = $logger;
|
||||
$this->debug = $debug;
|
||||
$this->charset = $charset;
|
||||
}
|
||||
|
||||
public function logKernelException(GetResponseForExceptionEvent $event)
|
||||
{
|
||||
$exception = $event->getException();
|
||||
$request = $event->getRequest();
|
||||
|
||||
$this->logException($exception, sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine()));
|
||||
}
|
||||
@@ -72,7 +67,7 @@ class ExceptionListener implements EventSubscriberInterface
|
||||
}
|
||||
}
|
||||
|
||||
$prev = new \ReflectionProperty('Exception', 'previous');
|
||||
$prev = new \ReflectionProperty($wrapper instanceof \Exception ? \Exception::class : \Error::class, 'previous');
|
||||
$prev->setAccessible(true);
|
||||
$prev->setValue($wrapper, $exception);
|
||||
|
||||
@@ -94,7 +89,7 @@ class ExceptionListener implements EventSubscriberInterface
|
||||
{
|
||||
return array(
|
||||
KernelEvents::EXCEPTION => array(
|
||||
array('logKernelException', 2048),
|
||||
array('logKernelException', 0),
|
||||
array('onKernelException', -128),
|
||||
),
|
||||
);
|
||||
@@ -128,12 +123,8 @@ class ExceptionListener implements EventSubscriberInterface
|
||||
protected function duplicateRequest(\Exception $exception, Request $request)
|
||||
{
|
||||
$attributes = array(
|
||||
'exception' => $exception = FlattenException::create($exception),
|
||||
'_controller' => $this->controller ?: function () use ($exception) {
|
||||
$handler = new ExceptionHandler($this->debug, $this->charset);
|
||||
|
||||
return new Response($handler->getHtml($exception), $exception->getStatusCode(), $exception->getHeaders());
|
||||
},
|
||||
'_controller' => $this->controller,
|
||||
'exception' => FlattenException::create($exception),
|
||||
'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null,
|
||||
);
|
||||
$request = $request->duplicate(null, null, $attributes);
|
||||
|
||||
@@ -121,7 +121,7 @@ class ProfilerListener implements EventSubscriberInterface
|
||||
{
|
||||
return array(
|
||||
KernelEvents::RESPONSE => array('onKernelResponse', -100),
|
||||
KernelEvents::EXCEPTION => array('onKernelException', 2048),
|
||||
KernelEvents::EXCEPTION => array('onKernelException', 0),
|
||||
KernelEvents::TERMINATE => array('onKernelTerminate', -1024),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -115,7 +115,9 @@ class InlineFragmentRenderer extends RoutableFragmentRenderer
|
||||
$server['HTTP_X_FORWARDED_FOR'] = ($currentXForwardedFor ? $currentXForwardedFor.', ' : '').$request->getClientIp();
|
||||
}
|
||||
|
||||
$server['REMOTE_ADDR'] = '127.0.0.1';
|
||||
$trustedProxies = Request::getTrustedProxies();
|
||||
$server['REMOTE_ADDR'] = $trustedProxies ? reset($trustedProxies) : '127.0.0.1';
|
||||
|
||||
unset($server['HTTP_IF_MODIFIED_SINCE']);
|
||||
unset($server['HTTP_IF_NONE_MATCH']);
|
||||
|
||||
|
||||
@@ -165,7 +165,11 @@ class HttpCache implements HttpKernelInterface, TerminableInterface
|
||||
// FIXME: catch exceptions and implement a 500 error page here? -> in Varnish, there is a built-in error page mechanism
|
||||
if (HttpKernelInterface::MASTER_REQUEST === $type) {
|
||||
$this->traces = array();
|
||||
$this->request = $request;
|
||||
// Keep a clone of the original request for surrogates so they can access it.
|
||||
// We must clone here to get a separate instance because the application will modify the request during
|
||||
// the application flow (we know it always does because we do ourselves by setting REMOTE_ADDR to 127.0.0.1
|
||||
// and adding the X-Forwarded-For header, see HttpCache::forward()).
|
||||
$this->request = clone $request;
|
||||
if (null !== $this->surrogate) {
|
||||
$this->surrogateCacheStrategy = $this->surrogate->createCacheStrategy();
|
||||
}
|
||||
|
||||
6
vendor/symfony/http-kernel/Kernel.php
vendored
6
vendor/symfony/http-kernel/Kernel.php
vendored
@@ -63,11 +63,11 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
|
||||
private $requestStackSize = 0;
|
||||
private $resetServices = false;
|
||||
|
||||
const VERSION = '4.1.0';
|
||||
const VERSION_ID = 40100;
|
||||
const VERSION = '4.1.1';
|
||||
const VERSION_ID = 40101;
|
||||
const MAJOR_VERSION = 4;
|
||||
const MINOR_VERSION = 1;
|
||||
const RELEASE_VERSION = 0;
|
||||
const RELEASE_VERSION = 1;
|
||||
const EXTRA_VERSION = '';
|
||||
|
||||
const END_OF_MAINTENANCE = '01/2019';
|
||||
|
||||
@@ -12,10 +12,12 @@
|
||||
namespace Symfony\Component\HttpKernel\Tests\Controller\ArgumentResolver;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\ServiceLocator;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\ServiceValueResolver;
|
||||
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
|
||||
use Symfony\Component\HttpKernel\DependencyInjection\RegisterControllerArgumentLocatorsPass;
|
||||
|
||||
class ServiceValueResolverTest extends TestCase
|
||||
{
|
||||
@@ -85,6 +87,25 @@ class ServiceValueResolverTest extends TestCase
|
||||
$this->assertYieldEquals(array(new DummyService()), $resolver->resolve($request, $argument));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
|
||||
* @expectedExceptionMessage Cannot autowire argument $dummy of "Symfony\Component\HttpKernel\Tests\Controller\ArgumentResolver\DummyController::index()": it references class "Symfony\Component\HttpKernel\Tests\Controller\ArgumentResolver\DummyService" but no such service exists.
|
||||
*/
|
||||
public function testErrorIsTruncated()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->addCompilerPass(new RegisterControllerArgumentLocatorsPass());
|
||||
|
||||
$container->register('argument_resolver.service', ServiceValueResolver::class)->addArgument(null)->setPublic(true);
|
||||
$container->register(DummyController::class)->addTag('controller.service_arguments')->setPublic(true);
|
||||
|
||||
$container->compile();
|
||||
|
||||
$request = $this->requestWithAttributes(array('_controller' => array(DummyController::class, 'index')));
|
||||
$argument = new ArgumentMetadata('dummy', DummyService::class, false, false, null);
|
||||
$container->get('argument_resolver.service')->resolve($request, $argument)->current();
|
||||
}
|
||||
|
||||
private function requestWithAttributes(array $attributes)
|
||||
{
|
||||
$request = Request::create('/');
|
||||
@@ -110,3 +131,10 @@ class ServiceValueResolverTest extends TestCase
|
||||
class DummyService
|
||||
{
|
||||
}
|
||||
|
||||
class DummyController
|
||||
{
|
||||
public function index(DummyService $dummy)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\DataCollector\DumpDataCollector;
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
use Symfony\Component\VarDumper\Dumper\CliDumper;
|
||||
use Symfony\Component\VarDumper\Dumper\ServerDumper;
|
||||
use Symfony\Component\VarDumper\Server\Connection;
|
||||
|
||||
/**
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
@@ -57,13 +57,13 @@ class DumpDataCollectorTest extends TestCase
|
||||
$this->assertSame('a:2:{i:0;b:0;i:1;s:5:"UTF-8";}', $collector->serialize());
|
||||
}
|
||||
|
||||
public function testDumpWithServerDumper()
|
||||
public function testDumpWithServerConnection()
|
||||
{
|
||||
$data = new Data(array(array(123)));
|
||||
|
||||
// Server is up, server dumper is used
|
||||
$serverDumper = $this->getMockBuilder(ServerDumper::class)->disableOriginalConstructor()->getMock();
|
||||
$serverDumper->expects($this->once())->method('dump');
|
||||
$serverDumper = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock();
|
||||
$serverDumper->expects($this->once())->method('write')->willReturn(true);
|
||||
|
||||
$collector = new DumpDataCollector(null, null, null, null, $serverDumper);
|
||||
$collector->dump($data);
|
||||
|
||||
@@ -155,23 +155,6 @@ class ExceptionListenerTest extends TestCase
|
||||
$this->assertFalse($response->headers->has('content-security-policy'), 'CSP header has been removed');
|
||||
$this->assertFalse($dispatcher->hasListeners(KernelEvents::RESPONSE), 'CSP removal listener has been removed');
|
||||
}
|
||||
|
||||
public function testNullController()
|
||||
{
|
||||
$listener = new ExceptionListener(null);
|
||||
$kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
|
||||
$kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) {
|
||||
$controller = $request->attributes->get('_controller');
|
||||
|
||||
return $controller();
|
||||
}));
|
||||
$request = Request::create('/');
|
||||
$event = new GetResponseForExceptionEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, new \Exception('foo'));
|
||||
|
||||
$listener->onKernelException($event);
|
||||
|
||||
$this->assertContains('Whoops, looks like something went wrong.', $event->getResponse()->getContent());
|
||||
}
|
||||
}
|
||||
|
||||
class TestLogger extends Logger implements DebugLoggerInterface
|
||||
|
||||
@@ -19,6 +19,7 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
|
||||
use Symfony\Component\HttpKernel\EventListener\AbstractSessionListener;
|
||||
use Symfony\Component\HttpKernel\EventListener\SessionListener;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
@@ -59,8 +60,7 @@ class SessionListenerTest extends TestCase
|
||||
public function testResponseIsPrivateIfSessionStarted()
|
||||
{
|
||||
$session = $this->getMockBuilder(Session::class)->disableOriginalConstructor()->getMock();
|
||||
$session->expects($this->exactly(2))->method('isStarted')->willReturn(false);
|
||||
$session->expects($this->once())->method('hasBeenStarted')->willReturn(true);
|
||||
$session->expects($this->exactly(2))->method('getUsageIndex')->will($this->onConsecutiveCalls(0, 1));
|
||||
|
||||
$container = new Container();
|
||||
$container->set('initialized_session', $session);
|
||||
@@ -68,6 +68,9 @@ class SessionListenerTest extends TestCase
|
||||
$listener = new SessionListener($container);
|
||||
$kernel = $this->getMockBuilder(HttpKernelInterface::class)->disableOriginalConstructor()->getMock();
|
||||
|
||||
$request = new Request();
|
||||
$listener->onKernelRequest(new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST));
|
||||
|
||||
$response = new Response();
|
||||
$listener->onKernelResponse(new FilterResponseEvent($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, $response));
|
||||
|
||||
@@ -80,8 +83,7 @@ class SessionListenerTest extends TestCase
|
||||
public function testResponseIsStillPublicIfSessionStartedAndHeaderPresent()
|
||||
{
|
||||
$session = $this->getMockBuilder(Session::class)->disableOriginalConstructor()->getMock();
|
||||
$session->expects($this->exactly(2))->method('isStarted')->willReturn(false);
|
||||
$session->expects($this->once())->method('hasBeenStarted')->willReturn(true);
|
||||
$session->expects($this->exactly(2))->method('getUsageIndex')->will($this->onConsecutiveCalls(0, 1));
|
||||
|
||||
$container = new Container();
|
||||
$container->set('initialized_session', $session);
|
||||
@@ -89,6 +91,9 @@ class SessionListenerTest extends TestCase
|
||||
$listener = new SessionListener($container);
|
||||
$kernel = $this->getMockBuilder(HttpKernelInterface::class)->disableOriginalConstructor()->getMock();
|
||||
|
||||
$request = new Request();
|
||||
$listener->onKernelRequest(new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST));
|
||||
|
||||
$response = new Response();
|
||||
$response->setSharedMaxAge(60);
|
||||
$response->headers->set(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER, 'true');
|
||||
@@ -113,4 +118,39 @@ class SessionListenerTest extends TestCase
|
||||
$listener = new SessionListener($container);
|
||||
$listener->onKernelResponse($event);
|
||||
}
|
||||
|
||||
public function testSurrogateMasterRequestIsPublic()
|
||||
{
|
||||
$session = $this->getMockBuilder(Session::class)->disableOriginalConstructor()->getMock();
|
||||
$session->expects($this->exactly(4))->method('getUsageIndex')->will($this->onConsecutiveCalls(0, 1, 1, 1));
|
||||
|
||||
$container = new Container();
|
||||
$container->set('initialized_session', $session);
|
||||
$container->set('session', $session);
|
||||
|
||||
$listener = new SessionListener($container);
|
||||
$kernel = $this->getMockBuilder(HttpKernelInterface::class)->disableOriginalConstructor()->getMock();
|
||||
|
||||
$request = new Request();
|
||||
$response = new Response();
|
||||
$response->setCache(array('public' => true, 'max_age' => '30'));
|
||||
$listener->onKernelRequest(new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST));
|
||||
$this->assertTrue($request->hasSession());
|
||||
|
||||
$subRequest = clone $request;
|
||||
$this->assertSame($request->getSession(), $subRequest->getSession());
|
||||
$listener->onKernelRequest(new GetResponseEvent($kernel, $subRequest, HttpKernelInterface::MASTER_REQUEST));
|
||||
$listener->onKernelResponse(new FilterResponseEvent($kernel, $subRequest, HttpKernelInterface::MASTER_REQUEST, $response));
|
||||
$listener->onFinishRequest(new FinishRequestEvent($kernel, $subRequest, HttpKernelInterface::MASTER_REQUEST));
|
||||
|
||||
$this->assertFalse($response->headers->hasCacheControlDirective('private'));
|
||||
$this->assertFalse($response->headers->hasCacheControlDirective('must-revalidate'));
|
||||
$this->assertSame('30', $response->headers->getCacheControlDirective('max-age'));
|
||||
|
||||
$listener->onKernelResponse(new FilterResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response));
|
||||
|
||||
$this->assertTrue($response->headers->hasCacheControlDirective('private'));
|
||||
$this->assertTrue($response->headers->hasCacheControlDirective('must-revalidate'));
|
||||
$this->assertSame('0', $response->headers->getCacheControlDirective('max-age'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,11 @@ use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
class ValidateRequestListenerTest extends TestCase
|
||||
{
|
||||
protected function tearDown()
|
||||
{
|
||||
Request::setTrustedProxies(array(), -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException
|
||||
*/
|
||||
|
||||
@@ -168,16 +168,33 @@ class InlineFragmentRendererTest extends TestCase
|
||||
public function testHeadersPossiblyResultingIn304AreNotAssignedToSubrequest()
|
||||
{
|
||||
$expectedSubRequest = Request::create('/');
|
||||
if (Request::HEADER_X_FORWARDED_FOR & Request::getTrustedHeaderSet()) {
|
||||
$expectedSubRequest->headers->set('x-forwarded-for', array('127.0.0.1'));
|
||||
$expectedSubRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1');
|
||||
}
|
||||
$expectedSubRequest->headers->set('x-forwarded-for', array('127.0.0.1'));
|
||||
$expectedSubRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1');
|
||||
|
||||
$strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($expectedSubRequest));
|
||||
$request = Request::create('/', 'GET', array(), array(), array(), array('HTTP_IF_MODIFIED_SINCE' => 'Fri, 01 Jan 2016 00:00:00 GMT', 'HTTP_IF_NONE_MATCH' => '*'));
|
||||
$strategy->render('/', $request);
|
||||
}
|
||||
|
||||
public function testFirstTrustedProxyIsSetAsRemote()
|
||||
{
|
||||
Request::setTrustedProxies(array('1.1.1.1'), -1);
|
||||
|
||||
$expectedSubRequest = Request::create('/');
|
||||
$expectedSubRequest->headers->set('Surrogate-Capability', 'abc="ESI/1.0"');
|
||||
$expectedSubRequest->server->set('REMOTE_ADDR', '1.1.1.1');
|
||||
$expectedSubRequest->headers->set('x-forwarded-for', array('127.0.0.1'));
|
||||
$expectedSubRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1');
|
||||
|
||||
$strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($expectedSubRequest));
|
||||
|
||||
$request = Request::create('/');
|
||||
$request->headers->set('Surrogate-Capability', 'abc="ESI/1.0"');
|
||||
$strategy->render('/', $request);
|
||||
|
||||
Request::setTrustedProxies(array(), -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Kernel expecting a request equals to $request
|
||||
* Allows delta in comparison in case REQUEST_TIME changed by 1 second.
|
||||
|
||||
@@ -11,9 +11,11 @@
|
||||
|
||||
namespace Symfony\Component\HttpKernel\Tests\HttpCache;
|
||||
|
||||
use Symfony\Component\HttpKernel\HttpCache\Esi;
|
||||
use Symfony\Component\HttpKernel\HttpCache\HttpCache;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\HttpCache\Store;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
|
||||
/**
|
||||
@@ -1350,6 +1352,8 @@ class HttpCacheTest extends HttpCacheTestCase
|
||||
$this->request('GET', '/', array('REMOTE_ADDR' => '10.0.0.1'));
|
||||
|
||||
$this->assertEquals($expected, Request::getTrustedProxies());
|
||||
|
||||
Request::setTrustedProxies(array(), -1);
|
||||
}
|
||||
|
||||
public function getTrustedProxyData()
|
||||
@@ -1465,6 +1469,42 @@ class HttpCacheTest extends HttpCacheTestCase
|
||||
$this->assertHttpKernelIsNotCalled();
|
||||
$this->assertSame('get', $this->response->getContent());
|
||||
}
|
||||
|
||||
public function testUsesOriginalRequestForSurrogate()
|
||||
{
|
||||
$kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
|
||||
$store = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpCache\StoreInterface')->getMock();
|
||||
|
||||
$kernel
|
||||
->expects($this->exactly(2))
|
||||
->method('handle')
|
||||
->willReturnCallback(function (Request $request) {
|
||||
$this->assertSame('127.0.0.1', $request->server->get('REMOTE_ADDR'));
|
||||
|
||||
return new Response();
|
||||
});
|
||||
|
||||
$cache = new HttpCache($kernel,
|
||||
$store,
|
||||
new Esi()
|
||||
);
|
||||
|
||||
$request = Request::create('/');
|
||||
$request->server->set('REMOTE_ADDR', '10.0.0.1');
|
||||
|
||||
// Main request
|
||||
$cache->handle($request, HttpKernelInterface::MASTER_REQUEST);
|
||||
|
||||
// Main request was now modified by HttpCache
|
||||
// The surrogate will ask for the request using $this->cache->getRequest()
|
||||
// which MUST return the original request so the surrogate
|
||||
// can actually behave like a reverse proxy like e.g. Varnish would.
|
||||
$this->assertSame('10.0.0.1', $cache->getRequest()->getClientIp());
|
||||
$this->assertSame('10.0.0.1', $cache->getRequest()->server->get('REMOTE_ADDR'));
|
||||
|
||||
// Surrogate request
|
||||
$cache->handle($request, HttpKernelInterface::SUB_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
class TestKernel implements HttpKernelInterface
|
||||
|
||||
@@ -331,6 +331,8 @@ class HttpKernelTest extends TestCase
|
||||
|
||||
$kernel = $this->getHttpKernel($dispatcher);
|
||||
$kernel->handle($request, $kernel::MASTER_REQUEST, false);
|
||||
|
||||
Request::setTrustedProxies(array(), -1);
|
||||
}
|
||||
|
||||
private function getHttpKernel(EventDispatcherInterface $eventDispatcher, $controller = null, RequestStack $requestStack = null, array $arguments = array())
|
||||
|
||||
6
vendor/symfony/http-kernel/composer.json
vendored
6
vendor/symfony/http-kernel/composer.json
vendored
@@ -18,7 +18,7 @@
|
||||
"require": {
|
||||
"php": "^7.1.3",
|
||||
"symfony/event-dispatcher": "~4.1",
|
||||
"symfony/http-foundation": "~4.1",
|
||||
"symfony/http-foundation": "^4.1.1",
|
||||
"symfony/debug": "~3.4|~4.0",
|
||||
"symfony/polyfill-ctype": "~1.8",
|
||||
"psr/log": "~1.0"
|
||||
@@ -37,7 +37,7 @@
|
||||
"symfony/stopwatch": "~3.4|~4.0",
|
||||
"symfony/templating": "~3.4|~4.0",
|
||||
"symfony/translation": "~3.4|~4.0",
|
||||
"symfony/var-dumper": "~4.1",
|
||||
"symfony/var-dumper": "^4.1.1",
|
||||
"psr/cache": "~1.0"
|
||||
},
|
||||
"provide": {
|
||||
@@ -46,7 +46,7 @@
|
||||
"conflict": {
|
||||
"symfony/config": "<3.4",
|
||||
"symfony/dependency-injection": "<4.1",
|
||||
"symfony/var-dumper": "<4.1",
|
||||
"symfony/var-dumper": "<4.1.1",
|
||||
"twig/twig": "<1.34|<2.4,>=2"
|
||||
},
|
||||
"suggest": {
|
||||
|
||||
2
vendor/symfony/process/ExecutableFinder.php
vendored
2
vendor/symfony/process/ExecutableFinder.php
vendored
@@ -73,7 +73,7 @@ class ExecutableFinder
|
||||
$suffixes = array('');
|
||||
if ('\\' === DIRECTORY_SEPARATOR) {
|
||||
$pathExt = getenv('PATHEXT');
|
||||
$suffixes = array_merge($suffixes, $pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes);
|
||||
$suffixes = array_merge($pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes);
|
||||
}
|
||||
foreach ($suffixes as $suffix) {
|
||||
foreach ($dirs as $dir) {
|
||||
|
||||
@@ -117,6 +117,36 @@ class ExecutableFinderTest extends TestCase
|
||||
$this->assertSamePath(PHP_BINARY, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 5.4
|
||||
*/
|
||||
public function testFindBatchExecutableOnWindows()
|
||||
{
|
||||
if (ini_get('open_basedir')) {
|
||||
$this->markTestSkipped('Cannot test when open_basedir is set');
|
||||
}
|
||||
if ('\\' !== DIRECTORY_SEPARATOR) {
|
||||
$this->markTestSkipped('Can be only tested on windows');
|
||||
}
|
||||
|
||||
$target = tempnam(sys_get_temp_dir(), 'example-windows-executable');
|
||||
|
||||
touch($target);
|
||||
touch($target.'.BAT');
|
||||
|
||||
$this->assertFalse(is_executable($target));
|
||||
|
||||
$this->setPath(sys_get_temp_dir());
|
||||
|
||||
$finder = new ExecutableFinder();
|
||||
$result = $finder->find(basename($target), false);
|
||||
|
||||
unlink($target);
|
||||
unlink($target.'.BAT');
|
||||
|
||||
$this->assertSamePath($target.'.BAT', $result);
|
||||
}
|
||||
|
||||
private function assertSamePath($expected, $tested)
|
||||
{
|
||||
if ('\\' === DIRECTORY_SEPARATOR) {
|
||||
|
||||
@@ -376,10 +376,10 @@ EOF;
|
||||
if ($hostRegex) {
|
||||
preg_match('#^.\^(.*)\$.[a-zA-Z]*$#', $hostRegex, $rx);
|
||||
$state->vars = array();
|
||||
$hostRegex = '(?i:'.preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]).')';
|
||||
$hostRegex = '(?i:'.preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]).')\.';
|
||||
$state->hostVars = $state->vars;
|
||||
} else {
|
||||
$hostRegex = '[^/]*+';
|
||||
$hostRegex = '(?:(?:[^.]*+\.)++)';
|
||||
$state->hostVars = array();
|
||||
}
|
||||
$state->mark += strlen($rx = ($prev ? ')' : '')."|{$hostRegex}(?");
|
||||
@@ -406,6 +406,7 @@ EOF;
|
||||
$rx = ")$}{$modifiers}";
|
||||
$code .= "\n .'{$rx}',";
|
||||
$state->regex .= $rx;
|
||||
$state->markTail = 0;
|
||||
|
||||
// if the regex is too large, throw a signaling exception to recompute with smaller chunk size
|
||||
set_error_handler(function ($type, $message) { throw 0 === strpos($message, $this->signalingException->getMessage()) ? $this->signalingException : new \ErrorException($message); });
|
||||
@@ -427,7 +428,7 @@ EOF;
|
||||
EOF;
|
||||
}
|
||||
|
||||
$matchedPathinfo = $matchHost ? '$host.$pathinfo' : '$pathinfo';
|
||||
$matchedPathinfo = $matchHost ? '$host.\'.\'.$pathinfo' : '$pathinfo';
|
||||
unset($state->getVars);
|
||||
|
||||
return <<<EOF
|
||||
|
||||
@@ -63,11 +63,9 @@ class StaticPrefixCollection
|
||||
*
|
||||
* @param array|self $route
|
||||
*/
|
||||
public function addRoute(string $prefix, $route, string $staticPrefix = null)
|
||||
public function addRoute(string $prefix, $route)
|
||||
{
|
||||
if (null === $staticPrefix) {
|
||||
list($prefix, $staticPrefix) = $this->getCommonPrefix($prefix, $prefix);
|
||||
}
|
||||
list($prefix, $staticPrefix) = $this->getCommonPrefix($prefix, $prefix);
|
||||
|
||||
for ($i = \count($this->items) - 1; 0 <= $i; --$i) {
|
||||
$item = $this->items[$i];
|
||||
@@ -102,7 +100,7 @@ class StaticPrefixCollection
|
||||
|
||||
if ($item instanceof self && $this->prefixes[$i] === $commonPrefix) {
|
||||
// the new route is a child of a previous one, let's nest it
|
||||
$item->addRoute($prefix, $route, $staticPrefix);
|
||||
$item->addRoute($prefix, $route);
|
||||
} else {
|
||||
// the new route and a previous one have a common prefix, let's merge them
|
||||
$child = new self($commonPrefix);
|
||||
@@ -187,6 +185,12 @@ class StaticPrefixCollection
|
||||
}
|
||||
}
|
||||
restore_error_handler();
|
||||
if ($i < $end && 0b10 === (\ord($prefix[$i]) >> 6) && preg_match('//u', $prefix.' '.$anotherPrefix)) {
|
||||
do {
|
||||
// Prevent cutting in the middle of an UTF-8 characters
|
||||
--$i;
|
||||
} while (0b10 === (\ord($prefix[$i]) >> 6));
|
||||
}
|
||||
|
||||
return array(substr($prefix, 0, $i), substr($prefix, 0, $staticLength ?? $i));
|
||||
}
|
||||
|
||||
2
vendor/symfony/routing/RouteCompiler.php
vendored
2
vendor/symfony/routing/RouteCompiler.php
vendored
@@ -321,7 +321,7 @@ class RouteCompiler implements RouteCompilerInterface
|
||||
continue;
|
||||
}
|
||||
$regexp = substr_replace($regexp, '?:', $i, 0);
|
||||
$i += 2;
|
||||
++$i;
|
||||
}
|
||||
|
||||
return $regexp;
|
||||
|
||||
@@ -79,50 +79,50 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$matchedPathinfo = $host.$pathinfo;
|
||||
$matchedPathinfo = $host.'.'.$pathinfo;
|
||||
$regexList = array(
|
||||
0 => '{^(?'
|
||||
.'|[^/]*+(?'
|
||||
.'|/foo/(baz|symfony)(*:34)'
|
||||
.'|(?:(?:[^.]*+\\.)++)(?'
|
||||
.'|/foo/(baz|symfony)(*:46)'
|
||||
.'|/bar(?'
|
||||
.'|/([^/]++)(*:57)'
|
||||
.'|head/([^/]++)(*:77)'
|
||||
.'|/([^/]++)(*:69)'
|
||||
.'|head/([^/]++)(*:89)'
|
||||
.')'
|
||||
.'|/test/([^/]++)/(?'
|
||||
.'|(*:103)'
|
||||
.'|(*:115)'
|
||||
.')'
|
||||
.'|/([\']+)(*:119)'
|
||||
.'|/([\']+)(*:131)'
|
||||
.'|/a/(?'
|
||||
.'|b\'b/([^/]++)(?'
|
||||
.'|(*:148)'
|
||||
.'|(*:156)'
|
||||
.'|(*:160)'
|
||||
.'|(*:168)'
|
||||
.')'
|
||||
.'|(.*)(*:169)'
|
||||
.'|(.*)(*:181)'
|
||||
.'|b\'b/([^/]++)(?'
|
||||
.'|(*:192)'
|
||||
.'|(*:200)'
|
||||
.'|(*:204)'
|
||||
.'|(*:212)'
|
||||
.')'
|
||||
.')'
|
||||
.'|/multi/hello(?:/([^/]++))?(*:236)'
|
||||
.'|/multi/hello(?:/([^/]++))?(*:248)'
|
||||
.'|/([^/]++)/b/([^/]++)(?'
|
||||
.'|(*:267)'
|
||||
.'|(*:275)'
|
||||
.'|(*:279)'
|
||||
.'|(*:287)'
|
||||
.')'
|
||||
.'|/aba/([^/]++)(*:297)'
|
||||
.')|(?i:([^\\.]++)\\.example\\.com)(?'
|
||||
.'|/aba/([^/]++)(*:309)'
|
||||
.')|(?i:([^\\.]++)\\.example\\.com)\\.(?'
|
||||
.'|/route1(?'
|
||||
.'|3/([^/]++)(*:357)'
|
||||
.'|4/([^/]++)(*:375)'
|
||||
.'|3/([^/]++)(*:371)'
|
||||
.'|4/([^/]++)(*:389)'
|
||||
.')'
|
||||
.')|(?i:c\\.example\\.com)(?'
|
||||
.'|/route15/([^/]++)(*:425)'
|
||||
.')|[^/]*+(?'
|
||||
.'|/route16/([^/]++)(*:460)'
|
||||
.')|(?i:c\\.example\\.com)\\.(?'
|
||||
.'|/route15/([^/]++)(*:441)'
|
||||
.')|(?:(?:[^.]*+\\.)++)(?'
|
||||
.'|/route16/([^/]++)(*:488)'
|
||||
.'|/a/(?'
|
||||
.'|a\\.\\.\\.(*:481)'
|
||||
.'|a\\.\\.\\.(*:509)'
|
||||
.'|b/(?'
|
||||
.'|([^/]++)(*:502)'
|
||||
.'|c/([^/]++)(*:520)'
|
||||
.'|([^/]++)(*:530)'
|
||||
.'|c/([^/]++)(*:548)'
|
||||
.')'
|
||||
.')'
|
||||
.')'
|
||||
@@ -132,7 +132,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
foreach ($regexList as $offset => $regex) {
|
||||
while (preg_match($regex, $matchedPathinfo, $matches)) {
|
||||
switch ($m = (int) $matches['MARK']) {
|
||||
case 103:
|
||||
case 115:
|
||||
$matches = array('foo' => $matches[1] ?? null);
|
||||
|
||||
// baz4
|
||||
@@ -159,7 +159,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
not_bazbaz6:
|
||||
|
||||
break;
|
||||
case 148:
|
||||
case 160:
|
||||
$matches = array('foo' => $matches[1] ?? null);
|
||||
|
||||
// foo1
|
||||
@@ -173,14 +173,14 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
not_foo1:
|
||||
|
||||
break;
|
||||
case 192:
|
||||
case 204:
|
||||
$matches = array('foo1' => $matches[1] ?? null);
|
||||
|
||||
// foo2
|
||||
return $this->mergeDefaults(array('_route' => 'foo2') + $matches, array());
|
||||
|
||||
break;
|
||||
case 267:
|
||||
case 279:
|
||||
$matches = array('_locale' => $matches[1] ?? null, 'foo' => $matches[2] ?? null);
|
||||
|
||||
// foo3
|
||||
@@ -189,23 +189,23 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
break;
|
||||
default:
|
||||
$routes = array(
|
||||
34 => array(array('_route' => 'foo', 'def' => 'test'), array('bar'), null, null),
|
||||
57 => array(array('_route' => 'bar'), array('foo'), array('GET' => 0, 'HEAD' => 1), null),
|
||||
77 => array(array('_route' => 'barhead'), array('foo'), array('GET' => 0), null),
|
||||
119 => array(array('_route' => 'quoter'), array('quoter'), null, null),
|
||||
156 => array(array('_route' => 'bar1'), array('bar'), null, null),
|
||||
169 => array(array('_route' => 'overridden'), array('var'), null, null),
|
||||
200 => array(array('_route' => 'bar2'), array('bar1'), null, null),
|
||||
236 => array(array('_route' => 'helloWorld', 'who' => 'World!'), array('who'), null, null),
|
||||
275 => array(array('_route' => 'bar3'), array('_locale', 'bar'), null, null),
|
||||
297 => array(array('_route' => 'foo4'), array('foo'), null, null),
|
||||
357 => array(array('_route' => 'route13'), array('var1', 'name'), null, null),
|
||||
375 => array(array('_route' => 'route14', 'var1' => 'val'), array('var1', 'name'), null, null),
|
||||
425 => array(array('_route' => 'route15'), array('name'), null, null),
|
||||
460 => array(array('_route' => 'route16', 'var1' => 'val'), array('name'), null, null),
|
||||
481 => array(array('_route' => 'a'), array(), null, null),
|
||||
502 => array(array('_route' => 'b'), array('var'), null, null),
|
||||
520 => array(array('_route' => 'c'), array('var'), null, null),
|
||||
46 => array(array('_route' => 'foo', 'def' => 'test'), array('bar'), null, null),
|
||||
69 => array(array('_route' => 'bar'), array('foo'), array('GET' => 0, 'HEAD' => 1), null),
|
||||
89 => array(array('_route' => 'barhead'), array('foo'), array('GET' => 0), null),
|
||||
131 => array(array('_route' => 'quoter'), array('quoter'), null, null),
|
||||
168 => array(array('_route' => 'bar1'), array('bar'), null, null),
|
||||
181 => array(array('_route' => 'overridden'), array('var'), null, null),
|
||||
212 => array(array('_route' => 'bar2'), array('bar1'), null, null),
|
||||
248 => array(array('_route' => 'helloWorld', 'who' => 'World!'), array('who'), null, null),
|
||||
287 => array(array('_route' => 'bar3'), array('_locale', 'bar'), null, null),
|
||||
309 => array(array('_route' => 'foo4'), array('foo'), null, null),
|
||||
371 => array(array('_route' => 'route13'), array('var1', 'name'), null, null),
|
||||
389 => array(array('_route' => 'route14', 'var1' => 'val'), array('var1', 'name'), null, null),
|
||||
441 => array(array('_route' => 'route15'), array('name'), null, null),
|
||||
488 => array(array('_route' => 'route16', 'var1' => 'val'), array('name'), null, null),
|
||||
509 => array(array('_route' => 'a'), array(), null, null),
|
||||
530 => array(array('_route' => 'b'), array('var'), null, null),
|
||||
548 => array(array('_route' => 'c'), array('var'), null, null),
|
||||
);
|
||||
|
||||
list($ret, $vars, $requiredMethods, $requiredSchemes) = $routes[$m];
|
||||
@@ -231,7 +231,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if (520 === $m) {
|
||||
if (548 === $m) {
|
||||
break;
|
||||
}
|
||||
$regex = substr_replace($regex, 'F', $m - $offset, 1 + strlen($m));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,12 +27,12 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
$canonicalMethod = 'GET';
|
||||
}
|
||||
|
||||
$matchedPathinfo = $host.$pathinfo;
|
||||
$matchedPathinfo = $host.'.'.$pathinfo;
|
||||
$regexList = array(
|
||||
0 => '{^(?'
|
||||
.'|(?i:([^\\.]++)\\.exampple\\.com)(?'
|
||||
.'|(?i:([^\\.]++)\\.exampple\\.com)\\.(?'
|
||||
.'|/abc([^/]++)(?'
|
||||
.'|(*:54)'
|
||||
.'|(*:56)'
|
||||
.')'
|
||||
.')'
|
||||
.')$}sD',
|
||||
@@ -41,7 +41,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
foreach ($regexList as $offset => $regex) {
|
||||
while (preg_match($regex, $matchedPathinfo, $matches)) {
|
||||
switch ($m = (int) $matches['MARK']) {
|
||||
case 54:
|
||||
case 56:
|
||||
$matches = array('foo' => $matches[1] ?? null, 'foo' => $matches[2] ?? null);
|
||||
|
||||
// r1
|
||||
@@ -53,7 +53,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
break;
|
||||
}
|
||||
|
||||
if (54 === $m) {
|
||||
if (56 === $m) {
|
||||
break;
|
||||
}
|
||||
$regex = substr_replace($regex, 'F', $m - $offset, 1 + strlen($m));
|
||||
|
||||
@@ -116,50 +116,50 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$matchedPathinfo = $host.$pathinfo;
|
||||
$matchedPathinfo = $host.'.'.$pathinfo;
|
||||
$regexList = array(
|
||||
0 => '{^(?'
|
||||
.'|[^/]*+(?'
|
||||
.'|/foo/(baz|symfony)(*:34)'
|
||||
.'|(?:(?:[^.]*+\\.)++)(?'
|
||||
.'|/foo/(baz|symfony)(*:46)'
|
||||
.'|/bar(?'
|
||||
.'|/([^/]++)(*:57)'
|
||||
.'|head/([^/]++)(*:77)'
|
||||
.'|/([^/]++)(*:69)'
|
||||
.'|head/([^/]++)(*:89)'
|
||||
.')'
|
||||
.'|/test/([^/]++)/(?'
|
||||
.'|(*:103)'
|
||||
.'|(*:115)'
|
||||
.')'
|
||||
.'|/([\']+)(*:119)'
|
||||
.'|/([\']+)(*:131)'
|
||||
.'|/a/(?'
|
||||
.'|b\'b/([^/]++)(?'
|
||||
.'|(*:148)'
|
||||
.'|(*:156)'
|
||||
.'|(*:160)'
|
||||
.'|(*:168)'
|
||||
.')'
|
||||
.'|(.*)(*:169)'
|
||||
.'|(.*)(*:181)'
|
||||
.'|b\'b/([^/]++)(?'
|
||||
.'|(*:192)'
|
||||
.'|(*:200)'
|
||||
.'|(*:204)'
|
||||
.'|(*:212)'
|
||||
.')'
|
||||
.')'
|
||||
.'|/multi/hello(?:/([^/]++))?(*:236)'
|
||||
.'|/multi/hello(?:/([^/]++))?(*:248)'
|
||||
.'|/([^/]++)/b/([^/]++)(?'
|
||||
.'|(*:267)'
|
||||
.'|(*:275)'
|
||||
.'|(*:279)'
|
||||
.'|(*:287)'
|
||||
.')'
|
||||
.'|/aba/([^/]++)(*:297)'
|
||||
.')|(?i:([^\\.]++)\\.example\\.com)(?'
|
||||
.'|/aba/([^/]++)(*:309)'
|
||||
.')|(?i:([^\\.]++)\\.example\\.com)\\.(?'
|
||||
.'|/route1(?'
|
||||
.'|3/([^/]++)(*:357)'
|
||||
.'|4/([^/]++)(*:375)'
|
||||
.'|3/([^/]++)(*:371)'
|
||||
.'|4/([^/]++)(*:389)'
|
||||
.')'
|
||||
.')|(?i:c\\.example\\.com)(?'
|
||||
.'|/route15/([^/]++)(*:425)'
|
||||
.')|[^/]*+(?'
|
||||
.'|/route16/([^/]++)(*:460)'
|
||||
.')|(?i:c\\.example\\.com)\\.(?'
|
||||
.'|/route15/([^/]++)(*:441)'
|
||||
.')|(?:(?:[^.]*+\\.)++)(?'
|
||||
.'|/route16/([^/]++)(*:488)'
|
||||
.'|/a/(?'
|
||||
.'|a\\.\\.\\.(*:481)'
|
||||
.'|a\\.\\.\\.(*:509)'
|
||||
.'|b/(?'
|
||||
.'|([^/]++)(*:502)'
|
||||
.'|c/([^/]++)(*:520)'
|
||||
.'|([^/]++)(*:530)'
|
||||
.'|c/([^/]++)(*:548)'
|
||||
.')'
|
||||
.')'
|
||||
.')'
|
||||
@@ -169,7 +169,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
foreach ($regexList as $offset => $regex) {
|
||||
while (preg_match($regex, $matchedPathinfo, $matches)) {
|
||||
switch ($m = (int) $matches['MARK']) {
|
||||
case 103:
|
||||
case 115:
|
||||
$matches = array('foo' => $matches[1] ?? null);
|
||||
|
||||
// baz4
|
||||
@@ -196,7 +196,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
not_bazbaz6:
|
||||
|
||||
break;
|
||||
case 148:
|
||||
case 160:
|
||||
$matches = array('foo' => $matches[1] ?? null);
|
||||
|
||||
// foo1
|
||||
@@ -210,14 +210,14 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
not_foo1:
|
||||
|
||||
break;
|
||||
case 192:
|
||||
case 204:
|
||||
$matches = array('foo1' => $matches[1] ?? null);
|
||||
|
||||
// foo2
|
||||
return $this->mergeDefaults(array('_route' => 'foo2') + $matches, array());
|
||||
|
||||
break;
|
||||
case 267:
|
||||
case 279:
|
||||
$matches = array('_locale' => $matches[1] ?? null, 'foo' => $matches[2] ?? null);
|
||||
|
||||
// foo3
|
||||
@@ -226,23 +226,23 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
break;
|
||||
default:
|
||||
$routes = array(
|
||||
34 => array(array('_route' => 'foo', 'def' => 'test'), array('bar'), null, null),
|
||||
57 => array(array('_route' => 'bar'), array('foo'), array('GET' => 0, 'HEAD' => 1), null),
|
||||
77 => array(array('_route' => 'barhead'), array('foo'), array('GET' => 0), null),
|
||||
119 => array(array('_route' => 'quoter'), array('quoter'), null, null),
|
||||
156 => array(array('_route' => 'bar1'), array('bar'), null, null),
|
||||
169 => array(array('_route' => 'overridden'), array('var'), null, null),
|
||||
200 => array(array('_route' => 'bar2'), array('bar1'), null, null),
|
||||
236 => array(array('_route' => 'helloWorld', 'who' => 'World!'), array('who'), null, null),
|
||||
275 => array(array('_route' => 'bar3'), array('_locale', 'bar'), null, null),
|
||||
297 => array(array('_route' => 'foo4'), array('foo'), null, null),
|
||||
357 => array(array('_route' => 'route13'), array('var1', 'name'), null, null),
|
||||
375 => array(array('_route' => 'route14', 'var1' => 'val'), array('var1', 'name'), null, null),
|
||||
425 => array(array('_route' => 'route15'), array('name'), null, null),
|
||||
460 => array(array('_route' => 'route16', 'var1' => 'val'), array('name'), null, null),
|
||||
481 => array(array('_route' => 'a'), array(), null, null),
|
||||
502 => array(array('_route' => 'b'), array('var'), null, null),
|
||||
520 => array(array('_route' => 'c'), array('var'), null, null),
|
||||
46 => array(array('_route' => 'foo', 'def' => 'test'), array('bar'), null, null),
|
||||
69 => array(array('_route' => 'bar'), array('foo'), array('GET' => 0, 'HEAD' => 1), null),
|
||||
89 => array(array('_route' => 'barhead'), array('foo'), array('GET' => 0), null),
|
||||
131 => array(array('_route' => 'quoter'), array('quoter'), null, null),
|
||||
168 => array(array('_route' => 'bar1'), array('bar'), null, null),
|
||||
181 => array(array('_route' => 'overridden'), array('var'), null, null),
|
||||
212 => array(array('_route' => 'bar2'), array('bar1'), null, null),
|
||||
248 => array(array('_route' => 'helloWorld', 'who' => 'World!'), array('who'), null, null),
|
||||
287 => array(array('_route' => 'bar3'), array('_locale', 'bar'), null, null),
|
||||
309 => array(array('_route' => 'foo4'), array('foo'), null, null),
|
||||
371 => array(array('_route' => 'route13'), array('var1', 'name'), null, null),
|
||||
389 => array(array('_route' => 'route14', 'var1' => 'val'), array('var1', 'name'), null, null),
|
||||
441 => array(array('_route' => 'route15'), array('name'), null, null),
|
||||
488 => array(array('_route' => 'route16', 'var1' => 'val'), array('name'), null, null),
|
||||
509 => array(array('_route' => 'a'), array(), null, null),
|
||||
530 => array(array('_route' => 'b'), array('var'), null, null),
|
||||
548 => array(array('_route' => 'c'), array('var'), null, null),
|
||||
);
|
||||
|
||||
list($ret, $vars, $requiredMethods, $requiredSchemes) = $routes[$m];
|
||||
@@ -268,7 +268,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if (520 === $m) {
|
||||
if (548 === $m) {
|
||||
break;
|
||||
}
|
||||
$regex = substr_replace($regex, 'F', $m - $offset, 1 + strlen($m));
|
||||
|
||||
@@ -32,10 +32,10 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
.'|/(a)(*:11)'
|
||||
.')$}sD',
|
||||
11 => '{^(?'
|
||||
.'|/(.)(*:26)'
|
||||
.'|/(.)(*:22)'
|
||||
.')$}sDu',
|
||||
26 => '{^(?'
|
||||
.'|/(.)(*:41)'
|
||||
22 => '{^(?'
|
||||
.'|/(.)(*:33)'
|
||||
.')$}sD',
|
||||
);
|
||||
|
||||
@@ -45,8 +45,8 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
default:
|
||||
$routes = array(
|
||||
11 => array(array('_route' => 'a'), array('a'), null, null),
|
||||
26 => array(array('_route' => 'b'), array('a'), null, null),
|
||||
41 => array(array('_route' => 'c'), array('a'), null, null),
|
||||
22 => array(array('_route' => 'b'), array('a'), null, null),
|
||||
33 => array(array('_route' => 'c'), array('a'), null, null),
|
||||
);
|
||||
|
||||
list($ret, $vars, $requiredMethods, $requiredSchemes) = $routes[$m];
|
||||
@@ -72,7 +72,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if (41 === $m) {
|
||||
if (33 === $m) {
|
||||
break;
|
||||
}
|
||||
$regex = substr_replace($regex, 'F', $m - $offset, 1 + strlen($m));
|
||||
|
||||
@@ -245,6 +245,18 @@ class UrlMatcherTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function testMultipleParams()
|
||||
{
|
||||
$coll = new RouteCollection();
|
||||
$coll->add('foo1', new Route('/foo/{a}/{b}'));
|
||||
$coll->add('foo2', new Route('/foo/{a}/test/test/{b}'));
|
||||
$coll->add('foo3', new Route('/foo/{a}/{b}/{c}/{d}'));
|
||||
|
||||
$route = $this->getUrlMatcher($coll)->match('/foo/test/test/test/bar')['_route'];
|
||||
|
||||
$this->assertEquals('foo2', $route);
|
||||
}
|
||||
|
||||
public function testDefaultRequirementForOptionalVariables()
|
||||
{
|
||||
$coll = new RouteCollection();
|
||||
@@ -621,6 +633,43 @@ class UrlMatcherTest extends TestCase
|
||||
$this->assertEquals(array('_route' => 'a', 'id' => 'foo/bar'), $matcher->match('/foo/bar.html'));
|
||||
}
|
||||
|
||||
public function testHostPattern()
|
||||
{
|
||||
$coll = new RouteCollection();
|
||||
$coll->add('a', new Route('/{app}/{action}/{unused}', array(), array(), array(), '{host}'));
|
||||
|
||||
$expected = array(
|
||||
'_route' => 'a',
|
||||
'app' => 'an_app',
|
||||
'action' => 'an_action',
|
||||
'unused' => 'unused',
|
||||
'host' => 'foo',
|
||||
);
|
||||
$matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'foo'));
|
||||
$this->assertEquals($expected, $matcher->match('/an_app/an_action/unused'));
|
||||
}
|
||||
|
||||
public function testUtf8Prefix()
|
||||
{
|
||||
$coll = new RouteCollection();
|
||||
$coll->add('a', new Route('/é{foo}', array(), array(), array('utf8' => true)));
|
||||
$coll->add('b', new Route('/è{bar}', array(), array(), array('utf8' => true)));
|
||||
|
||||
$matcher = $this->getUrlMatcher($coll);
|
||||
$this->assertEquals('a', $matcher->match('/éo')['_route']);
|
||||
}
|
||||
|
||||
public function testUtf8AndMethodMatching()
|
||||
{
|
||||
$coll = new RouteCollection();
|
||||
$coll->add('a', new Route('/admin/api/list/{shortClassName}/{id}.{_format}', array(), array(), array('utf8' => true), '', array(), array('PUT')));
|
||||
$coll->add('b', new Route('/admin/api/package.{_format}', array(), array(), array(), '', array(), array('POST')));
|
||||
$coll->add('c', new Route('/admin/api/package.{_format}', array('_format' => 'json'), array(), array(), '', array(), array('GET')));
|
||||
|
||||
$matcher = $this->getUrlMatcher($coll);
|
||||
$this->assertEquals('c', $matcher->match('/admin/api/package.json')['_route']);
|
||||
}
|
||||
|
||||
protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null)
|
||||
{
|
||||
return new UrlMatcher($routes, $context ?: new RequestContext());
|
||||
|
||||
@@ -398,6 +398,7 @@ class RouteCompilerTest extends TestCase
|
||||
yield array('#^/(?P<foo>(?:b))$#sD', '(?:b)');
|
||||
yield array('#^/(?P<foo>(?(b)b))$#sD', '(?(b)b)');
|
||||
yield array('#^/(?P<foo>(*F))$#sD', '(*F)');
|
||||
yield array('#^/(?P<foo>(?:(?:foo)))$#sD', '((foo))');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1
vendor/symfony/routing/composer.json
vendored
1
vendor/symfony/routing/composer.json
vendored
@@ -25,7 +25,6 @@
|
||||
"symfony/expression-language": "~3.4|~4.0",
|
||||
"symfony/dependency-injection": "~3.4|~4.0",
|
||||
"doctrine/annotations": "~1.0",
|
||||
"doctrine/common": "~2.2",
|
||||
"psr/log": "~1.0"
|
||||
},
|
||||
"conflict": {
|
||||
|
||||
@@ -45,7 +45,7 @@ abstract class AbstractFileExtractor
|
||||
|
||||
private function toSplFileInfo(string $file): \SplFileInfo
|
||||
{
|
||||
return ($file instanceof \SplFileInfo) ? $file : new \SplFileInfo($file);
|
||||
return new \SplFileInfo($file);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
53
vendor/symfony/var-dumper/Caster/SplCaster.php
vendored
53
vendor/symfony/var-dumper/Caster/SplCaster.php
vendored
@@ -29,30 +29,12 @@ class SplCaster
|
||||
|
||||
public static function castArrayObject(\ArrayObject $c, array $a, Stub $stub, $isNested)
|
||||
{
|
||||
$prefix = Caster::PREFIX_VIRTUAL;
|
||||
$class = $stub->class;
|
||||
$flags = $c->getFlags();
|
||||
return self::castSplArray($c, $a, $stub, $isNested);
|
||||
}
|
||||
|
||||
$b = array(
|
||||
$prefix.'flag::STD_PROP_LIST' => (bool) ($flags & \ArrayObject::STD_PROP_LIST),
|
||||
$prefix.'flag::ARRAY_AS_PROPS' => (bool) ($flags & \ArrayObject::ARRAY_AS_PROPS),
|
||||
$prefix.'iteratorClass' => new ClassStub($c->getIteratorClass()),
|
||||
$prefix.'storage' => $c->getArrayCopy(),
|
||||
);
|
||||
|
||||
if ('ArrayObject' === $class) {
|
||||
$a = $b;
|
||||
} else {
|
||||
if (!($flags & \ArrayObject::STD_PROP_LIST)) {
|
||||
$c->setFlags(\ArrayObject::STD_PROP_LIST);
|
||||
$a = Caster::castObject($c, $class);
|
||||
$c->setFlags($flags);
|
||||
}
|
||||
|
||||
$a += $b;
|
||||
}
|
||||
|
||||
return $a;
|
||||
public static function castArrayIterator(\ArrayIterator $c, array $a, Stub $stub, $isNested)
|
||||
{
|
||||
return self::castSplArray($c, $a, $stub, $isNested);
|
||||
}
|
||||
|
||||
public static function castHeap(\Iterator $c, array $a, Stub $stub, $isNested)
|
||||
@@ -186,7 +168,7 @@ class SplCaster
|
||||
|
||||
$clone = clone $c;
|
||||
foreach ($clone as $obj) {
|
||||
$storage[spl_object_hash($obj)] = array(
|
||||
$storage[] = array(
|
||||
'object' => $obj,
|
||||
'info' => $clone->getInfo(),
|
||||
);
|
||||
@@ -205,4 +187,27 @@ class SplCaster
|
||||
|
||||
return $a;
|
||||
}
|
||||
|
||||
private static function castSplArray($c, array $a, Stub $stub, $isNested)
|
||||
{
|
||||
$prefix = Caster::PREFIX_VIRTUAL;
|
||||
$class = $stub->class;
|
||||
$flags = $c->getFlags();
|
||||
|
||||
if (!($flags & \ArrayObject::STD_PROP_LIST)) {
|
||||
$c->setFlags(\ArrayObject::STD_PROP_LIST);
|
||||
$a = Caster::castObject($c, $class);
|
||||
$c->setFlags($flags);
|
||||
}
|
||||
$a += array(
|
||||
$prefix.'flag::STD_PROP_LIST' => (bool) ($flags & \ArrayObject::STD_PROP_LIST),
|
||||
$prefix.'flag::ARRAY_AS_PROPS' => (bool) ($flags & \ArrayObject::ARRAY_AS_PROPS),
|
||||
);
|
||||
if ($c instanceof \ArrayObject) {
|
||||
$a[$prefix.'iteratorClass'] = new ClassStub($c->getIteratorClass());
|
||||
}
|
||||
$a[$prefix.'storage'] = $c->getArrayCopy();
|
||||
|
||||
return $a;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,7 @@ abstract class AbstractCloner implements ClonerInterface
|
||||
'AMQPEnvelope' => array('Symfony\Component\VarDumper\Caster\AmqpCaster', 'castEnvelope'),
|
||||
|
||||
'ArrayObject' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayObject'),
|
||||
'ArrayIterator' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castArrayIterator'),
|
||||
'SplDoublyLinkedList' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castDoublyLinkedList'),
|
||||
'SplFileInfo' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castFileInfo'),
|
||||
'SplFileObject' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castFileObject'),
|
||||
|
||||
@@ -164,7 +164,7 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
|
||||
*/
|
||||
protected function dumpLine($depth)
|
||||
{
|
||||
call_user_func($this->lineDumper, $this->line, $depth, $this->indentPad);
|
||||
\call_user_func($this->lineDumper, $this->line, $depth, $this->indentPad);
|
||||
$this->line = '';
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Symfony\Component\VarDumper\Dumper;
|
||||
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface;
|
||||
use Symfony\Component\VarDumper\Server\Connection;
|
||||
|
||||
/**
|
||||
* ServerDumper forwards serialized Data clones to a server.
|
||||
@@ -21,10 +22,8 @@ use Symfony\Component\VarDumper\Dumper\ContextProvider\ContextProviderInterface;
|
||||
*/
|
||||
class ServerDumper implements DataDumperInterface
|
||||
{
|
||||
private $host;
|
||||
private $connection;
|
||||
private $wrappedDumper;
|
||||
private $contextProviders;
|
||||
private $socket;
|
||||
|
||||
/**
|
||||
* @param string $host The server host
|
||||
@@ -33,83 +32,22 @@ class ServerDumper implements DataDumperInterface
|
||||
*/
|
||||
public function __construct(string $host, DataDumperInterface $wrappedDumper = null, array $contextProviders = array())
|
||||
{
|
||||
if (false === strpos($host, '://')) {
|
||||
$host = 'tcp://'.$host;
|
||||
}
|
||||
|
||||
$this->host = $host;
|
||||
$this->connection = new Connection($host, $contextProviders);
|
||||
$this->wrappedDumper = $wrappedDumper;
|
||||
$this->contextProviders = $contextProviders;
|
||||
}
|
||||
|
||||
public function getContextProviders(): array
|
||||
{
|
||||
return $this->contextProviders;
|
||||
return $this->connection->getContextProviders();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function dump(Data $data, $output = null): void
|
||||
public function dump(Data $data)
|
||||
{
|
||||
set_error_handler(array(self::class, 'nullErrorHandler'));
|
||||
|
||||
$failed = false;
|
||||
try {
|
||||
if (!$this->socket = $this->socket ?: $this->createSocket()) {
|
||||
$failed = true;
|
||||
|
||||
return;
|
||||
}
|
||||
} finally {
|
||||
restore_error_handler();
|
||||
if ($failed && $this->wrappedDumper) {
|
||||
$this->wrappedDumper->dump($data);
|
||||
}
|
||||
if (!$this->connection->write($data) && $this->wrappedDumper) {
|
||||
$this->wrappedDumper->dump($data);
|
||||
}
|
||||
|
||||
set_error_handler(array(self::class, 'nullErrorHandler'));
|
||||
|
||||
$context = array('timestamp' => time());
|
||||
foreach ($this->contextProviders as $name => $provider) {
|
||||
$context[$name] = $provider->getContext();
|
||||
}
|
||||
$context = array_filter($context);
|
||||
|
||||
$encodedPayload = base64_encode(serialize(array($data, $context)))."\n";
|
||||
$failed = false;
|
||||
|
||||
try {
|
||||
$retry = 3;
|
||||
while ($retry > 0 && $failed = (-1 === stream_socket_sendto($this->socket, $encodedPayload))) {
|
||||
stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR);
|
||||
if ($failed = !$this->socket = $this->createSocket()) {
|
||||
break;
|
||||
}
|
||||
|
||||
--$retry;
|
||||
}
|
||||
} finally {
|
||||
restore_error_handler();
|
||||
if ($failed && $this->wrappedDumper) {
|
||||
$this->wrappedDumper->dump($data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function nullErrorHandler()
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
private function createSocket()
|
||||
{
|
||||
$socket = stream_socket_client($this->host, $errno, $errstr, 1, STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT);
|
||||
|
||||
if ($socket) {
|
||||
stream_set_blocking($socket, false);
|
||||
}
|
||||
|
||||
return $socket;
|
||||
}
|
||||
}
|
||||
|
||||
0
vendor/symfony/var-dumper/Resources/bin/var-dump-server
vendored
Normal file → Executable file
0
vendor/symfony/var-dumper/Resources/bin/var-dump-server
vendored
Normal file → Executable file
@@ -22,14 +22,6 @@ a {
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
code {
|
||||
color: #cc2255;
|
||||
background-color: #f7f7f9;
|
||||
border: 1px solid #e1e1e8;
|
||||
border-radius: 3px;
|
||||
margin-right: 5px;
|
||||
padding: 0 3px;
|
||||
}
|
||||
.text-small {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
@@ -60,6 +52,12 @@ article > header > .row > h2 {
|
||||
article > header > .row > h2 > code {
|
||||
white-space: nowrap;
|
||||
user-select: none;
|
||||
color: #cc2255;
|
||||
background-color: #f7f7f9;
|
||||
border: 1px solid #e1e1e8;
|
||||
border-radius: 3px;
|
||||
margin-right: 5px;
|
||||
padding: 0 3px;
|
||||
}
|
||||
article > header > .row > time.col {
|
||||
flex: 0;
|
||||
|
||||
@@ -163,4 +163,45 @@ EOTXT;
|
||||
|
||||
$this->assertDumpMatchesFormat('%ADateTime%A', $var);
|
||||
}
|
||||
|
||||
public function testCastArrayObject()
|
||||
{
|
||||
$var = new \ArrayObject(array(123));
|
||||
$var->foo = 234;
|
||||
|
||||
$expected = <<<EOTXT
|
||||
ArrayObject {
|
||||
+"foo": 234
|
||||
flag::STD_PROP_LIST: false
|
||||
flag::ARRAY_AS_PROPS: false
|
||||
iteratorClass: "ArrayIterator"
|
||||
storage: array:1 [
|
||||
0 => 123
|
||||
]
|
||||
}
|
||||
EOTXT;
|
||||
$this->assertDumpEquals($expected, $var);
|
||||
}
|
||||
|
||||
public function testArrayIterator()
|
||||
{
|
||||
$var = new MyArrayIterator(array(234));
|
||||
|
||||
$expected = <<<EOTXT
|
||||
Symfony\Component\VarDumper\Tests\Caster\MyArrayIterator {
|
||||
-foo: 123
|
||||
flag::STD_PROP_LIST: false
|
||||
flag::ARRAY_AS_PROPS: false
|
||||
storage: array:1 [
|
||||
0 => 234
|
||||
]
|
||||
}
|
||||
EOTXT;
|
||||
$this->assertDumpEquals($expected, $var);
|
||||
}
|
||||
}
|
||||
|
||||
class MyArrayIterator extends \ArrayIterator
|
||||
{
|
||||
private $foo = 123;
|
||||
}
|
||||
|
||||
@@ -55,26 +55,24 @@ class ServerDumperTest extends TestCase
|
||||
|
||||
$dumped = null;
|
||||
$process = $this->getServerProcess();
|
||||
$process->start(function ($type, $buffer) use ($process, &$dumped) {
|
||||
$process->start(function ($type, $buffer) use ($process, &$dumped, $dumper, $data) {
|
||||
if (Process::ERR === $type) {
|
||||
$process->stop();
|
||||
$this->fail();
|
||||
} elseif ("READY\n" === $buffer) {
|
||||
$dumper->dump($data);
|
||||
} else {
|
||||
$dumped .= $buffer;
|
||||
}
|
||||
});
|
||||
|
||||
sleep(3);
|
||||
|
||||
$dumper->dump($data);
|
||||
|
||||
$process->wait();
|
||||
|
||||
$this->assertTrue($process->isSuccessful());
|
||||
$this->assertStringMatchesFormat(<<<'DUMP'
|
||||
(3) "foo"
|
||||
[
|
||||
"timestamp" => %d
|
||||
"timestamp" => %d.%d
|
||||
"foo_provider" => [
|
||||
(3) "foo"
|
||||
]
|
||||
|
||||
@@ -29,6 +29,8 @@ $server = new DumpServer(getenv('VAR_DUMPER_SERVER'));
|
||||
|
||||
$server->start();
|
||||
|
||||
echo "READY\n";
|
||||
|
||||
$server->listen(function (Data $data, array $context, $clientId) {
|
||||
dump((string) $data, $context, $clientId);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user