Merge branch 'master' into fix-ss-4-master

This commit is contained in:
Garion Herman 2017-08-28 21:52:32 +12:00
commit 9a289a2e17
28 changed files with 322 additions and 206 deletions

View File

@ -1,4 +1,4 @@
# See https://github.com/silverstripe-labs/silverstripe-travis-support for setup details # See https://github.com/silverstripe/silverstripe-travis-support for setup details
language: php language: php
@ -11,7 +11,7 @@ php:
env: env:
global: global:
- CORE_RELEASE=master - CORE_RELEASE=4
matrix: matrix:
- DB=MYSQL - DB=MYSQL
- DB=PGSQL - DB=PGSQL
@ -24,13 +24,13 @@ matrix:
before_script: before_script:
- composer self-update || true - composer self-update || true
- phpenv rehash - phpenv rehash
- git clone git://github.com/silverstripe-labs/silverstripe-travis-support.git ~/travis-support - git clone git://github.com/silverstripe/silverstripe-travis-support.git ~/travis-support
- "if [ \"$BEHAT_TEST\" = \"\" ]; then php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss; fi" - "if [ \"$BEHAT_TEST\" = \"\" ]; then php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss; fi"
- "if [ \"$BEHAT_TEST\" = \"1\" ]; then php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss --require silverstripe/behat-extension; fi" - "if [ \"$BEHAT_TEST\" = \"1\" ]; then php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss --require silverstripe/behat-extension; fi"
- cd ~/builds/ss - cd ~/builds/ss
- php ~/travis-support/travis_setup_selenium.php --if-env BEHAT_TEST - php ~/travis-support/travis_setup_selenium.php --if-env BEHAT_TEST
- php ~/travis-support/travis_setup_php54_webserver.php --if-env BEHAT_TEST - php ~/travis-support/travis_setup_php54_webserver.php --if-env BEHAT_TEST
script: script:
- "if [ \"$BEHAT_TEST\" = \"\" ]; then vendor/bin/phpunit subsites/tests; fi" - "if [ \"$BEHAT_TEST\" = \"\" ]; then vendor/bin/phpunit subsites/tests; fi"
- "if [ \"$BEHAT_TEST\" = \"1\" ]; then vendor/bin/behat @subsites; fi" - "if [ \"$BEHAT_TEST\" = \"1\" ]; then vendor/bin/behat @subsites; fi"

View File

@ -4,4 +4,3 @@ use SilverStripe\Reports\Report;
use SilverStripe\Subsites\Reports\SubsiteReportWrapper; use SilverStripe\Subsites\Reports\SubsiteReportWrapper;
Report::add_excluded_reports(SubsiteReportWrapper::class); Report::add_excluded_reports(SubsiteReportWrapper::class);

View File

@ -6,6 +6,6 @@ After:
SilverStripe\AssetAdmin\Controller\AssetAdmin: SilverStripe\AssetAdmin\Controller\AssetAdmin:
treats_subsite_0_as_global: true treats_subsite_0_as_global: true
SilverStripe\Control\Director: Director:
rules: rules:
SubsiteXHRController: SilverStripe\Subsites\Controller\SubsiteXHRController SubsiteXHRController: SilverStripe\Subsites\Controller\SubsiteXHRController

View File

@ -13,5 +13,4 @@ class CMSPageAddControllerExtension extends Extension
{ {
$fields->push(new HiddenField('SubsiteID', 'SubsiteID', Subsite::currentSubsiteID())); $fields->push(new HiddenField('SubsiteID', 'SubsiteID', Subsite::currentSubsiteID()));
} }
} }

View File

@ -5,27 +5,24 @@ namespace SilverStripe\Subsites\Extensions;
use SilverStripe\Core\Extension; use SilverStripe\Core\Extension;
use SilverStripe\Subsites\Model\Subsite; use SilverStripe\Subsites\Model\Subsite;
use SilverStripe\View\SSViewer; use SilverStripe\View\SSViewer;
/** /**
* @package subsites * @package subsites
*/ */
class ControllerSubsites extends Extension class ControllerSubsites extends Extension
{ {
public function controllerAugmentInit() public function controllerAugmentInit()
{ {
$subsite = $this->CurrentSubsite(); if ($subsite = Subsite::currentSubsite()) {
if ($subsite && $theme = $subsite->Theme) { if ($theme = $subsite->Theme) {
SSViewer::set_themes([$theme, SSViewer::DEFAULT_THEME]); SSViewer::set_themes([$theme, SSViewer::DEFAULT_THEME]);
}
} }
} }
/**
* @return Subsite
*/
public function CurrentSubsite() public function CurrentSubsite()
{ {
return Subsite::currentSubsite(); if ($subsite = Subsite::currentSubsite()) {
return $subsite;
}
} }
} }

View File

