diff --git a/src/Illuminate/Foundation/Application.php b/src/Illuminate/Foundation/Application.php index 928bc0ba4..ed43efbc7 100755 --- a/src/Illuminate/Foundation/Application.php +++ b/src/Illuminate/Foundation/Application.php @@ -861,7 +861,7 @@ public function prepareRequest(Request $request) { if ( ! is_null($this['config']['session.driver']) && ! $request->hasSession()) { - $request->setSession($this['session']->driver()); + $request->setLaravelSession($this['session']->driver()); } return $request; diff --git a/src/Illuminate/Foundation/Console/Optimize/config.php b/src/Illuminate/Foundation/Console/Optimize/config.php index 9b838ea48..ee3a13a24 100755 --- a/src/Illuminate/Foundation/Console/Optimize/config.php +++ b/src/Illuminate/Foundation/Console/Optimize/config.php @@ -68,7 +68,6 @@ $basePath.'/vendor/laravel/framework/src/Illuminate/Database/DatabaseManager.php', $basePath.'/vendor/laravel/framework/src/Illuminate/Database/ConnectionResolverInterface.php', $basePath.'/vendor/laravel/framework/src/Illuminate/Database/Connectors/ConnectionFactory.php', - $basePath.'/vendor/laravel/framework/src/Illuminate/Session/SessionInterface.php', $basePath.'/vendor/laravel/framework/src/Illuminate/Session/Middleware.php', $basePath.'/vendor/laravel/framework/src/Illuminate/Session/Store.php', $basePath.'/vendor/laravel/framework/src/Illuminate/Session/SessionManager.php', diff --git a/src/Illuminate/Http/Request.php b/src/Illuminate/Http/Request.php index 092c7c727..c190e75eb 100755 --- a/src/Illuminate/Http/Request.php +++ b/src/Illuminate/Http/Request.php @@ -1,10 +1,13 @@ session instanceof SymfonySessionDecorator; + } + + /** + * Get the Symfony session (decorator) associated with the request. + * + * @return \Symfony\Component\HttpFoundation\Session\SessionInterface + * + * @throws \Symfony\Component\HttpFoundation\Exception\SessionNotFoundException + */ + #[\Override] + public function getSession(): SessionInterface + { + return $this->hasSession() + ? $this->session + : throw new SessionNotFoundException; + } + + /** + * Get the session store associated with the request. * * @return \Illuminate\Session\Store * @@ -607,7 +637,18 @@ public function session() throw new \RuntimeException("Session store not set on request."); } - return $this->getSession(); + return $this->session->store; + } + + /** + * Set the session instance on the request. + * + * @param \Illuminate\Contracts\Session\Session $session + * @return void + */ + public function setLaravelSession($session) + { + $this->session = new SymfonySessionDecorator($session); } } diff --git a/src/Illuminate/Session/Middleware.php b/src/Illuminate/Session/Middleware.php index e99937459..171eca4f1 100644 --- a/src/Illuminate/Session/Middleware.php +++ b/src/Illuminate/Session/Middleware.php @@ -2,6 +2,7 @@ use Closure; use Carbon\Carbon; +use Illuminate\Contracts\Session\Session; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -66,7 +67,7 @@ public function handle(Request $request, $type = HttpKernelInterface::MAIN_REQUE { $session = $this->startSession($request); - $request->setSession($session); + $request->setLaravelSession($session); } $response = $this->app->handle($request, $type, $catch); @@ -105,7 +106,7 @@ public function checkRequestForArraySessions(Request $request) * Start the session for the given request. * * @param \Symfony\Component\HttpFoundation\Request $request - * @return \Illuminate\Session\SessionInterface + * @return \Illuminate\Contracts\Session\Session */ protected function startSession(Request $request) { @@ -119,10 +120,10 @@ protected function startSession(Request $request) /** * Close the session handling for the request. * - * @param \Illuminate\Session\SessionInterface $session + * @param \Illuminate\Contracts\Session\Session $session * @return void */ - protected function closeSession(SessionInterface $session) + protected function closeSession(Session $session) { $session->save(); @@ -145,10 +146,10 @@ protected function getUrl(Request $request) /** * Remove the garbage from the session if necessary. * - * @param \Illuminate\Session\SessionInterface $session + * @param \Illuminate\Contracts\Session\Session $session * @return void */ - protected function collectGarbage(SessionInterface $session) + protected function collectGarbage(Session $session) { $config = $this->manager->getSessionConfig(); @@ -183,10 +184,10 @@ protected function storeCurrentUrl(Request $request, $session) * Add the session cookie to the application response. * * @param \Symfony\Component\HttpFoundation\Response $response - * @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session + * @param \Illuminate\Contracts\Session\Session $session * @return void */ - protected function addCookieToResponse(Response $response, SessionInterface $session) + protected function addCookieToResponse(Response $response, Session $session) { $s = $session; @@ -252,7 +253,7 @@ protected function sessionIsPersistent(?array $config = null) * Get the session implementation from the manager. * * @param \Symfony\Component\HttpFoundation\Request $request - * @return \Illuminate\Session\SessionInterface + * @return \Illuminate\Contracts\Session\Session */ public function getSession(Request $request) { diff --git a/src/Illuminate/Session/SessionInterface.php b/src/Illuminate/Session/SessionInterface.php deleted file mode 100644 index 43537d412..000000000 --- a/src/Illuminate/Session/SessionInterface.php +++ /dev/null @@ -1,30 +0,0 @@ -setId($id); $this->name = $name; $this->handler = $handler; - $this->metaBag = new MetadataBag; } /** - * {@inheritdoc} + * Start the session, reading the data from a handler. + * + * @return bool */ public function start(): bool { @@ -100,13 +79,6 @@ public function start(): bool protected function loadSession() { $this->attributes = $this->readFromHandler(); - - foreach (array_merge($this->bags, array($this->metaBag)) as $bag) - { - $this->initializeLocalBag($bag); - - $bag->initialize($this->bagData[$bag->getStorageKey()]); - } } /** @@ -122,18 +94,9 @@ protected function readFromHandler() } /** - * Initialize a bag in storage if it doesn't exist. + * Get the current session ID. * - * @param \Symfony\Component\HttpFoundation\Session\SessionBagInterface $bag - * @return void - */ - protected function initializeLocalBag($bag) - { - $this->bagData[$bag->getStorageKey()] = $this->pull($bag->getStorageKey(), []); - } - - /** - * {@inheritdoc} + * @return string */ public function getId(): string { @@ -141,7 +104,10 @@ public function getId(): string } /** - * {@inheritdoc} + * Set the session ID. + * + * @param string $id + * @return void */ public function setId($id) { @@ -175,7 +141,9 @@ protected function generateSessionId(): string } /** - * {@inheritdoc} + * Get the name of the session. + * + * @return string */ public function getName(): string { @@ -183,7 +151,10 @@ public function getName(): string } /** - * {@inheritdoc} + * Set the name of the session. + * + * @param string $name + * @return void */ public function setName($name) { @@ -191,9 +162,11 @@ public function setName($name) } /** - * {@inheritdoc} + * Flush the session data and regenerate the ID. + * + * @return bool */ - public function invalidate($lifetime = null): bool + public function invalidate(): bool { $this->attributes = array(); @@ -203,9 +176,12 @@ public function invalidate($lifetime = null): bool } /** - * {@inheritdoc} + * Generate a new session ID for the session. + * + * @param bool $destroy + * @return bool */ - public function migrate($destroy = false, $lifetime = null): bool + public function migrate($destroy = false): bool { if ($destroy) $this->handler->destroy($this->getId()); @@ -226,12 +202,12 @@ public function regenerate($destroy = false) } /** - * {@inheritdoc} + * Save the session data to storage. + * + * @return void */ public function save() { - $this->addBagDataToSession(); - $this->ageFlashData(); $this->handler->write($this->getId(), serialize($this->attributes)); @@ -239,19 +215,6 @@ public function save() $this->started = false; } - /** - * Merge all of the bag data into the session. - * - * @return void - */ - protected function addBagDataToSession() - { - foreach (array_merge($this->bags, array($this->metaBag)) as $bag) - { - $this->put($bag->getStorageKey(), $this->bagData[$bag->getStorageKey()]); - } - } - /** * Age the flash data for the session. * @@ -267,7 +230,28 @@ public function ageFlashData() } /** - * {@inheritdoc} + * Checks if a key exists. + * + * @param string|array $key + * @return bool + */ + public function exists($key): bool + { + $placeholder = new stdClass; + + foreach (is_array($key) ? $key : func_get_args() as $k) + { + if ($this->get($k, $placeholder) === $placeholder) return false; + } + + return true; + } + + /** + * Determine if a key is present and not null. + * + * @param string $name + * @return bool */ public function has($name): bool { @@ -275,7 +259,11 @@ public function has($name): bool } /** - * {@inheritdoc} + * Get an item from the session. + * + * @param string $name + * @param mixed $default + * @return mixed */ public function get($name, $default = null): mixed { @@ -325,7 +313,11 @@ public function getOldInput($key = null, $default = null) } /** - * {@inheritdoc} + * Set a key / value pair in the session. + * + * @param string $name + * @param mixed $value + * @return void */ public function set($name, $value) { @@ -372,7 +364,8 @@ public function push($key, $value) * @param mixed $value * @return void */ - public function flash($key, $value) + // ponytail: keeps 4.2 flash.{new,old} keys, not v13 _flash.* — align at the illuminate/session swap when live sessions drain. + public function flash($key, $value = true) { $this->put($key, $value); @@ -444,7 +437,9 @@ protected function removeFromOldFlashData(array $keys) } /** - * {@inheritdoc} + * Get all of the session data. + * + * @return array */ public function all(): array { @@ -452,7 +447,10 @@ public function all(): array } /** - * {@inheritdoc} + * Replace the given session attributes entirely. + * + * @param array $attributes + * @return void */ public function replace(array $attributes) { @@ -463,7 +461,10 @@ public function replace(array $attributes) } /** - * {@inheritdoc} + * Remove an item from the session, returning its value. + * + * @param string $name + * @return mixed */ public function remove($name): mixed { @@ -471,9 +472,9 @@ public function remove($name): mixed } /** - * Remove an item from the session. + * Remove one or many items from the session. * - * @param string $key + * @param string|array $key * @return void */ public function forget($key) @@ -481,19 +482,6 @@ public function forget($key) array_forget($this->attributes, $key); } - /** - * {@inheritdoc} - */ - public function clear() - { - $this->attributes = array(); - - foreach ($this->bags as $bag) - { - $bag->clear(); - } - } - /** * Remove all of the items from the session. * @@ -501,55 +489,19 @@ public function clear() */ public function flush() { - $this->clear(); + $this->attributes = array(); } /** - * {@inheritdoc} + * Determine if the session has been started. + * + * @return bool */ public function isStarted(): bool { return $this->started; } - /** - * {@inheritdoc} - */ - public function registerBag(SessionBagInterface $bag) - { - $this->bags[$bag->getStorageKey()] = $bag; - } - - /** - * {@inheritdoc} - */ - public function getBag($name): SessionBagInterface - { - return array_get($this->bags, $name, function() - { - throw new \InvalidArgumentException("Bag not registered."); - }); - } - - /** - * {@inheritdoc} - */ - public function getMetadataBag(): MetadataBag - { - return $this->metaBag; - } - - /** - * Get the raw bag data array for a given bag. - * - * @param string $name - * @return array - */ - public function getBagData($name) - { - return array_get($this->bagData, $name, array()); - } - /** * Get the CSRF token value. * @@ -638,10 +590,10 @@ public function handlerNeedsRequest() /** * Set the request on the handler instance. * - * @param \Symfony\Component\HttpFoundation\Request $request + * @param \Illuminate\Http\Request $request * @return void */ - public function setRequestOnHandler(Request $request) + public function setRequestOnHandler($request) { if ($this->handlerNeedsRequest()) { diff --git a/src/Illuminate/Session/SymfonySessionDecorator.php b/src/Illuminate/Session/SymfonySessionDecorator.php new file mode 100644 index 000000000..54a899ea7 --- /dev/null +++ b/src/Illuminate/Session/SymfonySessionDecorator.php @@ -0,0 +1,191 @@ +store = $store; + } + + /** + * {@inheritdoc} + */ + public function start(): bool + { + return $this->store->start(); + } + + /** + * {@inheritdoc} + */ + public function getId(): string + { + return $this->store->getId(); + } + + /** + * {@inheritdoc} + */ + public function setId(string $id): void + { + $this->store->setId($id); + } + + /** + * {@inheritdoc} + */ + public function getName(): string + { + return $this->store->getName(); + } + + /** + * {@inheritdoc} + */ + public function setName(string $name): void + { + $this->store->setName($name); + } + + /** + * {@inheritdoc} + */ + public function invalidate(?int $lifetime = null): bool + { + $this->store->invalidate(); + + return true; + } + + /** + * {@inheritdoc} + */ + public function migrate(bool $destroy = false, ?int $lifetime = null): bool + { + $this->store->migrate($destroy); + + return true; + } + + /** + * {@inheritdoc} + */ + public function save(): void + { + $this->store->save(); + } + + /** + * {@inheritdoc} + */ + public function has(string $name): bool + { + return $this->store->has($name); + } + + /** + * {@inheritdoc} + */ + public function get(string $name, mixed $default = null): mixed + { + return $this->store->get($name, $default); + } + + /** + * {@inheritdoc} + */ + public function set(string $name, mixed $value): void + { + $this->store->put($name, $value); + } + + /** + * {@inheritdoc} + */ + public function all(): array + { + return $this->store->all(); + } + + /** + * {@inheritdoc} + */ + public function replace(array $attributes): void + { + $this->store->replace($attributes); + } + + /** + * {@inheritdoc} + */ + public function remove(string $name): mixed + { + return $this->store->remove($name); + } + + /** + * {@inheritdoc} + */ + public function clear(): void + { + $this->store->flush(); + } + + /** + * {@inheritdoc} + */ + public function isStarted(): bool + { + return $this->store->isStarted(); + } + + /** + * {@inheritdoc} + * + * @throws \BadMethodCallException + */ + public function registerBag(SessionBagInterface $bag): void + { + throw new BadMethodCallException('Method not implemented by Laravel.'); + } + + /** + * {@inheritdoc} + * + * @throws \BadMethodCallException + */ + public function getBag(string $name): SessionBagInterface + { + throw new BadMethodCallException('Method not implemented by Laravel.'); + } + + /** + * {@inheritdoc} + * + * @throws \BadMethodCallException + */ + public function getMetadataBag(): MetadataBag + { + throw new BadMethodCallException('Method not implemented by Laravel.'); + } +} diff --git a/tests/Http/HttpRequestTest.php b/tests/Http/HttpRequestTest.php index 840aa6cfd..656b83737 100755 --- a/tests/Http/HttpRequestTest.php +++ b/tests/Http/HttpRequestTest.php @@ -368,7 +368,7 @@ public function testOldMethodCallsSession() $request = Request::create('/', 'GET'); $session = m::mock(Store::class); $session->shouldReceive('getOldInput')->once()->with('foo', 'bar')->andReturn('boom'); - $request->setSession($session); + $request->setLaravelSession($session); $this->assertEquals('boom', $request->old('foo', 'bar')); } @@ -378,7 +378,7 @@ public function testFlushMethodCallsSession() $request = Request::create('/', 'GET'); $session = m::mock(Store::class); $session->shouldReceive('flashInput')->once(); - $request->setSession($session); + $request->setLaravelSession($session); $request->flush(); } diff --git a/tests/Routing/RoutingUrlGeneratorTest.php b/tests/Routing/RoutingUrlGeneratorTest.php index 6c3b5d363..700aee701 100755 --- a/tests/Routing/RoutingUrlGeneratorTest.php +++ b/tests/Routing/RoutingUrlGeneratorTest.php @@ -265,7 +265,7 @@ public function testPreviousUrlFromSession(): void $request = Illuminate\Http\Request::create('http://www.foo.com/some'); $session->shouldReceive('previousUrl')->andReturn('http://www.foo.com/previous-page'); - $request->setSession($session); + $request->setLaravelSession($session); $url = new UrlGenerator( new Illuminate\Routing\RouteCollection, diff --git a/tests/Session/SessionMiddlewareTest.php b/tests/Session/SessionMiddlewareTest.php index 0cac3622a..99f742216 100644 --- a/tests/Session/SessionMiddlewareTest.php +++ b/tests/Session/SessionMiddlewareTest.php @@ -17,7 +17,7 @@ protected function tearDown(): void public function testSessionIsProperlyStartedAndClosed() { - $request = Symfony\Component\HttpFoundation\Request::create('http://www.foo.com/some', 'GET'); + $request = Illuminate\Http\Request::create('http://www.foo.com/some', 'GET'); $response = new Symfony\Component\HttpFoundation\Response; $middle = new Illuminate\Session\Middleware( diff --git a/tests/Session/SessionStoreTest.php b/tests/Session/SessionStoreTest.php index 81337c841..85553fcdd 100644 --- a/tests/Session/SessionStoreTest.php +++ b/tests/Session/SessionStoreTest.php @@ -6,7 +6,6 @@ use L4\Tests\BackwardCompatibleTestCase; use Mockery as m; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag; class SessionStoreTest extends BackwardCompatibleTestCase { @@ -23,15 +22,12 @@ public function testSessionIsLoadedFromHandler() $session->getHandler()->shouldReceive('read')->once()->with($this->getSessionId())->andReturn( serialize(['foo' => 'bar', 'bagged' => ['name' => 'taylor']]) ); - $session->registerBag(new Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag('bagged')); $session->start(); $this->assertEquals('bar', $session->get('foo')); $this->assertEquals('baz', $session->get('bar', 'baz')); $this->assertTrue($session->has('foo')); $this->assertFalse($session->has('bar')); - $this->assertEquals('taylor', $session->getBag('bagged')->get('name')); - $this->assertInstanceOf(MetadataBag::class, $session->getMetadataBag()); $this->assertTrue($session->isStarted()); $session->put('baz', 'boom'); @@ -39,11 +35,20 @@ public function testSessionIsLoadedFromHandler() } - public function testSessionGetBagException() + public function testExists() { - $this->expectException('InvalidArgumentException'); $session = $this->getSession(); - $session->getBag('doesNotExist'); + $session->put('foo', 'bar'); + $session->put('baz', null); + + $this->assertTrue($session->exists('foo')); + $this->assertTrue($session->exists('baz')); + $this->assertTrue($session->exists(['foo', 'baz'])); + $this->assertFalse($session->exists(['foo', 'bar'])); + $this->assertFalse($session->exists('bar')); + + $this->assertTrue($session->has('foo')); + $this->assertFalse($session->has('baz')); } @@ -119,7 +124,6 @@ public function testSessionIsProperlySaved() 'new' => [], 'old' => ['baz'], ], - '_sf2_meta' => $session->getBagData('_sf2_meta'), ]) ); $session->save(); @@ -219,25 +223,15 @@ public function testRemove() } - public function testClear() + public function testFlush() { $session = $this->getSession(); - $session->set('foo', 'bar'); - - $bag = new Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag('bagged'); - $bag->set('qu', 'ux'); - $session->registerBag($bag); - - $session->clear(); - $this->assertFalse($session->has('foo')); - $this->assertFalse($session->getBag('bagged')->has('qu')); - - $session->set('foo', 'bar'); - $session->getBag('bagged')->set('qu', 'ux'); + $session->put('foo', 'bar'); $session->flush(); + $this->assertFalse($session->has('foo')); - $this->assertFalse($session->getBag('bagged')->has('qu')); + $this->assertEmpty($session->all()); }