merge ss4 fixes by cheddam
@ -4,6 +4,8 @@ language: php
|
||||
|
||||
sudo: false
|
||||
|
||||
sudo: false
|
||||
|
||||
php:
|
||||
- 5.5
|
||||
|
||||
|
39
CHANGELOG.md
Normal file
@ -0,0 +1,39 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [1.2.3]
|
||||
|
||||
* BUG Fix issue with urlsegment being renamed in subsites
|
||||
|
||||
## [1.2.2]
|
||||
|
||||
* Update translations.
|
||||
* Added attributes to menu link
|
||||
|
||||
## [1.2.1]
|
||||
|
||||
* BUG: The move to subsite folder dropdown in files is gone
|
||||
* Update templates for 3.3 compatibility
|
||||
* Update userhelp documentation
|
||||
* Fix Subsite module does not picks up themes
|
||||
* Update translations
|
||||
|
||||
## [1.2.0]
|
||||
|
||||
* API Add option to specify http / https on subsite domains
|
||||
|
||||
## [1.1.0]
|
||||
|
||||
* Changelog added.
|
||||
* Fixes #135: LeftAndMain switching between subsites
|
||||
* BUG Fix incompatibility with framework 3.2
|
||||
* Adjusted tests to new SiteTree->canCreate() logic in 3.1.11+
|
||||
* Fix subsites to use correct permissions
|
||||
* Wrong edit link in SubsitesVirtualPage
|
||||
* Added missing route to `SubsiteXHRController` for SilverStripe 3.2 compatibility.
|
||||
* Add sticky nav toggle button
|
||||
* BUG Subsites selection on SubsitesVirtualPage (fixes #45 and #47)
|
||||
* Update translations
|
@ -21,8 +21,8 @@ permissions" will imply that the person will likely be able to escalate his/her
|
||||
|
||||
For user documentation please see:
|
||||
|
||||
1. [Setting up subsites](docs/en/set_up.md)
|
||||
1. [Working with subsites](docs/en/working_with.md)
|
||||
1. [Setting up subsites](docs/en/userguide/set_up.md)
|
||||
1. [Working with subsites](docs/en/userguide/working_with.md)
|
||||
|
||||
## Features & limitations
|
||||
|
||||
@ -41,7 +41,7 @@ For user documentation please see:
|
||||
|
||||
* 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
|
||||
* However, you can remove page types from a subsite when creating the subsite - [see the setup documentation for further details](set_up.md)
|
||||
* However, you can remove page types from a subsite when creating the subsite - [see the setup documentation for further details](docs/en/userguide/set_up.md)
|
||||
* 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.
|
||||
|
36
code/SubsiteAdmin.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\Forms\GridField\GridFieldDetailForm;
|
||||
use SilverStripe\Admin\ModelAdmin;
|
||||
/**
|
||||
* Admin interface to manage and create {@link Subsite} instances.
|
||||
*
|
||||
* @package subsites
|
||||
*/
|
||||
class SubsiteAdmin extends ModelAdmin
|
||||
{
|
||||
private static $managed_models = array('Subsite');
|
||||
|
||||
private static $url_segment = 'subsites';
|
||||
|
||||
private static $menu_title = "Subsites";
|
||||
|
||||
private static $menu_icon = "subsites/images/subsites.png";
|
||||
|
||||
public $showImportForm=false;
|
||||
|
||||
private static $tree_class = 'Subsite';
|
||||
|
||||
public function getEditForm($id = null, $fields = null)
|
||||
{
|
||||
$form = parent::getEditForm($id, $fields);
|
||||
|
||||
$grid=$form->Fields()->dataFieldByName('Subsite');
|
||||
if ($grid) {
|
||||
$grid->getConfig()->removeComponentsByType(GridFieldDetailForm::class);
|
||||
$grid->getConfig()->addComponent(new GridFieldSubsiteDetailForm());
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
}
|
73
code/SubsiteReportWrapper.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\Forms\TreeMultiselectField;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Reports\ReportWrapper;
|
||||
|
||||
/**
|
||||
* Creates a subsite-aware version of another report.
|
||||
* Pass another report (or its classname) into the constructor.
|
||||
*/
|
||||
class SubsiteReportWrapper extends ReportWrapper
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Filtering
|
||||
|
||||
public function parameterFields()
|
||||
{
|
||||
$subsites = Subsite::accessible_sites('CMS_ACCESS_CMSMain', true);
|
||||
$options = $subsites->toDropdownMap('ID', 'Title');
|
||||
|
||||
$subsiteField = new TreeMultiselectField(
|
||||
'Subsites',
|
||||
_t('SubsiteReportWrapper.ReportDropdown', 'Sites'),
|
||||
$options
|
||||
);
|
||||
$subsiteField->setValue(array_keys($options));
|
||||
|
||||
// We don't need to make the field editable if only one subsite is available
|
||||
if (sizeof($options) <= 1) {
|
||||
$subsiteField = $subsiteField->performReadonlyTransformation();
|
||||
}
|
||||
|
||||
$fields = parent::parameterFields();
|
||||
if ($fields) {
|
||||
$fields->insertBefore($subsiteField, $fields->First()->Name());
|
||||
} else {
|
||||
$fields = new FieldList($subsiteField);
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Columns
|
||||
|
||||
public function columns()
|
||||
{
|
||||
$columns = parent::columns();
|
||||
$columns['Subsite.Title'] = "Subsite";
|
||||
return $columns;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Querying
|
||||
|
||||
public function beforeQuery($params)
|
||||
{
|
||||
// The user has select a few specific sites
|
||||
if (!empty($params['Subsites'])) {
|
||||
Subsite::$force_subsite = $params['Subsites'];
|
||||
|
||||
// Default: restrict to all accessible sites
|
||||
} else {
|
||||
$subsites = Subsite::accessible_sites('CMS_ACCESS_CMSMain');
|
||||
$options = $subsites->toDropdownMap('ID', 'Title');
|
||||
Subsite::$force_subsite = join(',', array_keys($options));
|
||||
}
|
||||
}
|
||||
public function afterQuery()
|
||||
{
|
||||
// Manually manage the subsite filtering
|
||||
Subsite::$force_subsite = null;
|
||||
}
|
||||
}
|
59
code/SubsiteXHRController.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\Security\Permission;
|
||||
use SilverStripe\Admin\LeftAndMain;
|
||||
|
||||
/**
|
||||
* Section-agnostic PJAX controller.
|
||||
*/
|
||||
class SubsiteXHRController extends LeftAndMain
|
||||
{
|
||||
/**
|
||||
* Relax the access permissions, so anyone who has access to any CMS subsite can access this controller.
|
||||
*/
|
||||
public function canView($member = null)
|
||||
{
|
||||
if (parent::canView()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Subsite::all_accessible_sites()->count()>0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow access if user allowed into the CMS at all.
|
||||
*/
|
||||
public function canAccess()
|
||||
{
|
||||
// Allow if any cms access is available
|
||||
return Permission::check(array(
|
||||
'CMS_ACCESS', // Supported by 3.1.14 and up
|
||||
'CMS_ACCESS_LeftAndMain'
|
||||
));
|
||||
}
|
||||
|
||||
public function getResponseNegotiator()
|
||||
{
|
||||
$negotiator = parent::getResponseNegotiator();
|
||||
$self = $this;
|
||||
|
||||
// Register a new callback
|
||||
$negotiator->setCallback('SubsiteList', function () use (&$self) {
|
||||
return $self->SubsiteList();
|
||||
});
|
||||
|
||||
return $negotiator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the list of available subsites as a cms-section-agnostic PJAX handler.
|
||||
*/
|
||||
public function SubsiteList()
|
||||
{
|
||||
return $this->renderWith('SubsiteList');
|
||||
}
|
||||
}
|
206
code/SubsitesVirtualPage.php
Normal file
@ -0,0 +1,206 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\ArrayList;
|
||||
use SilverStripe\View\ArrayData;
|
||||
use SilverStripe\Forms\DropdownField;
|
||||
use SilverStripe\CMS\Model\SiteTree;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Forms\LabelField;
|
||||
use SilverStripe\Forms\TextField;
|
||||
use SilverStripe\Forms\TextareaField;
|
||||
use SilverStripe\Control\Session;
|
||||
use SilverStripe\CMS\Model\VirtualPage;
|
||||
|
||||
class SubsitesVirtualPage extends VirtualPage
|
||||
{
|
||||
private static $description = 'Displays the content of a page on another subsite';
|
||||
|
||||
private static $db = array(
|
||||
'CustomMetaTitle' => 'Varchar(255)',
|
||||
'CustomMetaKeywords' => 'Varchar(255)',
|
||||
'CustomMetaDescription' => 'Text',
|
||||
'CustomExtraMeta' => 'HTMLText'
|
||||
);
|
||||
|
||||
public function getCMSFields()
|
||||
{
|
||||
$fields = parent::getCMSFields();
|
||||
|
||||
$subsites = DataObject::get('Subsite');
|
||||
if (!$subsites) {
|
||||
$subsites = new ArrayList();
|
||||
} else {
|
||||
$subsites=ArrayList::create($subsites->toArray());
|
||||
}
|
||||
|
||||
$subsites->push(new ArrayData(array('Title' => 'Main site', 'ID' => 0)));
|
||||
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
DropdownField::create(
|
||||
"CopyContentFromID_SubsiteID",
|
||||
_t('SubsitesVirtualPage.SubsiteField', "Subsite"),
|
||||
$subsites->map('ID', 'Title')
|
||||
)->addExtraClass('subsitestreedropdownfield-chooser no-change-track'),
|
||||
'CopyContentFromID'
|
||||
);
|
||||
|
||||
// Setup the linking to the original page.
|
||||
$pageSelectionField = new SubsitesTreeDropdownField(
|
||||
"CopyContentFromID",
|
||||
_t('VirtualPage.CHOOSE', "Choose a page to link to"),
|
||||
SiteTree::class,
|
||||
"ID",
|
||||
"MenuTitle"
|
||||
);
|
||||
|
||||
if (Controller::has_curr() && Controller::curr()->getRequest()) {
|
||||
$subsiteID = Controller::curr()->getRequest()->requestVar('CopyContentFromID_SubsiteID');
|
||||
$pageSelectionField->setSubsiteID($subsiteID);
|
||||
}
|
||||
$fields->replaceField('CopyContentFromID', $pageSelectionField);
|
||||
|
||||
// Create links back to the original object in the CMS
|
||||
if ($this->CopyContentFromID) {
|
||||
$editLink = "admin/pages/edit/show/$this->CopyContentFromID/?SubsiteID=" . $this->CopyContentFrom()->SubsiteID;
|
||||
$linkToContent = "
|
||||
<a class=\"cmsEditlink\" href=\"$editLink\">" .
|
||||
_t('VirtualPage.EDITCONTENT', 'Click here to edit the content') .
|
||||
"</a>";
|
||||
$fields->removeByName("VirtualPageContentLinkLabel");
|
||||
$fields->addFieldToTab(
|
||||
"Root.Main",
|
||||
$linkToContentLabelField = new LabelField('VirtualPageContentLinkLabel', $linkToContent),
|
||||
'Title'
|
||||
);
|
||||
$linkToContentLabelField->setAllowHTML(true);
|
||||
}
|
||||
|
||||
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
TextField::create(
|
||||
'CustomMetaTitle',
|
||||
$this->fieldLabel('CustomMetaTitle')
|
||||
)->setDescription(_t('SubsitesVirtualPage.OverrideNote', 'Overrides inherited value from the source')),
|
||||
'MetaTitle'
|
||||
);
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
TextareaField::create(
|
||||
'CustomMetaKeywords',
|
||||
$this->fieldLabel('CustomMetaTitle')
|
||||
)->setDescription(_t('SubsitesVirtualPage.OverrideNote')),
|
||||
'MetaKeywords'
|
||||
);
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
TextareaField::create(
|
||||
'CustomMetaDescription',
|
||||
$this->fieldLabel('CustomMetaTitle')
|
||||
)->setDescription(_t('SubsitesVirtualPage.OverrideNote')),
|
||||
'MetaDescription'
|
||||
);
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
TextField::create(
|
||||
'CustomExtraMeta',
|
||||
$this->fieldLabel('CustomMetaTitle')
|
||||
)->setDescription(_t('SubsitesVirtualPage.OverrideNote')),
|
||||
'ExtraMeta'
|
||||
);
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function fieldLabels($includerelations = true)
|
||||
{
|
||||
$labels = parent::fieldLabels($includerelations);
|
||||
$labels['CustomMetaTitle'] = _t('Subsite.CustomMetaTitle', 'Title');
|
||||
$labels['CustomMetaKeywords'] = _t('Subsite.CustomMetaKeywords', 'Keywords');
|
||||
$labels['CustomMetaDescription'] = _t('Subsite.CustomMetaDescription', 'Description');
|
||||
$labels['CustomExtraMeta'] = _t('Subsite.CustomExtraMeta', 'Custom Meta Tags');
|
||||
|
||||
return $labels;
|
||||
}
|
||||
|
||||
public function getCopyContentFromID_SubsiteID()
|
||||
{
|
||||
return ($this->CopyContentFromID) ? (int)$this->CopyContentFrom()->SubsiteID : (int)Session::get('SubsiteID');
|
||||
}
|
||||
|
||||
public function getVirtualFields()
|
||||
{
|
||||
$fields = parent::getVirtualFields();
|
||||
foreach ($fields as $k => $v) {
|
||||
if ($v == 'SubsiteID') {
|
||||
unset($fields[$k]);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (self::$db as $field => $type) {
|
||||
if (in_array($field, $fields)) {
|
||||
unset($fields[array_search($field, $fields)]);
|
||||
}
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
public function syncLinkTracking()
|
||||
{
|
||||
$oldState = Subsite::$disable_subsite_filter;
|
||||
Subsite::$disable_subsite_filter = true;
|
||||
if ($this->CopyContentFromID) {
|
||||
$this->HasBrokenLink = DataObject::get_by_id(SiteTree::class, $this->CopyContentFromID) ? false : true;
|
||||
}
|
||||
Subsite::$disable_subsite_filter = $oldState;
|
||||
}
|
||||
|
||||
public function onBeforeWrite()
|
||||
{
|
||||
parent::onBeforeWrite();
|
||||
|
||||
if ($this->CustomMetaTitle) {
|
||||
$this->MetaTitle = $this->CustomMetaTitle;
|
||||
} else {
|
||||
$this->MetaTitle = $this->ContentSource()->MetaTitle ? $this->ContentSource()->MetaTitle : $this->MetaTitle;
|
||||
}
|
||||
if ($this->CustomMetaKeywords) {
|
||||
$this->MetaKeywords = $this->CustomMetaKeywords;
|
||||
} else {
|
||||
$this->MetaKeywords = $this->ContentSource()->MetaKeywords ? $this->ContentSource()->MetaKeywords : $this->MetaKeywords;
|
||||
}
|
||||
if ($this->CustomMetaDescription) {
|
||||
$this->MetaDescription = $this->CustomMetaDescription;
|
||||
} else {
|
||||
$this->MetaDescription = $this->ContentSource()->MetaDescription ? $this->ContentSource()->MetaDescription : $this->MetaDescription;
|
||||
}
|
||||
if ($this->CustomExtraMeta) {
|
||||
$this->ExtraMeta = $this->CustomExtraMeta;
|
||||
} else {
|
||||
$this->ExtraMeta = $this->ContentSource()->ExtraMeta ? $this->ContentSource()->ExtraMeta : $this->ExtraMeta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//class SubsitesVirtualPage_Controller extends VirtualPage_Controller
|
||||
//{
|
||||
// public function reloadContent()
|
||||
// {
|
||||
// $this->failover->copyFrom($this->failover->CopyContentFrom());
|
||||
// $this->failover->write();
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// public function init()
|
||||
// {
|
||||
// $origDisableSubsiteFilter = Subsite::$disable_subsite_filter;
|
||||
// Subsite::$disable_subsite_filter = true;
|
||||
//
|
||||
// parent::init();
|
||||
//
|
||||
// Subsite::$disable_subsite_filter = $origDisableSubsiteFilter;
|
||||
// }
|
||||
//}
|
@ -12,7 +12,7 @@ use SilverStripe\View\SSViewer;
|
||||
*/
|
||||
class ControllerSubsites extends Extension
|
||||
{
|
||||
function controllerAugmentInit()
|
||||
public function controllerAugmentInit()
|
||||
{
|
||||
if ($subsite = Subsite::currentSubsite()) {
|
||||
if ($theme = $subsite->Theme) {
|
||||
@ -21,12 +21,10 @@ class ControllerSubsites extends Extension
|
||||
}
|
||||
}
|
||||
|
||||
function CurrentSubsite()
|
||||
public function CurrentSubsite()
|
||||
{
|
||||
if ($subsite = Subsite::currentSubsite()) {
|
||||
return $subsite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
@ -2,28 +2,26 @@
|
||||
|
||||
namespace SilverStripe\Subsites\Extensions;
|
||||
|
||||
|
||||
use SilverStripe\ORM\DataExtension;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\CMS\Model\SiteTree;
|
||||
use SilverStripe\ORM\DataExtension;
|
||||
use SilverStripe\Subsites\Model\Subsite;
|
||||
|
||||
|
||||
class ErrorPageSubsite extends DataExtension
|
||||
{
|
||||
|
||||
/**
|
||||
* Alter file path to generated a static (static) error page file to handle error page template on different sub-sites
|
||||
*
|
||||
* {@see Error::get_error_filename()}
|
||||
* @see Error::get_filepath_for_errorcode()
|
||||
*
|
||||
* FIXME since {@link Subsite::currentSubsite()} partly relies on Session, viewing other sub-site (including main site) between
|
||||
* opening ErrorPage in the CMS and publish ErrorPage causes static error page to get generated incorrectly.
|
||||
*
|
||||
* @param string $name Filename to write to
|
||||
* @param int $statusCode Integer error code
|
||||
*/
|
||||
public function updateErrorFilename(&$name, $statusCode)
|
||||
public function alternateFilepathForErrorcode($statusCode, $locale = null)
|
||||
{
|
||||
$static_filepath = Config::inst()->get($this->owner->ClassName, 'static_filepath');
|
||||
$subdomainPart = "";
|
||||
|
||||
// Try to get current subsite from session
|
||||
$subsite = Subsite::currentSubsite(false);
|
||||
@ -32,17 +30,23 @@ class ErrorPageSubsite extends DataExtension
|
||||
if (!$subsite) {
|
||||
$subsiteID = Subsite::getSubsiteIDForDomain();
|
||||
if ($subsiteID != 0) {
|
||||
$subsite = DataObject::get_by_id(Subsite::class, $subsiteID);
|
||||
$subsite = DataObject::get_by_id("Subsite", $subsiteID);
|
||||
} else {
|
||||
$subsite = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Without subsite, don't rewrite
|
||||
if ($subsite) {
|
||||
// Add subdomain to end of filename, just before .html
|
||||
// This should preserve translatable locale in the filename as well
|
||||
$subdomain = $subsite->domain();
|
||||
$name = substr($name, 0, -5) . "-{$subdomain}.html";
|
||||
}
|
||||
$subdomainPart = "-{$subdomain}";
|
||||
}
|
||||
|
||||
if (singleton(SiteTree::class)->hasExtension('Translatable') && $locale && $locale != Translatable::default_locale()) {
|
||||
$filepath = $static_filepath . "/error-{$statusCode}-{$locale}{$subdomainPart}.html";
|
||||
} else {
|
||||
$filepath = $static_filepath . "/error-{$statusCode}{$subdomainPart}.html";
|
||||
}
|
||||
|
||||
return $filepath;
|
||||
}
|
||||
}
|
||||
|
@ -21,13 +21,12 @@ use SilverStripe\Subsites\Model\Subsite;
|
||||
* @package subsites
|
||||
*/
|
||||
class FileSubsites extends DataExtension
|
||||
{
|
||||
|
||||
{
|
||||
// If this is set to true, all folders created will be default be
|
||||
// considered 'global', unless set otherwise
|
||||
static $default_root_folders_global = false;
|
||||
public static $default_root_folders_global = false;
|
||||
|
||||
private static $has_one = [
|
||||
private static $has_one=[
|
||||
'Subsite' => Subsite::class,
|
||||
];
|
||||
|
||||
@ -35,43 +34,42 @@ class FileSubsites extends DataExtension
|
||||
* Amends the CMS tree title for folders in the Files & Images section.
|
||||
* Prefixes a '* ' to the folders that are accessible from all subsites.
|
||||
*/
|
||||
function alternateTreeTitle()
|
||||
public function alternateTreeTitle()
|
||||
{
|
||||
if ($this->owner->SubsiteID == 0) {
|
||||
return " * " . $this->owner->Title;
|
||||
} else {
|
||||
return $this->owner->Title;
|
||||
}
|
||||
|
||||
return $this->owner->Title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add subsites-specific fields to the folder editor.
|
||||
*/
|
||||
function updateCMSFields(FieldList $fields)
|
||||
public function updateCMSFields(FieldList $fields)
|
||||
{
|
||||
if ($this->owner instanceof Folder) {
|
||||
if($this->owner instanceof Folder) {
|
||||
$sites = Subsite::accessible_sites('CMS_ACCESS_AssetAdmin');
|
||||
$values = [];
|
||||
$values[0] = _t('FileSubsites.AllSitesDropdownOpt', 'All sites');
|
||||
$values[0] = _t('FileSubsites.AllSitesDropdownOpt','All sites');
|
||||
foreach ($sites as $site) {
|
||||
$values[$site->ID] = $site->Title;
|
||||
}
|
||||
ksort($values);
|
||||
if ($sites) {
|
||||
if($sites){
|
||||
//Dropdown needed to move folders between subsites
|
||||
$dropdown = new DropdownField(
|
||||
'SubsiteID',
|
||||
_t('FileSubsites.SubsiteFieldLabel', Subsite::class),
|
||||
_t('FileSubsites.SubsiteFieldLabel',Subsite::class),
|
||||
$values
|
||||
);
|
||||
$dropdown->addExtraClass('subsites-move-dropdown');
|
||||
$fields->push($dropdown);
|
||||
$fields->push(new LiteralField(
|
||||
'Message',
|
||||
'<p class="message notice">' .
|
||||
_t('ASSETADMIN.SUBSITENOTICE',
|
||||
'Folders and files created in the main site are accessible by all subsites.')
|
||||
. '</p>'
|
||||
'<p class="message notice">'.
|
||||
_t('ASSETADMIN.SUBSITENOTICE', 'Folders and files created in the main site are accessible by all subsites.')
|
||||
.'</p>'
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -112,7 +110,7 @@ class FileSubsites extends DataExtension
|
||||
}
|
||||
}
|
||||
|
||||
function onBeforeWrite()
|
||||
public function onBeforeWrite()
|
||||
{
|
||||
if (!$this->owner->ID && !$this->owner->SubsiteID) {
|
||||
if (self::$default_root_folders_global) {
|
||||
@ -123,7 +121,7 @@ class FileSubsites extends DataExtension
|
||||
}
|
||||
}
|
||||
|
||||
function onAfterUpload()
|
||||
public function onAfterUpload()
|
||||
{
|
||||
// If we have a parent, use it's subsite as our subsite
|
||||
if ($this->owner->Parent()) {
|
||||
@ -134,28 +132,27 @@ class FileSubsites extends DataExtension
|
||||
$this->owner->write();
|
||||
}
|
||||
|
||||
function canEdit($member = null)
|
||||
public function canEdit($member = null)
|
||||
{
|
||||
// Check the CMS_ACCESS_SecurityAdmin privileges on the subsite that owns this group
|
||||
$subsiteID = Session::get('SubsiteID');
|
||||
if ($subsiteID && $subsiteID == $this->owner->SubsiteID) {
|
||||
if($subsiteID&&$subsiteID == $this->owner->SubsiteID) {
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
|
||||
Session::set('SubsiteID', $this->owner->SubsiteID);
|
||||
$access = Permission::check(['CMS_ACCESS_AssetAdmin', 'CMS_ACCESS_LeftAndMain']);
|
||||
Session::set('SubsiteID', $subsiteID);
|
||||
|
||||
return $access;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a piece of text to keep DataObject cache keys appropriately specific
|
||||
*/
|
||||
function cacheKeyComponent()
|
||||
public function cacheKeyComponent()
|
||||
{
|
||||
return 'subsite-' . Subsite::currentSubsiteID();
|
||||
return 'subsite-'.Subsite::currentSubsiteID();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,6 @@ use SilverStripe\Subsites\Model\Subsite;
|
||||
*/
|
||||
class GroupSubsites extends DataExtension implements PermissionProvider
|
||||
{
|
||||
|
||||
private static $db = [
|
||||
'AccessAllSubsites' => 'Boolean'
|
||||
];
|
||||
@ -41,7 +40,7 @@ class GroupSubsites extends DataExtension implements PermissionProvider
|
||||
/**
|
||||
* Migrations for GroupSubsites data.
|
||||
*/
|
||||
function requireDefaultRecords()
|
||||
public function requireDefaultRecords()
|
||||
{
|
||||
// Migration for Group.SubsiteID data from when Groups only had a single subsite
|
||||
$schema = $this->owner->getSchema();
|
||||
@ -65,15 +64,13 @@ class GroupSubsites extends DataExtension implements PermissionProvider
|
||||
if (!DB::query('SELECT "Group"."ID" FROM "Group"
|
||||
LEFT JOIN "Group_Subsites" ON "Group_Subsites"."GroupID" = "Group"."ID" AND "Group_Subsites"."SubsiteID" > 0
|
||||
WHERE "AccessAllSubsites" = 1
|
||||
OR "Group_Subsites"."GroupID" IS NOT NULL ')->value()
|
||||
) {
|
||||
|
||||
OR "Group_Subsites"."GroupID" IS NOT NULL ')->value()) {
|
||||
DB::query('UPDATE "Group" SET "AccessAllSubsites" = 1');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateCMSFields(FieldList $fields)
|
||||
public function updateCMSFields(FieldList $fields)
|
||||
{
|
||||
if ($this->owner->canEdit()) {
|
||||
// i18n tab
|
||||
@ -83,11 +80,11 @@ class GroupSubsites extends DataExtension implements PermissionProvider
|
||||
$subsiteMap = $subsites->map();
|
||||
|
||||
// Prevent XSS injection
|
||||
$subsiteMap = Convert::raw2xml($subsiteMap);
|
||||
$subsiteMap = Convert::raw2xml($subsiteMap->toArray());
|
||||
|
||||
// Interface is different if you have the rights to modify subsite group values on
|
||||
// all subsites
|
||||
if (isset($subsiteMap[0])) {
|
||||
if(isset($subsiteMap[0])) {
|
||||
$fields->addFieldToTab("Root.Subsites", new OptionsetField("AccessAllSubsites",
|
||||
_t('GroupSubsites.ACCESSRADIOTITLE', 'Give this group access to'),
|
||||
[
|
||||
@ -120,7 +117,7 @@ class GroupSubsites extends DataExtension implements PermissionProvider
|
||||
* to make it easy to distinguish in the tree-view
|
||||
* of the security admin interface.
|
||||
*/
|
||||
function alternateTreeTitle()
|
||||
public function alternateTreeTitle()
|
||||
{
|
||||
if ($this->owner->AccessAllSubsites) {
|
||||
$title = _t('GroupSubsites.GlobalGroup', 'global group');
|
||||
@ -176,12 +173,12 @@ class GroupSubsites extends DataExtension implements PermissionProvider
|
||||
// WORKAROUND for databases that complain about an ORDER BY when the column wasn't selected (e.g. SQL Server)
|
||||
$select = $query->getSelect();
|
||||
if (isset($select[0]) && !$select[0] == 'COUNT(*)') {
|
||||
$query->orderby = "\"AccessAllSubsites\" DESC" . ($query->orderby ? ', ' : '') . $query->orderby;
|
||||
$query->addOrderBy("AccessAllSubsites", "DESC");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onBeforeWrite()
|
||||
public function onBeforeWrite()
|
||||
{
|
||||
// New record test approximated by checking whether the ID has changed.
|
||||
// Note also that the after write test is only used when we're *not* on a subsite
|
||||
@ -190,7 +187,7 @@ class GroupSubsites extends DataExtension implements PermissionProvider
|
||||
}
|
||||
}
|
||||
|
||||
function onAfterWrite()
|
||||
public function onAfterWrite()
|
||||
{
|
||||
// New record test approximated by checking whether the ID has changed.
|
||||
// Note also that the after write test is only used when we're on a subsite
|
||||
@ -200,7 +197,7 @@ class GroupSubsites extends DataExtension implements PermissionProvider
|
||||
}
|
||||
}
|
||||
|
||||
function alternateCanEdit()
|
||||
public function alternateCanEdit()
|
||||
{
|
||||
// Find the sites that this group belongs to and the sites where we have appropriate perm.
|
||||
$accessibleSites = Subsite::accessible_sites('CMS_ACCESS_SecurityAdmin')->column('ID');
|
||||
@ -211,7 +208,7 @@ class GroupSubsites extends DataExtension implements PermissionProvider
|
||||
return (bool)array_intersect($accessibleSites, $linkedSites);
|
||||
}
|
||||
|
||||
function providePermissions()
|
||||
public function providePermissions()
|
||||
{
|
||||
return [
|
||||
'SECURITY_SUBSITE_GROUP' => [
|
||||
@ -225,5 +222,3 @@ class GroupSubsites extends DataExtension implements PermissionProvider
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
@ -1,25 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Subsites\Extensions;
|
||||
|
||||
|
||||
use SilverStripe\Admin\CMSMenu;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Control\Session;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\View\Requirements;
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Core\Extension;
|
||||
use SilverStripe\Forms\HiddenField;
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\ORM\ArrayList;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\Security\Permission;
|
||||
use SilverStripe\Security\Security;
|
||||
use SilverStripe\Subsites\Model\Subsite;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\View\ArrayData;
|
||||
use SilverStripe\View\Requirements;
|
||||
|
||||
|
||||
use SilverStripe\Security\Permission;
|
||||
use SilverStripe\Control\Session;
|
||||
use SilverStripe\Admin\CMSMenu;
|
||||
use SilverStripe\Security\Security;
|
||||
use SilverStripe\CMS\Model\SiteTree;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Core\Extension;
|
||||
/**
|
||||
* Decorator designed to add subsites support to LeftAndMain
|
||||
*
|
||||
@ -27,8 +22,7 @@ use SilverStripe\View\Requirements;
|
||||
*/
|
||||
class LeftAndMainSubsites extends Extension
|
||||
{
|
||||
|
||||
private static $allowed_actions = ['CopyToSubsite'];
|
||||
private static $allowed_actions = array('CopyToSubsite');
|
||||
|
||||
/**
|
||||
* Normally SubsiteID=0 on a DataObject means it is only accessible from the special "main site".
|
||||
@ -37,7 +31,7 @@ class LeftAndMainSubsites extends Extension
|
||||
*/
|
||||
private static $treats_subsite_0_as_global = false;
|
||||
|
||||
function init()
|
||||
public function init()
|
||||
{
|
||||
Requirements::css('subsites/css/LeftAndMain_Subsites.css');
|
||||
Requirements::javascript('subsites/javascript/LeftAndMain_Subsites.js');
|
||||
@ -47,13 +41,13 @@ class LeftAndMainSubsites extends Extension
|
||||
/**
|
||||
* Set the title of the CMS tree
|
||||
*/
|
||||
function getCMSTreeTitle()
|
||||
public function getCMSTreeTitle()
|
||||
{
|
||||
$subsite = Subsite::currentSubSite();
|
||||
return $subsite ? Convert::raw2xml($subsite->Title) : _t('LeftAndMain.SITECONTENTLEFT');
|
||||
}
|
||||
|
||||
function updatePageOptions(&$fields)
|
||||
public function updatePageOptions(&$fields)
|
||||
{
|
||||
$fields->push(new HiddenField('SubsiteID', 'SubsiteID', Subsite::currentSubsiteID()));
|
||||
}
|
||||
@ -63,7 +57,7 @@ class LeftAndMainSubsites extends Extension
|
||||
*
|
||||
* @return ArrayList of {@link Subsite} instances.
|
||||
*/
|
||||
function sectionSites($includeMainSite = true, $mainSiteTitle = "Main site", $member = null)
|
||||
public function sectionSites($includeMainSite = true, $mainSiteTitle = "Main site", $member = null)
|
||||
{
|
||||
if ($mainSiteTitle == 'Main site') {
|
||||
$mainSiteTitle = _t('Subsites.MainSiteTitle', 'Main site');
|
||||
@ -77,12 +71,12 @@ class LeftAndMainSubsites extends Extension
|
||||
return new ArrayList();
|
||||
}
|
||||
if (!is_object($member)) {
|
||||
$member = DataObject::get_by_id('SilverStripe\\Security\\Member', $member);
|
||||
$member = DataObject::get_by_id(Member::class, $member);
|
||||
}
|
||||
|
||||
// Collect permissions - honour the LeftAndMain::required_permission_codes, current model requires
|
||||
// us to check if the user satisfies ALL permissions. Code partly copied from LeftAndMain::canView.
|
||||
$codes = [];
|
||||
$codes = array();
|
||||
$extraCodes = Config::inst()->get($this->owner->class, 'required_permission_codes');
|
||||
if ($extraCodes !== false) {
|
||||
if ($extraCodes) {
|
||||
@ -96,8 +90,8 @@ class LeftAndMainSubsites extends Extension
|
||||
}
|
||||
|
||||
// Find subsites satisfying all permissions for the Member.
|
||||
$codesPerSite = [];
|
||||
$sitesArray = [];
|
||||
$codesPerSite = array();
|
||||
$sitesArray = array();
|
||||
foreach ($codes as $code) {
|
||||
$sites = Subsite::accessible_sites($code, $includeMainSite, $mainSiteTitle, $member);
|
||||
foreach ($sites as $site) {
|
||||
@ -112,7 +106,7 @@ class LeftAndMainSubsites extends Extension
|
||||
// Find sites that satisfy all codes conjuncitvely.
|
||||
$accessibleSites = new ArrayList();
|
||||
foreach ($codesPerSite as $siteID => $siteCodes) {
|
||||
if (count($siteCodes) == count($codes)) {
|
||||
if (count($siteCodes)==count($codes)) {
|
||||
$accessibleSites->push($sitesArray[$siteID]);
|
||||
}
|
||||
}
|
||||
@ -151,11 +145,11 @@ class LeftAndMainSubsites extends Extension
|
||||
foreach ($list as $subsite) {
|
||||
$CurrentState = $subsite->ID == $currentSubsiteID ? 'selected' : '';
|
||||
|
||||
$output->push(new ArrayData([
|
||||
$output->push(new ArrayData(array(
|
||||
'CurrentState' => $CurrentState,
|
||||
'ID' => $subsite->ID,
|
||||
'Title' => Convert::raw2xml($subsite->Title)
|
||||
]));
|
||||
)));
|
||||
}
|
||||
|
||||
return $output;
|
||||
@ -194,10 +188,10 @@ class LeftAndMainSubsites extends Extension
|
||||
*/
|
||||
public function shouldChangeSubsite($adminClass, $recordSubsiteID, $currentSubsiteID)
|
||||
{
|
||||
if (Config::inst()->get($adminClass, 'treats_subsite_0_as_global') && $recordSubsiteID == 0) {
|
||||
if (Config::inst()->get($adminClass, 'treats_subsite_0_as_global') && $recordSubsiteID==0) {
|
||||
return false;
|
||||
}
|
||||
if ($recordSubsiteID != $currentSubsiteID) {
|
||||
if ($recordSubsiteID!=$currentSubsiteID) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -206,17 +200,15 @@ class LeftAndMainSubsites extends Extension
|
||||
/**
|
||||
* Check if the current controller is accessible for this user on this subsite.
|
||||
*/
|
||||
function canAccess()
|
||||
public function canAccess()
|
||||
{
|
||||
// Admin can access everything, no point in checking.
|
||||
$member = Member::currentUser();
|
||||
if ($member &&
|
||||
(
|
||||
Permission::checkMember($member, 'ADMIN') || // 'Full administrative rights' in SecurityAdmin
|
||||
Permission::checkMember($member,
|
||||
'CMS_ACCESS_LeftAndMain') // 'Access to all CMS sections' in SecurityAdmin
|
||||
)
|
||||
) {
|
||||
Permission::checkMember($member, 'CMS_ACCESS_LeftAndMain') // 'Access to all CMS sections' in SecurityAdmin
|
||||
)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -279,7 +271,6 @@ class LeftAndMainSubsites extends Extension
|
||||
// This is needed to properly initialise the session in situations where someone opens the CMS via a link.
|
||||
$record = $this->owner->currentPage();
|
||||
if ($record && isset($record->SubsiteID) && is_numeric($record->SubsiteID) && isset($this->owner->urlParams['ID'])) {
|
||||
|
||||
if ($this->shouldChangeSubsite($this->owner->class, $record->SubsiteID, Subsite::currentSubsiteID())) {
|
||||
// Update current subsite in session
|
||||
Subsite::changeSubsite($record->SubsiteID);
|
||||
@ -291,20 +282,17 @@ class LeftAndMainSubsites extends Extension
|
||||
//Redirect to the default CMS section
|
||||
return $this->owner->redirect('admin/');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// SECOND, check if we need to change subsites due to lack of permissions.
|
||||
|
||||
if (!$this->owner->canAccess()) {
|
||||
|
||||
$member = Member::currentUser();
|
||||
|
||||
// Current section is not accessible, try at least to stick to the same subsite.
|
||||
$menu = CMSMenu::get_menu_items();
|
||||
foreach ($menu as $candidate) {
|
||||
if ($candidate->controller && $candidate->controller != $this->owner->class) {
|
||||
|
||||
if ($candidate->controller && $candidate->controller!=$this->owner->class) {
|
||||
$accessibleSites = singleton($candidate->controller)->sectionSites(true, 'Main site', $member);
|
||||
if ($accessibleSites->count() && $accessibleSites->find('ID', Subsite::currentSubsiteID())) {
|
||||
// Section is accessible, redirect there.
|
||||
@ -326,34 +314,41 @@ class LeftAndMainSubsites extends Extension
|
||||
|
||||
// We have not found any accessible section or subsite. User should be denied access.
|
||||
return Security::permissionFailure($this->owner);
|
||||
|
||||
}
|
||||
|
||||
// Current site is accessible. Allow through.
|
||||
return;
|
||||
}
|
||||
|
||||
function augmentNewSiteTreeItem(&$item)
|
||||
public function augmentNewSiteTreeItem(&$item)
|
||||
{
|
||||
$item->SubsiteID = isset($_POST['SubsiteID']) ? $_POST['SubsiteID'] : Subsite::currentSubsiteID();
|
||||
}
|
||||
|
||||
function onAfterSave($record)
|
||||
public function onAfterSave($record)
|
||||
{
|
||||
if ($record->hasMethod('NormalRelated') && ($record->NormalRelated() || $record->ReverseRelated())) {
|
||||
$this->owner->response->addHeader('X-Status',
|
||||
rawurlencode(_t('LeftAndMainSubsites.Saved', 'Saved, please update related pages.')));
|
||||
$this->owner->response->addHeader('X-Status', rawurlencode(_t('LeftAndMainSubsites.Saved', 'Saved, please update related pages.')));
|
||||
}
|
||||
}
|
||||
|
||||
function copytosubsite($data, $form)
|
||||
/**
|
||||
* @param array $data
|
||||
* @param Form $form
|
||||
*/
|
||||
public function copytosubsite($data, $form)
|
||||
{
|
||||
$page = DataObject::get_by_id('SilverStripe\\CMS\\Model\\SiteTree', $data['ID']);
|
||||
$subsite = DataObject::get_by_id(Subsite::class, $data['CopyToSubsiteID']);
|
||||
$newPage = $page->duplicateToSubsite($subsite->ID, true);
|
||||
$page = DataObject::get_by_id(SiteTree::class, $data['ID']);
|
||||
$subsite = DataObject::get_by_id('Subsite', $data['CopyToSubsiteID']);
|
||||
$includeChildren = (isset($data['CopyToSubsiteWithChildren'])) ? $data['CopyToSubsiteWithChildren'] : false;
|
||||
|
||||
$newPage = $page->duplicateToSubsite($subsite->ID, $includeChildren);
|
||||
$response = $this->owner->getResponse();
|
||||
$response->addHeader('X-Reload', true);
|
||||
return $this->owner->redirect(Controller::join_links($this->owner->Link('show'), $newPage->ID));
|
||||
}
|
||||
|
||||
return $this->owner->redirect(Controller::join_links(
|
||||
$this->owner->Link('show'),
|
||||
$newPage->ID
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ use SilverStripe\Subsites\Model\Subsite;
|
||||
*/
|
||||
class SiteConfigSubsites extends DataExtension
|
||||
{
|
||||
|
||||
private static $has_one = [
|
||||
'Subsite' => Subsite::class, // The subsite that this page belongs to
|
||||
];
|
||||
@ -25,11 +24,8 @@ class SiteConfigSubsites extends DataExtension
|
||||
/**
|
||||
* Update any requests to limit the results to the current site
|
||||
*/
|
||||
public function augmentSQL(SQLSelect $query, DataQuery $dataQuery = null)
|
||||
{
|
||||
if (Subsite::$disable_subsite_filter) {
|
||||
return;
|
||||
}
|
||||
public function augmentSQL(SQLSelect$query, DataQuery $dataQuery = null) {
|
||||
if(Subsite::$disable_subsite_filter) {return;}
|
||||
|
||||
// If you're querying by ID, ignore the sub-site - this is a bit ugly...
|
||||
if ($query->filtersOnID()) {
|
||||
@ -42,20 +38,16 @@ class SiteConfigSubsites extends DataExtension
|
||||
}
|
||||
}
|
||||
|
||||
/*if($context = DataObject::context_obj()) $subsiteID = (int)$context->SubsiteID;
|
||||
else */
|
||||
$subsiteID = (int)Subsite::currentSubsiteID();
|
||||
|
||||
$froms = $query->getFrom();
|
||||
$froms = array_keys($froms);
|
||||
$froms=$query->getFrom();
|
||||
$froms=array_keys($froms);
|
||||
$tableName = array_shift($froms);
|
||||
if ($tableName != SiteConfig::class) {
|
||||
return;
|
||||
}
|
||||
if($tableName != SiteConfig::class) { return;}
|
||||
$query->addWhere("\"$tableName\".\"SubsiteID\" IN ($subsiteID)");
|
||||
}
|
||||
|
||||
function onBeforeWrite()
|
||||
public function onBeforeWrite()
|
||||
{
|
||||
if ((!is_numeric($this->owner->ID) || !$this->owner->ID) && !$this->owner->SubsiteID) {
|
||||
$this->owner->SubsiteID = Subsite::currentSubsiteID();
|
||||
@ -65,12 +57,12 @@ class SiteConfigSubsites extends DataExtension
|
||||
/**
|
||||
* Return a piece of text to keep DataObject cache keys appropriately specific
|
||||
*/
|
||||
function cacheKeyComponent()
|
||||
public function cacheKeyComponent()
|
||||
{
|
||||
return 'subsite-' . Subsite::currentSubsiteID();
|
||||
return 'subsite-'.Subsite::currentSubsiteID();
|
||||
}
|
||||
|
||||
function updateCMSFields(FieldList $fields)
|
||||
public function updateCMSFields(FieldList $fields)
|
||||
{
|
||||
$fields->push(new HiddenField('SubsiteID', 'SubsiteID', Subsite::currentSubsiteID()));
|
||||
}
|
||||
|
@ -1,47 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Subsites\Extensions;
|
||||
|
||||
|
||||
use Page;
|
||||
use SilverStripe\CMS\Model\SiteTree;
|
||||
use SilverStripe\ORM\DataQuery;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\DropdownField;
|
||||
use SilverStripe\Forms\CheckboxField;
|
||||
use SilverStripe\Forms\InlineFormAction;
|
||||
use SilverStripe\Forms\ToggleCompositeField;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\ORM\Queries\SQLSelect;
|
||||
use SilverStripe\SiteConfig\SiteConfig;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\View\SSViewer;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Control\HTTP;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Forms\DropdownField;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\InlineFormAction;
|
||||
use SilverStripe\ORM\DataExtension;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DataQuery;
|
||||
use SilverStripe\ORM\Queries\SQLSelect;
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\SiteConfig\SiteConfig;
|
||||
use SilverStripe\Subsites\Model\Subsite;
|
||||
|
||||
|
||||
/**
|
||||
* Extension for the SiteTree object to add subsites support
|
||||
*/
|
||||
class SiteTreeSubsites extends DataExtension
|
||||
{
|
||||
private static $has_one = array(
|
||||
'Subsite' => 'Subsite', // The subsite that this page belongs to
|
||||
);
|
||||
|
||||
private static $has_one = [
|
||||
'Subsite' => Subsite::class, // The subsite that this page belongs to
|
||||
];
|
||||
private static $many_many = array(
|
||||
'CrossSubsiteLinkTracking' => SiteTree::class // Stored separately, as the logic for URL rewriting is different
|
||||
);
|
||||
|
||||
private static $many_many = [
|
||||
'CrossSubsiteLinkTracking' => 'SilverStripe\\CMS\\Model\\SiteTree'
|
||||
// Stored separately, as the logic for URL rewriting is different
|
||||
];
|
||||
private static $many_many_extraFields = array(
|
||||
"CrossSubsiteLinkTracking" => array("FieldName" => "Varchar")
|
||||
);
|
||||
|
||||
private static $many_many_extraFields = [
|
||||
"CrossSubsiteLinkTracking" => ["FieldName" => "Varchar"]
|
||||
];
|
||||
|
||||
function isMainSite()
|
||||
public function isMainSite()
|
||||
{
|
||||
if ($this->owner->SubsiteID == 0) {
|
||||
return true;
|
||||
@ -51,13 +46,15 @@ class SiteTreeSubsites extends DataExtension
|
||||
|
||||
/**
|
||||
* Update any requests to limit the results to the current site
|
||||
* @param SQLSelect $query
|
||||
* @param DataQuery $dataQuery
|
||||
*/
|
||||
public function augmentSQL(SQLSelect $query, DataQuery $dataQuery = null)
|
||||
{
|
||||
if (Subsite::$disable_subsite_filter) {
|
||||
return;
|
||||
}
|
||||
if ($dataQuery->getQueryParam('Subsite.filter') === false) {
|
||||
if ($dataQuery && $dataQuery->getQueryParam('Subsite.filter') === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -71,8 +68,7 @@ class SiteTreeSubsites extends DataExtension
|
||||
$subsiteID = Subsite::$force_subsite;
|
||||
} else {
|
||||
/*if($context = DataObject::context_obj()) $subsiteID = (int)$context->SubsiteID;
|
||||
else */
|
||||
$subsiteID = (int)Subsite::currentSubsiteID();
|
||||
else */$subsiteID = (int)Subsite::currentSubsiteID();
|
||||
}
|
||||
|
||||
// The foreach is an ugly way of getting the first key :-)
|
||||
@ -86,7 +82,7 @@ class SiteTreeSubsites extends DataExtension
|
||||
}
|
||||
}
|
||||
|
||||
function onBeforeWrite()
|
||||
public function onBeforeWrite()
|
||||
{
|
||||
if (!$this->owner->ID && !$this->owner->SubsiteID) {
|
||||
$this->owner->SubsiteID = Subsite::currentSubsiteID();
|
||||
@ -95,57 +91,67 @@ class SiteTreeSubsites extends DataExtension
|
||||
parent::onBeforeWrite();
|
||||
}
|
||||
|
||||
function updateCMSFields(FieldList $fields)
|
||||
public function updateCMSFields(FieldList $fields)
|
||||
{
|
||||
$subsites = Subsite::accessible_sites("CMS_ACCESS_CMSMain");
|
||||
$subsitesMap = [];
|
||||
$subsitesMap = array();
|
||||
if ($subsites && $subsites->Count()) {
|
||||
$subsitesMap = $subsites->map('ID', 'Title')->toArray();
|
||||
unset($subsitesMap[$this->owner->SubsiteID]);
|
||||
$subsitesToMap = $subsites->exclude('ID', $this->owner->SubsiteID);
|
||||
$subsitesMap = $subsitesToMap->map('ID', 'Title');
|
||||
}
|
||||
|
||||
// Master page edit field (only allowed from default subsite to avoid inconsistent relationships)
|
||||
$isDefaultSubsite = $this->owner->SubsiteID == 0 || $this->owner->Subsite()->DefaultSite;
|
||||
|
||||
if ($isDefaultSubsite && $subsitesMap) {
|
||||
$fields->addFieldToTab(
|
||||
'Root.Main',
|
||||
new DropdownField(
|
||||
"CopyToSubsiteID",
|
||||
_t('SiteTreeSubsites.CopyToSubsite', "Copy page to subsite"),
|
||||
$subsitesMap,
|
||||
''
|
||||
)
|
||||
);
|
||||
$fields->addFieldToTab(
|
||||
$fields->addFieldsToTab(
|
||||
'Root.Main',
|
||||
ToggleCompositeField::create('SubsiteOperations',
|
||||
_t('SiteTreeSubsites.SubsiteOperations', 'Subsite Operations'),
|
||||
array(
|
||||
new DropdownField("CopyToSubsiteID", _t('SiteTreeSubsites.CopyToSubsite', "Copy page to subsite"), $subsitesMap),
|
||||
new CheckboxField("CopyToSubsiteWithChildren", _t('SiteTreeSubsites.CopyToSubsiteWithChildren', 'Include children pages?')),
|
||||
$copyAction = new InlineFormAction(
|
||||
"copytosubsite",
|
||||
_t('SiteTreeSubsites.CopyAction', "Copy")
|
||||
)
|
||||
)
|
||||
)->setHeadingLevel(4)
|
||||
);
|
||||
|
||||
|
||||
// $copyAction->includeDefaultJS(false);
|
||||
}
|
||||
|
||||
// replace readonly link prefix
|
||||
$subsite = $this->owner->Subsite();
|
||||
$nested_urls_enabled = Config::inst()->get('SilverStripe\\CMS\\Model\\SiteTree', 'nested_urls');
|
||||
if ($subsite && $subsite->ID) {
|
||||
$baseUrl = Director::protocol() . $subsite->domain() . '/';
|
||||
$nested_urls_enabled = Config::inst()->get(SiteTree::class, 'nested_urls');
|
||||
if ($subsite && $subsite->exists()) {
|
||||
// Use baseurl from domain
|
||||
$baseLink = $subsite->absoluteBaseURL();
|
||||
|
||||
// Add parent page if enabled
|
||||
if($nested_urls_enabled && $this->owner->ParentID) {
|
||||
$baseLink = Controller::join_links(
|
||||
$baseUrl,
|
||||
($nested_urls_enabled && $this->owner->ParentID ? $this->owner->Parent()->RelativeLink(true) : null)
|
||||
$baseLink,
|
||||
$this->owner->Parent()->RelativeLink(true)
|
||||
);
|
||||
}
|
||||
|
||||
$urlsegment = $fields->dataFieldByName('URLSegment');
|
||||
$urlsegment->setURLPrefix($baseLink);
|
||||
}
|
||||
}
|
||||
|
||||
function alternateSiteConfig()
|
||||
/**
|
||||
* @return SiteConfig
|
||||
*/
|
||||
public function alternateSiteConfig()
|
||||
{
|
||||
if (!$this->owner->SubsiteID) {
|
||||
return false;
|
||||
}
|
||||
$sc = DataObject::get_one('SilverStripe\\SiteConfig\\SiteConfig', '"SubsiteID" = ' . $this->owner->SubsiteID);
|
||||
$sc = DataObject::get_one(SiteConfig::class, '"SubsiteID" = ' . $this->owner->SubsiteID);
|
||||
if (!$sc) {
|
||||
$sc = new SiteConfig();
|
||||
$sc->SubsiteID = $this->owner->SubsiteID;
|
||||
@ -163,9 +169,8 @@ class SiteTreeSubsites extends DataExtension
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
function canEdit($member = null)
|
||||
public function canEdit($member = null)
|
||||
{
|
||||
|
||||
if (!$member) {
|
||||
$member = Member::currentUser();
|
||||
}
|
||||
@ -193,9 +198,9 @@ class SiteTreeSubsites extends DataExtension
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
function canDelete($member = null)
|
||||
public function canDelete($member = null)
|
||||
{
|
||||
if (!$member && $member !== FALSE) {
|
||||
if (!$member && $member !== false) {
|
||||
$member = Member::currentUser();
|
||||
}
|
||||
|
||||
@ -205,9 +210,9 @@ class SiteTreeSubsites extends DataExtension
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
function canAddChildren($member = null)
|
||||
public function canAddChildren($member = null)
|
||||
{
|
||||
if (!$member && $member !== FALSE) {
|
||||
if (!$member && $member !== false) {
|
||||
$member = Member::currentUser();
|
||||
}
|
||||
|
||||
@ -217,9 +222,9 @@ class SiteTreeSubsites extends DataExtension
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
function canPublish($member = null)
|
||||
public function canPublish($member = null)
|
||||
{
|
||||
if (!$member && $member !== FALSE) {
|
||||
if (!$member && $member !== false) {
|
||||
$member = Member::currentUser();
|
||||
}
|
||||
|
||||
@ -227,98 +232,64 @@ class SiteTreeSubsites extends DataExtension
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the basic duplication, but doesn't write anything
|
||||
* this means we can subclass this easier and do more complex
|
||||
* relation duplication.
|
||||
* Create a duplicate of this page and save it to another subsite
|
||||
*
|
||||
* @param int|Subsite $subsiteID The Subsite to copy to, or its ID
|
||||
* @param bool $includeChildren Recursively copy child Pages.
|
||||
* @param int $parentID Where to place the Page in the SiteTree's structure.
|
||||
*
|
||||
* @return SiteTree duplicated page
|
||||
*/
|
||||
public function duplicateToSubsitePrep($subsiteID)
|
||||
public function duplicateToSubsite($subsiteID = null, $includeChildren = false, $parentID = 0)
|
||||
{
|
||||
if (is_object($subsiteID)) {
|
||||
if ($subsiteID instanceof Subsite) {
|
||||
$subsiteID = $subsiteID->ID;
|
||||
}
|
||||
|
||||
$oldSubsite = Subsite::currentSubsiteID();
|
||||
|
||||
if ($subsiteID) {
|
||||
Subsite::changeSubsite($subsiteID);
|
||||
} else {
|
||||
$subsiteID = $oldSubsite;
|
||||
}
|
||||
// doesn't write as we need to reset the SubsiteID, ParentID etc
|
||||
$clone = $this->owner->duplicate(false);
|
||||
$clone->CheckedPublicationDifferences = $clone->AddedToStage = true;
|
||||
|
||||
$page = $this->owner->duplicate(false);
|
||||
|
||||
$page->CheckedPublicationDifferences = $page->AddedToStage = true;
|
||||
$subsiteID = ($subsiteID ? $subsiteID : $oldSubsite);
|
||||
$clone->SubsiteID = $subsiteID;
|
||||
// We have no idea what the parentID should be, so as a workaround use the url-segment and subsite ID
|
||||
if ($this->owner->Parent()) {
|
||||
$parentSeg = $this->owner->Parent()->URLSegment;
|
||||
$newParentPage = Page::get()->filter('URLSegment', $parentSeg)->first();
|
||||
if ($newParentPage) {
|
||||
$clone->ParentID = $newParentPage->ID;
|
||||
} else {
|
||||
// reset it to the top level, so the user can decide where to put it
|
||||
$clone->ParentID = 0;
|
||||
}
|
||||
}
|
||||
$page->SubsiteID = $subsiteID;
|
||||
|
||||
$page->ParentID = $parentID;
|
||||
|
||||
// MasterPageID is here for legacy purposes, to satisfy the subsites_relatedpages module
|
||||
$clone->MasterPageID = $this->owner->ID;
|
||||
return $clone;
|
||||
$page->MasterPageID = $this->owner->ID;
|
||||
$page->write();
|
||||
|
||||
Subsite::changeSubsite($oldSubsite);
|
||||
|
||||
if($includeChildren) {
|
||||
foreach($this->owner->AllChildren() as $child) {
|
||||
$child->duplicateToSubsite($subsiteID, $includeChildren, $page->ID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a duplicate of this page and save it to another subsite
|
||||
* @param $subsiteID int|Subsite The Subsite to copy to, or its ID
|
||||
*/
|
||||
public function duplicateToSubsite($subsiteID = null)
|
||||
{
|
||||
$clone = $this->owner->duplicateToSubsitePrep($subsiteID);
|
||||
$clone->invokeWithExtensions('onBeforeDuplicateToSubsite', $this->owner);
|
||||
$clone->write();
|
||||
$clone->duplicateSubsiteRelations($this->owner);
|
||||
// new extension hooks which happens after write,
|
||||
// onAfterDuplicate isn't reliable due to
|
||||
// https://github.com/silverstripe/silverstripe-cms/issues/1253
|
||||
$clone->invokeWithExtensions('onAfterDuplicateToSubsite', $this->owner);
|
||||
return $clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate relations using a static property to define
|
||||
* which ones we want to duplicate
|
||||
*
|
||||
* It may be that some relations are not diostinct to sub site so can stay
|
||||
* whereas others may need to be duplicated
|
||||
*
|
||||
*/
|
||||
public function duplicateSubsiteRelations($originalPage)
|
||||
{
|
||||
$thisClass = $originalPage->ClassName;
|
||||
$relations = Config::inst()->get($thisClass, 'duplicate_to_subsite_relations');
|
||||
|
||||
if ($relations && !empty($relations)) {
|
||||
foreach ($relations as $relation) {
|
||||
$items = $originalPage->$relation();
|
||||
foreach ($items as $item) {
|
||||
$duplicateItem = $item->duplicate(false);
|
||||
$duplicateItem->{$thisClass . 'ID'} = $this->owner->ID;
|
||||
$duplicateItem->write();
|
||||
}
|
||||
}
|
||||
}
|
||||
return $page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by ContentController::init();
|
||||
*/
|
||||
static function contentcontrollerInit($controller)
|
||||
public static function contentcontrollerInit($controller)
|
||||
{
|
||||
$subsite = Subsite::currentSubsite();
|
||||
|
||||
if ($subsite && $subsite->Theme) {
|
||||
Config::modify()->set('SilverStripe\\View\\SSViewer', 'theme', Subsite::currentSubsite()->Theme);
|
||||
Config::inst()->update(SSViewer::class, 'theme', Subsite::currentSubsite()->Theme);
|
||||
}
|
||||
}
|
||||
|
||||
function alternateAbsoluteLink()
|
||||
public function alternateAbsoluteLink()
|
||||
{
|
||||
// Generate the existing absolute URL and replace the domain with the subsite domain.
|
||||
// This helps deal with Link() returning an absolute URL.
|
||||
@ -333,7 +304,7 @@ class SiteTreeSubsites extends DataExtension
|
||||
* Use the CMS domain for iframed CMS previews to prevent single-origin violations
|
||||
* and SSL cert problems.
|
||||
*/
|
||||
function alternatePreviewLink($action = null)
|
||||
public function alternatePreviewLink($action = null)
|
||||
{
|
||||
$url = Director::absoluteURL($this->owner->Link());
|
||||
if ($this->owner->SubsiteID) {
|
||||
@ -345,7 +316,7 @@ class SiteTreeSubsites extends DataExtension
|
||||
/**
|
||||
* Inject the subsite ID into the content so it can be used by frontend scripts.
|
||||
*/
|
||||
function MetaTags(&$tags)
|
||||
public function MetaTags(&$tags)
|
||||
{
|
||||
if ($this->owner->SubsiteID) {
|
||||
$tags .= "<meta name=\"x-subsite-id\" content=\"" . $this->owner->SubsiteID . "\" />\n";
|
||||
@ -354,11 +325,11 @@ class SiteTreeSubsites extends DataExtension
|
||||
return $tags;
|
||||
}
|
||||
|
||||
function augmentSyncLinkTracking()
|
||||
public function augmentSyncLinkTracking()
|
||||
{
|
||||
// Set LinkTracking appropriately
|
||||
$links = HTTP::getLinksIn($this->owner->Content);
|
||||
$linkedPages = [];
|
||||
$linkedPages = array();
|
||||
|
||||
if ($links) {
|
||||
foreach ($links as $link) {
|
||||
@ -375,9 +346,7 @@ class SiteTreeSubsites extends DataExtension
|
||||
|
||||
$origDisableSubsiteFilter = Subsite::$disable_subsite_filter;
|
||||
Subsite::disable_subsite_filter(true);
|
||||
$candidatePage = DataObject::get_one("SilverStripe\\CMS\\Model\\SiteTree",
|
||||
"\"URLSegment\" = '" . Convert::raw2sql(urldecode($rest)) . "' AND \"SubsiteID\" = " . $subsiteID,
|
||||
false);
|
||||
$candidatePage = DataObject::get_one(SiteTree::class, "\"URLSegment\" = '" . Convert::raw2sql(urldecode($rest)) . "' AND \"SubsiteID\" = " . $subsiteID, false);
|
||||
Subsite::disable_subsite_filter($origDisableSubsiteFilter);
|
||||
|
||||
if ($candidatePage) {
|
||||
@ -393,19 +362,46 @@ class SiteTreeSubsites extends DataExtension
|
||||
$this->owner->CrossSubsiteLinkTracking()->setByIDList($linkedPages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that valid url segments are checked within the correct subsite of the owner object,
|
||||
* even if the current subsiteID is set to some other subsite.
|
||||
*
|
||||
* @return null|bool Either true or false, or null to not influence result
|
||||
*/
|
||||
public function augmentValidURLSegment()
|
||||
{
|
||||
// If this page is being filtered in the current subsite, then no custom validation query is required.
|
||||
$subsite = Subsite::$force_subsite ?: Subsite::currentSubsiteID();
|
||||
if (empty($this->owner->SubsiteID) || $subsite == $this->owner->SubsiteID) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Backup forced subsite
|
||||
$prevForceSubsite = Subsite::$force_subsite;
|
||||
Subsite::$force_subsite = $this->owner->SubsiteID;
|
||||
|
||||
// Repeat validation in the correct subsite
|
||||
$isValid = $this->owner->validURLSegment();
|
||||
|
||||
// Restore
|
||||
Subsite::$force_subsite = $prevForceSubsite;
|
||||
|
||||
return (bool)$isValid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a piece of text to keep DataObject cache keys appropriately specific
|
||||
*/
|
||||
function cacheKeyComponent()
|
||||
public function cacheKeyComponent()
|
||||
{
|
||||
return 'subsite-' . Subsite::currentSubsiteID();
|
||||
return 'subsite-'.Subsite::currentSubsiteID();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Member
|
||||
* @return boolean|null
|
||||
*/
|
||||
function canCreate($member = null)
|
||||
public function canCreate($member = null)
|
||||
{
|
||||
// Typically called on a singleton, so we're not using the Subsite() relation
|
||||
$subsite = Subsite::currentSubsite();
|
||||
|
@ -16,7 +16,6 @@ class GridFieldSubsiteDetailForm extends GridFieldDetailForm
|
||||
|
||||
class GridFieldSubsiteDetailForm_ItemRequest extends GridFieldDetailForm_ItemRequest
|
||||
{
|
||||
|
||||
private static $allowed_actions = [
|
||||
'ItemEditForm',
|
||||
];
|
||||
@ -32,7 +31,7 @@ class GridFieldSubsiteDetailForm_ItemRequest extends GridFieldDetailForm_ItemReq
|
||||
* @return Form
|
||||
* @see GridFieldDetailForm_ItemRequest::ItemEditForm()
|
||||
*/
|
||||
function ItemEditForm()
|
||||
public function ItemEditForm()
|
||||
{
|
||||
$form = parent::ItemEditForm();
|
||||
|
||||
@ -52,7 +51,7 @@ class GridFieldSubsiteDetailForm_ItemRequest extends GridFieldDetailForm_ItemReq
|
||||
return $form;
|
||||
}
|
||||
|
||||
function doSave($data, $form)
|
||||
public function doSave($data, $form)
|
||||
{
|
||||
$new_record = $this->record->ID == 0;
|
||||
if ($new_record && isset($data['TemplateID']) && !empty($data['TemplateID'])) {
|
||||
|
@ -17,16 +17,15 @@ use SilverStripe\View\Requirements;
|
||||
*/
|
||||
class SubsitesTreeDropdownField extends TreeDropdownField
|
||||
{
|
||||
|
||||
private static $allowed_actions = [
|
||||
private static $allowed_actions = array(
|
||||
'tree'
|
||||
];
|
||||
);
|
||||
|
||||
protected $subsiteID = 0;
|
||||
|
||||
protected $extraClasses = [SubsitesTreeDropdownField::class];
|
||||
protected $extraClasses = array('SubsitesTreeDropdownField');
|
||||
|
||||
function Field($properties = [])
|
||||
public function Field($properties = array())
|
||||
{
|
||||
$html = parent::Field($properties);
|
||||
|
||||
@ -35,17 +34,17 @@ class SubsitesTreeDropdownField extends TreeDropdownField
|
||||
return $html;
|
||||
}
|
||||
|
||||
function setSubsiteID($id)
|
||||
public function setSubsiteID($id)
|
||||
{
|
||||
$this->subsiteID = $id;
|
||||
}
|
||||
|
||||
function getSubsiteID()
|
||||
public function getSubsiteID()
|
||||
{
|
||||
return $this->subsiteID;
|
||||
}
|
||||
|
||||
function tree(HTTPRequest $request)
|
||||
public function tree(HTTPRequest $request)
|
||||
{
|
||||
$oldSubsiteID = Session::get('SubsiteID');
|
||||
Session::set('SubsiteID', $this->subsiteID);
|
||||
|
45
code/forms/WildcardDomainField.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\Forms\TextField;
|
||||
|
||||
/**
|
||||
* A text field that accepts only valid domain names, but allows the wildcard (*) character
|
||||
*/
|
||||
class WildcardDomainField extends TextField
|
||||
{
|
||||
/**
|
||||
* Validate this field as a valid hostname
|
||||
*
|
||||
* @param Validator $validator
|
||||
* @return bool
|
||||
*/
|
||||
public function validate($validator)
|
||||
{
|
||||
if ($this->checkHostname($this->Value())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$validator->validationError(
|
||||
$this->getName(),
|
||||
_t("DomainNameField.INVALID_DOMAIN", "Invalid domain name"),
|
||||
"validation"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given hostname is valid.
|
||||
*
|
||||
* @param string $hostname
|
||||
* @return bool True if this hostname is valid
|
||||
*/
|
||||
public function checkHostname($hostname)
|
||||
{
|
||||
return (bool)preg_match('/^([a-z0-9\*]+[\-\.])*([a-z0-9\*]+)$/', $hostname);
|
||||
}
|
||||
|
||||
public function Type()
|
||||
{
|
||||
return 'text wildcarddomain';
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@ use SilverStripe\CMS\Model\SiteTree;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Control\Session;
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Forms\CheckboxField;
|
||||
use SilverStripe\Forms\CheckboxSetField;
|
||||
use SilverStripe\Forms\DropdownField;
|
||||
@ -29,6 +30,7 @@ use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DB;
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\Security\Permission;
|
||||
use SilverStripe\Security\Group;
|
||||
use SilverStripe\Versioned\Versioned;
|
||||
use UnexpectedValueException;
|
||||
|
||||
@ -104,8 +106,7 @@ class Subsite extends DataObject
|
||||
*/
|
||||
public static $check_is_public = true;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
/*** @return array
|
||||
*/
|
||||
private static $summary_fields = [
|
||||
'Title',
|
||||
@ -119,8 +120,7 @@ class Subsite extends DataObject
|
||||
* @param array $themes - Numeric array of all themes which are allowed to be selected for all subsites.
|
||||
*/
|
||||
public static function set_allowed_themes($themes)
|
||||
{
|
||||
self::$allowed_themes = $themes;
|
||||
{self::$allowed_themes = $themes;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -130,8 +130,7 @@ class Subsite extends DataObject
|
||||
* @return Subsite
|
||||
*/
|
||||
public static function currentSubsite()
|
||||
{
|
||||
// get_by_id handles caching so we don't have to
|
||||
{// get_by_id handles caching so we don't have to
|
||||
return DataObject::get_by_id(Subsite::class, self::currentSubsiteID());
|
||||
}
|
||||
|
||||
@ -145,22 +144,18 @@ class Subsite extends DataObject
|
||||
*
|
||||
* @todo Pass $request object from controller so we don't have to rely on $_GET
|
||||
*
|
||||
* @param boolean $cache
|
||||
* @return int ID of the current subsite instance
|
||||
*/
|
||||
public static function currentSubsiteID()
|
||||
{
|
||||
$id = NULL;
|
||||
{$id = null;
|
||||
|
||||
if (isset($_GET['SubsiteID'])) {
|
||||
$id = (int)$_GET['SubsiteID'];
|
||||
} else {
|
||||
if (Subsite::$use_session_subsiteid) {
|
||||
} elseif (Subsite::$use_session_subsiteid) {
|
||||
$id = Session::get('SubsiteID');
|
||||
}
|
||||
}
|
||||
|
||||
if ($id === NULL) {
|
||||
if($id === null) {
|
||||
$id = self::getSubsiteIDForDomain();
|
||||
}
|
||||
|
||||
@ -173,26 +168,20 @@ class Subsite extends DataObject
|
||||
*
|
||||
* @param int|Subsite $subsite Either the ID of the subsite, or the subsite object itself
|
||||
*/
|
||||
public static function changeSubsite($subsite)
|
||||
{
|
||||
public static function changeSubsite($subsite) {
|
||||
// Session subsite change only meaningful if the session is active.
|
||||
// Otherwise we risk setting it to wrong value, e.g. if we rely on currentSubsiteID.
|
||||
if (!Subsite::$use_session_subsiteid) {
|
||||
return;
|
||||
}
|
||||
if (!Subsite::$use_session_subsiteid) return;
|
||||
|
||||
if (is_object($subsite)) {
|
||||
$subsiteID = $subsite->ID;
|
||||
} else {
|
||||
$subsiteID = $subsite;
|
||||
}
|
||||
if(is_object($subsite)) $subsiteID = $subsite->ID;
|
||||
else $subsiteID = $subsite;
|
||||
|
||||
Session::set('SubsiteID', (int)$subsiteID);
|
||||
|
||||
// Set locale
|
||||
if (is_object($subsite) && $subsite->Language != '') {
|
||||
$locale = i18n::get_locale_from_lang($subsite->Language);
|
||||
if ($locale) {
|
||||
if($locale) {
|
||||
i18n::set_locale($locale);
|
||||
}
|
||||
}
|
||||
@ -209,18 +198,15 @@ class Subsite extends DataObject
|
||||
* @param $host The host to find the subsite for. If not specified, $_SERVER['HTTP_HOST'] is used.
|
||||
* @return int Subsite ID
|
||||
*/
|
||||
public static function getSubsiteIDForDomain($host = null, $checkPermissions = true)
|
||||
{
|
||||
if ($host == null && isset($_SERVER['HTTP_HOST'])) {
|
||||
public static function getSubsiteIDForDomain($host = null, $checkPermissions = true) {
|
||||
if($host == null && isset($_SERVER['HTTP_HOST'])) {
|
||||
$host = $_SERVER['HTTP_HOST'];
|
||||
}
|
||||
|
||||
$matchingDomains = null;
|
||||
$cacheKey = null;
|
||||
if ($host) {
|
||||
if (!self::$strict_subdomain_matching) {
|
||||
$host = preg_replace('/^www\./', '', $host);
|
||||
}
|
||||
if(!self::$strict_subdomain_matching) $host = preg_replace('/^www\./', '', $host);
|
||||
|
||||
$cacheKey = implode('_', [$host, Member::currentUserID(), self::$check_is_public]);
|
||||
if (isset(self::$_cache_subsite_for_domain[$cacheKey])) {
|
||||
@ -232,14 +218,13 @@ class Subsite extends DataObject
|
||||
SubsiteDomain::class,
|
||||
"'$SQL_host' LIKE replace(\"SubsiteDomain\".\"Domain\",'*','%')",
|
||||
"\"IsPrimary\" DESC"
|
||||
)->innerJoin('Subsite',
|
||||
"\"Subsite\".\"ID\" = \"SubsiteDomain\".\"SubsiteID\" AND \"Subsite\".\"IsPublic\"=1");
|
||||
)->innerJoin('Subsite', "\"Subsite\".\"ID\" = \"SubsiteDomain\".\"SubsiteID\" AND \"Subsite\".\"IsPublic\"=1");
|
||||
}
|
||||
|
||||
if ($matchingDomains && $matchingDomains->Count()) {
|
||||
if($matchingDomains && $matchingDomains->Count()) {
|
||||
$subsiteIDs = array_unique($matchingDomains->column('SubsiteID'));
|
||||
$subsiteDomains = array_unique($matchingDomains->column('Domain'));
|
||||
if (sizeof($subsiteIDs) > 1) {
|
||||
if(sizeof($subsiteIDs) > 1) {
|
||||
throw new UnexpectedValueException(sprintf(
|
||||
"Multiple subsites match on '%s': %s",
|
||||
$host,
|
||||
@ -249,14 +234,13 @@ class Subsite extends DataObject
|
||||
|
||||
$subsiteID = $subsiteIDs[0];
|
||||
} else {
|
||||
if ($default = DataObject::get_one(Subsite::class, "\"DefaultSite\" = 1")) {
|
||||
if($default = DataObject::get_one(Subsite::class, "\"DefaultSite\" = 1")) {
|
||||
// Check for a 'default' subsite
|
||||
$subsiteID = $default->ID;
|
||||
} else {
|
||||
// Default subsite id = 0, the main site
|
||||
$subsiteID = 0;
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
if ($cacheKey) {
|
||||
self::$_cache_subsite_for_domain[$cacheKey] = $subsiteID;
|
||||
@ -274,8 +258,7 @@ class Subsite extends DataObject
|
||||
* @param string $limit
|
||||
* @return DataList
|
||||
*/
|
||||
public static function get_from_all_subsites($className, $filter = "", $sort = "", $join = "", $limit = "")
|
||||
{
|
||||
public static function get_from_all_subsites($className, $filter = "", $sort = "", $join = "", $limit = "") {
|
||||
$result = DataObject::get($className, $filter, $sort, $join, $limit);
|
||||
$result = $result->setDataQueryParam('Subsite.filter', false);
|
||||
return $result;
|
||||
@ -307,7 +290,7 @@ class Subsite extends DataObject
|
||||
{
|
||||
$subsites = Subsite::get();
|
||||
|
||||
if ($includeMainSite) {
|
||||
if($includeMainSite) {
|
||||
$subsites = $subsites->toArray();
|
||||
|
||||
$mainSite = new Subsite();
|
||||
@ -336,14 +319,14 @@ class Subsite extends DataObject
|
||||
return new ArrayList();
|
||||
}
|
||||
if (!is_object($member)) {
|
||||
$member = DataObject::get_by_id('SilverStripe\\Security\\Member', $member);
|
||||
$member = DataObject::get_by_id(Member::class, $member);
|
||||
}
|
||||
|
||||
$subsites = new ArrayList();
|
||||
|
||||
// Collect subsites for all sections.
|
||||
$menu = CMSMenu::get_viewable_menu_items();
|
||||
foreach ($menu as $candidate) {
|
||||
foreach($menu as $candidate) {
|
||||
if ($candidate->controller) {
|
||||
$accessibleSites = singleton($candidate->controller)->sectionSites(
|
||||
$includeMainSite,
|
||||
@ -371,12 +354,7 @@ class Subsite extends DataObject
|
||||
* @param $member
|
||||
* @return DataList of {@link Subsite} instances
|
||||
*/
|
||||
public static function accessible_sites(
|
||||
$permCode,
|
||||
$includeMainSite = true,
|
||||
$mainSiteTitle = "Main site",
|
||||
$member = null
|
||||
)
|
||||
public static function accessible_sites($permCode, $includeMainSite = true, $mainSiteTitle = "Main site", $member = null)
|
||||
{
|
||||
// Rationalise member arguments
|
||||
if (!$member) {
|
||||
@ -386,19 +364,16 @@ class Subsite extends DataObject
|
||||
return new ArrayList();
|
||||
}
|
||||
if (!is_object($member)) {
|
||||
$member = DataObject::get_by_id('SilverStripe\\Security\\Member', $member);
|
||||
$member = DataObject::get_by_id(Member::class, $member);
|
||||
}
|
||||
|
||||
// Rationalise permCode argument
|
||||
if (is_array($permCode)) {
|
||||
$SQL_codes = "'" . implode("', '", Convert::raw2sql($permCode)) . "'";
|
||||
} else {
|
||||
$SQL_codes = "'" . Convert::raw2sql($permCode) . "'";
|
||||
}
|
||||
if(is_array($permCode)) $SQL_codes = "'" . implode("', '", Convert::raw2sql($permCode)) . "'";
|
||||
else $SQL_codes = "'" . Convert::raw2sql($permCode) . "'";
|
||||
|
||||
// Cache handling
|
||||
$cacheKey = $SQL_codes . '-' . $member->ID . '-' . $includeMainSite . '-' . $mainSiteTitle;
|
||||
if (isset(self::$_cache_accessible_sites[$cacheKey])) {
|
||||
if(isset(self::$_cache_accessible_sites[$cacheKey])) {
|
||||
return self::$_cache_accessible_sites[$cacheKey];
|
||||
}
|
||||
|
||||
@ -412,9 +387,7 @@ class Subsite extends DataObject
|
||||
->innerJoin('Permission',
|
||||
"\"Group\".\"ID\"=\"Permission\".\"GroupID\" AND \"Permission\".\"Code\" IN ($SQL_codes, 'CMS_ACCESS_LeftAndMain', 'ADMIN')");
|
||||
|
||||
if (!$subsites) {
|
||||
$subsites = new ArrayList();
|
||||
}
|
||||
if(!$subsites) $subsites = new ArrayList();
|
||||
|
||||
$rolesSubsites = DataList::create(Subsite::class)
|
||||
->where("\"Subsite\".\"Title\" != ''")
|
||||
@ -428,19 +401,15 @@ class Subsite extends DataObject
|
||||
->innerJoin('PermissionRoleCode',
|
||||
"\"PermissionRole\".\"ID\"=\"PermissionRoleCode\".\"RoleID\" AND \"PermissionRoleCode\".\"Code\" IN ($SQL_codes, 'CMS_ACCESS_LeftAndMain', 'ADMIN')");
|
||||
|
||||
if (!$subsites && $rolesSubsites) {
|
||||
return $rolesSubsites;
|
||||
}
|
||||
if(!$subsites && $rolesSubsites) return $rolesSubsites;
|
||||
|
||||
$subsites = new ArrayList($subsites->toArray());
|
||||
|
||||
if ($rolesSubsites) {
|
||||
foreach ($rolesSubsites as $subsite) {
|
||||
if (!$subsites->find('ID', $subsite->ID)) {
|
||||
if($rolesSubsites) foreach($rolesSubsites as $subsite) {
|
||||
if(!$subsites->find('ID', $subsite->ID)) {
|
||||
$subsites->push($subsite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($includeMainSite) {
|
||||
if (!is_array($permCode)) {
|
||||
@ -528,17 +497,13 @@ class Subsite extends DataObject
|
||||
user_error('Permissions must be passed to Subsite::hasMainSitePermission as an array', E_USER_ERROR);
|
||||
}
|
||||
|
||||
if (!$member && $member !== FALSE) {
|
||||
if (!$member && $member !== false) {
|
||||
$member = Member::currentUser();
|
||||
}
|
||||
|
||||
if (!$member) {
|
||||
return false;
|
||||
}
|
||||
if(!$member) return false;
|
||||
|
||||
if (!in_array("ADMIN", $permissionCodes)) {
|
||||
$permissionCodes[] = "ADMIN";
|
||||
}
|
||||
if(!in_array("ADMIN", $permissionCodes)) $permissionCodes[] = "ADMIN";
|
||||
|
||||
$SQLa_perm = Convert::raw2sql($permissionCodes);
|
||||
$SQL_perms = join("','", $SQLa_perm);
|
||||
@ -603,7 +568,7 @@ class Subsite extends DataObject
|
||||
* @var array
|
||||
*/
|
||||
private static $belongs_many_many = [
|
||||
"Groups" => "SilverStripe\\Security\\Group",
|
||||
"Groups" => Group::class,
|
||||
];
|
||||
|
||||
/**
|
||||
@ -635,8 +600,7 @@ class Subsite extends DataObject
|
||||
* @return boolean
|
||||
*/
|
||||
public function canEdit($member = false)
|
||||
{
|
||||
return true;
|
||||
{return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -646,7 +610,7 @@ class Subsite extends DataObject
|
||||
*/
|
||||
public function getCMSFields()
|
||||
{
|
||||
if ($this->ID != 0) {
|
||||
if ($this->ID!=0) {
|
||||
$domainTable = new GridField(
|
||||
"Domains",
|
||||
_t('Subsite.DomainsListTitle', "Domains"),
|
||||
@ -656,18 +620,17 @@ class Subsite extends DataObject
|
||||
} else {
|
||||
$domainTable = new LiteralField(
|
||||
'Domains',
|
||||
'<p>' . _t('Subsite.DOMAINSAVEFIRST',
|
||||
'You can only add domains after saving for the first time') . '</p>'
|
||||
'<p>'._t('Subsite.DOMAINSAVEFIRST', 'You can only add domains after saving for the first time').'</p>'
|
||||
);
|
||||
}
|
||||
|
||||
$languageSelector = new DropdownField(
|
||||
'Language',
|
||||
$this->fieldLabel('Language'),
|
||||
(new IntlLocales)->getLocales()
|
||||
Injector::inst()->get(IntlLocales::class)->getLocales()
|
||||
);
|
||||
|
||||
$pageTypeMap = [];
|
||||
$pageTypeMap = array();
|
||||
$pageTypes = SiteTree::page_type_classes();
|
||||
foreach ($pageTypes as $pageType) {
|
||||
$pageTypeMap[$pageType] = singleton($pageType)->i18n_singular_name();
|
||||
@ -679,11 +642,11 @@ class Subsite extends DataObject
|
||||
new Tab(
|
||||
'Configuration',
|
||||
_t('Subsite.TabTitleConfig', 'Configuration'),
|
||||
new HeaderField('ConfigurationHeader', $this->getClassName() . ' configuration', 2),
|
||||
new HeaderField('ConfigForSubsiteHeaderField', $this->getClassName() . ' configuration'),
|
||||
new TextField('Title', $this->fieldLabel('Title'), $this->Title),
|
||||
|
||||
new HeaderField(
|
||||
'DomainsHeader',
|
||||
'DomainsForSubsiteHeaderField',
|
||||
_t('Subsite.DomainsHeadline', "Domains for this subsite")
|
||||
),
|
||||
$domainTable,
|
||||
@ -692,7 +655,7 @@ class Subsite extends DataObject
|
||||
new CheckboxField('DefaultSite', $this->fieldLabel('DefaultSite'), $this->DefaultSite),
|
||||
new CheckboxField('IsPublic', $this->fieldLabel('IsPublic'), $this->IsPublic),
|
||||
|
||||
new DropdownField('Theme', $this->fieldLabel('Theme'), $this->allowedThemes(), $this->Theme),
|
||||
new DropdownField('Theme',$this->fieldLabel('Theme'), $this->allowedThemes(), $this->Theme),
|
||||
|
||||
|
||||
new LiteralField(
|
||||
@ -724,8 +687,7 @@ class Subsite extends DataObject
|
||||
* @param boolean $includerelations
|
||||
* @return array
|
||||
*/
|
||||
public function fieldLabels($includerelations = true)
|
||||
{
|
||||
public function fieldLabels($includerelations = true) {
|
||||
$labels = parent::fieldLabels($includerelations);
|
||||
$labels['Title'] = _t('Subsites.TitleFieldLabel', 'Subsite Name');
|
||||
$labels['RedirectURL'] = _t('Subsites.RedirectURLFieldLabel', 'Redirect URL');
|
||||
@ -741,22 +703,20 @@ class Subsite extends DataObject
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
* Return the themes that can be used with this subsite, as an array of themecode => description
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function allowedThemes()
|
||||
{
|
||||
if ($themes = $this->stat('allowed_themes')) {
|
||||
{if($themes = $this->stat('allowed_themes')) {
|
||||
return ArrayLib::valuekey($themes);
|
||||
} else {
|
||||
$themes = [];
|
||||
if (is_dir('../themes/')) {
|
||||
foreach (scandir('../themes/') as $theme) {
|
||||
if ($theme[0] == '.') {
|
||||
continue;
|
||||
}
|
||||
$theme = strtok($theme, '_');
|
||||
if(is_dir(THEMES_PATH)) {
|
||||
foreach(scandir(THEMES_PATH) as $theme) {
|
||||
if($theme[0] == '.') {continue;}
|
||||
$theme = strtok($theme,'_');
|
||||
$themes[$theme] = $theme;
|
||||
}
|
||||
ksort($themes);
|
||||
@ -768,9 +728,8 @@ class Subsite extends DataObject
|
||||
/**
|
||||
* @return string Current locale of the subsite
|
||||
*/
|
||||
public function getLanguage()
|
||||
{
|
||||
if ($this->getField('Language')) {
|
||||
public function getLanguage() {
|
||||
if($this->getField('Language')) {
|
||||
return $this->getField('Language');
|
||||
} else {
|
||||
return i18n::get_locale();
|
||||
@ -781,10 +740,9 @@ class Subsite extends DataObject
|
||||
*
|
||||
* @return ValidationResult
|
||||
*/
|
||||
public function validate()
|
||||
{
|
||||
public function validate() {
|
||||
$result = parent::validate();
|
||||
if (!$this->Title) {
|
||||
if(!$this->Title) {
|
||||
$result->error(_t('Subsite.ValidateTitle', 'Please add a "Title"'));
|
||||
}
|
||||
return $result;
|
||||
@ -809,26 +767,27 @@ class Subsite extends DataObject
|
||||
*/
|
||||
public function domain()
|
||||
{
|
||||
if ($this->ID) {
|
||||
$domains = DataObject::get(SubsiteDomain::class, "\"SubsiteID\" = $this->ID", "\"IsPrimary\" DESC", "", 1);
|
||||
if ($domains && $domains->Count() > 0) {
|
||||
$domain = $domains->First()->Domain;
|
||||
// If there are wildcards in the primary domain (not recommended), make some
|
||||
// educated guesses about what to replace them with:
|
||||
$domain = preg_replace('/\.\*$/', ".$_SERVER[HTTP_HOST]", $domain);
|
||||
// Default to "subsite." prefix for first wildcard
|
||||
// TODO Whats the significance of "subsite" in this context?!
|
||||
$domain = preg_replace('/^\*\./', "subsite.", $domain);
|
||||
// *Only* removes "intermediate" subdomains, so 'subdomain.www.domain.com' becomes 'subdomain.domain.com'
|
||||
$domain = str_replace('.www.', '.', $domain);
|
||||
|
||||
return $domain;
|
||||
// Get best SubsiteDomain object
|
||||
$domainObject = $this->getPrimarySubsiteDomain();
|
||||
if ($domainObject) {
|
||||
return $domainObject->SubstitutedDomain;
|
||||
}
|
||||
|
||||
// SubsiteID = 0 is often used to refer to the main site, just return $_SERVER['HTTP_HOST']
|
||||
} else {
|
||||
// If there are no objects, default to the current hostname
|
||||
return $_SERVER['HTTP_HOST'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the primary {@see SubsiteDomain} object for this subsite
|
||||
*
|
||||
* @return SubsiteDomain
|
||||
*/
|
||||
public function getPrimarySubsiteDomain()
|
||||
{
|
||||
return $this
|
||||
->Domains()
|
||||
->sort('"IsPrimary" DESC')
|
||||
->first();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -841,19 +800,25 @@ class Subsite extends DataObject
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Get the absolute URL for this subsite
|
||||
* @return string
|
||||
*/
|
||||
public function absoluteBaseURL()
|
||||
{
|
||||
return "http://" . $this->domain() . Director::baseURL();
|
||||
// Get best SubsiteDomain object
|
||||
$domainObject = $this->getPrimarySubsiteDomain();
|
||||
if ($domainObject) {
|
||||
return $domainObject->absoluteBaseURL();
|
||||
}
|
||||
|
||||
// Fall back to the current base url
|
||||
return Director::absoluteBaseURL();
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo getClassName is redundant, already stored as a database field?
|
||||
*/
|
||||
public function getClassName()
|
||||
{
|
||||
public function getClassName() {
|
||||
return $this->class;
|
||||
}
|
||||
|
||||
@ -863,8 +828,7 @@ class Subsite extends DataObject
|
||||
* @return string - javascript
|
||||
*/
|
||||
public function adminDuplicate()
|
||||
{
|
||||
$newItem = $this->duplicate();
|
||||
{$newItem = $this->duplicate();
|
||||
$message = _t(
|
||||
'Subsite.CopyMessage',
|
||||
'Created a copy of {title}',
|
||||
@ -880,8 +844,7 @@ JS;
|
||||
/**
|
||||
* Make this subsite the current one
|
||||
*/
|
||||
public function activate()
|
||||
{
|
||||
public function activate() {
|
||||
Subsite::changeSubsite($this);
|
||||
}
|
||||
|
||||
@ -900,21 +863,19 @@ JS;
|
||||
$SQL_permissionCodes = join("','", $SQL_permissionCodes);
|
||||
|
||||
return DataObject::get(
|
||||
'SilverStripe\\Security\\Member',
|
||||
Member::class,
|
||||
"\"Group\".\"SubsiteID\" = $this->ID AND \"Permission\".\"Code\" IN ('$SQL_permissionCodes')",
|
||||
'',
|
||||
"LEFT JOIN \"Group_Members\" ON \"Member\".\"ID\" = \"Group_Members\".\"MemberID\"
|
||||
LEFT JOIN \"Group\" ON \"Group\".\"ID\" = \"Group_Members\".\"GroupID\"
|
||||
LEFT JOIN \"Permission\" ON \"Permission\".\"GroupID\" = \"Group\".\"ID\""
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate this subsite
|
||||
*/
|
||||
public function duplicate($doWrite = true)
|
||||
{
|
||||
public function duplicate($doWrite = true) {
|
||||
$duplicate = parent::duplicate($doWrite);
|
||||
|
||||
$oldSubsiteID = Session::get('SubsiteID');
|
||||
@ -931,8 +892,8 @@ JS;
|
||||
list($sourceParentID, $destParentID) = array_pop($stack);
|
||||
$children = Versioned::get_by_stage('Page', 'Live', "\"ParentID\" = $sourceParentID", '');
|
||||
|
||||
if ($children) {
|
||||
foreach ($children as $child) {
|
||||
if($children) {
|
||||
foreach($children as $child) {
|
||||
self::changeSubsite($duplicate->ID); //Change to destination subsite
|
||||
|
||||
$childClone = $child->duplicateToSubsite($duplicate, false);
|
||||
|
@ -2,17 +2,21 @@
|
||||
|
||||
namespace SilverStripe\Subsites\Model;
|
||||
|
||||
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Forms\CheckboxField;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\TextField;
|
||||
use SilverStripe\Forms\OptionsetField;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
|
||||
/**
|
||||
* @property text Domain domain name of this subsite. Do not include the URL scheme here
|
||||
* @property bool IsPrimary Is this the primary subdomain?
|
||||
* @property string $Domain domain name of this subsite. Can include wildcards. Do not include the URL scheme here
|
||||
* @property string $Protocol Required protocol (http or https) if only one is supported. 'automatic' implies
|
||||
* that any links to this subsite should use the current protocol, and that both are supported.
|
||||
* @property string $SubstitutedDomain Domain name with all wildcards filled in
|
||||
* @property string $FullProtocol Full protocol including ://
|
||||
* @property bool $IsPrimary Is this the primary subdomain?
|
||||
*/
|
||||
class SubsiteDomain extends DataObject
|
||||
{
|
||||
@ -25,15 +29,39 @@ class SubsiteDomain extends DataObject
|
||||
*/
|
||||
private static $default_sort = "\"IsPrimary\" DESC";
|
||||
|
||||
/**
|
||||
*
|
||||
/** *
|
||||
* @var array
|
||||
*/
|
||||
private static $db = [
|
||||
"Domain" => "Varchar(255)",
|
||||
"Protocol" => "Enum('http,https,automatic','automatic')",
|
||||
"IsPrimary" => "Boolean",
|
||||
];
|
||||
|
||||
/*** Specifies that this subsite is http only
|
||||
*/
|
||||
const PROTOCOL_HTTP = 'http';
|
||||
|
||||
/**
|
||||
* Specifies that this subsite is https only
|
||||
*/
|
||||
const PROTOCOL_HTTPS = 'https';
|
||||
|
||||
/**
|
||||
* Specifies that this subsite supports both http and https
|
||||
*/
|
||||
const PROTOCOL_AUTOMATIC = 'automatic';
|
||||
|
||||
/**
|
||||
* Get the descriptive title for this domain
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->Domain;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @var array
|
||||
@ -43,22 +71,30 @@ class SubsiteDomain extends DataObject
|
||||
];
|
||||
|
||||
/**
|
||||
*
|
||||
*@config
|
||||
* @var array
|
||||
*/
|
||||
private static $summary_fields = [
|
||||
private static $summary_fields=[
|
||||
'Domain',
|
||||
'IsPrimary',
|
||||
];
|
||||
|
||||
/*** @config
|
||||
* @var array
|
||||
*/
|
||||
private static $casting = array(
|
||||
'SubstitutedDomain' => 'Varchar',
|
||||
'FullProtocol' => 'Varchar',
|
||||
'AbsoluteLink' => 'Varchar',
|
||||
);
|
||||
|
||||
/**
|
||||
* Whenever a Subsite Domain is written, rewrite the hostmap
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onAfterWrite()
|
||||
{
|
||||
Subsite::writeHostMap();
|
||||
{Subsite::writeHostMap();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,10 +103,26 @@ class SubsiteDomain extends DataObject
|
||||
*/
|
||||
public function getCMSFields()
|
||||
{
|
||||
$fields = new FieldList(
|
||||
new TextField('Domain', $this->fieldLabel('Domain'), null, 255),
|
||||
new CheckboxField('IsPrimary', $this->fieldLabel('IsPrimary'))
|
||||
);
|
||||
$protocols = array(
|
||||
self::PROTOCOL_HTTP => _t('SubsiteDomain.PROTOCOL_HTTP', 'http://'),
|
||||
self::PROTOCOL_HTTPS => _t('SubsiteDomain.PROTOCOL_HTTPS', 'https://'),
|
||||
self::PROTOCOL_AUTOMATIC => _t('SubsiteDomain.PROTOCOL_AUTOMATIC', 'Automatic')
|
||||
);$fields = new FieldList(
|
||||
WildcardDomainField::create('Domain', $this->fieldLabel('Domain'), null, 255)
|
||||
->setDescription(_t(
|
||||
'SubsiteDomain.DOMAIN_DESCRIPTION',
|
||||
'Hostname of this subsite (exclude protocol). Allows wildcards (*).'
|
||||
)),
|
||||
OptionsetField::create('Protocol', $this->fieldLabel('Protocol'), $protocols)
|
||||
->setDescription(_t(
|
||||
'SubsiteDomain.PROTOCOL_DESCRIPTION',
|
||||
'When generating links to this subsite, use the selected protocol. <br />' .
|
||||
'Selecting \'Automatic\' means subsite links will default to the current protocol.'
|
||||
)), CheckboxField::create('IsPrimary', $this->fieldLabel('IsPrimary'))
|
||||
->setDescription(_t(
|
||||
'SubsiteDomain.PROTOCOL_DESCRIPTION',
|
||||
'Mark this as the default domain for this subsite'
|
||||
)));
|
||||
|
||||
$this->extend('updateCMSFields', $fields);
|
||||
return $fields;
|
||||
@ -85,7 +137,8 @@ class SubsiteDomain extends DataObject
|
||||
{
|
||||
$labels = parent::fieldLabels($includerelations);
|
||||
$labels['Domain'] = _t('SubsiteDomain.DOMAIN', 'Domain');
|
||||
$labels['IsPrimary'] = _t('SubsiteDomain.IS_PRIMARY', 'Is Primary Domain');
|
||||
$labels['Protocol'] = _t('SubsiteDomain.Protocol', 'Protocol');
|
||||
$labels['IsPrimary'] = _t('SubsiteDomain.IS_PRIMARY', 'Is Primary Domain?');
|
||||
|
||||
return $labels;
|
||||
}
|
||||
@ -97,8 +150,85 @@ class SubsiteDomain extends DataObject
|
||||
public function onBeforeWrite()
|
||||
{
|
||||
parent::onBeforeWrite();
|
||||
}
|
||||
|
||||
//strip out any HTML to avoid XSS attacks
|
||||
$this->Domain = Convert::html2raw($this->Domain);
|
||||
/**
|
||||
* Get the link to this subsite
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function Link()
|
||||
{
|
||||
return $this->getFullProtocol() . $this->Domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the full protocol (including ://) for this domain
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFullProtocol()
|
||||
{
|
||||
switch ($this->Protocol) {
|
||||
case self::PROTOCOL_HTTPS:
|
||||
{
|
||||
return 'https://';
|
||||
}
|
||||
case self::PROTOCOL_HTTP:
|
||||
{
|
||||
return 'http://';
|
||||
}
|
||||
default:
|
||||
{
|
||||
return Director::protocol();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves domain name with wildcards substituted with actual values
|
||||
*
|
||||
* @todo Refactor domains into separate wildcards / primary domains
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSubstitutedDomain()
|
||||
{
|
||||
$currentHost = $_SERVER['HTTP_HOST'];
|
||||
|
||||
// If there are wildcards in the primary domain (not recommended), make some
|
||||
// educated guesses about what to replace them with:
|
||||
$domain = preg_replace('/\.\*$/', ".{$currentHost}", $this->Domain );
|
||||
|
||||
// Default to "subsite." prefix for first wildcard
|
||||
// TODO Whats the significance of "subsite" inthiscontext?!
|
||||
$domain = preg_replace('/^\*\./', "subsite.", $domain);
|
||||
|
||||
// *Only* removes "intermediate" subdomains, so 'subdomain.www.domain.com' becomes 'subdomain.domain.com'
|
||||
$domain = str_replace('.www.', '.', $domain);
|
||||
|
||||
return $domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get absolute link for this domain
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAbsoluteLink()
|
||||
{
|
||||
return $this->getFullProtocol() . $this->getSubstitutedDomain();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get absolute baseURL for this domain
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function absoluteBaseURL()
|
||||
{
|
||||
return Controller::join_links(
|
||||
$this->getAbsoluteLink(),
|
||||
Director::baseURL());
|
||||
}
|
||||
}
|
||||
|
@ -13,25 +13,27 @@ use SilverStripe\Versioned\Versioned;
|
||||
|
||||
/**
|
||||
* Handy alternative to copying pages when creating a subsite through the UI.
|
||||
* Can be used to batch-add new pages after subsite creation,
|
||||
* or simply to process a large site outside of the UI.
|
||||
*
|
||||
* Can be used to batch-add new pages after subsite creation, or simply to
|
||||
* process a large site outside of the UI.
|
||||
*
|
||||
* Example: sake dev/tasks/SubsiteCopyPagesTask from=<subsite-source> to=<subsite-target>
|
||||
*
|
||||
* @package subsites
|
||||
*/
|
||||
class SubsiteCopyPagesTask extends BuildTask
|
||||
{
|
||||
|
||||
protected $title = 'Copy pages to different subsite';
|
||||
|
||||
protected $description = '';
|
||||
|
||||
function run($request)
|
||||
public function run($request)
|
||||
{
|
||||
$subsiteFromId = $request->getVar('from');
|
||||
if (!is_numeric($subsiteFromId)) {
|
||||
throw new InvalidArgumentException('Missing "from" parameter');
|
||||
}
|
||||
$subsiteFrom = DataObject::get_by_id(Subsite::class, $subsiteFromId);
|
||||
$subsiteFrom = DataObject::get_by_id('Subsite', $subsiteFromId);
|
||||
if (!$subsiteFrom) {
|
||||
throw new InvalidArgumentException('Subsite not found');
|
||||
}
|
||||
@ -40,7 +42,7 @@ class SubsiteCopyPagesTask extends BuildTask
|
||||
if (!is_numeric($subsiteToId)) {
|
||||
throw new InvalidArgumentException('Missing "to" parameter');
|
||||
}
|
||||
$subsiteTo = DataObject::get_by_id(Subsite::class, $subsiteToId);
|
||||
$subsiteTo = DataObject::get_by_id('Subsite', $subsiteToId);
|
||||
if (!$subsiteTo) {
|
||||
throw new InvalidArgumentException('Subsite not found');
|
||||
}
|
||||
@ -53,12 +55,11 @@ class SubsiteCopyPagesTask extends BuildTask
|
||||
// This will make sure that the new parents on the new subsite are correct, and there are no funny
|
||||
// issues with having to check whether or not the new parents have been added to the site tree
|
||||
// when a page, etc, is duplicated
|
||||
$stack = [[0, 0]];
|
||||
$stack = array(array(0,0));
|
||||
while (count($stack) > 0) {
|
||||
list($sourceParentID, $destParentID) = array_pop($stack);
|
||||
|
||||
$children = Versioned::get_by_stage('SilverStripe\\CMS\\Model\\SiteTree', 'Live',
|
||||
"\"ParentID\" = $sourceParentID", '');
|
||||
$children = Versioned::get_by_stage(SiteTree::class, 'Live', "\"ParentID\" = $sourceParentID", '');
|
||||
|
||||
if ($children) {
|
||||
foreach ($children as $child) {
|
||||
@ -74,7 +75,7 @@ class SubsiteCopyPagesTask extends BuildTask
|
||||
$childClone->ParentID = $destParentID;
|
||||
$childClone->writeToStage('Stage');
|
||||
$childClone->publish('Stage', 'Live');
|
||||
array_push($stack, [$child->ID, $childClone->ID]);
|
||||
array_push($stack, array($child->ID, $childClone->ID));
|
||||
|
||||
$this->log(sprintf('Copied "%s" (#%d, %s)', $child->Title, $child->ID, $child->Link()));
|
||||
}
|
||||
@ -84,7 +85,7 @@ class SubsiteCopyPagesTask extends BuildTask
|
||||
}
|
||||
}
|
||||
|
||||
function log($msg)
|
||||
public function log($msg)
|
||||
{
|
||||
echo $msg . "\n";
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
{
|
||||
"name": "silverstripe/subsites",
|
||||
"description": "Run multiple sites from a single SilverStripe install.",
|
||||
"license": "BSD-3-Clause",
|
||||
"type": "silverstripe-module",
|
||||
"keywords": ["silverstripe", "subsites", "multisite"],
|
||||
"authors": [
|
||||
|
@ -95,6 +95,7 @@ body.SubsiteAdmin .right form #URL .fieldgroup * {
|
||||
display:none;
|
||||
}
|
||||
|
||||
#Root_DetailsView .subsites-move-dropdown{
|
||||
#Root_DetailsView .subsites-move-dropdown,
|
||||
#Form_ItemEditForm .subsites-move-dropdown {
|
||||
display:block;
|
||||
}
|
||||
|
@ -1,84 +1,9 @@
|
||||
## Introduction
|
||||
# Subsites
|
||||
|
||||
Subsites is a module to allow you manage multiple related sites from a single CMS interface.
|
||||
|
||||
When Subsites is installed your existing site is defined as the main site, you will be then be able to create related subsites under the main site.
|
||||
|
||||
One of the benefits of subsites is that it is easy to copy pages between the subsites and you have access to all of
|
||||
the assets across all of the subsites.
|
||||
|
||||
Subsites is not for running unrelated websites on a single SilverStripe instance so if 2 sites have different vhosts
|
||||
you will not be able to run them with Subsites on a single SilverStripe instance.
|
||||
|
||||
With Subsites you can set up users to have access to all subsites or just a selection of subsites.
|
||||
|
||||
## When to use the Subsites module
|
||||
|
||||
* You have a clear parent/main website and a set of subsites associated with it.
|
||||
* You have a group of simple, commonly themed websites
|
||||
* Your websites contain some overlapping content, and you want to avoid the redundancy of making the same update to content that exists on multiple CMS installations.
|
||||
* You have simple content websites that use the same templates and modules, and are managed by the same team, but have different themes.
|
||||
* Content editing of the subsites is through the same team, so there is no problem around editors having access to all the files for each subsite, nor around having CMS admin(s) who control access to all the sites.
|
||||
|
||||
## When to avoid the Subsites module
|
||||
|
||||
* You have constraints on what content CMS editors can and cannot view between subsites.
|
||||
* You have a business critical website, and adding complexity around changes and releases for subsites creates unwanted risk.
|
||||
* There is a significant security risk around putting the websites into the same CMS installation. This could be the risk of content bleeding between sites, or the risk of an editor on one site gaining access to content on the other site.
|
||||
* Websites that are distinct and use customised modules and/or bespoke code
|
||||
* Websites that are owned by different business units and/or managed by different development and web teams. (not technical, it just organisational complexity).
|
||||
|
||||
It is important to remember that the only unique trait each site can have is its theme (look and feel), whilst all the other building blocks of the site — the code, database, and modules — are shared. Therefore, one of the biggest drawbacks to using subsites is exposure to a single point of failure. If there is a bug in code that is only used on one subsite, it nevertheless affects all other subsites, because they share a codebase. Similarly, if the database becomes corrupt, all subsites are affected. Further, it is not possible to create or restore backups of any given subsite. Backups must represent and replace the entire collection of sites.
|
||||
|
||||
## Access
|
||||
|
||||
Access to certain subsites can be limited to administrators based on the groups they are in.
|
||||
So for example if you had a couple of subsites you could create a group for each subsite and then specify that the
|
||||
group had access to all subsites or just a specific subsites.
|
||||
To access this functionality go to
|
||||
|
||||
|
||||
Security -> Groups
|
||||
|
||||
![alt text](_images/subsite-admin-security-group.png "Groups")
|
||||
|
||||
Select the group you want to modify and then go to the Subsites tab
|
||||
|
||||
You can also limit the page types that are available for a subsite (but not the main site).
|
||||
This can be done via accessing the particular subsite you want to amend via the Subsite admin section, underneath the
|
||||
Subsite theme will be a link called 'Disallow page types?' clicking on that link will display a list of checkboxes for
|
||||
all of the page types which can be selected to disable that page type for the subsite you are editing.
|
||||
This is useful when you create a content editor and you do not want them to be able to add certain page types.
|
||||
|
||||
## Theme
|
||||
A theme is group of templates, images and CSS for the look of a website.
|
||||
When you are using Subsites you may have different themes installed for your site so you could apply different
|
||||
themes for each subsite.
|
||||
|
||||
## Page types
|
||||
Page types refer to the type of pages that can be set up on a site.
|
||||
A page type will have certain features and functionality some examples on SilverStripe would be 'Page', 'HomePage'
|
||||
and 'ErrorPage' these all differ to each other in what they would be used for so you would use Page for any pages
|
||||
underneath the HomePage.
|
||||
|
||||
|
||||
You would only have one HomePage for your site and you may have some logic to only allow you to create one of these
|
||||
pages, ErrorPage would only be used for error pages and would be designed to be very minimal to work in situations
|
||||
where the site is experiencing difficulties like no DB access.
|
||||
|
||||
|
||||
You can set up a Subsite to only work with certain page types so you may have a page type with a contact form for a
|
||||
particular department so you may set up a new subsite and not allow that page type to be used on a particular subsite.
|
||||
You will not be able to filter Page Types for the main site.
|
||||
|
||||
## Assets
|
||||
Assets are files that have been uploaded via the CMS.
|
||||
It is suggested to use a naming convention for files designated to be used on a particular subsite or to create folders
|
||||
for each subsite to help organise them.
|
||||
[User guide](userguide/index.md)
|
||||
|
||||
## FAQ
|
||||
|
||||
|
||||
### How can I restrict a content author to a particular subsite?
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 153 KiB After Width: | Height: | Size: 153 KiB |
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 176 KiB After Width: | Height: | Size: 176 KiB |
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 128 KiB |
48
docs/en/userguide/index.md
Normal file
@ -0,0 +1,48 @@
|
||||
title: Working with multiple websites
|
||||
summary: Setting up and editing multiple websites using SilverStripe
|
||||
|
||||
# Working with multiple sites
|
||||
|
||||
## In this section:
|
||||
|
||||
* Understand subsites
|
||||
* Learn how to create and delete subsites
|
||||
* Learn how to manage subsite permissions
|
||||
* Enable/Disable public access to subsites
|
||||
* Learn how to create and use subsite templates
|
||||
* Learn how to edit existing subsites
|
||||
* Sharing content between the main site and subsites
|
||||
|
||||
## Before we begin:
|
||||
|
||||
* Make sure you have the SilverStripe [Subsites](http://addons.silverstripe.org/add-ons/silverstripe/subsites) module installed.
|
||||
* Make sure you are in the "Subsites" section on the Navigation Tabs.
|
||||
* Make sure you have full administrative rights on your site.
|
||||
|
||||
## Understanding subsites
|
||||
|
||||
Subsites is a module to allow you manage multiple related sites from a single CMS interface. Because all sites run on a single installation of SilverStripe, they can share users, content and assets. They can all use the same templates, or each use different ones.
|
||||
|
||||
When Subsites is installed your existing site is defined as the main site, you will be then be able to create related subsites under the main site.
|
||||
|
||||
So for example you may have an international presence and you want to create a subsite for a country where you do business which is geared just for that market. You could create a subsite for this and have all information related to that country kept under this subsite, you can also set up a subdomain for this site.
|
||||
|
||||
One of the benefits of subsites is that it is easy to copy pages between the subsites and you have access to all of the assets across all of the subsites.
|
||||
|
||||
Subsites is not for running unrelated websites on a single SilverStripe instance so if two sites have different vhosts you will not be able to run them with Subsites on a single SilverStripe instance.
|
||||
|
||||
With Subsites you can set up users to have access to all subsites or just a selection of subsites.
|
||||
|
||||
## Common subsite uses
|
||||
|
||||
Subsites can be used for various different reasons here are some of the common ones:
|
||||
|
||||
* Setting up a subsite for a small campaign so for example a clothing company may set up a summer or winter subsite to market just that season of clothing.
|
||||
* Locking down a particular subsite you may create a particular department like recruitment who would have access to create and edit pages for their particular subsite but they would not be able to modify the main website.
|
||||
* Running sub-domains on a single SilverStripe instance, with subsites if a sub-domain is pointing to the same instance and has been setup correctly you can manage this via a single CMS instance.
|
||||
* Subsites can not be used to run multiple websites on a single instance. Subsites does not allow you to run multiple domains/vhosts on a single instance.
|
||||
|
||||
## Documentation
|
||||
|
||||
* [Set up](set_up.md)
|
||||
* [Working with subsites](working_with.md)
|
@ -2,44 +2,42 @@
|
||||
|
||||
## Creating subsites
|
||||
|
||||
To view, edit and create subsites, go to the *Subsite* section of the CMS. Click *Search* to view a list of all
|
||||
existing subsites.
|
||||
To view, edit and create subsites, go to the *Subsite* section of the CMS. Click *Search* to view a list of all existing subsites.
|
||||
|
||||
![View subsites](_images/view-subsites.jpg)
|
||||
|
||||
Click on a subsite name to edit its details. Click the red X to delete a subsite (you will be asked for confirmation.)
|
||||
To create a new subsite, click *Add Subsite*. This opens the *Subsite configuration* subsection.
|
||||
Click on a subsite name to edit its details. To create a new subsite, click *Add Subsite*. This opens the *Subsite configuration* subsection.
|
||||
|
||||
## Deleting a subsite
|
||||
|
||||
Click the red X to delete a subsite (you will be asked for confirmation.)
|
||||
|
||||
## Subsite configuration
|
||||
|
||||
![Subsite configuration](_images/subsite-configuration.jpg)
|
||||
|
||||
You can configure the following details for a subsite:
|
||||
|
||||
* *Name of subsite:* This is the display name for the site in the CMS (not public-facing)
|
||||
* *Domains for this subsite:* Lets you add one or more domains for this subsite, e.g., subsite.co.nz, subsite.org.nz,
|
||||
subsite.com
|
||||
* *Domains for this subsite:* Lets you add one or more domains for this subsite, e.g., subsite.co.nz, subsite.org.nz, subsite.com
|
||||
* *Language:* Sets the language for the subsite. This affects the spellchecker (not the CMS interface language)
|
||||
* *Default site:* If your site is accessed by a domain not listed in any subsites, this subsite is shown as default.
|
||||
* *Enable public access:* Enables/disables the subsite. Corresponds to the *Active Subsite* column.
|
||||
* *Theme:* Shows the list of available themes that exist in the themes directory. The subsite will use the templates
|
||||
and styles from the selected theme.
|
||||
* *Disallow page types:* Lets you mark some page types to prevent being used within this subsite.
|
||||
* *Copy structure from:* Gives you the option to select an existing subsite from which to copy pages and files (see
|
||||
"Copying subsites" for more information about this)
|
||||
* *Theme:* Shows the list of available themes that exist in the themes directory. The subsite will use the templates and styles from the selected theme.
|
||||
* *Disallow page types:* Lets you mark some page types to prevent them being used within this subsite (but not the main site). Clicking on that link will display a list of checkboxes for all of the page types which can be selected to disable that page type for the subsite you are editing. This is useful when you create a content editor and you do not want them to be able to add certain page types.
|
||||
* *Copy structure from:* Gives you the option to select an existing subsite from which to copy pages and files (see "Copying subsites" for more information about this)
|
||||
|
||||
## Roles
|
||||
|
||||
When creating roles, you can assign the following subsite-specific permissions:
|
||||
|
||||
* *Access to 'Subsites' section:* Shows the *Subsite* section in the CMS, allowing you to manage subsites for your
|
||||
site (ie, create, edit, view.)
|
||||
* *Access to 'Subsites' section:* Shows the *Subsite* section in the CMS, allowing you to manage subsites for your site (ie, create, edit, view.)
|
||||
* *Manage subsites for groups:* Ability to limit the permissions for a group to one or more subsites.
|
||||
* *Manage assets for subsites:* Ability to select the subsite to which an asset folder belongs (also requires access to
|
||||
*Files* section)
|
||||
* *Manage assets for subsites:* Ability to select the subsite to which an asset folder belongs (also requires access to *Files* section)
|
||||
|
||||
## Groups
|
||||
|
||||
Groups can have access to all sites, or to one or more specific subsites. If you have different staff in charge of each
|
||||
subsite, you probably want to create a separate group for each subsite.
|
||||
Groups can have access to all sites, or to one or more specific subsites. If you have different staff in charge of each subsite, you probably want to [create](#creating-groups) a separate group for each subsite.
|
||||
|
||||
The dropdown in the upper left corner of the CMS indicates which subsite you are currently on.
|
||||
|
||||
@ -50,7 +48,19 @@ these subsites* to reveal a checklist of all available sites.
|
||||
|
||||
![Group subsites access](_images/group-subsites-access.png)
|
||||
|
||||
### Creating groups
|
||||
|
||||
Access to certain subsites can be limited to administrators based on the groups they are in.
|
||||
So for example if you had a couple of subsites you could create a group for each subsite and then specify that the group had access to all subsites or just a specific subsites.
|
||||
|
||||
To access this functionality go to Security -> Groups
|
||||
|
||||
![Creating Groups](_images/subsite-admin-security-group.png "Groups")
|
||||
|
||||
Select the group you want to modify and then go to the Subsites tab
|
||||
|
||||
## Copying subsites
|
||||
|
||||
Duplicating subsites can be useful if you want to create several subsites based on the same general site structure. You can set up a collection of pages, files, and images and use it as a template. When you create a new subsite, instead of starting from scratch you can copy it all from your existing subsite. This will copy all pages, files and images from that subsite into your new subsite.
|
||||
|
||||
To create a new subsite template, create a new subsite described above under "Creating subsites" but don't add any domains. Add a name that will make it easy to see that it is a template. Select the new template from the subsites dropdown in the upper right and create the pages and add the files and images you'd like to become part of the
|
||||
@ -60,7 +70,14 @@ When you create a new subsite, you can now choose to Copy structure from your te
|
||||
|
||||
![Copy subsite structure](_images/copy-structure.jpg)
|
||||
|
||||
## Disable particular page types from a subsite
|
||||
## Page types
|
||||
Page types refer to the type of pages that can be set up on a site. A page type will have certain features and functionality some examples on SilverStripe would be 'Page', 'HomePage' and 'ErrorPage' these all differ to each other in what they would be used for so you would use Page for any pages
|
||||
underneath the HomePage.
|
||||
|
||||
You would only have one HomePage for your site and you may have some logic to only allow you to create one of these pages, ErrorPage would only be used for error pages and would be designed to be very minimal to work in situations where the site is experiencing difficulties (like no database access).
|
||||
|
||||
### Disable particular page types from a subsite
|
||||
|
||||
Sometimes, you will have two or more websites that are very similar, but have some small differences. For example, a head office and its 3 satellite offices may have 4 subsites, but only the head office site will have a "Company News" section on the site. In this instance, you can still use the subsites module, and use the 'Disallow page types' ability to remove certain page types from being created on subsites.
|
||||
|
||||
1. Create a new subsite as you normally would via the Subsites section in the CMS
|
||||
@ -69,7 +86,7 @@ Sometimes, you will have two or more websites that are very similar, but have so
|
||||
4. Select the page types that you wish to forbid from this subsite.
|
||||
5. Click the Save button at the bottom of the section.
|
||||
|
||||
Note that this process is exactly the same when editing an existing subsite, you just select the subsite you want to remove page types from instead of creating a new subsite.
|
||||
*Note:* This process is exactly the same when editing an existing subsite, you just select the subsite you want to remove page types from instead of creating a new subsite. Also you cannot not filter Page Types for the main site.
|
||||
|
||||
![Disallow page types screenshot](_images/disallow-page-types.png)
|
||||
|
||||
@ -80,3 +97,9 @@ Now, whenever someone wants to create a new page on the subsite (the 'London Bra
|
||||
The page type blacklist applies only to future pages, not existing ones. If an administrator blacklists a defined page type on a subsite, existing pages of that type will remain on the subsite. The administrator (or another user) can later change it to a type that is not blacklisted after the page is published; however, once a user does that, that "grandfathered" pagetype will no longer be available to the published page.
|
||||
|
||||
For example, say a subsite user publishes a new Company Page before it was forbidden by an administrator. Later, a user with full administrative rights decides to disallow Company Pages from being created on the subsite. This restriction will only apply to all future pages that are published, but not to existing Company Pages. The full administrator (or any user with sufficient publishing rights) will have to manually convert any published Company Pages on the subsite to that of another allowed type.
|
||||
|
||||
## Themes
|
||||
A theme is group of templates, images and CSS for the look of a website. When you are using Subsites you may have different themes installed for your site so you could apply different themes for each subsite.
|
||||
|
||||
## Assets
|
||||
Assets are files that have been uploaded via the CMS. It is suggested to use a naming convention for files designated to be used on a particular subsite or to create folders for each subsite to help organise them.
|
@ -2,11 +2,11 @@
|
||||
|
||||
## Managing content across subsites
|
||||
|
||||
Select a subsite from the dropdown in the upper left to display the content for that site in the site tree.
|
||||
To edit a particular subsite, choose the subsite from the dropdown menu in the left-hand menu.
|
||||
|
||||
![Subsites dropdown](_images/subsites-dropdown.png)
|
||||
|
||||
## Subsites virtual pages
|
||||
### Subsites virtual pages
|
||||
|
||||
You can pull in the content from a page that resides on another subsite by creating a page of the type **Subsites
|
||||
Virtual Page**. Pick the subsite from which you want to pull the content, then select the page. As with regular virtual
|
||||
@ -15,7 +15,7 @@ the original content changes.
|
||||
|
||||
![Subsites virtual page](_images/subsites-virtual-page.jpg)
|
||||
|
||||
## Duplicating pages from the main site
|
||||
### Duplicating pages from the main site
|
||||
|
||||
If you have an existing page on the main site that you would like to copy to a subsite, all you need to do is:
|
||||
|
28
lang/ar.yml
@ -1,13 +1,9 @@
|
||||
ar:
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: مواقع فرعية
|
||||
SubsiteXHRController:
|
||||
MENUTITLE: المراقب XHR للموقع الفرعي
|
||||
ASSETADMIN:
|
||||
SUBSITENOTICE: 'يمكن الوصول إلى المجلدات والملفات التي تم إنشاؤها في الموقع الرئيسي من طرف كل المواقع الفرعية.'
|
||||
FileSubsites:
|
||||
AllSitesDropdownOpt: 'كافة المواقع'
|
||||
SubsiteFieldLabel: الموقع الفرعي
|
||||
SubsiteFieldLabel: 'الموقع الفرعي'
|
||||
GridFieldAddFromTemplateButton:
|
||||
AddFromTemplate: 'اضف جديد من القالب'
|
||||
GroupSubsites:
|
||||
@ -17,7 +13,7 @@ ar:
|
||||
GlobalGroup: 'المجموعة العامة'
|
||||
MANAGE_SUBSITES: 'إدارة مواقع فرعية للمجموعات'
|
||||
MANAGE_SUBSITES_HELP: 'القدرة على الحد من أذونات مجموعة ما على موقع فرعي واحدة أو أكثر.'
|
||||
SECURITYTABTITLE: مواقع فرعية
|
||||
SECURITYTABTITLE: 'مواقع فرعية'
|
||||
LeftAndMainSubsites:
|
||||
Saved: 'تمّ الحفظ، يرجى تحديث الصفحات ذات الصلة.'
|
||||
SiteTreeSubsites:
|
||||
@ -28,27 +24,30 @@ ar:
|
||||
CopyMessage: 'إنشاء نسخة من {title}'
|
||||
CustomExtraMeta: 'العلامات الوصفية المخصصة'
|
||||
CustomMetaDescription: الوصف
|
||||
CustomMetaKeywords: كلمات البحث
|
||||
CustomMetaKeywords: 'كلمات البحث'
|
||||
CustomMetaTitle: عنوان
|
||||
DOMAINSAVEFIRST: 'لا يمكنك إضافة النطاقات إلا بعد القيام بالحفظ لأول مرة'
|
||||
DomainsHeadline: 'نطاقات هذا الموقع الفرعي'
|
||||
DomainsListTitle: النطاقات
|
||||
IsPublicHeaderField: 'موقع فرعي نشط'
|
||||
NOTEMPLATE: 'بدون قالب'
|
||||
PLURALNAME: المواقع الفرعية
|
||||
PLURALNAME: 'المواقع الفرعية'
|
||||
PageTypeBlacklistField: 'عدم السماح بأصناف الصفحات؟'
|
||||
SINGULARNAME: الموقع الفرعي
|
||||
SINGULARNAME: 'الموقع الفرعي'
|
||||
SiteConfigSubtitle: 'هنا سطر الوصف الخاص بك'
|
||||
SiteConfigTitle: 'اسم موقعك'
|
||||
TabTitleConfig: المواصفات
|
||||
TabTitleConfig: 'المواصفات'
|
||||
ValidateTitle: 'الرجاء إضافة "عنوان"'
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: 'مواقع فرعية'
|
||||
SubsiteDomain:
|
||||
DOMAIN: نطاق
|
||||
IS_PRIMARY: 'هو نطاق أساسي'
|
||||
PLURALNAME: 'نطاقات موقع فرعي'
|
||||
SINGULARNAME: 'نطاق موقع فرعي'
|
||||
SubsiteReportWrapper:
|
||||
ReportDropdown: المواقع
|
||||
ReportDropdown: 'المواقع'
|
||||
SubsiteXHRController:
|
||||
MENUTITLE: 'المراقب XHR للموقع الفرعي'
|
||||
Subsites:
|
||||
DefaultSiteFieldLabel: 'الموقع الافتراضي'
|
||||
DomainFieldLabel: النطاق
|
||||
@ -58,10 +57,9 @@ ar:
|
||||
PageTypeBlacklistFieldLabel: 'نوع الصفحة قائمة سوداء'
|
||||
PrimaryDomainFieldLabel: 'النطاق الأساسي'
|
||||
RedirectURLFieldLabel: 'إعادة توجيه عنوان موقع الويب'
|
||||
ThemeFieldLabel: المحور
|
||||
ThemeFieldLabel: 'المحور'
|
||||
TitleFieldLabel: 'اسم الموقع الفرعي'
|
||||
SubsitesVirtualPage:
|
||||
DESCRIPTION: 'يعرض محتوى صفحة على موقع فرعي آخر'
|
||||
PLURALNAME: 'قاعدة الصفحات'
|
||||
SINGULARNAME: 'الصفحة الإفتراضية للمواقع الفرعية'
|
||||
SubsiteField: الموقع الفرعي
|
||||
SubsiteField: 'الموقع الفرعي'
|
||||
|
34
lang/cs.yml
Normal file
@ -0,0 +1,34 @@
|
||||
cs:
|
||||
LeftAndMain_Menu:
|
||||
Hello: Ahoj
|
||||
LOGOUT: 'Odhlásit se'
|
||||
SiteTreeSubsites:
|
||||
CopyAction: Kopírovat
|
||||
Subsite:
|
||||
CustomExtraMeta: 'Vlastní meta tagy'
|
||||
CustomMetaDescription: Popis
|
||||
CustomMetaKeywords: 'Klíčová slova'
|
||||
CustomMetaTitle: Název
|
||||
DOMAINSAVEFIRST: 'Domény můžete přidávat až po uložení'
|
||||
DomainsHeadline: 'Domény pro tento web'
|
||||
DomainsListTitle: Domény
|
||||
SiteConfigSubtitle: 'Slogan Vašeho webu'
|
||||
SiteConfigTitle: 'Název Vašeho webu'
|
||||
TabTitleConfig: Konfigurace
|
||||
ValidateTitle: 'Prosím vložte "Název"'
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: Subsites
|
||||
SubsiteDomain:
|
||||
DOMAIN: Doména
|
||||
PLURALNAME: 'Domény webů'
|
||||
SINGULARNAME: 'Doména webu'
|
||||
SubsiteReportWrapper:
|
||||
ReportDropdown: Weby
|
||||
Subsites:
|
||||
DefaultSiteFieldLabel: 'Výchozí web'
|
||||
DomainFieldLabel: Doména
|
||||
LanguageFieldLabel: Jazyk
|
||||
ThemeFieldLabel: Téma
|
||||
TitleFieldLabel: 'Název subsite'
|
||||
SubsitesVirtualPage:
|
||||
PLURALNAME: 'Základní stránky'
|
30
lang/de.yml
@ -1,10 +1,8 @@
|
||||
de:
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: Subsites
|
||||
SubsiteXHRController:
|
||||
MENUTITLE: SubsiteXHRController
|
||||
ASSETADMIN:
|
||||
SUBSITENOTICE: 'Auf Ordner und Dateien der Hauptseite kann von allen Subsites zugegriffen werden.'
|
||||
DomainNameField:
|
||||
INVALID_DOMAIN: 'Ungültige Domain'
|
||||
FileSubsites:
|
||||
AllSitesDropdownOpt: 'Alle Subseiten'
|
||||
SubsiteFieldLabel: Subseite
|
||||
@ -19,7 +17,10 @@ de:
|
||||
MANAGE_SUBSITES_HELP: 'Möglichkeit, die Berechtigungen einer Gruppe auf bestimmte Subsites zu beschränken.'
|
||||
SECURITYTABTITLE: Subsites
|
||||
LeftAndMainSubsites:
|
||||
Saved: 'Gespeichert.'
|
||||
Saved: Gespeichert.
|
||||
LeftAndMain_Menu:
|
||||
Hello: Hallo
|
||||
LOGOUT: Abmelden
|
||||
SiteTreeSubsites:
|
||||
CopyAction: Kopieren
|
||||
CopyToSubsite: 'Seite auf Subseite Kopieren'
|
||||
@ -42,26 +43,37 @@ de:
|
||||
SiteConfigTitle: 'Name Ihrer Website'
|
||||
TabTitleConfig: Einstellungen
|
||||
ValidateTitle: 'Bitte geben Sie einen Titel an'
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: Subsites
|
||||
SubsiteDomain:
|
||||
DOMAIN: Domain
|
||||
IS_PRIMARY: 'Ist primäre Domain'
|
||||
DOMAIN_DESCRIPTION: 'Hostname dieser Subsite (ohne Protokol). Joker (*) ist erlaubt.'
|
||||
IS_PRIMARY: 'Ist Hauptdomain?'
|
||||
PLURALNAME: 'Subsite Domains'
|
||||
PROTOCOL_AUTOMATIC: Automatisch
|
||||
PROTOCOL_HTTP: 'http://'
|
||||
PROTOCOL_HTTPS: 'https://'
|
||||
Protocol: Protokoll
|
||||
SINGULARNAME: 'Subsite Domain'
|
||||
SubsiteReportWrapper:
|
||||
ReportDropdown: Seiten
|
||||
SubsiteXHRController:
|
||||
MENUTITLE: SubsiteXHRController
|
||||
Subsites:
|
||||
DefaultSiteFieldLabel: 'Standard Seite'
|
||||
DomainFieldLabel: Domäne
|
||||
IsPublicFieldLabel: 'Öffentlich zugänglich'
|
||||
LanguageFieldLabel: Sprache
|
||||
MainSiteTitle: 'Hauptsite'
|
||||
MainSiteTitle: Hauptsite
|
||||
PageTypeBlacklistFieldLabel: 'Ausgeschlossene Seitentypen'
|
||||
PrimaryDomainFieldLabel: 'Primäre Domain'
|
||||
RedirectURLFieldLabel: 'Weierleitungs-URL'
|
||||
RedirectURLFieldLabel: Weierleitungs-URL
|
||||
ThemeFieldLabel: Theme
|
||||
TitleFieldLabel: 'Name der Subsite'
|
||||
SubsitesVirtualPage:
|
||||
DESCRIPTION: 'Zeigt den Inhalt einer anderen Seite von einer anderen Subsite an'
|
||||
PLURALNAME: 'Subsites Virtuelle Seiten'
|
||||
PLURALNAME: 'Basis Seiten'
|
||||
SINGULARNAME: 'Subsites Virtuelle Seite'
|
||||
SubsiteField: Subsite
|
||||
VirtualPage:
|
||||
EDITCONTENT: 'Klicken Sie hier, um den Inhalt zu bearbeiten'
|
||||
|
12
lang/en.yml
@ -1,6 +1,8 @@
|
||||
en:
|
||||
ASSETADMIN:
|
||||
SUBSITENOTICE: 'Folders and files created in the main site are accessible by all subsites.'
|
||||
DomainNameField:
|
||||
INVALID_DOMAIN: 'Invalid domain name'
|
||||
FileSubsites:
|
||||
AllSitesDropdownOpt: 'All sites'
|
||||
SubsiteFieldLabel: Subsite
|
||||
@ -22,6 +24,8 @@ en:
|
||||
SiteTreeSubsites:
|
||||
CopyAction: Copy
|
||||
CopyToSubsite: 'Copy page to subsite'
|
||||
CopyToSubsiteWithChildren: 'Include children pages?'
|
||||
SubsiteOperations: 'Subsite Operations'
|
||||
Subsite:
|
||||
COPYSTRUCTURE: 'Copy structure from:'
|
||||
CopyMessage: 'Created a copy of {title}'
|
||||
@ -45,8 +49,14 @@ en:
|
||||
MENUTITLE: Subsites
|
||||
SubsiteDomain:
|
||||
DOMAIN: Domain
|
||||
IS_PRIMARY: 'Is Primary Domain'
|
||||
DOMAIN_DESCRIPTION: 'Hostname of this subsite (exclude protocol). Allows wildcards (*).'
|
||||
IS_PRIMARY: 'Is Primary Domain?'
|
||||
PLURALNAME: 'Subsite Domains'
|
||||
PROTOCOL_AUTOMATIC: Automatic
|
||||
PROTOCOL_DESCRIPTION: 'Mark this as the default domain for this subsite'
|
||||
PROTOCOL_HTTP: 'http://'
|
||||
PROTOCOL_HTTPS: 'https://'
|
||||
Protocol: Protocol
|
||||
SINGULARNAME: 'Subsite Domain'
|
||||
SubsiteReportWrapper:
|
||||
ReportDropdown: Sites
|
||||
|
27
lang/eo.yml
@ -1,10 +1,8 @@
|
||||
eo:
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: Subretejoj
|
||||
SubsiteXHRController:
|
||||
MENUTITLE: SubsiteXHRController
|
||||
ASSETADMIN:
|
||||
SUBSITENOTICE: 'Dosierujoj kaj dosieroj kreitaj en la ĉefa retejo estas alireblaj de ĉiuj retejoj'
|
||||
DomainNameField:
|
||||
INVALID_DOMAIN: 'Nevalida domajna nomo'
|
||||
FileSubsites:
|
||||
AllSitesDropdownOpt: 'Ĉiuj retejoj'
|
||||
SubsiteFieldLabel: Subretejo
|
||||
@ -20,9 +18,14 @@ eo:
|
||||
SECURITYTABTITLE: Subsites
|
||||
LeftAndMainSubsites:
|
||||
Saved: 'Konservita, bonvole ĝisdatigi rilatajn paĝojn.'
|
||||
LeftAndMain_Menu:
|
||||
Hello: Saluton
|
||||
LOGOUT: Elsaluti
|
||||
SiteTreeSubsites:
|
||||
CopyAction: Kopio
|
||||
CopyToSubsite: 'Kopii paĝon al subretejo'
|
||||
CopyToSubsiteWithChildren: 'Ĉu inkluzivi paĝidojn?'
|
||||
SubsiteOperations: 'Subretejaj operacioj'
|
||||
Subsite:
|
||||
COPYSTRUCTURE: 'Kopii strukturon de:'
|
||||
CopyMessage: 'Kreis kopion de {title}'
|
||||
@ -42,13 +45,23 @@ eo:
|
||||
SiteConfigTitle: 'Nomo de via retejo'
|
||||
TabTitleConfig: Agordaro
|
||||
ValidateTitle: 'Bonvole aldonu "Titolon"'
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: Subretejoj
|
||||
SubsiteDomain:
|
||||
DOMAIN: Domajno
|
||||
IS_PRIMARY: 'Estas unuaranga domajno'
|
||||
DOMAIN_DESCRIPTION: 'Gastiga nomo de ĉi tiu subretejo (ellasu protokolon). Permesas ĵokerojn (*).'
|
||||
IS_PRIMARY: 'Ĉu unuaranga domajno?'
|
||||
PLURALNAME: 'Subretejaj domajnoj'
|
||||
PROTOCOL_AUTOMATIC: Aŭtomata
|
||||
PROTOCOL_DESCRIPTION: 'Marki ĉi tion kiel la aprioran domajnon por ĉi tiu subretejo'
|
||||
PROTOCOL_HTTP: 'http://'
|
||||
PROTOCOL_HTTPS: 'https://'
|
||||
Protocol: Protokolo
|
||||
SINGULARNAME: 'Subreteja domajno'
|
||||
SubsiteReportWrapper:
|
||||
ReportDropdown: Retejoj
|
||||
SubsiteXHRController:
|
||||
MENUTITLE: SubsiteXHRController
|
||||
Subsites:
|
||||
DefaultSiteFieldLabel: 'Apriora retejo'
|
||||
DomainFieldLabel: Domajno
|
||||
@ -62,6 +75,8 @@ eo:
|
||||
TitleFieldLabel: 'Nomo de subretejo'
|
||||
SubsitesVirtualPage:
|
||||
DESCRIPTION: 'Vidigas la enhavon de paĝo en alia subretejo'
|
||||
PLURALNAME: 'Virtualaj paĝoj de subretejoj'
|
||||
PLURALNAME: 'Bazaj paĝoj'
|
||||
SINGULARNAME: 'Virtuala paĝo de subretejoj'
|
||||
SubsiteField: Subretejo
|
||||
VirtualPage:
|
||||
EDITCONTENT: 'Alklaku ĉi tie por redakti la enhavon'
|
||||
|
46
lang/fa_IR.yml
Normal file
@ -0,0 +1,46 @@
|
||||
fa_IR:
|
||||
DomainNameField:
|
||||
INVALID_DOMAIN: 'نام دامنه نامعتبر'
|
||||
FileSubsites:
|
||||
AllSitesDropdownOpt: 'تمامی سایت ها'
|
||||
SubsiteFieldLabel: 'زیر سایت ها'
|
||||
GroupSubsites:
|
||||
ACCESSALL: 'تمامی زیر سایت ها'
|
||||
ACCESSONLY: 'فقط این زیر سایت ها'
|
||||
SECURITYTABTITLE: 'زیر سایت ها'
|
||||
LeftAndMain_Menu:
|
||||
Hello: 'سلام'
|
||||
LOGOUT: خروج
|
||||
Subsite:
|
||||
CustomMetaKeywords: 'کلید واژه ها'
|
||||
CustomMetaTitle: عنوان
|
||||
DomainsHeadline: 'دامنه های این زیر سایت'
|
||||
DomainsListTitle: 'دامنه ها'
|
||||
IsPublicHeaderField: 'زیر سایت فعال'
|
||||
NOTEMPLATE: 'بدون قالب'
|
||||
PLURALNAME: 'زیر سایت ها'
|
||||
SINGULARNAME: 'زیر سایت'
|
||||
SiteConfigTitle: 'نام سایت شما'
|
||||
TabTitleConfig: پیکربندی
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: 'زیر سایت ها'
|
||||
SubsiteDomain:
|
||||
DOMAIN: 'دامنه'
|
||||
PLURALNAME: 'دامنه های زیر سایت'
|
||||
PROTOCOL_AUTOMATIC: 'به صورت خودکار'
|
||||
Protocol: پروتکل
|
||||
SINGULARNAME: 'دمنه زیرسایت'
|
||||
SubsiteReportWrapper:
|
||||
ReportDropdown: 'سایت ها'
|
||||
Subsites:
|
||||
DefaultSiteFieldLabel: 'سایت پیش فرض'
|
||||
DomainFieldLabel: 'دامنه'
|
||||
LanguageFieldLabel: زبان
|
||||
PrimaryDomainFieldLabel: 'دامنه اولیه'
|
||||
ThemeFieldLabel: پوسته
|
||||
TitleFieldLabel: 'نام زیر سایت'
|
||||
SubsitesVirtualPage:
|
||||
PLURALNAME: 'صفحه اصلی'
|
||||
SubsiteField: 'زیر سایت'
|
||||
VirtualPage:
|
||||
EDITCONTENT: 'برای ویرایش محتوا اینجا را کلیک کنید'
|
21
lang/fi.yml
@ -1,8 +1,4 @@
|
||||
fi:
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: Alasivustot
|
||||
SubsiteXHRController:
|
||||
MENUTITLE: SubsiteXHRController
|
||||
ASSETADMIN:
|
||||
SUBSITENOTICE: 'Kansiot ja tiedostot, jotka on luotu pääsivustolla, ovat käytettävissä kaikissa alisivustoissa.'
|
||||
FileSubsites:
|
||||
@ -14,7 +10,7 @@ fi:
|
||||
ACCESSALL: 'Kaikki alasivustot'
|
||||
ACCESSONLY: 'Vain nämä alasivustot'
|
||||
ACCESSRADIOTITLE: 'Anna tälle ryhmälle pääsy kohteeseen'
|
||||
GlobalGroup: 'Globaaliryhmä'
|
||||
GlobalGroup: Globaaliryhmä
|
||||
MANAGE_SUBSITES: 'Hallinnoi ryhmien alisivustoja'
|
||||
MANAGE_SUBSITES_HELP: 'Mahdollisuus rajoittaa ryhmän oikeuksia yhdelle tai useammalle alisivustolle.'
|
||||
SECURITYTABTITLE: Alisivustot
|
||||
@ -38,30 +34,33 @@ fi:
|
||||
PLURALNAME: Alasivustot
|
||||
PageTypeBlacklistField: 'Kiellä sivutyyppien käyttö?'
|
||||
SINGULARNAME: Alisivusto
|
||||
SiteConfigSubtitle: 'Iskulauseesi'
|
||||
SiteConfigSubtitle: Iskulauseesi
|
||||
SiteConfigTitle: 'Sivuston nimi'
|
||||
TabTitleConfig: Asetukset
|
||||
ValidateTitle: 'Lisää "Otsikko"'
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: Alasivustot
|
||||
SubsiteDomain:
|
||||
DOMAIN: Domain
|
||||
IS_PRIMARY: 'On päädomain'
|
||||
PLURALNAME: 'Alisivuston domain-osoitteet'
|
||||
SINGULARNAME: 'Alisivuston domain-osoite'
|
||||
SubsiteReportWrapper:
|
||||
ReportDropdown: Sivustot
|
||||
SubsiteXHRController:
|
||||
MENUTITLE: SubsiteXHRController
|
||||
Subsites:
|
||||
DefaultSiteFieldLabel: 'Oletussivusto'
|
||||
DefaultSiteFieldLabel: Oletussivusto
|
||||
DomainFieldLabel: Domain
|
||||
IsPublicFieldLabel: 'Aktivoi julkinen pääsy'
|
||||
LanguageFieldLabel: Kieli
|
||||
MainSiteTitle: 'Pääsivusto'
|
||||
MainSiteTitle: Pääsivusto
|
||||
PageTypeBlacklistFieldLabel: 'Sivutyyppien mustalista'
|
||||
PrimaryDomainFieldLabel: 'Oletusdomain'
|
||||
PrimaryDomainFieldLabel: Oletusdomain
|
||||
RedirectURLFieldLabel: 'Edelleenohjaus URL'
|
||||
ThemeFieldLabel: Teema
|
||||
TitleFieldLabel: 'Alisivuston nimi'
|
||||
SubsitesVirtualPage:
|
||||
DESCRIPTION: 'Näyttää sisällön toisen alisivuston sivulta'
|
||||
PLURALNAME: 'Alisivustojen virtuaaliset sivut'
|
||||
PLURALNAME: Pohjasivut
|
||||
SINGULARNAME: 'Alisivuston Virtuaalisivu'
|
||||
SubsiteField: Alisivu
|
||||
|
80
lang/hr.yml
Normal file
@ -0,0 +1,80 @@
|
||||
hr:
|
||||
ASSETADMIN:
|
||||
SUBSITENOTICE: 'Direktoriji i datoteke kreirane u glavnom sajtu su dostupne svim podsajtovima.'
|
||||
DomainNameField:
|
||||
INVALID_DOMAIN: 'Netočan naziv domene'
|
||||
FileSubsites:
|
||||
AllSitesDropdownOpt: 'Svi sajtovi'
|
||||
SubsiteFieldLabel: Podsajt
|
||||
GridFieldAddFromTemplateButton:
|
||||
AddFromTemplate: 'Dodaj novi iz predloška'
|
||||
GroupSubsites:
|
||||
ACCESSALL: 'Svi podsajtovi'
|
||||
ACCESSONLY: 'Samo ovi podsajtovi'
|
||||
ACCESSRADIOTITLE: 'Dodijeli ovoj grupi pristup za'
|
||||
GlobalGroup: 'globalna grupa'
|
||||
MANAGE_SUBSITES: 'Upravljaj podsajtove za grupe'
|
||||
MANAGE_SUBSITES_HELP: 'Mogućnost limitiranja prava za grupu za jedan ili više podsajtova.'
|
||||
SECURITYTABTITLE: Podsajtovi
|
||||
LeftAndMainSubsites:
|
||||
Saved: 'Spremljeno, molimo osvježite povezane stranice.'
|
||||
LeftAndMain_Menu:
|
||||
Hello: Pozdrav
|
||||
LOGOUT: Odjava
|
||||
SiteTreeSubsites:
|
||||
CopyAction: Kopiraj
|
||||
CopyToSubsite: 'Kopiraj stranicu u podsajt'
|
||||
Subsite:
|
||||
COPYSTRUCTURE: 'Kopiraj strukturu od:'
|
||||
CopyMessage: 'Kreirana kopija od {title}'
|
||||
CustomExtraMeta: 'Prilagođeni Meta tagovi'
|
||||
CustomMetaDescription: Opis
|
||||
CustomMetaKeywords: 'Ključne riječi'
|
||||
CustomMetaTitle: Naslov
|
||||
DOMAINSAVEFIRST: 'Možete dodati domene nakon prvog spremanja'
|
||||
DomainsHeadline: 'Domene za ove podsajtove'
|
||||
DomainsListTitle: Domene
|
||||
IsPublicHeaderField: 'Aktivni podsajtovi'
|
||||
NOTEMPLATE: 'Nema predloška'
|
||||
PLURALNAME: Podsajtovi
|
||||
PageTypeBlacklistField: 'Ne dopuštaj tipove stranica?'
|
||||
SINGULARNAME: Podsajt
|
||||
SiteConfigSubtitle: 'vaš slogan ovdje'
|
||||
SiteConfigTitle: 'Naziv vašeg weba'
|
||||
TabTitleConfig: Konfiguracija
|
||||
ValidateTitle: 'Molimo dodajte "Naslov"'
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: Podsajtovi
|
||||
SubsiteDomain:
|
||||
DOMAIN: Domena
|
||||
DOMAIN_DESCRIPTION: 'Hostname ovog podsajta (bez protokola). Omogućava wildcard (*).'
|
||||
IS_PRIMARY: 'Da li je glavna domena?'
|
||||
PLURALNAME: 'Domene podsajtova'
|
||||
PROTOCOL_AUTOMATIC: Automatsko
|
||||
PROTOCOL_DESCRIPTION: 'Označi kao zadanu domenu za ovu podstranicu'
|
||||
PROTOCOL_HTTP: 'http://'
|
||||
PROTOCOL_HTTPS: 'https://'
|
||||
Protocol: Protokol
|
||||
SINGULARNAME: 'Domena podsajta'
|
||||
SubsiteReportWrapper:
|
||||
ReportDropdown: Sajtovi
|
||||
SubsiteXHRController:
|
||||
MENUTITLE: SubsiteXHRController
|
||||
Subsites:
|
||||
DefaultSiteFieldLabel: 'Zadani sajt'
|
||||
DomainFieldLabel: Domena
|
||||
IsPublicFieldLabel: 'Omogućni javni pristup'
|
||||
LanguageFieldLabel: Jezik
|
||||
MainSiteTitle: 'Glavni sajt'
|
||||
PageTypeBlacklistFieldLabel: 'Crna lista tipova stranica'
|
||||
PrimaryDomainFieldLabel: 'Glavna domena'
|
||||
RedirectURLFieldLabel: 'Link preusmjeravanja'
|
||||
ThemeFieldLabel: Tema
|
||||
TitleFieldLabel: 'Naziv podsajta'
|
||||
SubsitesVirtualPage:
|
||||
DESCRIPTION: 'Prikazuje sadržaj stranice na drugom podsajtu'
|
||||
PLURALNAME: 'Bazna stranica'
|
||||
SINGULARNAME: 'Virtualna stranica podsajta'
|
||||
SubsiteField: Podsajt
|
||||
VirtualPage:
|
||||
EDITCONTENT: 'Klikni ovdje za uređivanje sadržaja'
|
@ -1,16 +1,16 @@
|
||||
id:
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: Subsitus
|
||||
FileSubsites:
|
||||
SubsiteFieldLabel: Subsitus
|
||||
GroupSubsites:
|
||||
SECURITYTABTITLE: Subsitus
|
||||
Subsite:
|
||||
CustomMetaDescription: Deskripsi
|
||||
CustomMetaKeywords: Kata kunci
|
||||
CustomMetaKeywords: 'Kata kunci'
|
||||
CustomMetaTitle: Judul
|
||||
PLURALNAME: Subsitus
|
||||
SINGULARNAME: Subsitus
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: Subsitus
|
||||
SubsiteReportWrapper:
|
||||
ReportDropdown: Situs
|
||||
Subsites:
|
||||
|
13
lang/ja.yml
@ -1,17 +1,16 @@
|
||||
ja:
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: サブサイト
|
||||
GridFieldAddFromTemplateButton:
|
||||
AddFromTemplate: 'テンプレートから新しく追加'
|
||||
GroupSubsites:
|
||||
ACCESSALL: '全てのサブサイト'
|
||||
ACCESSONLY: 'これらのサブサイトのみ'
|
||||
ACCESSONLY: これらのサブサイトのみ
|
||||
ACCESSRADIOTITLE: 'このグループに選択先へのアクセス権を与える'
|
||||
SECURITYTABTITLE: サブサイト
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: サブサイト
|
||||
SubsiteDomain:
|
||||
DOMAIN: ドメイン
|
||||
IS_PRIMARY: 'プライマリドメイン'
|
||||
PLURALNAME: 'サブサイトのドメイン'
|
||||
SINGULARNAME: 'サブサイトのドメイン'
|
||||
PLURALNAME: サブサイトのドメイン
|
||||
SINGULARNAME: サブサイトのドメイン
|
||||
SubsitesVirtualPage:
|
||||
SINGULARNAME: 'サブサイトの仮想ページ'
|
||||
SINGULARNAME: サブサイトの仮想ページ
|
||||
|
45
lang/lt.yml
Normal file
@ -0,0 +1,45 @@
|
||||
lt:
|
||||
FileSubsites:
|
||||
AllSitesDropdownOpt: 'Visos svetainės'
|
||||
GridFieldAddFromTemplateButton:
|
||||
AddFromTemplate: 'Sukurti naują pagal šabloną'
|
||||
LeftAndMainSubsites:
|
||||
Saved: 'Išsaugota, prašome atnaujinti susijusius puslapius'
|
||||
LeftAndMain_Menu:
|
||||
Hello: Sveiki
|
||||
LOGOUT: Atsijungti
|
||||
SiteTreeSubsites:
|
||||
CopyAction: Kopijuoti
|
||||
CopyToSubsite: 'Kopijuoti puslapį į kitą svetainę'
|
||||
Subsite:
|
||||
COPYSTRUCTURE: 'Kopijuoti struktūrą iš:'
|
||||
CopyMessage: 'Sukurta {title} kopija'
|
||||
CustomExtraMeta: 'Kitos meta žymės'
|
||||
CustomMetaDescription: Aprašymas
|
||||
CustomMetaKeywords: Raktažodžiai
|
||||
CustomMetaTitle: Pavadinimas
|
||||
DomainsHeadline: 'Šio puslapio domenai'
|
||||
DomainsListTitle: Domenai
|
||||
NOTEMPLATE: 'Nėra šablono'
|
||||
PageTypeBlacklistField: 'Neleidžiami puslapių tipai'
|
||||
SiteConfigSubtitle: 'Jūsų svetainės šūkis'
|
||||
SiteConfigTitle: 'Jūsų svetainės pavadinimas'
|
||||
TabTitleConfig: Nustatymai
|
||||
ValidateTitle: 'Prašome įvesti "Pavadinimą"'
|
||||
SubsiteDomain:
|
||||
DOMAIN: Domenas
|
||||
SubsiteReportWrapper:
|
||||
ReportDropdown: Svetainės
|
||||
SubsiteXHRController:
|
||||
MENUTITLE: SubsiteXHRController
|
||||
Subsites:
|
||||
DefaultSiteFieldLabel: 'Pagrindinė svetainė'
|
||||
DomainFieldLabel: Domenas
|
||||
IsPublicFieldLabel: 'Leisti pasiekti visiems'
|
||||
LanguageFieldLabel: Kalba
|
||||
MainSiteTitle: 'Pagrindinis puslapis'
|
||||
PrimaryDomainFieldLabel: 'Pagrindinis domenas'
|
||||
RedirectURLFieldLabel: 'Nukreipimo nuoroda'
|
||||
ThemeFieldLabel: Tema
|
||||
SubsitesVirtualPage:
|
||||
PLURALNAME: 'Baziniai puslapiai'
|
26
lang/mi.yml
@ -1,13 +1,9 @@
|
||||
mi:
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: Ngā pae iti
|
||||
SubsiteXHRController:
|
||||
MENUTITLE: ManaXHRPaeiti
|
||||
ASSETADMIN:
|
||||
SUBSITENOTICE: 'Ka taea ngā kōpaki me ngā kōnae kua hangaia i te pae matua te uru mā ngā pae iti katoa.'
|
||||
FileSubsites:
|
||||
AllSitesDropdownOpt: 'Ngā pae katoa'
|
||||
SubsiteFieldLabel: Pae iti
|
||||
SubsiteFieldLabel: 'Pae iti'
|
||||
GridFieldAddFromTemplateButton:
|
||||
AddFromTemplate: 'Tāpiri Hōu mai i te Tātauira'
|
||||
GroupSubsites:
|
||||
@ -17,7 +13,7 @@ mi:
|
||||
GlobalGroup: 'Rōpū Hurinoa'
|
||||
MANAGE_SUBSITES: 'Whakahaere pae iti mō ngā rōpū'
|
||||
MANAGE_SUBSITES_HELP: 'Te āheinga ki te whakawhāiti whakaaetanga mō tētahi rōpū ki tētahi neke atu rānei o ngā pae iti.'
|
||||
SECURITYTABTITLE: Ngā pae iti
|
||||
SECURITYTABTITLE: 'Ngā pae iti'
|
||||
LeftAndMainSubsites:
|
||||
Saved: 'Kua tiakina, whakahoutia ngā whārangi pāhono.'
|
||||
SiteTreeSubsites:
|
||||
@ -28,27 +24,30 @@ mi:
|
||||
CopyMessage: 'I hangaia he tārua o {title}'
|
||||
CustomExtraMeta: 'Ngā Tūtohu Meta Ritenga'
|
||||
CustomMetaDescription: Whakaahuatanga
|
||||
CustomMetaKeywords: Ngā kupumatua
|
||||
CustomMetaKeywords: 'Ngā kupumatua'
|
||||
CustomMetaTitle: Taitara
|
||||
DOMAINSAVEFIRST: 'Ka taea noa iho te tāpiri rohe i muri i te tiakinga tuatahitanga'
|
||||
DomainsHeadline: 'Ngā rohe mō tēnei pae iti'
|
||||
DomainsListTitle: Ngā Rohe
|
||||
DomainsListTitle: 'Ngā Rohe'
|
||||
IsPublicHeaderField: 'Pae iti hohe'
|
||||
NOTEMPLATE: 'Kāore he tātauira'
|
||||
PLURALNAME: Ngā pae iti
|
||||
PLURALNAME: 'Ngā pae iti'
|
||||
PageTypeBlacklistField: 'Me whakakāhore ngā momo whārangi?'
|
||||
SINGULARNAME: Pae iti
|
||||
SINGULARNAME: 'Pae iti'
|
||||
SiteConfigSubtitle: 'Tō rārangi tautuhinga ki konei'
|
||||
SiteConfigTitle: 'Tō Ingoa Pae'
|
||||
TabTitleConfig: Whirihoranga
|
||||
ValidateTitle: 'Tāurua he "Taitara"'
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: 'Ngā pae iti'
|
||||
SubsiteDomain:
|
||||
DOMAIN: Rohe
|
||||
IS_PRIMARY: 'Ko Te Rohe Matua'
|
||||
PLURALNAME: 'Ngā Rohe Pae Iti'
|
||||
SINGULARNAME: 'Rohe Pae Iti'
|
||||
SubsiteReportWrapper:
|
||||
ReportDropdown: Ngā Pae
|
||||
ReportDropdown: 'Ngā Pae'
|
||||
SubsiteXHRController:
|
||||
MENUTITLE: ManaXHRPaeiti
|
||||
Subsites:
|
||||
DefaultSiteFieldLabel: 'Pae taunoa'
|
||||
DomainFieldLabel: Rohe
|
||||
@ -62,6 +61,5 @@ mi:
|
||||
TitleFieldLabel: 'Ingoa Pae Iti'
|
||||
SubsitesVirtualPage:
|
||||
DESCRIPTION: 'Ka whakaatu i ngā ihirangi o tētahi whārangi ki tētahi atu pae iti'
|
||||
PLURALNAME: 'Ngā Whārangi Taketake'
|
||||
SINGULARNAME: 'Whārangi Mariko Pae Iti'
|
||||
SubsiteField: Pae iti
|
||||
SubsiteField: 'Pae iti'
|
||||
|
@ -1,6 +1,4 @@
|
||||
nb_NO:
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: Underdomener
|
||||
GridFieldAddFromTemplateButton:
|
||||
AddFromTemplate: 'Add New from Template'
|
||||
GroupSubsites:
|
||||
@ -8,9 +6,10 @@ nb_NO:
|
||||
ACCESSONLY: 'Only these subsites'
|
||||
ACCESSRADIOTITLE: 'Give this group access to'
|
||||
SECURITYTABTITLE: subdomener
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: Underdomener
|
||||
SubsiteDomain:
|
||||
DOMAIN: Domain
|
||||
IS_PRIMARY: 'Is Primary Domain'
|
||||
PLURALNAME: 'Subsite Domains'
|
||||
SINGULARNAME: 'Subsite Domain'
|
||||
SubsitesVirtualPage:
|
||||
|
@ -1,6 +1,4 @@
|
||||
nl:
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: Subsites
|
||||
FileSubsites:
|
||||
SubsiteFieldLabel: Subsite
|
||||
GridFieldAddFromTemplateButton:
|
||||
@ -17,9 +15,10 @@ nl:
|
||||
SINGULARNAME: Subsite
|
||||
SiteConfigTitle: 'Jouw Site Naam'
|
||||
TabTitleConfig: Configuratie
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: Subsites
|
||||
SubsiteDomain:
|
||||
DOMAIN: Domein
|
||||
IS_PRIMARY: 'Is Primaire domein'
|
||||
PLURALNAME: 'Subsite Domeinen'
|
||||
SINGULARNAME: 'Subsite Domein'
|
||||
Subsites:
|
||||
@ -29,6 +28,5 @@ nl:
|
||||
ThemeFieldLabel: Thema
|
||||
TitleFieldLabel: 'Subsite naam'
|
||||
SubsitesVirtualPage:
|
||||
PLURALNAME: 'Subsites Virtuele pagina'
|
||||
SINGULARNAME: 'Subsites Virtuele pagina'
|
||||
SubsiteField: Subsite
|
||||
|
@ -1,6 +1,4 @@
|
||||
pl_PL:
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: Podwitryny
|
||||
GridFieldAddFromTemplateButton:
|
||||
AddFromTemplate: 'Dodaj nową na podstawie szablonu'
|
||||
GroupSubsites:
|
||||
@ -8,9 +6,10 @@ pl_PL:
|
||||
ACCESSONLY: 'Tylko te podwitryny'
|
||||
ACCESSRADIOTITLE: 'Daj tej grupie dostęp do'
|
||||
SECURITYTABTITLE: Podwitryny
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: Podwitryny
|
||||
SubsiteDomain:
|
||||
DOMAIN: Domena
|
||||
IS_PRIMARY: 'Ma priorytet?'
|
||||
PLURALNAME: 'Domeny podwitryny'
|
||||
SINGULARNAME: 'Domena podwitryny'
|
||||
SubsitesVirtualPage:
|
||||
|
82
lang/ru.yml
Normal file
@ -0,0 +1,82 @@
|
||||
ru:
|
||||
ASSETADMIN:
|
||||
SUBSITENOTICE: 'Папки и файлы созданные на основном сайте так же доступны для под-сайтов.'
|
||||
DomainNameField:
|
||||
INVALID_DOMAIN: 'Неверный домен'
|
||||
FileSubsites:
|
||||
AllSitesDropdownOpt: 'Все сайты'
|
||||
SubsiteFieldLabel: Подсайт
|
||||
GridFieldAddFromTemplateButton:
|
||||
AddFromTemplate: 'Добавить из шаблона'
|
||||
GroupSubsites:
|
||||
ACCESSALL: 'Все подсайты'
|
||||
ACCESSONLY: 'Только эти подсайты'
|
||||
ACCESSRADIOTITLE: 'Разрешить этой группе доступ к'
|
||||
GlobalGroup: 'глобальная группа'
|
||||
MANAGE_SUBSITES: 'Управление подсайтами для групп'
|
||||
MANAGE_SUBSITES_HELP: 'Возможность ограничить права доступа для группы к одному и более подсайтам'
|
||||
SECURITYTABTITLE: Подсайты
|
||||
LeftAndMainSubsites:
|
||||
Saved: 'Сохранено, пожалуйста обновите связанные группы'
|
||||
LeftAndMain_Menu:
|
||||
Hello: Здравствуйте
|
||||
LOGOUT: 'Выход'
|
||||
SiteTreeSubsites:
|
||||
CopyAction: Копировать
|
||||
CopyToSubsite: 'Копировать страницу на подсайт'
|
||||
CopyToSubsiteWithChildren: 'Включая под-страницы?'
|
||||
SubsiteOperations: 'Операции над подсайтами'
|
||||
Subsite:
|
||||
COPYSTRUCTURE: 'Скопировать структуры из:'
|
||||
CopyMessage: 'Создана копия {title}'
|
||||
CustomExtraMeta: 'Пользовательские мета-тэги'
|
||||
CustomMetaDescription: Описание
|
||||
CustomMetaKeywords: 'Ключевые слова'
|
||||
CustomMetaTitle: Заголовок
|
||||
DOMAINSAVEFIRST: 'Вы можете добавлять домены только после первого сохранения'
|
||||
DomainsHeadline: 'Домены для этого подсайта'
|
||||
DomainsListTitle: Домены
|
||||
IsPublicHeaderField: 'Активный подсайт'
|
||||
NOTEMPLATE: 'Нет шаблона'
|
||||
PLURALNAME: Подсайты
|
||||
PageTypeBlacklistField: 'Запретить данные типы страниц?'
|
||||
SINGULARNAME: Подсайт
|
||||
SiteConfigSubtitle: 'ваш слоган здесь'
|
||||
SiteConfigTitle: 'Название сайта'
|
||||
TabTitleConfig: Конфигурация
|
||||
ValidateTitle: 'Пожалуйста, добавьте "Заголовок"'
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: Подсайты
|
||||
SubsiteDomain:
|
||||
DOMAIN: Домен
|
||||
DOMAIN_DESCRIPTION: 'Домен подсайта (без указания протоколов: http:// и https://). Разрешены (*) для обозначения поддоменов.'
|
||||
IS_PRIMARY: 'Это основной домен?'
|
||||
PLURALNAME: 'Домены подсайтов'
|
||||
PROTOCOL_AUTOMATIC: Автоматически
|
||||
PROTOCOL_DESCRIPTION: 'Отметить как основной домен для данного подсайта'
|
||||
PROTOCOL_HTTP: 'http://'
|
||||
PROTOCOL_HTTPS: 'https://'
|
||||
Protocol: Протокол
|
||||
SINGULARNAME: 'Домен подсайта'
|
||||
SubsiteReportWrapper:
|
||||
ReportDropdown: Сайты
|
||||
SubsiteXHRController:
|
||||
MENUTITLE: SubsiteXHRController
|
||||
Subsites:
|
||||
DefaultSiteFieldLabel: 'Основной сайт'
|
||||
DomainFieldLabel: Домен
|
||||
IsPublicFieldLabel: 'Разрешить публичный доступ'
|
||||
LanguageFieldLabel: Язык
|
||||
MainSiteTitle: 'Основной Сайт'
|
||||
PageTypeBlacklistFieldLabel: 'Запрещённые типы страниц'
|
||||
PrimaryDomainFieldLabel: 'Основной Домен'
|
||||
RedirectURLFieldLabel: 'Ссылка для перенаправления'
|
||||
ThemeFieldLabel: Оформление
|
||||
TitleFieldLabel: 'Название Подсайта'
|
||||
SubsitesVirtualPage:
|
||||
DESCRIPTION: 'Отображает содержимое выбранной страницы на другом подсайте'
|
||||
PLURALNAME: 'Базовые страницы'
|
||||
SINGULARNAME: 'Виртуальная страница подсайта'
|
||||
SubsiteField: Подсайт
|
||||
VirtualPage:
|
||||
EDITCONTENT: 'Нажмите для изменения содержимого'
|
@ -1,16 +1,15 @@
|
||||
tr_TR:
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: Alt Siteler
|
||||
GridFieldAddFromTemplateButton:
|
||||
AddFromTemplate: 'Add New from Template'
|
||||
GroupSubsites:
|
||||
ACCESSALL: 'All subsites'
|
||||
ACCESSONLY: 'Only these subsites'
|
||||
ACCESSRADIOTITLE: 'Give this group access to'
|
||||
SECURITYTABTITLE: Alt Siteler
|
||||
SECURITYTABTITLE: 'Alt Siteler'
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: 'Alt Siteler'
|
||||
SubsiteDomain:
|
||||
DOMAIN: Domain
|
||||
IS_PRIMARY: 'Is Primary Domain'
|
||||
PLURALNAME: 'Subsite Domains'
|
||||
SINGULARNAME: 'Subsite Domain'
|
||||
SubsitesVirtualPage:
|
||||
|
56
lang/zh.yml
@ -1,67 +1,65 @@
|
||||
zh:
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: 多个子网站
|
||||
SubsiteXHRController:
|
||||
MENUTITLE: 子网站 XHR 控制器
|
||||
ASSETADMIN:
|
||||
SUBSITENOTICE: '主网站上创建的文件夹和文件可以被所有子网站访问。'
|
||||
SUBSITENOTICE: 主网站上创建的文件夹和文件可以被所有子网站访问。
|
||||
FileSubsites:
|
||||
AllSitesDropdownOpt: '所有网站'
|
||||
AllSitesDropdownOpt: 所有网站
|
||||
SubsiteFieldLabel: 子网站
|
||||
GridFieldAddFromTemplateButton:
|
||||
AddFromTemplate: '从模板中取出新加入'
|
||||
GroupSubsites:
|
||||
ACCESSALL: '所有子网站'
|
||||
ACCESSALL: 所有子网站
|
||||
ACCESSONLY: '仅这些子网站'
|
||||
ACCESSRADIOTITLE: '准许该群进入'
|
||||
GlobalGroup: '全局小组'
|
||||
MANAGE_SUBSITES: '管理小组的子网站'
|
||||
MANAGE_SUBSITES_HELP: '能够将权限限制在一个小组、一个或多个子网站。'
|
||||
MANAGE_SUBSITES: 管理小组的子网站
|
||||
MANAGE_SUBSITES_HELP: 能够将权限限制在一个小组、一个或多个子网站。
|
||||
SECURITYTABTITLE: 多个子网站
|
||||
LeftAndMainSubsites:
|
||||
Saved: '已保存,请更新相关的页面。'
|
||||
SiteTreeSubsites:
|
||||
CopyAction: 复制
|
||||
CopyToSubsite: '将页面复制到子网站'
|
||||
CopyToSubsite: 将页面复制到子网站
|
||||
Subsite:
|
||||
COPYSTRUCTURE: '复制结构来自:'
|
||||
COPYSTRUCTURE: 复制结构来自:
|
||||
CopyMessage: '已创建一个 {title} 的副本'
|
||||
CustomExtraMeta: '自定义 Meta 标签'
|
||||
CustomMetaDescription: 说明
|
||||
CustomMetaKeywords: 关键词
|
||||
CustomMetaTitle: 标题
|
||||
CustomMetaKeywords: '关键词'
|
||||
CustomMetaTitle: '标题'
|
||||
DOMAINSAVEFIRST: '只有当您第一次保存后,才能添加域名'
|
||||
DomainsHeadline: '这个子网站的域名'
|
||||
DomainsHeadline: 这个子网站的域名
|
||||
DomainsListTitle: 域名
|
||||
IsPublicHeaderField: '活跃的子网站'
|
||||
NOTEMPLATE: '没有模板'
|
||||
IsPublicHeaderField: 活跃的子网站
|
||||
NOTEMPLATE: 没有模板
|
||||
PLURALNAME: 多个子网站
|
||||
PageTypeBlacklistField: '禁止页面类型?'
|
||||
PageTypeBlacklistField: 禁止页面类型?
|
||||
SINGULARNAME: 子网站
|
||||
SiteConfigSubtitle: '您的标语在这里'
|
||||
SiteConfigTitle: '您的网站名称'
|
||||
TabTitleConfig: 配置
|
||||
SiteConfigTitle: 您的网站名称
|
||||
TabTitleConfig: '配置'
|
||||
ValidateTitle: '请添加一个“标题”'
|
||||
SubsiteAdmin:
|
||||
MENUTITLE: 多个子网站
|
||||
SubsiteDomain:
|
||||
DOMAIN: 域名
|
||||
IS_PRIMARY: '是主域名'
|
||||
PLURALNAME: '多个子网站域名'
|
||||
SINGULARNAME: '子网站域名'
|
||||
PLURALNAME: 多个子网站域名
|
||||
SINGULARNAME: 子网站域名
|
||||
SubsiteReportWrapper:
|
||||
ReportDropdown: 网站
|
||||
SubsiteXHRController:
|
||||
MENUTITLE: '子网站 XHR 控制器'
|
||||
Subsites:
|
||||
DefaultSiteFieldLabel: '默认网站'
|
||||
DefaultSiteFieldLabel: 默认网站
|
||||
DomainFieldLabel: 域名
|
||||
IsPublicFieldLabel: '启用公共访问权'
|
||||
LanguageFieldLabel: 语言
|
||||
MainSiteTitle: '主网站'
|
||||
PageTypeBlacklistFieldLabel: '页面类型黑名单'
|
||||
PrimaryDomainFieldLabel: '主域名'
|
||||
MainSiteTitle: 主网站
|
||||
PageTypeBlacklistFieldLabel: 页面类型黑名单
|
||||
PrimaryDomainFieldLabel: 主域名
|
||||
RedirectURLFieldLabel: '重定向 URL'
|
||||
ThemeFieldLabel: 主题
|
||||
TitleFieldLabel: '子网站名称'
|
||||
TitleFieldLabel: 子网站名称
|
||||
SubsitesVirtualPage:
|
||||
DESCRIPTION: '显示另一个子网站上一个页面的内容'
|
||||
PLURALNAME: '基本页面'
|
||||
SINGULARNAME: '子网站虚拟页面'
|
||||
SINGULARNAME: 子网站虚拟页面
|
||||
SubsiteField: 子网站
|
||||
|
45
templates/LeftAndMain_Menu.ss
Normal file
@ -0,0 +1,45 @@
|
||||
<div class="cms-menu cms-panel cms-panel-layout west" id="cms-menu" data-layout-type="border">
|
||||
<div class="cms-logo-header north">
|
||||
<div class="cms-logo">
|
||||
<a href="$ApplicationLink" target="_blank" title="$ApplicationName (Version - $CMSVersion)">
|
||||
$ApplicationName <% if $CMSVersion %><abbr class="version">$CMSVersion</abbr><% end_if %>
|
||||
</a>
|
||||
<span><% if $SiteConfig %>$SiteConfig.Title<% else %>$ApplicationName<% end_if %></span>
|
||||
</div>
|
||||
|
||||
<div class="cms-login-status">
|
||||
<a href="$LogoutURL" class="logout-link font-icon-logout" title="<%t LeftAndMain_Menu_ss.LOGOUT 'Log out' %>"></a>
|
||||
<% with $CurrentMember %>
|
||||
<span>
|
||||
<%t LeftAndMain_Menu_ss.Hello 'Hi' %>
|
||||
<a href="{$AbsoluteBaseURL}admin/myprofile" class="profile-link">
|
||||
<% if $FirstName && $Surname %>$FirstName $Surname<% else_if $FirstName %>$FirstName<% else %>$Email<% end_if %>
|
||||
</a>
|
||||
</span>
|
||||
<% end_with %>
|
||||
</div>
|
||||
<% if $ListSubsites %>
|
||||
<% include SubsiteList %>
|
||||
<% end_if %>
|
||||
</div>
|
||||
|
||||
<div class="cms-panel-content center">
|
||||
<ul class="cms-menu-list">
|
||||
<% loop $MainMenu %>
|
||||
<li class="$LinkingMode $FirstLast <% if $LinkingMode == 'link' %><% else %>opened<% end_if %>" id="Menu-$Code" title="$Title.ATT">
|
||||
<a href="$Link" $AttributesHTML>
|
||||
<span class="icon icon-16 icon-{$Code.LowerCase}"> </span>
|
||||
<span class="text">$Title</span>
|
||||
</a>
|
||||
</li>
|
||||
<% end_loop %>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="cms-panel-toggle south">
|
||||
<button class="sticky-toggle" type="button" title="Sticky nav">Sticky nav</button>
|
||||
<span class="sticky-status-indicator">auto</span>
|
||||
<a class="toggle-expand" href="#"><span>»</span></a>
|
||||
<a class="toggle-collapse" href="#"><span>«</span></a>
|
||||
</div>
|
||||
</div>
|
@ -6,19 +6,18 @@ use SilverStripe\Subsites\Model\Subsite;
|
||||
class BaseSubsiteTest extends SapphireTest
|
||||
{
|
||||
|
||||
function setUp()
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
Subsite::$use_session_subsiteid = true;
|
||||
}
|
||||
Subsite::$force_subsite = null;}
|
||||
|
||||
/**
|
||||
* Avoid subsites filtering on fixture fetching.
|
||||
*/
|
||||
function objFromFixture($class, $id)
|
||||
{
|
||||
Subsite::disable_subsite_filter(true);
|
||||
public function objFromFixture($class, $id)
|
||||
{Subsite::disable_subsite_filter(true);
|
||||
$obj = parent::objFromFixture($class, $id);
|
||||
Subsite::disable_subsite_filter(false);
|
||||
|
||||
@ -28,9 +27,7 @@ class BaseSubsiteTest extends SapphireTest
|
||||
/**
|
||||
* Tests the initial state of disable_subsite_filter
|
||||
*/
|
||||
function testDisableSubsiteFilter()
|
||||
{
|
||||
$this->assertFalse(Subsite::$disable_subsite_filter);
|
||||
public function testDisableSubsiteFilter()
|
||||
{$this->assertFalse(Subsite::$disable_subsite_filter);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,33 +3,47 @@
|
||||
use SilverStripe\Assets\File;
|
||||
use SilverStripe\Assets\Folder;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Subsites\Extensions\FileSubsites;
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\Subsites\Model\Subsite;
|
||||
|
||||
|
||||
class FileSubsitesTest extends BaseSubsiteTest
|
||||
{
|
||||
static $fixture_file = 'subsites/tests/SubsiteTest.yml';
|
||||
public static $fixture_file = 'subsites/tests/SubsiteTest.yml';
|
||||
|
||||
function testTrivialFeatures()
|
||||
/**
|
||||
* Disable other file extensions
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $illegalExtensions = array(
|
||||
'File' => array(
|
||||
'SecureFileExtension',
|
||||
'VersionedFileExtension'
|
||||
),
|
||||
'SiteTree' => array(
|
||||
'Translatable',
|
||||
)
|
||||
);
|
||||
|
||||
public function testTrivialFeatures()
|
||||
{
|
||||
$this->assertTrue(is_array(singleton(FileSubsites::class)->extraStatics()));
|
||||
$this->assertTrue(is_array(singleton('FileSubsites')->extraStatics()));
|
||||
$file = new File();
|
||||
$file->Name = 'FileTitle';
|
||||
$file->Title = 'FileTitle';
|
||||
$this->assertEquals(' * FileTitle', $file->alternateTreeTitle());
|
||||
$file->SubsiteID = $this->objFromFixture(Subsite::class, 'domaintest1')->ID;
|
||||
$file->SubsiteID = $this->objFromFixture('Subsite', 'domaintest1')->ID;
|
||||
$this->assertEquals('FileTitle', $file->getTreeTitle());
|
||||
$this->assertTrue(singleton('SilverStripe\\Assets\\Folder')->getCMSFields() instanceof FieldList);
|
||||
$this->assertTrue(singleton(Folder::class)->getCMSFields() instanceof FieldList);
|
||||
Subsite::changeSubsite(1);
|
||||
$this->assertEquals($file->cacheKeyComponent(), 'subsite-1');
|
||||
}
|
||||
|
||||
function testWritingSubsiteID()
|
||||
public function testWritingSubsiteID()
|
||||
{
|
||||
$this->objFromFixture('SilverStripe\\Security\\Member', 'admin')->logIn();
|
||||
$this->objFromFixture(Member::class, 'admin')->logIn();
|
||||
|
||||
$subsite = $this->objFromFixture(Subsite::class, 'domaintest1');
|
||||
$subsite = $this->objFromFixture('Subsite', 'domaintest1');
|
||||
FileSubsites::$default_root_folders_global = true;
|
||||
|
||||
Subsite::changeSubsite(0);
|
||||
@ -64,24 +78,25 @@ class FileSubsitesTest extends BaseSubsiteTest
|
||||
$this->assertEquals($folder->SubsiteID, $file->SubsiteID);
|
||||
}
|
||||
|
||||
function testSubsitesFolderDropdown()
|
||||
public function testSubsitesFolderDropdown()
|
||||
{
|
||||
$this->objFromFixture('SilverStripe\\Security\\Member', 'admin')->logIn();
|
||||
$this->objFromFixture(Member::class, 'admin')->logIn();
|
||||
|
||||
$file = new Folder();
|
||||
|
||||
$source = array_values($file->getCMSFields()->dataFieldByName('SubsiteID')->getSource());
|
||||
asort($source);
|
||||
|
||||
$this->assertEquals([
|
||||
$this->assertEquals(array(
|
||||
'Main site',
|
||||
'Template',
|
||||
'Subsite1 Template',
|
||||
'Subsite2 Template',
|
||||
'Template',
|
||||
'Test 1',
|
||||
'Test 2',
|
||||
'Test 3'
|
||||
], $source);
|
||||
'Test 3',
|
||||
'Test Non-SSL',
|
||||
'Test SSL',
|
||||
), array_values($source));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,25 +1,24 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Security\Group;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Subsites\Extensions\GroupSubsites;
|
||||
use SilverStripe\Subsites\Model\Subsite;
|
||||
|
||||
|
||||
class GroupSubsitesTest extends BaseSubsiteTest
|
||||
{
|
||||
static $fixture_file = 'subsites/tests/SubsiteTest.yml';
|
||||
public static $fixture_file = 'subsites/tests/SubsiteTest.yml';
|
||||
|
||||
protected $requireDefaultRecordsFrom = [GroupSubsites::class];
|
||||
|
||||
function testTrivialFeatures()
|
||||
public function testTrivialFeatures()
|
||||
{
|
||||
$this->assertTrue(is_array(singleton(GroupSubsites::class)->extraStatics()));
|
||||
$this->assertTrue(is_array(singleton(GroupSubsites::class)->providePermissions()));
|
||||
$this->assertTrue(singleton('SilverStripe\\Security\\Group')->getCMSFields() instanceof FieldList);
|
||||
$this->assertTrue(is_array(singleton('GroupSubsites')->extraStatics()));
|
||||
$this->assertTrue(is_array(singleton('GroupSubsites')->providePermissions()));
|
||||
$this->assertTrue(singleton(Group::class)->getCMSFields() instanceof FieldList);
|
||||
}
|
||||
|
||||
function testAlternateTreeTitle()
|
||||
public function testAlternateTreeTitle()
|
||||
{
|
||||
$group = new Group();
|
||||
$group->Title = 'The A Team';
|
||||
|
@ -1,21 +1,21 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\CMS\Controllers\CMSMain;
|
||||
use SilverStripe\Admin\LeftAndMain;
|
||||
use SilverStripe\AssetAdmin\Controller\AssetAdmin;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\CMS\Controllers\CMSPageEditController;
|
||||
use SilverStripe\Dev\FunctionalTest;
|
||||
use SilverStripe\Subsites\Model\Subsite;
|
||||
|
||||
|
||||
class LeftAndMainSubsitesTest extends FunctionalTest
|
||||
{
|
||||
|
||||
static $fixture_file = 'subsites/tests/SubsiteTest.yml';
|
||||
public static $fixture_file = 'subsites/tests/SubsiteTest.yml';
|
||||
|
||||
/**
|
||||
* Avoid subsites filtering on fixture fetching.
|
||||
*/
|
||||
function objFromFixture($class, $id)
|
||||
public function objFromFixture($class, $id)
|
||||
{
|
||||
Subsite::disable_subsite_filter(true);
|
||||
$obj = parent::objFromFixture($class, $id);
|
||||
@ -24,34 +24,34 @@ class LeftAndMainSubsitesTest extends FunctionalTest
|
||||
return $obj;
|
||||
}
|
||||
|
||||
function testSectionSites()
|
||||
public function testSectionSites()
|
||||
{
|
||||
$member = $this->objFromFixture('SilverStripe\\Security\\Member', 'subsite1member');
|
||||
$member = $this->objFromFixture(Member::class, 'subsite1member');
|
||||
|
||||
$cmsmain = singleton('SilverStripe\\CMS\\Controllers\\CMSMain');
|
||||
$cmsmain = singleton(CMSMain::class);
|
||||
$subsites = $cmsmain->sectionSites(true, "Main site", $member);
|
||||
$this->assertDOSEquals([
|
||||
['Title' => 'Subsite1 Template']
|
||||
], $subsites, 'Lists member-accessible sites for the accessible controller.');
|
||||
$this->assertDOSEquals(array(
|
||||
array('Title' =>'Subsite1 Template')
|
||||
), $subsites, 'Lists member-accessible sites for the accessible controller.');
|
||||
|
||||
$assetadmin = singleton(AssetAdmin::class);
|
||||
$subsites = $assetadmin->sectionSites(true, "Main site", $member);
|
||||
$this->assertDOSEquals([], $subsites, 'Does not list any sites for forbidden controller.');
|
||||
|
||||
$member = $this->objFromFixture('SilverStripe\\Security\\Member', 'editor');
|
||||
$member = $this->objFromFixture(Member::class, 'editor');
|
||||
|
||||
$cmsmain = singleton('SilverStripe\\CMS\\Controllers\\CMSMain');
|
||||
$cmsmain = singleton(CMSMain::class);
|
||||
$subsites = $cmsmain->sectionSites(true, "Main site", $member);
|
||||
$this->assertDOSContains([
|
||||
['Title' => 'Main site']
|
||||
], $subsites, 'Includes the main site for members who can access all sites.');
|
||||
$this->assertDOSContains(array(
|
||||
array('Title' =>'Main site')
|
||||
), $subsites, 'Includes the main site for members who can access all sites.');
|
||||
}
|
||||
|
||||
function testAccessChecksDontChangeCurrentSubsite()
|
||||
public function testAccessChecksDontChangeCurrentSubsite()
|
||||
{
|
||||
$admin = $this->objFromFixture("SilverStripe\\Security\\Member", "admin");
|
||||
$admin = $this->objFromFixture(Member::class, "admin");
|
||||
$this->loginAs($admin);
|
||||
$ids = [];
|
||||
$ids = array();
|
||||
|
||||
$subsite1 = $this->objFromFixture(Subsite::class, 'domaintest1');
|
||||
$subsite2 = $this->objFromFixture(Subsite::class, 'domaintest2');
|
||||
@ -77,26 +77,23 @@ class LeftAndMainSubsitesTest extends FunctionalTest
|
||||
|
||||
}
|
||||
|
||||
function testShouldChangeSubsite()
|
||||
public function testShouldChangeSubsite()
|
||||
{
|
||||
$l = new LeftAndMain();
|
||||
Config::inst()->nest();
|
||||
|
||||
Config::modify()->set('SilverStripe\\CMS\\Controllers\\CMSPageEditController', 'treats_subsite_0_as_global',
|
||||
false);
|
||||
$this->assertTrue($l->shouldChangeSubsite('SilverStripe\\CMS\\Controllers\\CMSPageEditController', 0, 5));
|
||||
$this->assertFalse($l->shouldChangeSubsite('SilverStripe\\CMS\\Controllers\\CMSPageEditController', 0, 0));
|
||||
$this->assertTrue($l->shouldChangeSubsite('SilverStripe\\CMS\\Controllers\\CMSPageEditController', 1, 5));
|
||||
$this->assertFalse($l->shouldChangeSubsite('SilverStripe\\CMS\\Controllers\\CMSPageEditController', 1, 1));
|
||||
Config::inst()->update(CMSPageEditController::class, 'treats_subsite_0_as_global', false);
|
||||
$this->assertTrue($l->shouldChangeSubsite(CMSPageEditController::class, 0, 5));
|
||||
$this->assertFalse($l->shouldChangeSubsite(CMSPageEditController::class, 0, 0));
|
||||
$this->assertTrue($l->shouldChangeSubsite(CMSPageEditController::class, 1, 5));
|
||||
$this->assertFalse($l->shouldChangeSubsite(CMSPageEditController::class, 1, 1));
|
||||
|
||||
Config::modify()->set('SilverStripe\\CMS\\Controllers\\CMSPageEditController', 'treats_subsite_0_as_global',
|
||||
true);
|
||||
$this->assertFalse($l->shouldChangeSubsite('SilverStripe\\CMS\\Controllers\\CMSPageEditController', 0, 5));
|
||||
$this->assertFalse($l->shouldChangeSubsite('SilverStripe\\CMS\\Controllers\\CMSPageEditController', 0, 0));
|
||||
$this->assertTrue($l->shouldChangeSubsite('SilverStripe\\CMS\\Controllers\\CMSPageEditController', 1, 5));
|
||||
$this->assertFalse($l->shouldChangeSubsite('SilverStripe\\CMS\\Controllers\\CMSPageEditController', 1, 1));
|
||||
Config::inst()->update(CMSPageEditController::class, 'treats_subsite_0_as_global', true);
|
||||
$this->assertFalse($l->shouldChangeSubsite(CMSPageEditController::class, 0, 5));
|
||||
$this->assertFalse($l->shouldChangeSubsite(CMSPageEditController::class, 0, 0));
|
||||
$this->assertTrue($l->shouldChangeSubsite(CMSPageEditController::class, 1, 5));
|
||||
$this->assertFalse($l->shouldChangeSubsite(CMSPageEditController::class, 1, 1));
|
||||
|
||||
Config::inst()->unnest();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -41,5 +41,4 @@ class SiteConfigSubsitesTest extends BaseSubsiteTest
|
||||
$keys = SiteConfig::current_site_config()->extend('cacheKeyComponent');
|
||||
$this->assertContains('subsite-' . $subsite2->ID, $keys);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,13 +1,17 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\CMS\Controllers\CMSMain;
|
||||
use SilverStripe\CMS\Model\ErrorPage;
|
||||
use SilverStripe\CMS\Model\SiteTree;
|
||||
use SilverStripe\Control\Session;
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\SiteConfig\SiteConfig;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\CMS\Model\ErrorPage;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\Control\Session;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\CMS\Controllers\CMSMain;
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Versioned\Versioned;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\Subsites\Extensions\SiteTreeSubsites;
|
||||
use SilverStripe\Subsites\Model\Subsite;
|
||||
use SilverStripe\Subsites\Pages\SubsitesVirtualPage;
|
||||
@ -16,7 +20,7 @@ use SilverStripe\Subsites\Pages\SubsitesVirtualPage;
|
||||
class SiteTreeSubsitesTest extends BaseSubsiteTest
|
||||
{
|
||||
|
||||
static $fixture_file = 'subsites/tests/SubsiteTest.yml';
|
||||
public static $fixture_file = 'subsites/tests/SubsiteTest.yml';
|
||||
|
||||
protected $extraDataObjects = [
|
||||
'SiteTreeSubsitesTest_ClassA',
|
||||
@ -25,11 +29,10 @@ class SiteTreeSubsitesTest extends BaseSubsiteTest
|
||||
];
|
||||
|
||||
protected $illegalExtensions = [
|
||||
'SilverStripe\CMS\Model\SiteTree' => ['Translatable']
|
||||
SiteTree::class => ['Translatable']
|
||||
];
|
||||
|
||||
function testPagesInDifferentSubsitesCanShareURLSegment()
|
||||
{
|
||||
public function testPagesInDifferentSubsitesCanShareURLSegment() {
|
||||
$subsiteMain = $this->objFromFixture(Subsite::class, 'main');
|
||||
$subsite1 = $this->objFromFixture(Subsite::class, 'subsite1');
|
||||
|
||||
@ -59,31 +62,30 @@ class SiteTreeSubsitesTest extends BaseSubsiteTest
|
||||
);
|
||||
}
|
||||
|
||||
function testBasicSanity()
|
||||
{
|
||||
$this->assertTrue(singleton('SilverStripe\\CMS\\Model\\SiteTree')->getSiteConfig() instanceof SiteConfig);
|
||||
public function testBasicSanity() {
|
||||
$this->assertTrue(singleton(SiteTree::class)->getSiteConfig() instanceof SiteConfig);
|
||||
// The following assert is breaking in Translatable.
|
||||
$this->assertTrue(singleton('SilverStripe\\CMS\\Model\\SiteTree')->getCMSFields() instanceof FieldList);
|
||||
$this->assertTrue(singleton(SiteTree::class)->getCMSFields() instanceof FieldList);
|
||||
$this->assertTrue(singleton(SubsitesVirtualPage::class)->getCMSFields() instanceof FieldList);
|
||||
$this->assertTrue(is_array(singleton(SiteTreeSubsites::class)->extraStatics()));
|
||||
}
|
||||
|
||||
function testErrorPageLocations()
|
||||
{
|
||||
public function testErrorPageLocations() {
|
||||
$subsite1 = $this->objFromFixture(Subsite::class, 'domaintest1');
|
||||
|
||||
Subsite::changeSubsite($subsite1->ID);
|
||||
$path = SiteTreeSubsitesTest_ErrorPage::get_error_filename_spy(500);
|
||||
$path = ErrorPage::get_filepath_for_errorcode(500);
|
||||
|
||||
$expected_path = 'error-500-' . $subsite1->domain() . '.html';
|
||||
$static_path = Config::inst()->get(ErrorPage::class, 'static_filepath');
|
||||
$expected_path = $static_path . '/error-500-'.$subsite1->domain().'.html';
|
||||
$this->assertEquals($expected_path, $path);
|
||||
}
|
||||
|
||||
function testCanEditSiteTree()
|
||||
public function testCanEditSiteTree()
|
||||
{
|
||||
$admin = $this->objFromFixture('SilverStripe\\Security\\Member', 'admin');
|
||||
$subsite1member = $this->objFromFixture('SilverStripe\\Security\\Member', 'subsite1member');
|
||||
$subsite2member = $this->objFromFixture('SilverStripe\\Security\\Member', 'subsite2member');
|
||||
$admin = $this->objFromFixture(Member::class, 'admin');
|
||||
$subsite1member = $this->objFromFixture(Member::class, 'subsite1member');
|
||||
$subsite2member = $this->objFromFixture(Member::class, 'subsite2member');
|
||||
$mainpage = $this->objFromFixture('Page', 'home');
|
||||
$subsite1page = $this->objFromFixture('Page', 'subsite1_home');
|
||||
$subsite2page = $this->objFromFixture('Page', 'subsite2_home');
|
||||
@ -123,8 +125,7 @@ class SiteTreeSubsitesTest extends BaseSubsiteTest
|
||||
/**
|
||||
* Similar to {@link SubsitesVirtualPageTest->testSubsiteVirtualPageCanHaveSameUrlsegmentAsOtherSubsite()}.
|
||||
*/
|
||||
function testTwoPagesWithSameURLOnDifferentSubsites()
|
||||
{
|
||||
public function testTwoPagesWithSameURLOnDifferentSubsites() {
|
||||
// Set up a couple of pages with the same URL on different subsites
|
||||
$s1 = $this->objFromFixture(Subsite::class, 'domaintest1');
|
||||
$s2 = $this->objFromFixture(Subsite::class, 'domaintest2');
|
||||
@ -151,14 +152,13 @@ class SiteTreeSubsitesTest extends BaseSubsiteTest
|
||||
$this->assertEquals($p2->ID, SiteTree::get_by_link('test-page')->ID);
|
||||
}
|
||||
|
||||
function testPageTypesBlacklistInClassDropdown()
|
||||
{
|
||||
$editor = $this->objFromFixture('SilverStripe\\Security\\Member', 'editor');
|
||||
public function testPageTypesBlacklistInClassDropdown() {
|
||||
$editor = $this->objFromFixture(Member::class, 'editor');
|
||||
Session::set("loggedInAs", $editor->ID);
|
||||
|
||||
$s1 = $this->objFromFixture(Subsite::class, 'domaintest1');
|
||||
$s2 = $this->objFromFixture(Subsite::class, 'domaintest2');
|
||||
$page = singleton('SilverStripe\\CMS\\Model\\SiteTree');
|
||||
$page = singleton('SiteTree');
|
||||
|
||||
$s1->PageTypeBlacklist = 'SiteTreeSubsitesTest_ClassA,ErrorPage';
|
||||
$s1->write();
|
||||
@ -166,7 +166,7 @@ class SiteTreeSubsitesTest extends BaseSubsiteTest
|
||||
Subsite::changeSubsite($s1);
|
||||
$settingsFields = $page->getSettingsFields()->dataFieldByName('ClassName')->getSource();
|
||||
|
||||
$this->assertArrayNotHasKey('SilverStripe\\CMS\\Model\\ErrorPage',
|
||||
$this->assertArrayNotHasKey(ErrorPage::class,
|
||||
$settingsFields
|
||||
);
|
||||
$this->assertArrayNotHasKey('SiteTreeSubsitesTest_ClassA',
|
||||
@ -178,7 +178,7 @@ class SiteTreeSubsitesTest extends BaseSubsiteTest
|
||||
|
||||
Subsite::changeSubsite($s2);
|
||||
$settingsFields = $page->getSettingsFields()->dataFieldByName('ClassName')->getSource();
|
||||
$this->assertArrayHasKey('SilverStripe\\CMS\\Model\\ErrorPage',
|
||||
$this->assertArrayHasKey(ErrorPage::class,
|
||||
$settingsFields
|
||||
);
|
||||
$this->assertArrayHasKey('SiteTreeSubsitesTest_ClassA',
|
||||
@ -189,15 +189,41 @@ class SiteTreeSubsitesTest extends BaseSubsiteTest
|
||||
);
|
||||
}
|
||||
|
||||
function testPageTypesBlacklistInCMSMain()
|
||||
{
|
||||
$editor = $this->objFromFixture('SilverStripe\\Security\\Member', 'editor');
|
||||
public function testCopyToSubsite() {
|
||||
// Remove baseurl if testing in subdir
|
||||
Config::inst()->update(Director::class, 'alternate_base_url', '/');
|
||||
|
||||
/** @var Subsite $otherSubsite */
|
||||
$otherSubsite = $this->objFromFixture(Subsite::class, 'subsite1');
|
||||
$staffPage = $this->objFromFixture('Page', 'staff'); // nested page
|
||||
$contactPage = $this->objFromFixture('Page', 'contact'); // top level page
|
||||
|
||||
$staffPage2 = $staffPage->duplicateToSubsite($otherSubsite->ID);
|
||||
$contactPage2 = $contactPage->duplicateToSubsite($otherSubsite->ID);
|
||||
|
||||
$this->assertNotEquals($staffPage->ID, $staffPage2->ID);
|
||||
$this->assertNotEquals($staffPage->SubsiteID, $staffPage2->SubsiteID);
|
||||
$this->assertNotEquals($contactPage->ID, $contactPage2->ID);
|
||||
$this->assertNotEquals($contactPage->SubsiteID, $contactPage2->SubsiteID);
|
||||
$this->assertEmpty($staffPage2->ParentID);
|
||||
$this->assertEmpty($contactPage2->ParentID);
|
||||
$this->assertNotEmpty($staffPage->ParentID);
|
||||
$this->assertEmpty($contactPage->ParentID);
|
||||
|
||||
// Staff is shifted to top level and given a unique url segment
|
||||
$domain = $otherSubsite->domain();
|
||||
$this->assertEquals('http://'.$domain.'/staff-2/', $staffPage2->AbsoluteLink());
|
||||
$this->assertEquals('http://'.$domain.'/contact-us-2/', $contactPage2->AbsoluteLink());
|
||||
}
|
||||
|
||||
public function testPageTypesBlacklistInCMSMain() {
|
||||
$editor = $this->objFromFixture('Member', 'editor');
|
||||
Session::set("loggedInAs", $editor->ID);
|
||||
|
||||
$cmsmain = new CMSMain();
|
||||
|
||||
$s1 = $this->objFromFixture(Subsite::class, 'domaintest1');
|
||||
$s2 = $this->objFromFixture(Subsite::class, 'domaintest2');
|
||||
$s1 = $this->objFromFixture(Subsite::class,'domaintest1');
|
||||
$s2 = $this->objFromFixture(Subsite::class,'domaintest2');
|
||||
|
||||
$s1->PageTypeBlacklist = 'SiteTreeSubsitesTest_ClassA,ErrorPage';
|
||||
$s1->write();
|
||||
@ -205,24 +231,99 @@ class SiteTreeSubsitesTest extends BaseSubsiteTest
|
||||
Subsite::changeSubsite($s1);
|
||||
$hints = Convert::json2array($cmsmain->SiteTreeHints());
|
||||
$classes = $hints['Root']['disallowedChildren'];
|
||||
$this->assertContains('SilverStripe\\CMS\\Model\\ErrorPage', $classes);
|
||||
$this->assertContains(ErrorPage::class, $classes);
|
||||
$this->assertContains('SiteTreeSubsitesTest_ClassA', $classes);
|
||||
$this->assertNotContains('SiteTreeSubsitesTest_ClassB', $classes);
|
||||
|
||||
Subsite::changeSubsite($s2);
|
||||
$hints = Convert::json2array($cmsmain->SiteTreeHints());
|
||||
$classes = $hints['Root']['disallowedChildren'];
|
||||
$this->assertNotContains('SilverStripe\\CMS\\Model\\ErrorPage', $classes);
|
||||
$this->assertNotContains(ErrorPage::class, $classes);
|
||||
$this->assertNotContains('SiteTreeSubsitesTest_ClassA', $classes);
|
||||
$this->assertNotContains('SiteTreeSubsitesTest_ClassB', $classes);
|
||||
}
|
||||
/**
|
||||
* Tests that url segments between subsites don't conflict, but do conflict within them
|
||||
*/
|
||||
public function testValidateURLSegment() {
|
||||
$this->logInWithPermission('ADMIN');
|
||||
// Saving existing page in the same subsite doesn't change urls
|
||||
$mainHome = $this->objFromFixture('Page', 'home');
|
||||
$mainSubsiteID = $this->idFromFixture(Subsite::class, 'main');
|
||||
Subsite::changeSubsite($mainSubsiteID);
|
||||
$mainHome->Content = '<p>Some new content</p>';
|
||||
$mainHome->write();
|
||||
$this->assertEquals('home', $mainHome->URLSegment);
|
||||
$mainHome->doPublish();
|
||||
$mainHomeLive = Versioned::get_one_by_stage('Page', 'Live', sprintf('"SiteTree"."ID" = \'%d\'', $mainHome->ID));
|
||||
$this->assertEquals('home', $mainHomeLive->URLSegment);
|
||||
|
||||
// Saving existing page in another subsite doesn't change urls
|
||||
Subsite::changeSubsite($mainSubsiteID);
|
||||
$subsite1Home = $this->objFromFixture('Page', 'subsite1_home');
|
||||
$subsite1Home->Content = '<p>In subsite 1</p>';
|
||||
$subsite1Home->write();
|
||||
$this->assertEquals('home', $subsite1Home->URLSegment);
|
||||
$subsite1Home->doPublish();
|
||||
$subsite1HomeLive = Versioned::get_one_by_stage('Page', 'Live', sprintf('"SiteTree"."ID" = \'%d\'', $subsite1Home->ID));
|
||||
$this->assertEquals('home', $subsite1HomeLive->URLSegment);
|
||||
|
||||
// Creating a new page in a subsite doesn't conflict with urls in other subsites
|
||||
$subsite1ID = $this->idFromFixture(Subsite::class, 'subsite1');
|
||||
Subsite::changeSubsite($subsite1ID);
|
||||
$subsite1NewPage = new Page();
|
||||
$subsite1NewPage->SubsiteID = $subsite1ID;
|
||||
$subsite1NewPage->Title = 'Important Page (Subsite 1)';
|
||||
$subsite1NewPage->URLSegment = 'important-page'; // Also exists in main subsite
|
||||
$subsite1NewPage->write();
|
||||
$this->assertEquals('important-page', $subsite1NewPage->URLSegment);
|
||||
$subsite1NewPage->doPublish();
|
||||
$subsite1NewPageLive = Versioned::get_one_by_stage('Page', 'Live', sprintf('"SiteTree"."ID" = \'%d\'', $subsite1NewPage->ID));
|
||||
$this->assertEquals('important-page', $subsite1NewPageLive->URLSegment);
|
||||
|
||||
// Creating a new page in a subsite DOES conflict with urls in the same subsite
|
||||
$subsite1NewPage2 = new Page();
|
||||
$subsite1NewPage2->SubsiteID = $subsite1ID;
|
||||
$subsite1NewPage2->Title = 'Important Page (Subsite 1)';
|
||||
$subsite1NewPage2->URLSegment = 'important-page'; // Also exists in main subsite
|
||||
$subsite1NewPage2->write();
|
||||
$this->assertEquals('important-page-2', $subsite1NewPage2->URLSegment);
|
||||
$subsite1NewPage2->doPublish();
|
||||
$subsite1NewPage2Live = Versioned::get_one_by_stage('Page', 'Live', sprintf('"SiteTree"."ID" = \'%d\'', $subsite1NewPage2->ID));
|
||||
$this->assertEquals('important-page-2', $subsite1NewPage2Live->URLSegment);
|
||||
|
||||
// Original page is left un-modified
|
||||
$mainSubsiteImportantPageID = $this->idFromFixture('Page', 'importantpage');
|
||||
$mainSubsiteImportantPage = Page::get()->byID($mainSubsiteImportantPageID);
|
||||
$this->assertEquals('important-page', $mainSubsiteImportantPage->URLSegment);
|
||||
$mainSubsiteImportantPage->Content = '<p>New Important Page Content</p>';
|
||||
$mainSubsiteImportantPage->write();
|
||||
$this->assertEquals('important-page', $mainSubsiteImportantPage->URLSegment);
|
||||
}
|
||||
|
||||
public function testCopySubsiteWithChildren() {
|
||||
$page = $this->objFromFixture('Page', 'about');
|
||||
$newSubsite = $this->objFromFixture(Subsite::class, 'subsite1');
|
||||
|
||||
$moved = $page->duplicateToSubsite($newSubsite->ID, true);
|
||||
$this->assertEquals($moved->SubsiteID, $newSubsite->ID, 'Ensure returned records are on new subsite');
|
||||
$this->assertEquals($moved->AllChildren()->count(), $page->AllChildren()->count(), 'All pages are copied across');
|
||||
}
|
||||
|
||||
public function testCopySubsiteWithoutChildren() {
|
||||
$page = $this->objFromFixture('Page', 'about');
|
||||
$newSubsite = $this->objFromFixture(Subsite::class, 'subsite2');
|
||||
|
||||
$moved = $page->duplicateToSubsite($newSubsite->ID, false);
|
||||
$this->assertEquals($moved->SubsiteID, $newSubsite->ID, 'Ensure returned records are on new subsite');
|
||||
$this->assertEquals($moved->AllChildren()->count(), 0, 'All pages are copied across');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SiteTreeSubsitesTest_ClassA extends SiteTree implements TestOnly
|
||||
{
|
||||
}
|
||||
|
||||
class SiteTreeSubsitesTest_ClassB extends SiteTree implements TestOnly
|
||||
{
|
||||
}
|
||||
|
@ -1,23 +1,24 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\Control\Session;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\CMS\Controllers\CMSPageEditController;
|
||||
use SilverStripe\Dev\FunctionalTest;
|
||||
use SilverStripe\Subsites\Controller\SubsiteXHRController;
|
||||
use SilverStripe\Subsites\Model\Subsite;
|
||||
|
||||
|
||||
class SubsiteAdminFunctionalTest extends FunctionalTest
|
||||
{
|
||||
static $fixture_file = 'subsites/tests/SubsiteTest.yml';
|
||||
static $use_draft_site = true;
|
||||
public static $fixture_file = 'subsites/tests/SubsiteTest.yml';
|
||||
public static $use_draft_site = true;
|
||||
|
||||
protected $autoFollowRedirection = false;
|
||||
|
||||
/**
|
||||
* Helper: FunctionalTest is only able to follow redirection once, we want to go all the way.
|
||||
*/
|
||||
function getAndFollowAll($url)
|
||||
public function getAndFollowAll($url)
|
||||
{
|
||||
$response = $this->get($url);
|
||||
while ($location = $response->getHeader('Location')) {
|
||||
@ -31,7 +32,7 @@ class SubsiteAdminFunctionalTest extends FunctionalTest
|
||||
/**
|
||||
* Anonymous user cannot access anything.
|
||||
*/
|
||||
function testAnonymousIsForbiddenAdminAccess()
|
||||
public function testAnonymousIsForbiddenAdminAccess()
|
||||
{
|
||||
$response = $this->getAndFollowAll('admin/pages/?SubsiteID=0');
|
||||
$this->assertRegExp('#^Security/login.*#', $this->mainSession->lastUrl(), 'Admin is disallowed');
|
||||
@ -40,7 +41,7 @@ class SubsiteAdminFunctionalTest extends FunctionalTest
|
||||
$response = $this->getAndFollowAll("admin/pages/?SubsiteID={$subsite1->ID}");
|
||||
$this->assertRegExp('#^Security/login.*#', $this->mainSession->lastUrl(), 'Admin is disallowed');
|
||||
|
||||
$response = $this->getAndFollowAll(SubsiteXHRController::class);
|
||||
$response = $this->getAndFollowAll('SubsiteXHRController');
|
||||
$this->assertRegExp('#^Security/login.*#', $this->mainSession->lastUrl(),
|
||||
'SubsiteXHRController is disallowed');
|
||||
}
|
||||
@ -48,9 +49,9 @@ class SubsiteAdminFunctionalTest extends FunctionalTest
|
||||
/**
|
||||
* Admin should be able to access all subsites and the main site
|
||||
*/
|
||||
function testAdminCanAccessAllSubsites()
|
||||
public function testAdminCanAccessAllSubsites()
|
||||
{
|
||||
$member = $this->objFromFixture('SilverStripe\\Security\\Member', 'admin');
|
||||
$member = $this->objFromFixture(Member::class, 'admin');
|
||||
Session::set("loggedInAs", $member->ID);
|
||||
|
||||
$this->getAndFollowAll('admin/pages/?SubsiteID=0');
|
||||
@ -67,9 +68,9 @@ class SubsiteAdminFunctionalTest extends FunctionalTest
|
||||
'SubsiteXHRController is reachable');
|
||||
}
|
||||
|
||||
function testAdminIsRedirectedToObjectsSubsite()
|
||||
public function testAdminIsRedirectedToObjectsSubsite()
|
||||
{
|
||||
$member = $this->objFromFixture('SilverStripe\\Security\\Member', 'admin');
|
||||
$member = $this->objFromFixture(Member::class, 'admin');
|
||||
Session::set("loggedInAs", $member->ID);
|
||||
|
||||
$mainSubsitePage = $this->objFromFixture('Page', 'mainSubsitePage');
|
||||
@ -77,25 +78,20 @@ class SubsiteAdminFunctionalTest extends FunctionalTest
|
||||
|
||||
Config::inst()->nest();
|
||||
|
||||
Config::modify()->set('SilverStripe\\CMS\\Controllers\\CMSPageEditController', 'treats_subsite_0_as_global',
|
||||
false);
|
||||
Config::inst()->update(CMSPageEditController::class, 'treats_subsite_0_as_global', false);
|
||||
Subsite::changeSubsite(0);
|
||||
$this->getAndFollowAll("admin/pages/edit/show/$subsite1Home->ID");
|
||||
$this->assertEquals(Subsite::currentSubsiteID(), $subsite1Home->SubsiteID,
|
||||
'Loading an object switches the subsite');
|
||||
$this->assertEquals(Subsite::currentSubsiteID(), $subsite1Home->SubsiteID, 'Loading an object switches the subsite');
|
||||
$this->assertRegExp("#^admin/pages.*#", $this->mainSession->lastUrl(), 'Lands on the correct section');
|
||||
|
||||
Config::modify()->set('SilverStripe\\CMS\\Controllers\\CMSPageEditController', 'treats_subsite_0_as_global',
|
||||
true);
|
||||
Config::inst()->update(CMSPageEditController::class, 'treats_subsite_0_as_global', true);
|
||||
Subsite::changeSubsite(0);
|
||||
$this->getAndFollowAll("admin/pages/edit/show/$subsite1Home->ID");
|
||||
$this->assertEquals(Subsite::currentSubsiteID(), $subsite1Home->SubsiteID,
|
||||
'Loading a non-main-site object still switches the subsite if configured with treats_subsite_0_as_global');
|
||||
$this->assertEquals(Subsite::currentSubsiteID(), $subsite1Home->SubsiteID, 'Loading a non-main-site object still switches the subsite if configured with treats_subsite_0_as_global');
|
||||
$this->assertRegExp("#^admin/pages.*#", $this->mainSession->lastUrl(), 'Lands on the correct section');
|
||||
|
||||
$this->getAndFollowAll("admin/pages/edit/show/$mainSubsitePage->ID");
|
||||
$this->assertNotEquals(Subsite::currentSubsiteID(), $mainSubsitePage->SubsiteID,
|
||||
'Loading a main-site object does not change the subsite if configured with treats_subsite_0_as_global');
|
||||
$this->assertNotEquals(Subsite::currentSubsiteID(), $mainSubsitePage->SubsiteID, 'Loading a main-site object does not change the subsite if configured with treats_subsite_0_as_global');
|
||||
$this->assertRegExp("#^admin/pages.*#", $this->mainSession->lastUrl(), 'Lands on the correct section');
|
||||
|
||||
Config::inst()->unnest();
|
||||
@ -105,9 +101,9 @@ class SubsiteAdminFunctionalTest extends FunctionalTest
|
||||
* User which has AccessAllSubsites set to 1 should be able to access all subsites and main site,
|
||||
* even though he does not have the ADMIN permission.
|
||||
*/
|
||||
function testEditorCanAccessAllSubsites()
|
||||
public function testEditorCanAccessAllSubsites()
|
||||
{
|
||||
$member = $this->objFromFixture('SilverStripe\\Security\\Member', 'editor');
|
||||
$member = $this->objFromFixture(Member::class, 'editor');
|
||||
Session::set("loggedInAs", $member->ID);
|
||||
|
||||
$this->getAndFollowAll('admin/pages/?SubsiteID=0');
|
||||
@ -119,7 +115,7 @@ class SubsiteAdminFunctionalTest extends FunctionalTest
|
||||
$this->assertEquals(Subsite::currentSubsiteID(), $subsite1->ID, 'Can access other subsite.');
|
||||
$this->assertRegExp('#^admin/pages.*#', $this->mainSession->lastUrl(), 'Lands on the correct section');
|
||||
|
||||
$response = $this->getAndFollowAll(SubsiteXHRController::class);
|
||||
$response = $this->getAndFollowAll('SubsiteXHRController');
|
||||
$this->assertNotRegExp('#^Security/login.*#', $this->mainSession->lastUrl(),
|
||||
'SubsiteXHRController is reachable');
|
||||
}
|
||||
@ -127,9 +123,9 @@ class SubsiteAdminFunctionalTest extends FunctionalTest
|
||||
/**
|
||||
* Test a member who only has access to one subsite (subsite1) and only some sections (pages and security).
|
||||
*/
|
||||
function testSubsiteAdmin()
|
||||
public function testSubsiteAdmin()
|
||||
{
|
||||
$member = $this->objFromFixture('SilverStripe\\Security\\Member', 'subsite1member');
|
||||
$member = $this->objFromFixture(Member::class, 'subsite1member');
|
||||
Session::set("loggedInAs", $member->ID);
|
||||
|
||||
$subsite1 = $this->objFromFixture(Subsite::class, 'subsite1');
|
||||
|
@ -1,26 +1,26 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\CMS\Controllers\CMSMain;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\Control\Session;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\CMS\Controllers\CMSMain;
|
||||
use SilverStripe\Subsites\Model\Subsite;
|
||||
|
||||
|
||||
class SubsiteAdminTest extends BaseSubsiteTest
|
||||
{
|
||||
static $fixture_file = 'subsites/tests/SubsiteTest.yml';
|
||||
public static $fixture_file = 'subsites/tests/SubsiteTest.yml';
|
||||
|
||||
function adminLoggedInSession()
|
||||
public function adminLoggedInSession()
|
||||
{
|
||||
return new Session([
|
||||
'loggedInAs' => $this->idFromFixture('SilverStripe\\Security\\Member', 'admin')
|
||||
]);
|
||||
return new Session(array(
|
||||
'loggedInAs' => $this->idFromFixture(Member::class, 'admin')
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test generation of the view
|
||||
*/
|
||||
function testBasicView()
|
||||
public function testBasicView()
|
||||
{
|
||||
Subsite::$write_hostmap = false;
|
||||
$subsite1ID = $this->objFromFixture(Subsite::class, 'domaintest1')->ID;
|
||||
@ -41,9 +41,9 @@ class SubsiteAdminTest extends BaseSubsiteTest
|
||||
* Test that the main-site user with ADMIN permissions can access all subsites, regardless
|
||||
* of whether he is in a subsite-specific group or not.
|
||||
*/
|
||||
function testMainsiteAdminCanAccessAllSubsites()
|
||||
public function testMainsiteAdminCanAccessAllSubsites()
|
||||
{
|
||||
$member = $this->objFromFixture('SilverStripe\\Security\\Member', 'admin');
|
||||
$member = $this->objFromFixture(Member::class, 'admin');
|
||||
Session::set("loggedInAs", $member->ID);
|
||||
|
||||
$cmsMain = new CMSMain();
|
||||
@ -52,11 +52,9 @@ class SubsiteAdminTest extends BaseSubsiteTest
|
||||
}
|
||||
|
||||
$this->assertArrayHasKey(0, $ids, "Main site accessible");
|
||||
$this->assertArrayHasKey($this->idFromFixture(Subsite::class, 'main'), $ids, "Site with no groups inaccesible");
|
||||
$this->assertArrayHasKey($this->idFromFixture(Subsite::class, 'subsite1'), $ids,
|
||||
"Subsite1 Template inaccessible");
|
||||
$this->assertArrayHasKey($this->idFromFixture(Subsite::class, 'subsite2'), $ids,
|
||||
"Subsite2 Template inaccessible");
|
||||
$this->assertArrayHasKey($this->idFromFixture(Subsite::class,'main'), $ids, "Site with no groups inaccesible");
|
||||
$this->assertArrayHasKey($this->idFromFixture(Subsite::class,'subsite1'), $ids, "Subsite1 Template inaccessible");
|
||||
$this->assertArrayHasKey($this->idFromFixture(Subsite::class,'subsite2'), $ids, "Subsite2 Template inaccessible");
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,35 +1,53 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\CMS\Model\SiteTree;
|
||||
use SilverStripe\Security\Member;
|
||||
use SilverStripe\Subsites\Model\Subsite;
|
||||
use SilverStripe\Subsites\Model\SubsiteDomain;
|
||||
|
||||
|
||||
class SubsiteTest extends BaseSubsiteTest
|
||||
{
|
||||
public static $fixture_file = 'subsites/tests/SubsiteTest.yml';
|
||||
|
||||
static $fixture_file = 'subsites/tests/SubsiteTest.yml';
|
||||
/**
|
||||
* Original value of {@see SubSite::$strict_subdomain_matching}
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $origStrictSubdomainMatching = null;
|
||||
|
||||
function setUp()
|
||||
/**
|
||||
* Original value of $_REQUEST
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $origServer = array();
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
Config::inst()->update(Director::class, 'alternate_base_url', '/');
|
||||
$this->origStrictSubdomainMatching = Subsite::$strict_subdomain_matching;
|
||||
$this->origServer = $_SERVER;
|
||||
Subsite::$strict_subdomain_matching = false;
|
||||
}
|
||||
|
||||
function tearDown()
|
||||
public function tearDown()
|
||||
{
|
||||
parent::tearDown();
|
||||
|
||||
$_SERVER = $this->origServer;
|
||||
Subsite::$strict_subdomain_matching = $this->origStrictSubdomainMatching;
|
||||
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new subsite from the template and verify that all the template's pages are copied
|
||||
*/
|
||||
function testSubsiteCreation()
|
||||
public function testSubsiteCreation()
|
||||
{
|
||||
Subsite::$write_hostmap = false;
|
||||
|
||||
@ -38,11 +56,12 @@ class SubsiteTest extends BaseSubsiteTest
|
||||
|
||||
// Test that changeSubsite is working
|
||||
Subsite::changeSubsite($template->ID);
|
||||
$this->assertEquals($template->ID, Subsite::currentSubsiteID());
|
||||
$tmplStaff = $this->objFromFixture('Page', 'staff');
|
||||
$tmplHome = DataObject::get_one('Page', "\"URLSegment\" = 'home'");
|
||||
|
||||
// Publish all the pages in the template, testing that DataObject::get only returns pages from the chosen subsite
|
||||
$pages = DataObject::get("SilverStripe\\CMS\\Model\\SiteTree");
|
||||
$pages = DataObject::get(SiteTree::class);
|
||||
$totalPages = $pages->Count();
|
||||
foreach ($pages as $page) {
|
||||
$this->assertEquals($template->ID, $page->SubsiteID);
|
||||
@ -70,7 +89,7 @@ class SubsiteTest extends BaseSubsiteTest
|
||||
/**
|
||||
* Confirm that domain lookup is working
|
||||
*/
|
||||
function testDomainLookup()
|
||||
public function testDomainLookup()
|
||||
{
|
||||
// Clear existing fixtures
|
||||
foreach (DataObject::get(Subsite::class) as $subsite) {
|
||||
@ -81,20 +100,20 @@ class SubsiteTest extends BaseSubsiteTest
|
||||
}
|
||||
|
||||
// Much more expressive than YML in this case
|
||||
$subsite1 = $this->createSubsiteWithDomains([
|
||||
$subsite1 = $this->createSubsiteWithDomains(array(
|
||||
'one.example.org' => true,
|
||||
'one.*' => false,
|
||||
]);
|
||||
$subsite2 = $this->createSubsiteWithDomains([
|
||||
));
|
||||
$subsite2 = $this->createSubsiteWithDomains(array(
|
||||
'two.mysite.com' => true,
|
||||
'*.mysite.com' => false,
|
||||
'subdomain.onmultiplesubsites.com' => false,
|
||||
]);
|
||||
$subsite3 = $this->createSubsiteWithDomains([
|
||||
));
|
||||
$subsite3 = $this->createSubsiteWithDomains(array(
|
||||
'three.*' => true, // wildcards in primary domain are not recommended
|
||||
'subdomain.unique.com' => false,
|
||||
'*.onmultiplesubsites.com' => false,
|
||||
]);
|
||||
));
|
||||
|
||||
$this->assertEquals(
|
||||
$subsite3->ID,
|
||||
@ -142,10 +161,9 @@ class SubsiteTest extends BaseSubsiteTest
|
||||
Subsite::getSubsiteIDForDomain('unknown.madeup.com'),
|
||||
"Doesn't match unknown subsite"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
function testStrictSubdomainMatching()
|
||||
public function testStrictSubdomainMatching()
|
||||
{
|
||||
// Clear existing fixtures
|
||||
foreach (DataObject::get(Subsite::class) as $subsite) {
|
||||
@ -156,15 +174,15 @@ class SubsiteTest extends BaseSubsiteTest
|
||||
}
|
||||
|
||||
// Much more expressive than YML in this case
|
||||
$subsite1 = $this->createSubsiteWithDomains([
|
||||
$subsite1 = $this->createSubsiteWithDomains(array(
|
||||
'example.org' => true,
|
||||
'example.com' => false,
|
||||
'*.wildcard.com' => false,
|
||||
]);
|
||||
$subsite2 = $this->createSubsiteWithDomains([
|
||||
));
|
||||
$subsite2 = $this->createSubsiteWithDomains(array(
|
||||
'www.example.org' => true,
|
||||
'www.wildcard.com' => false,
|
||||
]);
|
||||
));
|
||||
|
||||
Subsite::$strict_subdomain_matching = false;
|
||||
|
||||
@ -216,21 +234,20 @@ class SubsiteTest extends BaseSubsiteTest
|
||||
$failed,
|
||||
'Fails on multiple matches with strict checking and wildcard vs. www'
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
protected function createSubsiteWithDomains($domains)
|
||||
{
|
||||
$subsite = new Subsite([
|
||||
$subsite = new Subsite(array(
|
||||
'Title' => 'My Subsite'
|
||||
]);
|
||||
));
|
||||
$subsite->write();
|
||||
foreach ($domains as $domainStr => $isPrimary) {
|
||||
$domain = new SubsiteDomain([
|
||||
$domain = new SubsiteDomain(array(
|
||||
'Domain' => $domainStr,
|
||||
'IsPrimary' => $isPrimary,
|
||||
'SubsiteID' => $subsite->ID
|
||||
]);
|
||||
));
|
||||
$domain->write();
|
||||
}
|
||||
|
||||
@ -240,7 +257,7 @@ class SubsiteTest extends BaseSubsiteTest
|
||||
/**
|
||||
* Test the Subsite->domain() method
|
||||
*/
|
||||
function testDefaultDomain()
|
||||
public function testDefaultDomain()
|
||||
{
|
||||
$this->assertEquals('one.example.org',
|
||||
$this->objFromFixture(Subsite::class, 'domaintest1')->domain());
|
||||
@ -248,8 +265,6 @@ class SubsiteTest extends BaseSubsiteTest
|
||||
$this->assertEquals('two.mysite.com',
|
||||
$this->objFromFixture(Subsite::class, 'domaintest2')->domain());
|
||||
|
||||
$originalHTTPHost = $_SERVER['HTTP_HOST'];
|
||||
|
||||
$_SERVER['HTTP_HOST'] = "www.example.org";
|
||||
$this->assertEquals('three.example.org',
|
||||
$this->objFromFixture(Subsite::class, 'domaintest3')->domain());
|
||||
@ -259,109 +274,157 @@ class SubsiteTest extends BaseSubsiteTest
|
||||
$this->objFromFixture(Subsite::class, 'domaintest3')->domain());
|
||||
|
||||
$this->assertEquals($_SERVER['HTTP_HOST'], singleton(Subsite::class)->PrimaryDomain);
|
||||
$this->assertEquals('http://' . $_SERVER['HTTP_HOST'] . Director::baseURL(),
|
||||
singleton(Subsite::class)->absoluteBaseURL());
|
||||
|
||||
$_SERVER['HTTP_HOST'] = $originalHTTPHost;
|
||||
$this->assertEquals('http://'.$_SERVER['HTTP_HOST'].Director::baseURL(), singleton(Subsite::class)->absoluteBaseURL());
|
||||
}
|
||||
|
||||
function testAllSites()
|
||||
/**
|
||||
* Tests that Subsite and SubsiteDomain both respect http protocol correctly
|
||||
*/
|
||||
public function testDomainProtocol() {
|
||||
// domaintest2 has 'protocol'
|
||||
$subsite2 = $this->objFromFixture(Subsite::class, 'domaintest2');
|
||||
$domain2a = $this->objFromFixture(SubsiteDomain::class, 'dt2a');
|
||||
$domain2b = $this->objFromFixture(SubsiteDomain::class, 'dt2b');
|
||||
|
||||
// domaintest4 is 'https' (primary only)
|
||||
$subsite4 = $this->objFromFixture(Subsite::class, 'domaintest4');
|
||||
$domain4a = $this->objFromFixture(SubsiteDomain::class, 'dt4a');
|
||||
$domain4b = $this->objFromFixture(SubsiteDomain::class, 'dt4b'); // secondary domain is http only though
|
||||
|
||||
// domaintest5 is 'http'
|
||||
$subsite5 = $this->objFromFixture(Subsite::class, 'domaintest5');
|
||||
$domain5a = $this->objFromFixture(SubsiteDomain::class, 'dt5');
|
||||
|
||||
// Check protocol when current protocol is http://
|
||||
$_SERVER['HTTP_HOST'] = 'www.mysite.com';
|
||||
$_SERVER['HTTPS'] = '';
|
||||
|
||||
$this->assertEquals('http://two.mysite.com/', $subsite2->absoluteBaseURL());
|
||||
$this->assertEquals('http://two.mysite.com/', $domain2a->absoluteBaseURL());
|
||||
$this->assertEquals('http://subsite.mysite.com/', $domain2b->absoluteBaseURL());
|
||||
$this->assertEquals('https://www.primary.com/', $subsite4->absoluteBaseURL());
|
||||
$this->assertEquals('https://www.primary.com/', $domain4a->absoluteBaseURL());
|
||||
$this->assertEquals('http://www.secondary.com/', $domain4b->absoluteBaseURL());
|
||||
$this->assertEquals('http://www.tertiary.com/', $subsite5->absoluteBaseURL());
|
||||
$this->assertEquals('http://www.tertiary.com/', $domain5a->absoluteBaseURL());
|
||||
|
||||
// Check protocol when current protocol is https://
|
||||
$_SERVER['HTTP_HOST'] = 'www.mysite.com';
|
||||
$_SERVER['HTTPS'] = 'ON';
|
||||
|
||||
$this->assertEquals('https://two.mysite.com/', $subsite2->absoluteBaseURL());
|
||||
$this->assertEquals('https://two.mysite.com/', $domain2a->absoluteBaseURL());
|
||||
$this->assertEquals('https://subsite.mysite.com/', $domain2b->absoluteBaseURL());
|
||||
$this->assertEquals('https://www.primary.com/', $subsite4->absoluteBaseURL());
|
||||
$this->assertEquals('https://www.primary.com/', $domain4a->absoluteBaseURL());
|
||||
$this->assertEquals('http://www.secondary.com/', $domain4b->absoluteBaseURL());
|
||||
$this->assertEquals('http://www.tertiary.com/', $subsite5->absoluteBaseURL());
|
||||
$this->assertEquals('http://www.tertiary.com/', $domain5a->absoluteBaseURL());
|
||||
}
|
||||
|
||||
public function testAllSites()
|
||||
{
|
||||
$subsites = Subsite::all_sites();
|
||||
$this->assertDOSEquals([
|
||||
['Title' => 'Main site'],
|
||||
['Title' => 'Template'],
|
||||
['Title' => 'Subsite1 Template'],
|
||||
['Title' => 'Subsite2 Template'],
|
||||
['Title' => 'Test 1'],
|
||||
['Title' => 'Test 2'],
|
||||
['Title' => 'Test 3']
|
||||
], $subsites, 'Lists all subsites');
|
||||
$this->assertDOSEquals(array(
|
||||
array('Title' =>'Main site'),
|
||||
array('Title' =>'Template'),
|
||||
array('Title' =>'Subsite1 Template'),
|
||||
array('Title' =>'Subsite2 Template'),
|
||||
array('Title' =>'Test 1'),
|
||||
array('Title' =>'Test 2'),
|
||||
array('Title' =>'Test 3'),
|
||||
array('Title' => 'Test Non-SSL'),
|
||||
array('Title' => 'Test SSL')
|
||||
), $subsites, 'Lists all subsites');
|
||||
}
|
||||
|
||||
function testAllAccessibleSites()
|
||||
public function testAllAccessibleSites()
|
||||
{
|
||||
$member = $this->objFromFixture('SilverStripe\\Security\\Member', 'subsite1member');
|
||||
$member = $this->objFromFixture(Member::class, 'subsite1member');
|
||||
|
||||
$subsites = Subsite::all_accessible_sites(true, 'Main site', $member);
|
||||
$this->assertDOSEquals([
|
||||
['Title' => 'Subsite1 Template']
|
||||
], $subsites, 'Lists member-accessible sites.');
|
||||
$this->assertDOSEquals(array(
|
||||
array('Title' =>'Subsite1 Template')
|
||||
), $subsites, 'Lists member-accessible sites.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Subsite::accessible_sites()
|
||||
*/
|
||||
function testAccessibleSites()
|
||||
public function testAccessibleSites()
|
||||
{
|
||||
$member1Sites = Subsite::accessible_sites("CMS_ACCESS_CMSMain", false, null,
|
||||
$this->objFromFixture('SilverStripe\\Security\\Member', 'subsite1member'));
|
||||
$this->objFromFixture(Member::class, 'subsite1member'));
|
||||
$member1SiteTitles = $member1Sites->column("Title");
|
||||
sort($member1SiteTitles);
|
||||
$this->assertEquals('Subsite1 Template', $member1SiteTitles[0], 'Member can get to a subsite via a group');
|
||||
|
||||
$adminSites = Subsite::accessible_sites("CMS_ACCESS_CMSMain", false, null,
|
||||
$this->objFromFixture('SilverStripe\\Security\\Member', 'admin'));
|
||||
$this->objFromFixture(Member::class, 'admin'));
|
||||
$adminSiteTitles = $adminSites->column("Title");
|
||||
sort($adminSiteTitles);
|
||||
$this->assertEquals([
|
||||
$this->assertEquals(array(
|
||||
'Subsite1 Template',
|
||||
'Subsite2 Template',
|
||||
'Template',
|
||||
'Test 1',
|
||||
'Test 2',
|
||||
'Test 3',
|
||||
], $adminSiteTitles);
|
||||
'Test Non-SSL',
|
||||
'Test SSL'
|
||||
), array_values($adminSiteTitles));
|
||||
|
||||
$member2Sites = Subsite::accessible_sites("CMS_ACCESS_CMSMain", false, null,
|
||||
$this->objFromFixture('SilverStripe\\Security\\Member', 'subsite1member2'));
|
||||
$member2Sites = Subsite::accessible_sites(
|
||||
"CMS_ACCESS_CMSMain", false, null,
|
||||
$this->objFromFixture(Member::class, 'subsite1member2')
|
||||
);
|
||||
$member2SiteTitles = $member2Sites->column("Title");
|
||||
sort($member2SiteTitles);
|
||||
$this->assertEquals('Subsite1 Template', $member2SiteTitles[0], 'Member can get to subsite via a group role');
|
||||
}
|
||||
|
||||
function testhasMainSitePermission()
|
||||
public function testhasMainSitePermission()
|
||||
{
|
||||
$admin = $this->objFromFixture('SilverStripe\\Security\\Member', 'admin');
|
||||
$subsite1member = $this->objFromFixture('SilverStripe\\Security\\Member', 'subsite1member');
|
||||
$subsite1admin = $this->objFromFixture('SilverStripe\\Security\\Member', 'subsite1admin');
|
||||
$allsubsitesauthor = $this->objFromFixture('SilverStripe\\Security\\Member', 'allsubsitesauthor');
|
||||
$admin = $this->objFromFixture(Member::class, 'admin');
|
||||
$subsite1member = $this->objFromFixture(Member::class, 'subsite1member');
|
||||
$subsite1admin = $this->objFromFixture(Member::class, 'subsite1admin');
|
||||
$allsubsitesauthor = $this->objFromFixture(Member::class, 'allsubsitesauthor');
|
||||
|
||||
$this->assertTrue(
|
||||
Subsite::hasMainSitePermission($admin),
|
||||
'Default permissions granted for super-admin'
|
||||
);
|
||||
$this->assertTrue(
|
||||
Subsite::hasMainSitePermission($admin, ["ADMIN"]),
|
||||
Subsite::hasMainSitePermission($admin, array("ADMIN")),
|
||||
'ADMIN permissions granted for super-admin'
|
||||
);
|
||||
$this->assertFalse(
|
||||
Subsite::hasMainSitePermission($subsite1admin, ["ADMIN"]),
|
||||
Subsite::hasMainSitePermission($subsite1admin, array("ADMIN")),
|
||||
'ADMIN permissions (on main site) denied for subsite1 admin'
|
||||
);
|
||||
$this->assertFalse(
|
||||
Subsite::hasMainSitePermission($subsite1admin, ["CMS_ACCESS_CMSMain"]),
|
||||
Subsite::hasMainSitePermission($subsite1admin, array("CMS_ACCESS_CMSMain")),
|
||||
'CMS_ACCESS_CMSMain (on main site) denied for subsite1 admin'
|
||||
);
|
||||
$this->assertFalse(
|
||||
Subsite::hasMainSitePermission($allsubsitesauthor, ["ADMIN"]),
|
||||
Subsite::hasMainSitePermission($allsubsitesauthor, array("ADMIN")),
|
||||
'ADMIN permissions (on main site) denied for CMS author with edit rights on all subsites'
|
||||
);
|
||||
$this->assertTrue(
|
||||
Subsite::hasMainSitePermission($allsubsitesauthor, ["CMS_ACCESS_CMSMain"]),
|
||||
Subsite::hasMainSitePermission($allsubsitesauthor, array("CMS_ACCESS_CMSMain")),
|
||||
'CMS_ACCESS_CMSMain (on main site) granted for CMS author with edit rights on all subsites'
|
||||
);
|
||||
$this->assertFalse(
|
||||
Subsite::hasMainSitePermission($subsite1member, ["ADMIN"]),
|
||||
Subsite::hasMainSitePermission($subsite1member, array("ADMIN")),
|
||||
'ADMIN (on main site) denied for subsite1 subsite1 cms author'
|
||||
);
|
||||
$this->assertFalse(
|
||||
Subsite::hasMainSitePermission($subsite1member, ["CMS_ACCESS_CMSMain"]),
|
||||
Subsite::hasMainSitePermission($subsite1member, array("CMS_ACCESS_CMSMain")),
|
||||
'CMS_ACCESS_CMSMain (on main site) denied for subsite1 cms author'
|
||||
);
|
||||
}
|
||||
|
||||
function testDuplicateSubsite()
|
||||
public function testDuplicateSubsite()
|
||||
{
|
||||
// get subsite1 & create page
|
||||
$subsite1 = $this->objFromFixture(Subsite::class, 'domaintest1');
|
||||
|
@ -1,79 +1,103 @@
|
||||
SilverStripe\Subsites\Model\Subsite:
|
||||
main:
|
||||
Title: 'Template'
|
||||
Title: Template
|
||||
subsite1:
|
||||
Title: 'Subsite1 Template'
|
||||
Title: Subsite1 Template
|
||||
subsite2:
|
||||
Title: 'Subsite2 Template'
|
||||
Title: Subsite2 Template
|
||||
domaintest1:
|
||||
Title: 'Test 1'
|
||||
Title: Test 1
|
||||
domaintest2:
|
||||
Title: 'Test 2'
|
||||
Title: Test 2
|
||||
domaintest3:
|
||||
Title: 'Test 3'
|
||||
Title: Test 3
|
||||
domaintest4:
|
||||
Title: 'Test SSL'
|
||||
domaintest5:
|
||||
Title: 'Test Non-SSL'
|
||||
SilverStripe\Subsites\Model\SubsiteDomain:
|
||||
subsite1:
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.subsite1
|
||||
Domain: 'subsite1.*'
|
||||
Domain: subsite1.*
|
||||
Protocol: automatic
|
||||
subsite2:
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.subsite2
|
||||
Domain: 'subsite2.*'
|
||||
Domain: subsite2.*
|
||||
Protocol: automatic
|
||||
dt1a:
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.domaintest1
|
||||
Domain: 'one.example.org'
|
||||
Domain: one.example.org
|
||||
Protocol: automatic
|
||||
IsPrimary: 1
|
||||
dt1b:
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.domaintest1
|
||||
Domain: 'one.*'
|
||||
Domain: one.*
|
||||
Protocol: automatic
|
||||
dt2a:
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.domaintest2
|
||||
Domain: 'two.mysite.com'
|
||||
Domain: two.mysite.com
|
||||
Protocol: automatic
|
||||
IsPrimary: 1
|
||||
dt2b:
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.domaintest2
|
||||
Domain: '*.mysite.com'
|
||||
Domain: *.mysite.com
|
||||
Protocol: automatic
|
||||
dt3:
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.domaintest3
|
||||
Domain: 'three.*'
|
||||
Domain: three.*
|
||||
Protocol: automatic
|
||||
IsPrimary: 1
|
||||
dt4a:
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.domaintest4
|
||||
Domain: www.primary.com
|
||||
Protocol: https
|
||||
dt4b:
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.domaintest4
|
||||
Domain: www.secondary.com
|
||||
Protocol: http
|
||||
dt5:
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.domaintest5
|
||||
Domain: www.tertiary.com
|
||||
Protocol: http
|
||||
IsPrimary: 1
|
||||
Page:
|
||||
mainSubsitePage:
|
||||
Title: 'MainSubsitePage'
|
||||
SubsiteID: 0
|
||||
home:
|
||||
URLSegment: mainsubsitepagehome:
|
||||
Title: 'Home'
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.main
|
||||
about:
|
||||
URLSegment: homeabout:
|
||||
Title: 'About'
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.main
|
||||
linky:
|
||||
URLSegment: aboutlinky:
|
||||
Title: 'Linky'
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.main
|
||||
staff:
|
||||
URLSegment: linkystaff:
|
||||
Title: 'Staff'
|
||||
ParentID: =>Page.about
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.main
|
||||
contact:
|
||||
URLSegment: staffcontact:
|
||||
Title: 'Contact Us'
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.main
|
||||
importantpage:
|
||||
URLSegment: contact-usimportantpage:
|
||||
Title: 'Important Page'
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.main
|
||||
subsite1_home:
|
||||
URLSegment: important-pagesubsite1_home:
|
||||
Title: 'Home (Subsite 1)'
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.subsite1
|
||||
subsite1_contactus:
|
||||
URLSegment: homesubsite1_contactus:
|
||||
Title: 'Contact Us (Subsite 1)'
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.subsite1
|
||||
subsite1_staff:
|
||||
URLSegment: contact-ussubsite1_staff:
|
||||
Title: 'Staff'
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.subsite1
|
||||
subsite2_home:
|
||||
URLSegment: staffsubsite2_home:
|
||||
Title: 'Home (Subsite 2)'
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.subsite2
|
||||
subsite2_contactus:
|
||||
URLSegment: homesubsite2_contactus:
|
||||
Title: 'Contact Us (Subsite 2)'
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.subsite2
|
||||
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.subsite2URLSegment: contact-us
|
||||
|
||||
SilverStripe\Security\PermissionRoleCode:
|
||||
roleCode1:
|
||||
|
47
tests/SubsiteXHRControllerTest.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\Control\Session;
|
||||
use SilverStripe\Dev\FunctionalTest;
|
||||
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: dmooyman
|
||||
* Date: 27/05/16
|
||||
* Time: 3:10 PM
|
||||
*/
|
||||
class SubsiteXHRControllerTest extends FunctionalTest
|
||||
{
|
||||
protected static $fixture_file = 'SubsiteTest.yml';
|
||||
|
||||
public function testCanView() {
|
||||
// Test unauthenticated access
|
||||
Session::clear('MemberID');
|
||||
$result = $this->get('SubsiteXHRController', null, array(
|
||||
'X-Pjax' => 'SubsiteList',
|
||||
'X-Requested-With' => 'XMLHttpRequest'
|
||||
));
|
||||
$this->assertEquals(403, $result->getStatusCode());
|
||||
|
||||
// Login with NO permissions
|
||||
$this->logInWithPermission('NOT_CMS_PERMISSION');
|
||||
$result = $this->get('SubsiteXHRController', null, array(
|
||||
'X-Pjax' => 'SubsiteList',
|
||||
'X-Requested-With' => 'XMLHttpRequest'
|
||||
));
|
||||
$this->assertEquals(403, $result->getStatusCode());
|
||||
|
||||
// Test cms user
|
||||
$this->logInWithPermission('CMS_ACCESS_CMSMain');
|
||||
$result = $this->get('SubsiteXHRController', null, array(
|
||||
'X-Pjax' => 'SubsiteList',
|
||||
'X-Requested-With' => 'XMLHttpRequest'
|
||||
));
|
||||
$this->assertEquals(200, $result->getStatusCode());
|
||||
$this->assertEquals('text/json', $result->getHeader('Content-Type'));
|
||||
$body = $result->getBody();
|
||||
$this->assertContains('Main site', $body);
|
||||
$this->assertContains('Test 1', $body);
|
||||
$this->assertContains('Test 2', $body);
|
||||
$this->assertContains('Test 3', $body);
|
||||
}
|
||||
}
|
@ -2,19 +2,25 @@
|
||||
|
||||
use SilverStripe\Assets\Filesystem;
|
||||
use SilverStripe\Assets\Tests\Storage\AssetStoreTest\TestAssetStore;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\CMS\Model\SiteTree;
|
||||
use SilverStripe\Assets\File;
|
||||
use SilverStripe\ORM\DB;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Versioned\Versioned;
|
||||
use SilverStripe\Subsites\Model\Subsite;
|
||||
use SilverStripe\Subsites\Pages\SubsitesVirtualPage;
|
||||
use SilverStripe\Versioned\Versioned;
|
||||
|
||||
|
||||
class SubsitesVirtualPageTest extends BaseSubsiteTest
|
||||
{
|
||||
static $fixture_file = [
|
||||
public static $fixture_file = array(
|
||||
'subsites/tests/SubsiteTest.yml',
|
||||
'subsites/tests/SubsitesVirtualPageTest.yml',
|
||||
];
|
||||
);
|
||||
|
||||
protected $illegalExtensions = array(
|
||||
'SiteTree' => array('Translatable')
|
||||
);
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
@ -24,8 +30,8 @@ class SubsitesVirtualPageTest extends BaseSubsiteTest
|
||||
TestAssetStore::activate('SubsitesVirtualPageTest');
|
||||
|
||||
// Create a test files for each of the fixture references
|
||||
$file = $this->objFromFixture('SilverStripe\\Assets\\File', 'file1');
|
||||
$page = $this->objFromFixture('SilverStripe\\CMS\\Model\\SiteTree', 'page1');
|
||||
$file = $this->objFromFixture(File::class, 'file1');
|
||||
$page = $this->objFromFixture(SiteTree::class, 'page1');
|
||||
$fromPath = __DIR__ . '/testscript-test-file.pdf';
|
||||
$destPath = TestAssetStore::getLocalPath($file);
|
||||
Filesystem::makeFolder(dirname($destPath));
|
||||
@ -65,13 +71,14 @@ class SubsitesVirtualPageTest extends BaseSubsiteTest
|
||||
$this->assertEquals($svp->Title, $linky->Title);
|
||||
}
|
||||
|
||||
function testFileLinkRewritingOnVirtualPages()
|
||||
public function testFileLinkRewritingOnVirtualPages()
|
||||
{
|
||||
// File setup
|
||||
$this->logInWithPermission('ADMIN');
|
||||
touch(Director::baseFolder() . '/assets/testscript-test-file.pdf');
|
||||
|
||||
// Publish the source page
|
||||
$page = $this->objFromFixture('SilverStripe\\CMS\\Model\\SiteTree', 'page1');
|
||||
$page = $this->objFromFixture(SiteTree::class, 'page1');
|
||||
$this->assertTrue($page->doPublish());
|
||||
|
||||
// Create a virtual page from it, and publish that
|
||||
@ -81,7 +88,7 @@ class SubsitesVirtualPageTest extends BaseSubsiteTest
|
||||
$svp->doPublish();
|
||||
|
||||
// Rename the file
|
||||
$file = $this->objFromFixture('SilverStripe\\Assets\\File', 'file1');
|
||||
$file = $this->objFromFixture(File::class, 'file1');
|
||||
$file->Name = 'renamed-test-file.pdf';
|
||||
$file->write();
|
||||
|
||||
@ -92,7 +99,7 @@ class SubsitesVirtualPageTest extends BaseSubsiteTest
|
||||
DB::query("SELECT \"Content\" FROM \"SiteTree_Live\" WHERE \"ID\" = $svp->ID")->value());
|
||||
}
|
||||
|
||||
function testSubsiteVirtualPagesArentInappropriatelyPublished()
|
||||
public function testSubsiteVirtualPagesArentInappropriatelyPublished()
|
||||
{
|
||||
// Fixture
|
||||
$p = new Page();
|
||||
@ -151,7 +158,7 @@ class SubsitesVirtualPageTest extends BaseSubsiteTest
|
||||
* is in a different subsite to the page you are editing and republishing,
|
||||
* otherwise the test will pass falsely due to current subsite ID being the same.
|
||||
*/
|
||||
function testPublishedSubsiteVirtualPagesUpdateIfTargetPageUpdates()
|
||||
public function testPublishedSubsiteVirtualPagesUpdateIfTargetPageUpdates()
|
||||
{
|
||||
// create page
|
||||
$p = new Page();
|
||||
@ -193,9 +200,9 @@ class SubsitesVirtualPageTest extends BaseSubsiteTest
|
||||
$this->assertEquals($svpdb->Title, $p->Title);
|
||||
}
|
||||
|
||||
function testUnpublishingParentPageUnpublishesSubsiteVirtualPages()
|
||||
public function testUnpublishingParentPageUnpublishesSubsiteVirtualPages()
|
||||
{
|
||||
Config::modify()->set('StaticPublisher', 'disable_realtime', true);
|
||||
Config::inst()->update('StaticPublisher', 'disable_realtime', true);
|
||||
|
||||
// Go to main site, get parent page
|
||||
$subsite = $this->objFromFixture(Subsite::class, 'main');
|
||||
@ -224,14 +231,12 @@ class SubsitesVirtualPageTest extends BaseSubsiteTest
|
||||
$page->doUnpublish();
|
||||
|
||||
Subsite::changeSubsite($vp1->SubsiteID);
|
||||
$onLive = Versioned::get_one_by_stage(SubsitesVirtualPage::class, 'Live',
|
||||
"\"SiteTree_Live\".\"ID\" = " . $vp1->ID);
|
||||
$onLive = Versioned::get_one_by_stage('SubsitesVirtualPage', 'Live', "\"SiteTree_Live\".\"ID\" = ".$vp1->ID);
|
||||
$this->assertNull($onLive, 'SVP has been removed from live');
|
||||
|
||||
$subsite = $this->objFromFixture(Subsite::class, 'subsite2');
|
||||
Subsite::changeSubsite($vp2->SubsiteID);
|
||||
$onLive = Versioned::get_one_by_stage(SubsitesVirtualPage::class, 'Live',
|
||||
"\"SiteTree_Live\".\"ID\" = " . $vp2->ID);
|
||||
$onLive = Versioned::get_one_by_stage('SubsitesVirtualPage', 'Live', "\"SiteTree_Live\".\"ID\" = ".$vp2->ID);
|
||||
$this->assertNull($onLive, 'SVP has been removed from live');
|
||||
}
|
||||
|
||||
@ -239,7 +244,7 @@ class SubsitesVirtualPageTest extends BaseSubsiteTest
|
||||
* Similar to {@link SiteTreeSubsitesTest->testTwoPagesWithSameURLOnDifferentSubsites()}
|
||||
* and {@link SiteTreeSubsitesTest->testPagesInDifferentSubsitesCanShareURLSegment()}.
|
||||
*/
|
||||
function testSubsiteVirtualPageCanHaveSameUrlsegmentAsOtherSubsite()
|
||||
public function testSubsiteVirtualPageCanHaveSameUrlsegmentAsOtherSubsite()
|
||||
{
|
||||
Subsite::$write_hostmap = false;
|
||||
$subsite1 = $this->objFromFixture(Subsite::class, 'subsite1');
|
||||
@ -274,16 +279,25 @@ class SubsitesVirtualPageTest extends BaseSubsiteTest
|
||||
$subsite2Vp->URLSegment,
|
||||
$subsite1Page->URLSegment,
|
||||
"Does allow explicit URLSegment overrides when only existing in a different subsite"
|
||||
);
|
||||
|
||||
// When changing subsites and re-saving this page, it doesn't trigger a change
|
||||
Subsite::changeSubsite($subsite1->ID);
|
||||
$subsite1Page->write();
|
||||
$subsite2Vp->write();
|
||||
$this->assertEquals(
|
||||
$subsite2Vp->URLSegment,
|
||||
$subsite1Page->URLSegment,
|
||||
"SubsiteVirtualPage doesn't change urls when being written in another subsite"
|
||||
);
|
||||
}
|
||||
|
||||
function fixVersionNumberCache($page)
|
||||
public function fixVersionNumberCache($page)
|
||||
{
|
||||
$pages = func_get_args();
|
||||
foreach ($pages as $p) {
|
||||
Versioned::prepopulate_versionnumber_cache('SilverStripe\\CMS\\Model\\SiteTree', 'Stage', [$p->ID]);
|
||||
Versioned::prepopulate_versionnumber_cache('SilverStripe\\CMS\\Model\\SiteTree', 'Live', [$p->ID]);
|
||||
Versioned::prepopulate_versionnumber_cache(SiteTree::class, 'Stage', array($p->ID));
|
||||
Versioned::prepopulate_versionnumber_cache(SiteTree::class, 'Live', array($p->ID));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
74
tests/WildcardDomainFieldTest.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
|
||||
/**
|
||||
* Tests {@see WildcardDomainField}
|
||||
*/
|
||||
class WildcardDomainFieldTest extends SapphireTest {
|
||||
|
||||
/**
|
||||
* Check that valid domains are accepted
|
||||
*
|
||||
* @dataProvider validDomains
|
||||
*/
|
||||
public function testValidDomains($domain) {
|
||||
$field = new WildcardDomainField('DomainField');
|
||||
$this->assertTrue($field->checkHostname($domain), "Validate that {$domain} is a valid domain name");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that valid domains are accepted
|
||||
*
|
||||
* @dataProvider invalidDomains
|
||||
*/
|
||||
public function testInvalidDomains($domain) {
|
||||
$field = new WildcardDomainField('DomainField');
|
||||
$this->assertFalse($field->checkHostname($domain), "Validate that {$domain} is an invalid domain name");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that valid domains are accepted
|
||||
*
|
||||
* @dataProvider validWildcards
|
||||
*/
|
||||
public function testValidWildcards($domain) {
|
||||
$field = new WildcardDomainField('DomainField');
|
||||
$this->assertTrue($field->checkHostname($domain), "Validate that {$domain} is a valid domain wildcard");
|
||||
}
|
||||
|
||||
public function validDomains() {
|
||||
return array(
|
||||
array('www.mysite.com'),
|
||||
array('domain7'),
|
||||
array('mysite.co.n-z'),
|
||||
array('subdomain.my-site.com'),
|
||||
array('subdomain.mysite')
|
||||
);
|
||||
}
|
||||
|
||||
public function invalidDomains() {
|
||||
return array(
|
||||
array('-mysite'),
|
||||
array('.mysite'),
|
||||
array('mys..ite'),
|
||||
array('mysite-'),
|
||||
array('mysite.'),
|
||||
array('-mysite.*'),
|
||||
array('.mysite.*'),
|
||||
array('mys..ite.*'),
|
||||
array('*.mysite-'),
|
||||
array('*.mysite.')
|
||||
);
|
||||
}
|
||||
|
||||
public function validWildcards() {
|
||||
return array(
|
||||
array('*.mysite.com'),
|
||||
array('mys*ite.com'),
|
||||
array('*.my-site.*'),
|
||||
array('*')
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -6,15 +6,20 @@ if (!class_exists('SilverStripe\BehatExtension\Context\SilverStripeContext')) {
|
||||
return;
|
||||
}
|
||||
|
||||
use SilverStripe\BehatExtension\Context\BasicContext;
|
||||
use SilverStripe\BehatExtension\Context\FixtureContext;
|
||||
use SilverStripe\BehatExtension\Context\LoginContext;
|
||||
use SilverStripe\BehatExtension\Context\SilverStripeContext;
|
||||
use SilverStripe\BehatExtension\Context\BasicContext;
|
||||
use SilverStripe\BehatExtension\Context\LoginContext;
|
||||
use SilverStripe\BehatExtension\Context\FixtureContext;
|
||||
use SilverStripe\Framework\Test\Behaviour\CmsFormsContext;
|
||||
use SilverStripe\Framework\Test\Behaviour\CmsUiContext;l
|
||||
use SilverStripe\Cms\Test\Behaviour;
|
||||
use SilverStripe\CMS\Model\SiteTree;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Framework\Test\Behaviour\CmsFormsContext;
|
||||
use SilverStripe\Framework\Test\Behaviour\CmsUiContext;
|
||||
|
||||
use SilverStripe\Dev\BehatFixtureFactory;
|
||||
use SilverStripe\Dev\FixtureBlueprint;
|
||||
use SilverStripe\Dev\FixtureFactory;
|
||||
use SilverStripe\Security\Member;
|
||||
|
||||
// PHPUnit
|
||||
require_once 'PHPUnit/Autoload.php';
|
||||
@ -27,8 +32,7 @@ require_once 'PHPUnit/Framework/Assert/Functions.php';
|
||||
* Uses subcontexts to extend functionality.
|
||||
*/
|
||||
class FeatureContext extends SilverStripeContext
|
||||
{
|
||||
|
||||
{
|
||||
/**
|
||||
* @var FixtureFactory
|
||||
*/
|
||||
@ -55,17 +59,17 @@ class FeatureContext extends SilverStripeContext
|
||||
|
||||
// Use blueprints to set user name from identifier
|
||||
$factory = $fixtureContext->getFixtureFactory();
|
||||
$blueprint = Injector::inst()->create('SilverStripe\\Dev\\FixtureBlueprint', 'SilverStripe\\Security\\Member');
|
||||
$blueprint = Injector::inst()->create(FixtureBlueprint::class, Member::class);
|
||||
$blueprint->addCallback('beforeCreate', function ($identifier, &$data, &$fixtures) {
|
||||
if (!isset($data['FirstName'])) {
|
||||
$data['FirstName'] = $identifier;
|
||||
}
|
||||
});
|
||||
$factory->define('SilverStripe\\Security\\Member', $blueprint);
|
||||
$factory->define(Member::class, $blueprint);
|
||||
|
||||
// Auto-publish pages
|
||||
foreach (ClassInfo::subclassesFor('SilverStripe\\CMS\\Model\\SiteTree') as $id => $class) {
|
||||
$blueprint = Injector::inst()->create('SilverStripe\\Dev\\FixtureBlueprint', $class);
|
||||
foreach (ClassInfo::subclassesFor(SiteTree::class) as $id => $class) {
|
||||
$blueprint = Injector::inst()->create(FixtureBlueprint::class, $class);
|
||||
$blueprint->addCallback('afterCreate', function ($obj, $identifier, &$data, &$fixtures) {
|
||||
$obj->publish('Stage', 'Live');
|
||||
});
|
||||
@ -88,7 +92,7 @@ class FeatureContext extends SilverStripeContext
|
||||
public function getFixtureFactory()
|
||||
{
|
||||
if (!$this->fixtureFactory) {
|
||||
$this->fixtureFactory = Injector::inst()->create('SilverStripe\\Dev\\BehatFixtureFactory');
|
||||
$this->fixtureFactory = Injector::inst()->create(BehatFixtureFactory::class);
|
||||
}
|
||||
|
||||
return $this->fixtureFactory;
|
||||
|