diff --git a/.github/psalm/cache/.gitignore b/.github/psalm/cache/.gitignore
new file mode 100644
index 0000000000..d6b7ef32c8
--- /dev/null
+++ b/.github/psalm/cache/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/.github/psalm/psalm.baseline.xml b/.github/psalm/psalm.baseline.xml
new file mode 100644
index 0000000000..f74693accd
--- /dev/null
+++ b/.github/psalm/psalm.baseline.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/.github/workflows/psalm.yml b/.github/workflows/psalm.yml
new file mode 100644
index 0000000000..11027c374e
--- /dev/null
+++ b/.github/workflows/psalm.yml
@@ -0,0 +1,97 @@
+name: Static analysis
+
+on:
+ pull_request: ~
+
+jobs:
+ psalm:
+ name: Psalm
+ runs-on: Ubuntu-20.04
+
+ steps:
+ - name: Set up PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '8.0'
+ extensions: "json,memcached,mongodb,redis,xsl,ldap,dom"
+ ini-values: "memory_limit=-1"
+ coverage: none
+
+ - name: Checkout PR
+ uses: actions/checkout@v2
+ with:
+ path: pr
+
+ - name: Checkout base
+ uses: actions/checkout@v2
+ with:
+ ref: ${{ github.base_ref }}
+ path: base
+
+ - name: Configure composer
+ run: |
+ cd base
+ COMPOSER_HOME="$(composer config home)"
+ ([ -d "$COMPOSER_HOME" ] || mkdir "$COMPOSER_HOME") && cp .github/composer-config.json "$COMPOSER_HOME/config.json"
+ echo "COMPOSER_ROOT_VERSION=$(grep -m1 SYMFONY_VERSION .travis.yml | grep -o '[0-9.x]*').x-dev" >> $GITHUB_ENV
+
+ - name: Determine composer cache directory
+ id: composer-cache
+ run: echo "::set-output name=dir::$(composer config cache-files-dir)"
+
+ - name: Cache composer dependencies
+ uses: actions/cache@v2
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: composer-${{ github.base_ref }}
+ restore-keys: composer-
+
+ - name: Install Psalm
+ run: |
+ composer require psalm/phar
+ cp ./vendor/bin/psalm.phar base/psalm.phar
+ cp ./vendor/bin/psalm.phar pr/psalm.phar
+
+ - name: Install dependencies for base
+ run: |
+ cd base
+ echo "::group::modify composer.json"
+ composer remove symfony/phpunit-bridge --no-interaction --no-update
+ composer require --no-update phpunit/phpunit php-http/discovery psr/event-dispatcher
+ echo "::endgroup::"
+ echo "::group::composer update"
+ composer update --no-progress --ansi
+ echo "::endgroup::"
+
+ - name: Generate Psalm baseline
+ run: |
+ cd base
+ ./psalm.phar --set-baseline=.github/psalm/psalm.baseline.xml --no-progress
+
+ - name: Copy baseline
+ run: |
+ cp base/.github/psalm/psalm.baseline.xml pr/.github/psalm/psalm.baseline.xml
+
+ - name: Install dependencies for PR
+ run: |
+ cd pr
+ echo "::group::modify composer.json"
+ composer remove symfony/phpunit-bridge --no-interaction --no-update
+ composer require --no-update phpunit/phpunit php-http/discovery psr/event-dispatcher
+ echo "::endgroup::"
+ echo "::group::composer update"
+ composer update --no-progress --ansi
+ echo "::endgroup::"
+
+ - name: Cache Psalm
+ uses: actions/cache@v2
+ with:
+ path: pr/.github/psalm/cache/
+ key: psalm-${{ github.base_ref }}
+ restore-keys: psalm-
+
+ - name: Psalm
+ run: |
+ cd pr
+ ./psalm.phar --version
+ ./psalm.phar --output-format=github --no-progress
diff --git a/psalm.xml b/psalm.xml
new file mode 100644
index 0000000000..3f12f1331c
--- /dev/null
+++ b/psalm.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php
index bb34d724b3..b96521f754 100644
--- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php
+++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php
@@ -389,6 +389,9 @@ class NativeSessionStorage implements SessionStorageInterface
$this->emulateSameSite = $value;
continue;
}
+ if ('cookie_secure' === $key && 'auto' === $value) {
+ continue;
+ }
ini_set('url_rewriter.tags' !== $key ? 'session.'.$key : $key, $value);
}
}
diff --git a/src/Symfony/Component/HttpKernel/EventListener/SessionListener.php b/src/Symfony/Component/HttpKernel/EventListener/SessionListener.php
index e982a795b2..93bbb2f117 100644
--- a/src/Symfony/Component/HttpKernel/EventListener/SessionListener.php
+++ b/src/Symfony/Component/HttpKernel/EventListener/SessionListener.php
@@ -14,6 +14,7 @@ namespace Symfony\Component\HttpKernel\EventListener;
use Psr\Container\ContainerInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
/**
* Sets the session in the request.
@@ -33,10 +34,12 @@ class SessionListener extends AbstractSessionListener
parent::__construct($container, $debug);
}
- protected function getSession(): ?SessionInterface
+ public function onKernelRequest(GetResponseEvent $event)
{
- if (!$this->container->has('session')) {
- return null;
+ parent::onKernelRequest($event);
+
+ if (!$event->isMasterRequest() || !$this->container->has('session')) {
+ return;
}
if ($this->container->has('session_storage')
@@ -46,6 +49,13 @@ class SessionListener extends AbstractSessionListener
) {
$storage->setOptions(['cookie_secure' => true]);
}
+ }
+
+ protected function getSession(): ?SessionInterface
+ {
+ if (!$this->container->has('session')) {
+ return null;
+ }
return $this->container->get('session');
}
diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php
index 8530494354..ac6175d98f 100644
--- a/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/SessionListenerTest.php
@@ -62,7 +62,7 @@ class SessionListenerTest extends TestCase
$listener = new SessionListener($container);
$event = $this->createMock(RequestEvent::class);
- $event->expects($this->once())->method('isMasterRequest')->willReturn(true);
+ $event->expects($this->exactly(2))->method('isMasterRequest')->willReturn(true);
$event->expects($this->once())->method('getRequest')->willReturn($request);
$listener->onKernelRequest($event);
@@ -206,12 +206,16 @@ class SessionListenerTest extends TestCase
$listener = new SessionListener($container);
$listener->onKernelRequest($event);
+ // storage->setOptions() should have been called already
+ $container->set('session_storage', null);
+ $sessionStorage = null;
+
$subRequest = $masterRequest->duplicate();
// at this point both master and subrequest have a closure to build the session
$masterRequest->getSession();
- // calling the factory on the subRequest should not trigger a second call to storage->sesOptions()
+ // calling the factory on the subRequest should not trigger a second call to storage->setOptions()
$subRequest->getSession();
}