@ -10,7 +10,6 @@ use SilverStripe\Subsites\Model\Subsite;
class ErrorPageSubsite extends DataExtension class ErrorPageSubsite extends DataExtension
{ {
/** /**
* Alter file path to generated a static (static) error page file to handle error page template on different sub-sites * Alter file path to generated a static (static) error page file to handle error page template on different sub-sites
* *
@ -53,5 +52,4 @@ class ErrorPageSubsite extends DataExtension
return $filepath; return $filepath;
} }
} }

View File

@ -158,5 +158,4 @@ class FileSubsites extends DataExtension
{ {
return 'subsite-' . Subsite::currentSubsiteID(); return 'subsite-' . Subsite::currentSubsiteID();
} }
} }

View File

@ -2,7 +2,6 @@
namespace SilverStripe\Subsites\Extensions; namespace SilverStripe\Subsites\Extensions;
use SilverStripe\Control\Cookie; use SilverStripe\Control\Cookie;
use SilverStripe\Core\Convert; use SilverStripe\Core\Convert;
use SilverStripe\Forms\CheckboxSetField; use SilverStripe\Forms\CheckboxSetField;
@ -17,7 +16,6 @@ use SilverStripe\Security\Group;
use SilverStripe\Security\PermissionProvider; use SilverStripe\Security\PermissionProvider;
use SilverStripe\Subsites\Model\Subsite; use SilverStripe\Subsites\Model\Subsite;
/** /**
* Extension for the Group object to add subsites support * Extension for the Group object to add subsites support
* *
@ -151,6 +149,7 @@ class GroupSubsites extends DataExtension implements PermissionProvider
if (!$query->filtersOnID()) { if (!$query->filtersOnID()) {
/*if($context = DataObject::context_obj()) $subsiteID = (int)$context->SubsiteID; /*if($context = DataObject::context_obj()) $subsiteID = (int)$context->SubsiteID;
else */ else */
$subsiteID = (int)Subsite::currentSubsiteID(); $subsiteID = (int)Subsite::currentSubsiteID();
@ -169,9 +168,9 @@ class GroupSubsites extends DataExtension implements PermissionProvider
if (!$hasGroupSubsites) { if (!$hasGroupSubsites) {
if ($subsiteID) { if ($subsiteID) {
$query->addLeftJoin('Group_Subsites', "\"Group_Subsites\".\"GroupID\" $query->addLeftJoin('Group_Subsites', "\"Group_Subsites\".\"GroupID\"
= \"Group\".\"ID\" AND \"Group_Subsites\".\"SubsiteID\" = $subsiteID"); = \"Group\".\"ID\" AND \"Group_Subsites\".\"SubsiteID\" = $subsiteID");
$query->addWhere('("Group_Subsites"."SubsiteID" IS NOT NULL OR $query->addWhere('("Group_Subsites"."SubsiteID" IS NOT NULL OR
"Group"."AccessAllSubsites" = 1)'); "Group"."AccessAllSubsites" = 1)');
} else { } else {
$query->addWhere('"Group"."AccessAllSubsites" = 1'); $query->addWhere('"Group"."AccessAllSubsites" = 1');
} }
@ -227,5 +226,4 @@ class GroupSubsites extends DataExtension implements PermissionProvider
] ]
]; ];
} }
} }

View File

@ -27,7 +27,6 @@ use SilverStripe\View\Requirements;
*/ */
class LeftAndMainSubsites extends Extension class LeftAndMainSubsites extends Extension
{ {
private static $allowed_actions = ['CopyToSubsite']; private static $allowed_actions = ['CopyToSubsite'];
/** /**
@ -219,12 +218,10 @@ class LeftAndMainSubsites extends Extension
// Admin can access everything, no point in checking. // Admin can access everything, no point in checking.
$member = Member::currentUser(); $member = Member::currentUser();
if ($member && if ($member &&
( (
Permission::checkMember($member, 'ADMIN') || // 'Full administrative rights' in SecurityAdmin Permission::checkMember($member, 'ADMIN') || // 'Full administrative rights' in SecurityAdmin
Permission::checkMember($member, Permission::checkMember($member, 'CMS_ACCESS_LeftAndMain') // 'Access to all CMS sections' in SecurityAdmin
'CMS_ACCESS_LeftAndMain') // 'Access to all CMS sections' in SecurityAdmin )) {
)
) {
return true; return true;
} }
@ -348,14 +345,15 @@ class LeftAndMainSubsites extends Extension
} }
} }
/** /**
* @param array $data * @param array $data
*/ * @param Form $form
public function copytosubsite($data) */
public function copytosubsite($data, $form)
{ {
$page = SiteTree::get()->byID($data['ID']); $page = DataObject::get_by_id('SiteTree', $data['ID']);
$subsite = Subsite::get()->byID($data['CopyToSubsiteID']); $subsite = DataObject::get_by_id('Subsite', $data['CopyToSubsiteID']);
$includeChildren = isset($data['CopyToSubsiteWithChildren']) ? $data['CopyToSubsiteWithChildren'] : false; $includeChildren = (isset($data['CopyToSubsiteWithChildren'])) ? $data['CopyToSubsiteWithChildren'] : false;
$newPage = $page->duplicateToSubsite($subsite->ID, $includeChildren); $newPage = $page->duplicateToSubsite($subsite->ID, $includeChildren);
$response = $this->owner->getResponse(); $response = $this->owner->getResponse();
@ -366,5 +364,4 @@ class LeftAndMainSubsites extends Extension
$newPage->ID $newPage->ID
)); ));
} }
} }

