Go to file
Dylan Wagstaff 3f8607ffbe
Merge pull request #447 from oilee80/master
Have JS work across different Form IDs
2019-12-05 15:09:57 +13:00
_config FIX allowed pagetypes displaying incorrectly when switching subsite 2019-05-31 11:28:15 +12:00
.tx Add transifex config file. Add missing files and merge translations. 2013-10-25 12:45:32 +13:00
css API Move subsite dropdown logic for folders into FolderFormFactoryExtension 2018-01-18 16:03:58 +13:00
docs/en DOCS Fix typos 2019-06-05 15:09:57 +12:00
images Add custom menu-icon 2013-05-29 10:15:17 +12:00
javascript Have JS work accross different Form IDs 2019-11-27 14:24:02 +00:00
lang Merge branch '2.2' into 2.3 2019-06-25 10:00:47 +12:00
src Merge branch '2.2' into 2.3 2019-09-25 15:00:47 -07:00
templates/SilverStripe NEW Hide subsite selector dropdown if no subsites have been created yet 2018-06-19 15:51:33 +12:00
tests Merge branch '2.2' into 2.3 2019-09-25 15:00:47 -07:00
_config.php NEW Add SubsiteState and initialisation middleware, replace Subsite::currentSubsiteID use 2017-08-30 11:47:11 +12:00
.editorconfig Add subsite switching behat tests and a test that shows a UI bug in publishing 2018-07-13 15:59:37 +12:00
.gitattributes Update Travis configuration for PHP 5.6-7.1, add composer dependencies and codecov.io config 2017-08-29 17:43:14 +12:00
.gitignore 3.2 compat changes 2015-06-09 10:50:43 +12:00
.scrutinizer.yml FIX Update Scrutinizer configuration to run new build system 2017-12-04 15:29:15 +13:00
.travis.yml Travis config update, remove branch aliases 2019-11-05 14:47:03 +13:00
.upgrade.yml FIX Update class name in upgrader map 2017-09-11 11:50:49 +12:00
behat.yml FIX Re-enable Behat using chromedriver and silverstripe/recipe-testing 2018-06-01 15:48:19 +12:00
CHANGELOG.md API Convert most of Subsite public statics to config properties 2018-01-23 12:09:48 +13:00
code-of-conduct.md Added standard code of conduct 2015-11-21 20:17:10 +13:00
codecov.yml Update Travis configuration for PHP 5.6-7.1, add composer dependencies and codecov.io config 2017-08-29 17:43:14 +12:00
composer.json Travis config update, remove branch aliases 2019-11-05 14:47:03 +13:00
license.md Updated license year 2016-01-01 06:45:57 +13:00
phpcs.xml.dist Add codesniffer ruleset 2018-01-31 10:08:21 +13:00
phpunit.xml.dist NEW Convert to vendor module 2017-12-04 15:26:17 +13:00
README.md Merge branch '2.3' 2019-09-25 15:01:00 -07:00

Subsites Module

Build Status Scrutinizer Code Quality codecov SilverStripe supported module

Introduction

The subsites module provides a convenient way of running multiple websites from a single installation of SilverStripe, sharing users, content, and assets between them - the sites will be managed from a single CMS.

A useful way to think of its use is where you have a business with a global headquarters and four branches in various countries. The subsites module allows the five offices to use a single SilverStripe installation, and have information from the headquarters flow down into the branches. The branches can hold information that is individual and the website templates can also be different.

All separation of content achieved with this module should be viewed as cosmetic and not appropriate for security-critical applications. The module gives some control over access rights especially in the "Pages" and "Files" area of the CMS, but other sections' separation is much weaker: for example giving someone any of the "Roles and access permissions" will imply that the person will likely be able to escalate his/her privileges to the global admin role.

For user documentation please see:

  1. Setting up subsites
  2. Working with subsites

Features & limitations

Features:

  • Each subsite appears as a standalone website from a users prospective
  • No need to duplicate existing code as all subsites use the same codebase as the main site
  • You can set individual permissions on each subsite domain name
  • Ability to copy a page and its content from the main site into a subsite
  • Create translations of subsite pages
  • Schedule the publishing of subsite pages
  • The database is shared between subsites (meaning duplicating content is easy)
  • When recovering from a disaster it's much easier to bring up a new copy of a single environment with 100 subsites than it is to bring up 100 environments.

Limitations:

  • Each subsite domain name has to be set up on the server first, and DNS records need to be updated as appropriate.
  • A subsite cannot use a different codebase as the main site, they are intrinsically tied
  • The only code a developer can edit between subsites is the theme
  • The separation between subsites in the CMS needs to be seen as cosmetic, and mostly applicable to the "Pages" and "Files" sections of the CMS.
  • All subsites run in the same process space and data set. Therefore if an outage affects one subsite it will affect all subsites, and if bad code or hardware corrupts one subsite's data, it's very likely that it has corrupted all subsite data.
    • This principle applies to application error, security vulnerabilities and high levels of traffic
  • It is not currently possible to backup or restore the data from a single subsite.
  • It is awkward (but not impossible) to have separate teams of developers working on different subsites - primarily because of the level of collaboration needed. It is more suited to the same group of developers being responsible for all of the subsites.

If more isolation of code, security, or performance is needed, then consider running multiple separate installations (e.g. on separate servers).

Requirements

  • SilverStripe 4.x

