From c37e59122d90c54f575c654a882df0e430a4facb Mon Sep 17 00:00:00 2001 From: Nathaniel Hammond Date: Tue, 31 Dec 2024 09:48:58 +0000 Subject: [PATCH 1/4] Allow passing of `X-Craft-Site` header to set current site in request --- src/web/Request.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/web/Request.php b/src/web/Request.php index 1bcd3270f75..6e695817ae4 100644 --- a/src/web/Request.php +++ b/src/web/Request.php @@ -276,7 +276,19 @@ public function init(): void } } - // Set the current site for the request + // Finally if this isn't a control panel request and the site header has been passed, set the current site + $siteHandle = $this->getHeaders()->get('X-Craft-Site'); + if (!$this->_isCpRequest && $siteHandle !== null) { + $site = $this->sites->getSiteByHandle($siteHandle, false); + // Fail silently if Craft isn’t installed yet or is in the middle of updating + if ($site === null && Craft::$app->getIsInstalled() && !Craft::$app->getUpdates()->getIsCraftUpdatePending()) { + /** @noinspection PhpUnhandledExceptionInspection */ + throw new SiteNotFoundException('Site does not exist.'); + } + + $baseUrl = rtrim($site->getBaseUrl() ?? '', '/'); + } + // Set the current site for the request if ($this->sites instanceof Sites) { $this->sites->setCurrentSite($site ?? null); } From e18382c40063bd8be580180c88822b9f95489f57 Mon Sep 17 00:00:00 2001 From: Nathaniel Hammond Date: Tue, 31 Dec 2024 09:52:17 +0000 Subject: [PATCH 2/4] tidy --- src/web/Request.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/web/Request.php b/src/web/Request.php index 6e695817ae4..85b023b3261 100644 --- a/src/web/Request.php +++ b/src/web/Request.php @@ -288,7 +288,8 @@ public function init(): void $baseUrl = rtrim($site->getBaseUrl() ?? '', '/'); } - // Set the current site for the request + + // Set the current site for the request if ($this->sites instanceof Sites) { $this->sites->setCurrentSite($site ?? null); } From 5d93583c5cf5430e7a3c9ac9de7e53fbbbe8411a Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Thu, 2 Jan 2025 11:41:26 -0800 Subject: [PATCH 3/4] Move to _requestedSite() and combine with CRAFT_SITE check --- src/config/app.php | 1 - src/web/Request.php | 28 +++++++++++++++------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/config/app.php b/src/config/app.php index 9bc01b6aa0c..d41ad577900 100644 --- a/src/config/app.php +++ b/src/config/app.php @@ -183,7 +183,6 @@ ], 'sites' => [ 'class' => craft\services\Sites::class, - 'currentSite' => craft\helpers\App::env('CRAFT_SITE'), ], 'i18n' => [ 'class' => craft\i18n\I18N::class, diff --git a/src/web/Request.php b/src/web/Request.php index 85b023b3261..0dd1deac087 100644 --- a/src/web/Request.php +++ b/src/web/Request.php @@ -17,6 +17,7 @@ use craft\helpers\StringHelper; use craft\models\Site; use craft\services\Sites; +use yii\base\InvalidArgumentException; use yii\base\InvalidConfigException; use yii\db\Exception as DbException; use yii\di\Instance; @@ -276,19 +277,6 @@ public function init(): void } } - // Finally if this isn't a control panel request and the site header has been passed, set the current site - $siteHandle = $this->getHeaders()->get('X-Craft-Site'); - if (!$this->_isCpRequest && $siteHandle !== null) { - $site = $this->sites->getSiteByHandle($siteHandle, false); - // Fail silently if Craft isn’t installed yet or is in the middle of updating - if ($site === null && Craft::$app->getIsInstalled() && !Craft::$app->getUpdates()->getIsCraftUpdatePending()) { - /** @noinspection PhpUnhandledExceptionInspection */ - throw new SiteNotFoundException('Site does not exist.'); - } - - $baseUrl = rtrim($site->getBaseUrl() ?? '', '/'); - } - // Set the current site for the request if ($this->sites instanceof Sites) { $this->sites->setCurrentSite($site ?? null); @@ -1529,6 +1517,20 @@ private function _requestedSite(?int &$siteScore = null): Site return $site; } + // Is CRAFT_SITE or X-Craft-Site present? + $siteId = App::env('CRAFT_SITE') ?? $this->getHeaders()->get('X-Craft-Site'); + if ($siteId !== null) { + if (is_numeric($siteId)) { + $site = $this->sites->getSiteById($siteId, false); + } else { + $site = $this->sites->getSiteByHandle($siteId, false); + } + if (!$site && Craft::$app->getIsInstalled() && !Craft::$app->getUpdates()->getIsCraftUpdatePending()) { + throw new InvalidArgumentException("Invalid site: $siteId"); + } + return $site; + } + $sites = $this->sites->getAllSites(false); if (empty($sites)) { From 6c260efd49d193c5c19de097bb31480a664aab4e Mon Sep 17 00:00:00 2001 From: brandonkelly Date: Thu, 2 Jan 2025 11:48:51 -0800 Subject: [PATCH 4/4] Release note [ci skip] --- CHANGELOG-WIP.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG-WIP.md b/CHANGELOG-WIP.md index 3e499a76e3a..1b38c6ccfaf 100644 --- a/CHANGELOG-WIP.md +++ b/CHANGELOG-WIP.md @@ -9,6 +9,7 @@ ## Development - Added the `primarySite` global Twig variable. ([#16370](https://github.com/craftcms/cms/discussions/16370)) - The `duration` Twig filter now has a `language` argument. ([#16332](https://github.com/craftcms/cms/pull/16332)) +- Added support for specifying the current site via an `X-Craft-Site` header set to a site ID or handle. ([#16367](https://github.com/craftcms/cms/pull/16367)) - Deprecated the `ucfirst` Twig filter. `capitalize` should be used instead. ## Extensibility