View File

@ -2,7 +2,6 @@
namespace SilverStripe\Subsites\Extensions; namespace SilverStripe\Subsites\Extensions;
use SilverStripe\Forms\FieldList; use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\HiddenField; use SilverStripe\Forms\HiddenField;
use SilverStripe\ORM\DataExtension; use SilverStripe\ORM\DataExtension;
@ -11,7 +10,6 @@ use SilverStripe\ORM\Queries\SQLSelect;
use SilverStripe\SiteConfig\SiteConfig; use SilverStripe\SiteConfig\SiteConfig;
use SilverStripe\Subsites\Model\Subsite; use SilverStripe\Subsites\Model\Subsite;
/** /**
* Extension for the SiteConfig object to add subsites support * Extension for the SiteConfig object to add subsites support
*/ */
@ -73,5 +71,4 @@ class SiteConfigSubsites extends DataExtension
{ {
$fields->push(new HiddenField('SubsiteID', 'SubsiteID', Subsite::currentSubsiteID())); $fields->push(new HiddenField('SubsiteID', 'SubsiteID', Subsite::currentSubsiteID()));
} }
} }

View File

@ -2,7 +2,6 @@
namespace SilverStripe\Subsites\Extensions; namespace SilverStripe\Subsites\Extensions;
use SilverStripe\CMS\Model\SiteTree; use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Control\Controller; use SilverStripe\Control\Controller;
use SilverStripe\Control\Director; use SilverStripe\Control\Director;
@ -23,13 +22,11 @@ use SilverStripe\SiteConfig\SiteConfig;
use SilverStripe\Subsites\Model\Subsite; use SilverStripe\Subsites\Model\Subsite;
use SilverStripe\View\SSViewer; use SilverStripe\View\SSViewer;
/** /**
* Extension for the SiteTree object to add subsites support * Extension for the SiteTree object to add subsites support
*/ */
class SiteTreeSubsites extends DataExtension class SiteTreeSubsites extends DataExtension
{ {
private static $has_one = [ private static $has_one = [
'Subsite' => Subsite::class, // The subsite that this page belongs to 'Subsite' => Subsite::class, // The subsite that this page belongs to
]; ];
@ -150,6 +147,86 @@ 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.
*/
public function duplicateToSubsitePrep($subsiteID)
{
if (is_object($subsiteID)) {
$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;
$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;
}
}
// MasterPageID is here for legacy purposes, to satisfy the subsites_relatedpages module
$clone->MasterPageID = $this->owner->ID;
return $clone;
}
/**
* 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 SiteConfig * @return SiteConfig
*/ */
@ -242,52 +319,6 @@ class SiteTreeSubsites extends DataExtension
return $this->canEdit($member); return $this->canEdit($member);
} }
/**
* 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 duplicateToSubsite($subsiteID = null, $includeChildren = false, $parentID = 0)
{
if ($subsiteID instanceof Subsite) {
$subsiteID = $subsiteID->ID;
}
$oldSubsite = Subsite::currentSubsiteID();
if ($subsiteID) {
Subsite::changeSubsite($subsiteID);
} else {
$subsiteID = $oldSubsite;
}
$page = $this->owner->duplicate(false);
$page->CheckedPublicationDifferences = $page->AddedToStage = true;
$subsiteID = ($subsiteID ? $subsiteID : $oldSubsite);
$page->SubsiteID = $subsiteID;
$page->ParentID = $parentID;
// MasterPageID is here for legacy purposes, to satisfy the subsites_relatedpages module
$page->MasterPageID = $this->owner->ID;
$page->write();
Subsite::changeSubsite($oldSubsite);
if ($includeChildren) {
foreach ($this->owner->AllChildren() as $child) {
$child->duplicateToSubsite($subsiteID, $includeChildren, $page->ID);
}
}
return $page;
}
/** /**
* Called by ContentController::init(); * Called by ContentController::init();
* @param $controller * @param $controller
@ -431,5 +462,4 @@ class SiteTreeSubsites extends DataExtension
} }
} }
} }
} }

View File

@ -18,10 +18,8 @@ use SilverStripe\Core\Extension;
class SubsiteMenuExtension extends Extension class SubsiteMenuExtension extends Extension
{ {
public function subsiteCMSShowInMenu() public function subsiteCMSShowInMenu()
{ {
return true; return true;
} }
} }

View File

@ -6,7 +6,5 @@ use SilverStripe\Forms\GridField\GridFieldDetailForm;
class GridFieldSubsiteDetailForm extends GridFieldDetailForm class GridFieldSubsiteDetailForm extends GridFieldDetailForm
{ {
protected $itemRequestClass = 'GridFieldSubsiteDetailForm_ItemRequest'; protected $itemRequestClass = 'GridFieldSubsiteDetailForm_ItemRequest';
} }

View File

@ -3,6 +3,7 @@
namespace SilverStripe\Subsites\Forms; namespace SilverStripe\Subsites\Forms;
use SilverStripe\Forms\DropdownField; use SilverStripe\Forms\DropdownField;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\GridField\GridFieldDetailForm_ItemRequest; use SilverStripe\Forms\GridField\GridFieldDetailForm_ItemRequest;
use SilverStripe\Subsites\Model\Subsite; use SilverStripe\Subsites\Model\Subsite;

View File

@ -3,6 +3,7 @@
namespace SilverStripe\Subsites\Forms; namespace SilverStripe\Subsites\Forms;
use SilverStripe\Control\Controller;
use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\Session; use SilverStripe\Control\Session;
use SilverStripe\Forms\TreeDropdownField; use SilverStripe\Forms\TreeDropdownField;
@ -46,12 +47,14 @@ class SubsitesTreeDropdownField extends TreeDropdownField
public function tree(HTTPRequest $request) public function tree(HTTPRequest $request)
{ {
$oldSubsiteID = Session::get('SubsiteID'); $session = Controller::curr()->getRequest()->getSession();
Session::set('SubsiteID', $this->subsiteID);
$oldSubsiteID = $session->get('SubsiteID');
$session->set('SubsiteID', $this->subsiteID);
$results = parent::tree($request); $results = parent::tree($request);
Session::set('SubsiteID', $oldSubsiteID); $session->set('SubsiteID', $oldSubsiteID);
return $results; return $results;
} }

View File

@ -1,15 +1,12 @@
<?php <?php
namespace SilverStripe\Subsites\Forms; namespace SilverStripe\Subsites\Forms;
use SilverStripe\Forms\TextField; use SilverStripe\Forms\TextField;
/** /**
* A text field that accepts only valid domain names, but allows the wildcard (*) character * A text field that accepts only valid domain names, but allows the wildcard (*) character
*/ */
class WildcardDomainField extends TextField class WildcardDomainField extends TextField
{ {
/** /**
* Validate this field as a valid hostname * Validate this field as a valid hostname
* *
@ -27,7 +24,6 @@ class WildcardDomainField extends TextField
_t('DomainNameField.INVALID_DOMAIN', 'Invalid domain name'), _t('DomainNameField.INVALID_DOMAIN', 'Invalid domain name'),
'validation' 'validation'
); );
return false; return false;
} }
@ -46,5 +42,4 @@ class WildcardDomainField extends TextField
{ {
return 'text wildcarddomain'; return 'text wildcarddomain';
} }
} }

View File

@ -505,7 +505,7 @@ class Subsite extends DataObject
} }
$data = "<?php \n"; $data = "<?php \n";
$data .= '// Generated by Subsite::writeHostMap() on ' . date('d/M/y') . "\n"; $data .= "// Generated by Subsite::writeHostMap() on " . date('d/M/y') . "\n";
$data .= '$subsiteHostmap = ' . var_export($hostmap, true) . ';'; $data .= '$subsiteHostmap = ' . var_export($hostmap, true) . ';';
if (is_writable(dirname($file)) || is_writable($file)) { if (is_writable(dirname($file)) || is_writable($file)) {
@ -555,7 +555,7 @@ class Subsite extends DataObject
INNER JOIN \"Group\" ON \"Group\".\"ID\" = \"Permission\".\"GroupID\" AND \"Group\".\"AccessAllSubsites\" = 1 INNER JOIN \"Group\" ON \"Group\".\"ID\" = \"Permission\".\"GroupID\" AND \"Group\".\"AccessAllSubsites\" = 1
INNER JOIN \"Group_Members\" ON \"Group_Members\".\"GroupID\" = \"Permission\".\"GroupID\" INNER JOIN \"Group_Members\" ON \"Group_Members\".\"GroupID\" = \"Permission\".\"GroupID\"
WHERE \"Permission\".\"Code\" IN ('$SQL_perms') WHERE \"Permission\".\"Code\" IN ('$SQL_perms')
AND \"MemberID\" = {$memberID} AND \"Group_Members\".\"MemberID\" = {$memberID}
")->value(); ")->value();
// Count this user's groups which have a role that can access the main site // Count this user's groups which have a role that can access the main site
@ -568,7 +568,7 @@ class Subsite extends DataObject
INNER JOIN \"PermissionRoleCode\" ON \"PermissionRole\".\"ID\"=\"PermissionRoleCode\".\"RoleID\" INNER JOIN \"PermissionRoleCode\" ON \"PermissionRole\".\"ID\"=\"PermissionRoleCode\".\"RoleID\"
WHERE \"PermissionRoleCode\".\"Code\" IN ('$SQL_perms') WHERE \"PermissionRoleCode\".\"Code\" IN ('$SQL_perms')
AND \"Group\".\"AccessAllSubsites\" = 1 AND \"Group\".\"AccessAllSubsites\" = 1
AND \"MemberID\" = {$memberID} AND \"Group_Members\".\"MemberID\" = {$memberID}
")->value(); ")->value();
// There has to be at least one that allows access. // There has to be at least one that allows access.
@ -678,40 +678,44 @@ class Subsite extends DataObject
new Tab( new Tab(
'Configuration', 'Configuration',
_t('Subsite.TabTitleConfig', 'Configuration'), _t('Subsite.TabTitleConfig', 'Configuration'),
new HeaderField('ConfigForSubsiteHeaderField', 'Subsite Configuration'), HeaderField::create('ConfigForSubsiteHeaderField', 'Subsite Configuration'),
new TextField('Title', $this->fieldLabel('Title'), $this->Title), TextField::create('Title', $this->fieldLabel('Title'), $this->Title),
new HeaderField( HeaderField::create(
'DomainsForSubsiteHeaderField', 'DomainsForSubsiteHeaderField',
_t('Subsite.DomainsHeadline', 'Domains for this subsite') _t('Subsite.DomainsHeadline', 'Domains for this subsite')
), ),
$domainTable, $domainTable,
$languageSelector, $languageSelector,
// new TextField('RedirectURL', 'Redirect to URL', $this->RedirectURL), // new TextField('RedirectURL', 'Redirect to URL', $this->RedirectURL),
new CheckboxField('DefaultSite', $this->fieldLabel('DefaultSite'), $this->DefaultSite), CheckboxField::create('DefaultSite', $this->fieldLabel('DefaultSite'), $this->DefaultSite),
new CheckboxField('IsPublic', $this->fieldLabel('IsPublic'), $this->IsPublic), CheckboxField::create('IsPublic', $this->fieldLabel('IsPublic'), $this->IsPublic),
new DropdownField('Theme', $this->fieldLabel('Theme'), $this->allowedThemes(), $this->Theme), LiteralField::create(
new LiteralField(
'PageTypeBlacklistToggle', 'PageTypeBlacklistToggle',
sprintf( sprintf(
'<div class="field"><a href="#" id="PageTypeBlacklistToggle">%s</a></div>', '<div class="field"><a href="#" id="PageTypeBlacklistToggle">%s</a></div>',
_t('Subsite.PageTypeBlacklistField', 'Disallow page types?') _t('Subsite.PageTypeBlacklistField', 'Disallow page types?')
) )
), ),
new CheckboxSetField( CheckboxSetField::create(
'PageTypeBlacklist', 'PageTypeBlacklist',
false, false,
$pageTypeMap $pageTypeMap
) )
) )
), ),
new HiddenField('ID', '', $this->ID), HiddenField::create('ID', '', $this->ID),
new HiddenField('IsSubsite', '', 1) HiddenField::create('IsSubsite', '', 1)
); );
// If there are any themes available, add the dropdown
$themes = $this->allowedThemes();
if (!empty($themes)) {
$fields->addFieldToTab('Root.Configuration',
DropdownField::create('Theme', $this->fieldLabel('Theme'), $this->allowedThemes(), $this->Theme)->setEmptyString(_t('Subsite.ThemeFieldEmptyString', '')), 'PageTypeBlacklistToggle');
}
$subsiteTabs->addExtraClass('subsite-model'); $subsiteTabs->addExtraClass('subsite-model');
$this->extend('updateCMSFields', $fields); $this->extend('updateCMSFields', $fields);

View File

@ -102,7 +102,7 @@ class SubsiteDomain extends DataObject
/** /**
* *
* @return \FieldList * @return FieldList
*/ */
public function getCMSFields() public function getCMSFields()
{ {
@ -122,11 +122,13 @@ class SubsiteDomain extends DataObject
'SubsiteDomain.PROTOCOL_DESCRIPTION', 'SubsiteDomain.PROTOCOL_DESCRIPTION',
'When generating links to this subsite, use the selected protocol. <br />' . 'When generating links to this subsite, use the selected protocol. <br />' .
'Selecting \'Automatic\' means subsite links will default to the current protocol.' 'Selecting \'Automatic\' means subsite links will default to the current protocol.'
)), CheckboxField::create('IsPrimary', $this->fieldLabel('IsPrimary')) )),
->setDescription(_t( CheckboxField::create('IsPrimary', $this->fieldLabel('IsPrimary'))
'SubsiteDomain.PROTOCOL_DESCRIPTION', ->setDescription(_t(
'Mark this as the default domain for this subsite' 'SubsiteDomain.PROTOCOL_DESCRIPTION',
))); 'Mark this as the default domain for this subsite'
))
);
$this->extend('updateCMSFields', $fields); $this->extend('updateCMSFields', $fields);
return $fields; return $fields;
@ -147,15 +149,6 @@ class SubsiteDomain extends DataObject
return $labels; return $labels;
} }
/**
* Before writing the Subsite Domain, strip out any HTML the user has entered.
* @return void
*/
public function onBeforeWrite()
{
parent::onBeforeWrite();
}
/** /**
* Get the link to this subsite * Get the link to this subsite
* *
@ -202,8 +195,8 @@ class SubsiteDomain extends DataObject
$domain = preg_replace('/\.\*$/', ".{$currentHost}", $this->Domain); $domain = preg_replace('/\.\*$/', ".{$currentHost}", $this->Domain);
// Default to "subsite." prefix for first wildcard // Default to "subsite." prefix for first wildcard
// TODO Whats the significance of "subsite" inthiscontext?! // TODO Whats the significance of "subsite" in this context?!
$domain = preg_replace('/^\*\./', 'subsite.', $domain); $domain = preg_replace('/^\*\./', "subsite.", $domain);
// *Only* removes "intermediate" subdomains, so 'subdomain.www.domain.com' becomes 'subdomain.domain.com' // *Only* removes "intermediate" subdomains, so 'subdomain.www.domain.com' becomes 'subdomain.domain.com'
$domain = str_replace('.www.', '.', $domain); $domain = str_replace('.www.', '.', $domain);
@ -230,6 +223,7 @@ class SubsiteDomain extends DataObject
{ {
return Controller::join_links( return Controller::join_links(
$this->getAbsoluteLink(), $this->getAbsoluteLink(),
Director::baseURL()); Director::baseURL()
);
} }
} }

View File

@ -4,6 +4,7 @@ namespace SilverStripe\Subsites\Tasks;
use InvalidArgumentException; use InvalidArgumentException;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Dev\BuildTask; use SilverStripe\Dev\BuildTask;
use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DataObject;
use SilverStripe\Subsites\Model\Subsite; use SilverStripe\Subsites\Model\Subsite;
@ -24,7 +25,6 @@ use SilverStripe\Versioned\Versioned;
class SubsiteCopyPagesTask extends BuildTask class SubsiteCopyPagesTask extends BuildTask
{ {
protected $title = 'Copy pages to different subsite'; protected $title = 'Copy pages to different subsite';
protected $description = ''; protected $description = '';
public function run($request) public function run($request)
@ -33,7 +33,7 @@ class SubsiteCopyPagesTask extends BuildTask
if (!is_numeric($subsiteFromId)) { if (!is_numeric($subsiteFromId)) {
throw new InvalidArgumentException('Missing "from" parameter'); throw new InvalidArgumentException('Missing "from" parameter');
} }
$subsiteFrom = DataObject::get_by_id('Subsite', $subsiteFromId); $subsiteFrom = DataObject::get_by_id(Subsite::class, $subsiteFromId);
if (!$subsiteFrom) { if (!$subsiteFrom) {
throw new InvalidArgumentException('Subsite not found'); throw new InvalidArgumentException('Subsite not found');
} }
@ -42,7 +42,7 @@ class SubsiteCopyPagesTask extends BuildTask
if (!is_numeric($subsiteToId)) { if (!is_numeric($subsiteToId)) {
throw new InvalidArgumentException('Missing "to" parameter'); throw new InvalidArgumentException('Missing "to" parameter');
} }
$subsiteTo = DataObject::get_by_id('Subsite', $subsiteToId); $subsiteTo = DataObject::get_by_id(Subsite::class, $subsiteToId);
if (!$subsiteTo) { if (!$subsiteTo) {
throw new InvalidArgumentException('Subsite not found'); throw new InvalidArgumentException('Subsite not found');
} }

View File

@ -1,33 +1,32 @@
{ {
"name": "silverstripe/subsites", "name": "silverstripe/subsites",
"description": "Run multiple sites from a single SilverStripe install.", "description": "Run multiple sites from a single SilverStripe install.",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"type": "silverstripe-module", "type": "silverstripe-module",
"keywords": ["silverstripe", "subsites", "multisite"], "keywords": ["silverstripe", "subsites", "multisite"],
"authors": [ "authors": [
{ {
"name": "Sam Minnee", "name": "Sam Minnee",
"email": "sam@silverstripe.com" "email": "sam@silverstripe.com"
} }
], ],
"require": "require": {
{ "silverstripe/framework": "~4.0",
"silverstripe/framework": "~4.0", "silverstripe/cms": "~4.0",
"silverstripe/cms": "~4.0",
"silverstripe/asset-admin": "~1.0.0" "silverstripe/asset-admin": "~1.0.0"
}, },
"require-dev": { "require-dev": {
"phpunit/PHPUnit": "~4.8@stable" "phpunit/PHPUnit": "~4.8@stable"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"SilverStripe\\Subsites\\": "code/", "SilverStripe\\Subsites\\": "code/",
"SilverStripe\\Subsites\\Tests\\": "tests/php/" "SilverStripe\\Subsites\\Tests\\": "tests/php/"
}
},
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
} }
},
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
}
} }

View File

@ -25,17 +25,12 @@
} }
.cms-menu .cms-subsites{ .cms-menu .cms-subsites{
padding: 0 8px 12px; padding:3px 0px 15px;
} }
.cms-menu .cms-subsites .field.dropdown{ .cms-menu .cms-subsites .field.dropdown{
padding-bottom:0; padding-bottom:0;
margin-bottom:0; margin-bottom:0;
} }
.cms-menu .cms-subsites .field.dropdown span {
color: #4f5861;
}
.cms-menu.collapsed .cms-subsites { .cms-menu.collapsed .cms-subsites {
display: none; display: none;
} }

View File

@ -72,6 +72,7 @@ en:
PrimaryDomainFieldLabel: 'Primary Domain' PrimaryDomainFieldLabel: 'Primary Domain'
RedirectURLFieldLabel: 'Redirect URL' RedirectURLFieldLabel: 'Redirect URL'
ThemeFieldLabel: Theme ThemeFieldLabel: Theme
ThemeFieldEmptyString: ''
TitleFieldLabel: 'Subsite Name' TitleFieldLabel: 'Subsite Name'
SubsitesVirtualPage: SubsitesVirtualPage:
DESCRIPTION: 'Displays the content of a page on another subsite' DESCRIPTION: 'Displays the content of a page on another subsite'

View File

@ -0,0 +1,44 @@
<?php
/**
* 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);
}
}

View File

@ -0,0 +1,72 @@
<?php
/**
* 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('*')
);
}
}

View File

@ -79,7 +79,6 @@ class FeatureContext extends SilverStripeContext
public function setMinkParameters(array $parameters) public function setMinkParameters(array $parameters)
{ {
parent::setMinkParameters($parameters); parent::setMinkParameters($parameters);
if (isset($parameters['files_path'])) { if (isset($parameters['files_path'])) {
$this->getSubcontext('FixtureContext')->setFilesPath($parameters['files_path']); $this->getSubcontext('FixtureContext')->setFilesPath($parameters['files_path']);
} }

View File

@ -378,7 +378,6 @@ class SiteTreeSubsitesTest_ClassB extends SiteTree implements TestOnly
class SiteTreeSubsitesTest_ErrorPage extends ErrorPage implements TestOnly class SiteTreeSubsitesTest_ErrorPage extends ErrorPage implements TestOnly
{ {
/** /**
* Helper method to call protected members * Helper method to call protected members
* *

View File

@ -112,14 +112,14 @@ Page:
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.subsite2 SubsiteID: =>SilverStripe\Subsites\Model\Subsite.subsite2
URLSegment: contact-us URLSegment: contact-us
SilverStripe\Security\PermissionRoleCode: PermissionRoleCode:
roleCode1: roleCode1:
Code: CMS_ACCESS_CMSMain Code: CMS_ACCESS_CMSMain
SilverStripe\Security\PermissionRole: PermissionRole:
role1: role1:
Title: role1 Title: role1
Codes: =>SilverStripe\Security\PermissionRoleCode.roleCode1 Codes: =>PermissionRoleCode.roleCode1
SilverStripe\Security\Group: Group:
admin: admin:
Title: Admin Title: Admin
Code: admin Code: admin
@ -151,71 +151,71 @@ SilverStripe\Security\Group:
Title: subsite1_group_via_role Title: subsite1_group_via_role
Code: subsite1_group_via_role Code: subsite1_group_via_role
AccessAllSubsites: 1 AccessAllSubsites: 1
Roles: =>SilverStripe\Security\PermissionRole.role1 Roles: =>PermissionRole.role1
SilverStripe\Security\Permission: Permission:
admin: admin:
Code: ADMIN Code: ADMIN
GroupID: =>SilverStripe\Security\Group.admin GroupID: =>Group.admin
editor1: editor1:
Code: CMS_ACCESS_CMSMain Code: CMS_ACCESS_CMSMain
GroupID: =>SilverStripe\Security\Group.editor GroupID: =>Group.editor
editor2: editor2:
Code: SITETREE_VIEW_ALL Code: SITETREE_VIEW_ALL
GroupID: =>SilverStripe\Security\Group.editor GroupID: =>Group.editor
editor3: editor3:
Code: VIEW_DRAFT_CONTENT Code: VIEW_DRAFT_CONTENT
GroupID: =>SilverStripe\Security\Group.editor GroupID: =>Group.editor
accesscmsmain1: accesscmsmain1:
Code: CMS_ACCESS_CMSMain Code: CMS_ACCESS_CMSMain
GroupID: =>SilverStripe\Security\Group.subsite1_group GroupID: =>Group.subsite1_group
accesscmsmain2: accesscmsmain2:
Code: CMS_ACCESS_CMSMain Code: CMS_ACCESS_CMSMain
GroupID: =>SilverStripe\Security\Group.subsite2_group GroupID: =>Group.subsite2_group
accesscmsmain3: accesscmsmain3:
Code: CMS_ACCESS_CMSMain Code: CMS_ACCESS_CMSMain
GroupID: =>SilverStripe\Security\Group.subsite1admins GroupID: =>Group.subsite1admins
accesscmsmain4: accesscmsmain4:
Code: CMS_ACCESS_CMSMain Code: CMS_ACCESS_CMSMain
GroupID: =>SilverStripe\Security\Group.allsubsitesauthors GroupID: =>Group.allsubsitesauthors
securityaccess1: securityaccess1:
Code: CMS_ACCESS_SecurityAdmin Code: CMS_ACCESS_SecurityAdmin
GroupID: =>SilverStripe\Security\Group.subsite1_group GroupID: =>Group.subsite1_group
securityaccess2: securityaccess2:
Code: CMS_ACCESS_SecurityAdmin Code: CMS_ACCESS_SecurityAdmin
GroupID: =>SilverStripe\Security\Group.subsite2_group GroupID: =>Group.subsite2_group
adminsubsite1: adminsubsite1:
Code: ADMIN Code: ADMIN
GroupID: =>SilverStripe\Security\Group.subsite1admins GroupID: =>Group.subsite1admins
SilverStripe\Security\Member: Member:
admin: admin:
FirstName: Admin FirstName: Admin
Surname: User Surname: User
Email: admin@test.com Email: admin@test.com
Password: rangi Password: rangi
Groups: =>SilverStripe\Security\Group.admin Groups: =>Group.admin
editor: editor:
FirstName: Editor FirstName: Editor
Surname: User Surname: User
Email: editor@test.com Email: editor@test.com
Password: rangi Password: rangi
Groups: =>SilverStripe\Security\Group.editor Groups: =>Group.editor
subsite1member: subsite1member:
Email: subsite1member@test.com Email: subsite1member@test.com
Groups: =>SilverStripe\Security\Group.subsite1_group Groups: =>Group.subsite1_group
subsite2member: subsite2member:
Email: subsite2member@test.com Email: subsite2member@test.com
Groups: =>SilverStripe\Security\Group.subsite2_group Groups: =>Group.subsite2_group
subsite1admin: subsite1admin:
Email: subsite1admin@test.com Email: subsite1admin@test.com
Groups: =>SilverStripe\Security\Group.subsite1admins Groups: =>Group.subsite1admins
allsubsitesauthor: allsubsitesauthor:
Email: allsubsitesauthor@test.com Email: allsubsitesauthor@test.com
Groups: =>SilverStripe\Security\Group.allsubsitesauthors Groups: =>Group.allsubsitesauthors
subsite1member2: subsite1member2:
Email: subsite1member2@test.com Email: subsite1member2@test.com
Groups: =>SilverStripe\Security\Group.subsite1_group_via_role Groups: =>Group.subsite1_group_via_role
SilverStripe\SiteConfig\SiteConfig: SiteConfig:
config: config:
CanCreateTopLevelType: LoggedInUsers CanCreateTopLevelType: LoggedInUsers

View File

@ -1,11 +1,11 @@
# These need to come first so that SiteTree has the link meta-data written. # These need to come first so that SiteTree has the link meta-data written.
SilverStripe\Assets\File: File:
file1: file1:
FileFilename: testscript-test-file.pdf FileFilename: testscript-test-file.pdf
FileHash: 464dedb70af0dc7f8f3360e7f3ae43cbbf1cdf4e FileHash: 464dedb70af0dc7f8f3360e7f3ae43cbbf1cdf4e
Name: testscript-test-file.pdf Name: testscript-test-file.pdf
SilverStripe\CMS\Model\SiteTree: SiteTree:
page1: page1:
Title: page1 Title: page1
URLSegment: page1 URLSegment: page1