Installation

  • Create necessary tables by visiting http://<yoursite>/dev/build (you should see a Subsite table created, among other things). You don't need to run this command for every subsite.
  • Login to the CMS as an administrator. You should now see a "Subsites" entry on the main menu, access that section now.
  • Hit the "Add Subsite" button to create a new subsite.
  • Once you've created a subsite, you'll see a "Create Subsite Domain" button, hit that button to enter a domain or subdomain for your subsite. This will determine the URL of your website. For example, if your site is running on http://localhost/mysite, and you set the subdomain to "subsite", then your subsite will be accessible on http://subsite.localhost/mysite
  • Go to the "Pages" section of the CMS. In the top-left above the menu, you'll see a dropdown listing the two subsites - "Main site" is the original site that you had before you installed the subsites module. Select your new subsite, and the site content tree will be changed. It should be empty at this stage.
  • Add a page - change its title to "Home", and its URL Segment will be changed to "home". Save the page.
  • Update your DNS and, if necessary, your webserver configuration, so that your subdomain will point to the SilverStripe installation on your webserver. Visit this new subdomain. You should see the new subsite homepage.

Usage

Strict Subdomain Matching

The module tries to provide sensible defaults, in which it regards example.com and www.example.com as the same domains. In case you want to distinguish between these variations, set Subsite::$strict_subdomain_matching to TRUE. This won't affect wildcard/asterisk checks, but removes the ambiguity about default subdomains.

Permissions

Groups can be associated with one or more subsites, in which case the granted page- and asset-related permissions only apply to this subsite.

Note that creating a Subsite-specific group, and giving it permissions unrelated to content editing and asset management will result in members of this group being able to escalate their privileges. An example here is giving that group "Full administrative rights" or some of the "Roles and access permissions", in which case it is possible for the member of that group to simply add himself to the global "Administrators" group or change his own group to having access to all sites.

The subsites module should be viewed as providing a convenience of visual separation for the sites on the interface level, rather than a fully tight security model for managing many sites on the same CMS (it is still the same CMS).

Access created domains

Once you have created some subsites/domains in your admin, you can check the overall functionality of subsites by

http://your.primary-domain.com/subsite-metadata-url?SubsiteID=1

In some Browsers the SubsiteID is visible if you hover over the "Edit" link in the search results of Subsite admin.

Subsite-specific themes

Download a second theme from http://www.silverstripe.com/themes/ and put it in your themes folder. Open admin/subsites?flush=1 and select one of your subsites from the menu on the bottom-left. You should see a Theme dropdown in the subsite details, and it should list both your original theme and the new theme. Select the new theme in the dropdown. Now, this subsite will use a different theme from the main site.

Cascading themes

In SilverStripe 4 themes will resolve theme files by looking through a list of themes (see the documentation on creating your own theme). Subsites will inherit this configuration for the order of themes. Choosing a theme for a Subsite will set the list of themes to that chosen theme, and all themes that are defined below the chosen theme in priority. For example, with a theme configuration as follows:

SilverStripe\View\SSViewer:
  themes:
    - '$public'
    - 'my-theme'
    - 'watea'
    - 'starter'
    - '$default'

Choosing watea in your Subsite will create a cascading config as follows:

themes:
  - 'watea'
  - '$public'
  - 'starter'
  - '$default'

You may also completely define your own cascading theme lists for CMS users to choose as theme options for their subsite:

SilverStripe\Subsites\Service\ThemeResolver:
  theme_options:
    normal:
      - '$public'
      - 'watea'
      - 'starter'
      - '$default'
    special:
      - 'my-theme'
      - 'starter'
      - '$default'

Limit available themes for a subsite

Not all themes might be suitable or adapted for all subsites. You can optionally limit usage of themes:

mysite/_config.php

:::php
Subsite::set_allowed_themes(array('blackcandy','mytheme'));

Enable Subsite support on DataObjects

To make your DataObject subsite aware, include a SubsiteID on your DataObject. eg:

MyDataObject.php

:::php
private static $has_one = array(
	'Subsite' => 'Subsite'
);

Include the current SubsiteID as a hidden field on getCMSFields, or updateCMSFields. eg:

MyDataObject.php

:::php
public function getCMSFields() {
	$fields = parent::getCMSFields();
	if(class_exists(Subsite::class)){
		$fields->push(new HiddenField('SubsiteID','SubsiteID', SubsiteState::singleton()->getSubsiteId()));
	}
	return $fields;
}

To limit your admin gridfields to the current Subsite records, you can do something like this:

MyAdmin.php

:::php
public function getEditForm($id = null, $fields = null){
	$form = parent::getEditForm($id, $fields);

	$gridField = $form->Fields()->fieldByName($this->sanitiseClassName($this->modelClass));
	if(class_exists(Subsite::class)){
		$list = $gridField->getList()->filter(['SubsiteID'=>SubsiteState::singleton()->getSubsiteId()]);
		$gridField->setList($list);
	}

	return $form;
}

Enable menu support for custom areas in subsites

Custom admin areas, by default, will not show in the menu of a subsite. Not all admins are adapted for or appropriate to show within a subsite. If your admin does have subsite support, or is intentionally global, you can enable the show in menu option either by applying:

mysite/_config.php

:::php
MyAdmin::add_extension('SubsiteMenuExtension');

or by defining the subsiteCMSShowInMenu function in your admin:

MyAdmin.php

:::php
public function subsiteCMSShowInMenu(){
	return true;
}

Public display of a subsite

By default, each subsite is available to the public (= not logged-in), provided a correct host mapping is set up. A subsite can be marked as non-public in its settings, in which case it only shows if a user with CMS permissions is logged in. This is useful to create and check subsites on a live system before publishing them.

Please note that you need to filter for this manually in your own queries:

$publicSubsites = DataObject::get(
	'Subsite',
	Subsite::$check_is_public ? '"IsPublic"=1' : '';
);

To ensure the logged-in status of a member is carried across to subdomains, you also need to configure PHP session cookies to be set for all subdomains:

// Example matching subsite1.example.org and www.example.org
Session::set_cookie_domain('.example.org');

Screenshots