Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add site limit #14307

Merged
merged 12 commits into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG-WIP.md
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,8 @@
- Added `craft\services\ProjectConfig::find()`.
- Added `craft\services\ProjectConfig::flush()`.
- Added `craft\services\ProjectConfig::writeYamlFiles()`.
- Added `craft\services\Sites::$maxSites`. ([#14307](https://github.com/craftcms/cms/pull/14307))
- Added `craft\services\Sites::getRemainingSites()`. ([#14307](https://github.com/craftcms/cms/pull/14307))
- Added `craft\web\CpScreenResponseBehavior::$actionMenuItems`.
- Added `craft\web\CpScreenResponseBehavior::$contextMenuItems`.
- Added `craft\web\CpScreenResponseBehavior::$selectableSites`.
Expand Down Expand Up @@ -609,6 +611,7 @@
- Improved the performance of autosaves for elements with newly-created Matrix entries.
- Slugs are no longer required for elements that don’t have a URI format that contains `slug`.
- Garbage collection now deletes orphaned nested entries.
- Craft now has a default limit of 100 sites, which can be increased via `craft\ervices\Sites::$maxSites` at your own peril. ([#14307](https://github.com/craftcms/cms/pull/14307))
- Fixed a bug where multi-site element queries weren’t scoring elements on a per-site basis. ([#13801](https://github.com/craftcms/cms/discussions/13801))
- Fixed an error that could occur if eager-loading aliases conflicted with native eager-loading handles, such as `author`. ([#14057](https://github.com/craftcms/cms/issues/14057))
- Fixed a bug where layout components provided by disabled plugins weren’t getting omitted. ([#14219](https://github.com/craftcms/cms/pull/14219))
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
- Improved global sidebar styling. ([#14281](https://github.com/craftcms/cms/pull/14281))
- The global sidebar is now collapsible. ([#14281](https://github.com/craftcms/cms/pull/14281))
- Entry cards without a thumbnail now show their entry type icon. ([#14305](https://github.com/craftcms/cms/issues/14305))
- Craft now has a default limit of 100 sites, which can be increased via `craft\ervices\Sites::$maxSites` at your own peril. ([#14307](https://github.com/craftcms/cms/pull/14307))
- Added `craft\services\Sites::$maxSites`. ([#14307](https://github.com/craftcms/cms/pull/14307))
- Added `craft\services\Sites::getRemainingSites()`. ([#14307](https://github.com/craftcms/cms/pull/14307))
- Added `Craft.ElementEditor::markDeltaNameAsModified()`.
- Removed `craft\elements\NestedElementManager::$allowDeletion`.
- Fixed a bug where element editor forms could submit duplicate input values. ([#14276](https://github.com/craftcms/cms/issues/14276))
Expand Down
4 changes: 1 addition & 3 deletions src/controllers/SitesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -88,9 +87,8 @@ public function actionSettingsIndex(?int $groupId = null): Response

return $this->renderTemplate('settings/sites/index.twig', compact(
'crumbs',
'allGroups',
'group',
'sites'
'sites',
));
}

Expand Down
29 changes: 29 additions & 0 deletions src/services/Sites.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,19 @@ 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.
*
* ::: warning
* Craft’s multi-site support is not designed to be infinitely scalable.
* Increase this limit at your own risk!
* :::
*
* @var int The maximum number of sites that can be created.
* @since 5.0.0
*/
public int $maxSites = 100;

/**
* @var MemoizableArray<SiteGroup>|null
* @see _groups()
Expand Down Expand Up @@ -633,6 +646,18 @@ public function getSiteByHandle(string $siteHandle, ?bool $withDisabled = null):
return ArrayHelper::firstWhere($this->_allSites($withDisabled), 'handle', $siteHandle, true);
}

/**
* Returns the number of sites that can be created, based on [[$maxSites]].
*
* @return int
* @see $maxSites
* @since 5.0.0
*/
public function getRemainingSites(): int
{
return max($this->maxSites - count($this->_allSitesById), 0);
}

/**
* Saves a site.
*
Expand All @@ -646,6 +671,10 @@ public function saveSite(Site $site, bool $runValidation = true): bool
{
$isNewSite = !$site->id;

if ($isNewSite && !$this->getRemainingSites()) {
throw new Exception("Maximum number of sites cannot exceed $this->maxSites.");
}

if (!empty($this->_allSitesById)) {
$primarySite = $this->getPrimarySite();
} else {
Expand Down
9 changes: 6 additions & 3 deletions src/templates/settings/sites/index.twig
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,19 @@


{% block actionButton %}
{% set newSiteUrl = url('settings/sites/new', (group ? { groupId: group.id } : null)) %}
<a href="{{ newSiteUrl }}" class="btn submit add icon">{{ "New site"|t('app') }}</a>
{{ 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 %}


{% block sidebar %}
<nav>
<ul id="groups">
<li><a href="{{ url('settings/sites') }}"{% if not group %} class="sel"{% endif %}>{{ "All Sites"|t('app') }}</a></li>
{% for g in allGroups %}
{% for g in craft.app.sites.getAllGroups() %}
<li>
{{ tag('a', {
href: url('settings/sites', {groupId: g.id}),
Expand Down
Loading