From 47ff1071a45ea0dd11803170913b3cb2b7171b41 Mon Sep 17 00:00:00 2001 From: Tim Kelty Date: Tue, 6 Feb 2024 09:09:46 -0500 Subject: [PATCH 01/10] Add general config --- src/config/GeneralConfig.php | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/config/GeneralConfig.php b/src/config/GeneralConfig.php index e3bab966e10..3e4e65bda6b 100644 --- a/src/config/GeneralConfig.php +++ b/src/config/GeneralConfig.php @@ -2822,6 +2822,23 @@ class GeneralConfig extends BaseConfig */ public bool $showFirstAndLastNameFields = false; + /** + * @var int The maximum number of sites that can be created. + * + * ::: code + * ```php Static Config + * ->maxSites(201) + * ``` + * ```shell Environment Override + * CRAFT_MAX_SITES=201 + * ``` + * ::: + * + * @group System + * @since 5.0.0 + */ + public int $maxSites = 200; + /** * @var mixed The amount of time before a soft-deleted item will be up for hard-deletion by garbage collection. * @@ -6340,6 +6357,25 @@ public function showFirstAndLastNameFields(bool $value = true): self return $this; } + /** + * The maximum number of sites that can be created. + * + * ```php + * ->maxSites(201) + * ``` + * + * @group System + * @param int $value + * @return self + * @see $maxSites + * @since 5.0.0 + */ + public function maxSites(int $value): self + { + $this->maxSites = $value; + return $this; + } + /** * The amount of time before a soft-deleted item will be up for hard-deletion by garbage collection. * From 036e866e83f99597ec2f1eb816f8c50c7de96622 Mon Sep 17 00:00:00 2001 From: Tim Kelty Date: Tue, 6 Feb 2024 09:10:39 -0500 Subject: [PATCH 02/10] Remove config --- src/config/GeneralConfig.php | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/src/config/GeneralConfig.php b/src/config/GeneralConfig.php index 3e4e65bda6b..e3bab966e10 100644 --- a/src/config/GeneralConfig.php +++ b/src/config/GeneralConfig.php @@ -2822,23 +2822,6 @@ class GeneralConfig extends BaseConfig */ public bool $showFirstAndLastNameFields = false; - /** - * @var int The maximum number of sites that can be created. - * - * ::: code - * ```php Static Config - * ->maxSites(201) - * ``` - * ```shell Environment Override - * CRAFT_MAX_SITES=201 - * ``` - * ::: - * - * @group System - * @since 5.0.0 - */ - public int $maxSites = 200; - /** * @var mixed The amount of time before a soft-deleted item will be up for hard-deletion by garbage collection. * @@ -6357,25 +6340,6 @@ public function showFirstAndLastNameFields(bool $value = true): self return $this; } - /** - * The maximum number of sites that can be created. - * - * ```php - * ->maxSites(201) - * ``` - * - * @group System - * @param int $value - * @return self - * @see $maxSites - * @since 5.0.0 - */ - public function maxSites(int $value): self - { - $this->maxSites = $value; - return $this; - } - /** * The amount of time before a soft-deleted item will be up for hard-deletion by garbage collection. * From ea19a0ff70a656f7760ecedd81c44a252b0e3ca3 Mon Sep 17 00:00:00 2001 From: Tim Kelty Date: Tue, 6 Feb 2024 09:33:10 -0500 Subject: [PATCH 03/10] Max site limit --- src/services/Sites.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/services/Sites.php b/src/services/Sites.php index 2b92f619d6c..0b524bb5ffa 100644 --- a/src/services/Sites.php +++ b/src/services/Sites.php @@ -125,6 +125,13 @@ class Sites extends Component */ public const EVENT_AFTER_DELETE_SITE = 'afterDeleteSite'; + /** + * This value can be configured as needed, but exists as a safeguard against performance issues. + * + * @var int The maximum number of sites that can be created. + */ + public int $maxSites = 200; + /** * @var MemoizableArray|null * @see _groups() @@ -646,6 +653,10 @@ public function saveSite(Site $site, bool $runValidation = true): bool { $isNewSite = !$site->id; + if ($isNewSite && count($this->_allSitesById) >= $this->maxSites) { + throw new Exception("Maximum number of sites cannot exceed $this->maxSites."); + } + if (!empty($this->_allSitesById)) { $primarySite = $this->getPrimarySite(); } else { From 6238a5d80433cd740dce862f1a44556b06ab240c Mon Sep 17 00:00:00 2001 From: Tim Kelty Date: Tue, 6 Feb 2024 09:34:20 -0500 Subject: [PATCH 04/10] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6557c074c9f..ecc06e28747 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Fixed a bug where element editor forms could submit duplicate input values. ([#14276](https://github.com/craftcms/cms/issues/14276)) - Fixed a bug where unedited, unpublished drafts created within Matrix fields would appear on page reload. - Fixed a bug where nested drafts weren’t getting deleted if no longer needed by a Matrix or Addresses field. +- Added `craft\services\Sites::maxSites`. ## 5.0.0-alpha.12 - 2024-02-05 From df6598a11151a1e5a2452157eb928db9a9b8abc8 Mon Sep 17 00:00:00 2001 From: Tim Kelty Date: Tue, 6 Feb 2024 10:45:46 -0500 Subject: [PATCH 05/10] Disable button --- src/controllers/SitesController.php | 4 +--- src/services/Sites.php | 10 +++++++++- src/templates/settings/sites/index.twig | 9 ++++++--- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/controllers/SitesController.php b/src/controllers/SitesController.php index 10bfa63c5a2..626e99c7983 100644 --- a/src/controllers/SitesController.php +++ b/src/controllers/SitesController.php @@ -56,7 +56,6 @@ public function beforeAction($action): bool public function actionSettingsIndex(?int $groupId = null): Response { $sitesService = Craft::$app->getSites(); - $allGroups = $sitesService->getAllGroups(); if ($groupId) { if (($group = $sitesService->getGroupById($groupId)) === null) { @@ -88,9 +87,8 @@ public function actionSettingsIndex(?int $groupId = null): Response return $this->renderTemplate('settings/sites/index.twig', compact( 'crumbs', - 'allGroups', 'group', - 'sites' + 'sites', )); } diff --git a/src/services/Sites.php b/src/services/Sites.php index 0b524bb5ffa..54daeed03fe 100644 --- a/src/services/Sites.php +++ b/src/services/Sites.php @@ -640,6 +640,14 @@ public function getSiteByHandle(string $siteHandle, ?bool $withDisabled = null): return ArrayHelper::firstWhere($this->_allSites($withDisabled), 'handle', $siteHandle, true); } + /** + * @return int + */ + public function getRemainingSites(): int + { + return max($this->maxSites - count($this->_allSitesById), 0); + } + /** * Saves a site. * @@ -653,7 +661,7 @@ public function saveSite(Site $site, bool $runValidation = true): bool { $isNewSite = !$site->id; - if ($isNewSite && count($this->_allSitesById) >= $this->maxSites) { + if ($isNewSite && !$this->getRemainingSites()) { throw new Exception("Maximum number of sites cannot exceed $this->maxSites."); } diff --git a/src/templates/settings/sites/index.twig b/src/templates/settings/sites/index.twig index a85f3eb9270..0cd6ade730c 100644 --- a/src/templates/settings/sites/index.twig +++ b/src/templates/settings/sites/index.twig @@ -6,8 +6,11 @@ {% block actionButton %} - {% set newSiteUrl = url('settings/sites/new', (group ? { groupId: group.id } : null)) %} - {{ "New site"|t('app') }} + {{ tag('a', { + href: url('settings/sites/new', (group ? { groupId: group.id } : null)), + class: ['btn', 'submit', 'add', 'icon', craft.app.sites.getRemainingSites() ? null : 'disabled'], + text: "New site"|t('app'), + }) }} {% endblock %} @@ -15,7 +18,7 @@