mirror of
https://github.com/silverstripe/silverstripe-subsites
synced 2024-06-26 06:29:31 +02:00
This commit is contained in:
parent
4635b8d3de
commit
9a556a31f9
158
code/Subsite.php
158
code/Subsite.php
|
@ -23,12 +23,11 @@ class Subsite extends DataObject implements PermissionProvider {
|
|||
static $use_domain = false;
|
||||
|
||||
static $db = array(
|
||||
'Subdomain' => 'Varchar',
|
||||
'Title' => 'Varchar(255)',
|
||||
'RedirectURL' => 'Varchar(255)',
|
||||
'DefaultSite' => 'Boolean',
|
||||
'Theme' => 'Varchar',
|
||||
'Domain' => 'Varchar',
|
||||
|
||||
// Used to hide unfinished/private subsites from public view.
|
||||
// If unset, will default to
|
||||
'IsPublic' => 'Boolean'
|
||||
|
@ -37,37 +36,15 @@ class Subsite extends DataObject implements PermissionProvider {
|
|||
static $has_one = array(
|
||||
);
|
||||
|
||||
static $indexes = array(
|
||||
'Subdomain' => true,
|
||||
'Domain' => true
|
||||
);
|
||||
|
||||
static $defaults = array(
|
||||
'IsPublic' => 1,
|
||||
);
|
||||
|
||||
/**
|
||||
* @var string $base_domain If {@link Domain} is not set for this subsite instance,
|
||||
* default to this domain (without subdomain or protocol prefix).
|
||||
*/
|
||||
static $base_domain;
|
||||
|
||||
/**
|
||||
* @var string $default_subdomain If {@link Subdomain} is not set for this subsite instance,
|
||||
* default to this domain (without domain or protocol prefix).
|
||||
*/
|
||||
static $default_subdomain;
|
||||
|
||||
/**
|
||||
* @var Subsite $cached_subsite Internal cache used by {@link currentSubsite()}.
|
||||
*/
|
||||
protected static $cached_subsite = null;
|
||||
|
||||
/**
|
||||
* @var array $allowed_domains Numeric array of all domains which are selectable for (without their subdomain-parts or http:// prefix)
|
||||
*/
|
||||
public static $allowed_domains = array();
|
||||
|
||||
/**
|
||||
* @var array $allowed_themes Numeric array of all themes which are allowed to be selected for all subsites.
|
||||
* Corresponds to subfolder names within the /themes folder. By default, all themes contained in this folder
|
||||
|
@ -76,29 +53,8 @@ class Subsite extends DataObject implements PermissionProvider {
|
|||
protected static $allowed_themes = array();
|
||||
|
||||
static function set_allowed_domains($domain){
|
||||
if(is_array($domain)){
|
||||
foreach($domain as $do){
|
||||
self::set_allowed_domains($do);
|
||||
}
|
||||
}else{
|
||||
self::$allowed_domains[] = $domain;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all domains (without their subdomain parts)
|
||||
* which are allowed to be combined to the full URL
|
||||
* (subdomain.domain). If no custom domains are set through
|
||||
* {@link set_allowed_domains()}, will fall back to the {@link base_domain()}.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static function allowed_domains() {
|
||||
if(self::$allowed_domains && count(self::$allowed_domains)) {
|
||||
return self::$allowed_domains;
|
||||
} else {
|
||||
return array(self::base_domain());
|
||||
}
|
||||
user_error('Subsite::set_allowed_domains() is deprecated; it is no longer necessary '
|
||||
. 'because users can now enter any domain name', E_USER_NOTICE);
|
||||
}
|
||||
|
||||
static function set_allowed_themes($themes) {
|
||||
|
@ -125,39 +81,25 @@ class Subsite extends DataObject implements PermissionProvider {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base domain for this set of subsites.
|
||||
* You can set this by setting Subsite::$base_domain, otherwise it defaults to HTTP_HOST
|
||||
*
|
||||
* @return string Domain name (without protocol prefix).
|
||||
*/
|
||||
static function base_domain() {
|
||||
if(self::$base_domain) return self::$base_domain;
|
||||
else return $_SERVER['HTTP_HOST'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default domain of this set of subsites. Generally this will be the base domain,
|
||||
* but you can also set Subsite::$default_subdomain to add a default prefix to this.
|
||||
*
|
||||
* @return string Domain name (without protocol prefix).
|
||||
*/
|
||||
static function default_domain() {
|
||||
if(self::$default_subdomain) return self::$default_subdomain . '.' . self::base_domain();
|
||||
else return self::base_domain();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the domain of this site
|
||||
*
|
||||
* @return string Domain name including subdomain (without protocol prefix)
|
||||
*/
|
||||
function domain() {
|
||||
$base = $this->Domain ? $this->Domain : self::base_domain();
|
||||
$sub = $this->Subdomain ? $this->Subdomain : self::$default_subdomain;
|
||||
|
||||
if($sub) return "$sub.$base";
|
||||
else return $base;
|
||||
if($this->ID) {
|
||||
$domains = DataObject::get("SubsiteDomain", "SubsiteID = $this->ID", "IsPrimary DESC",
|
||||
"", 1);
|
||||
if($domains) {
|
||||
$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);
|
||||
$domain = preg_replace("/^\\*\\./","subsite.", $domain);
|
||||
$domain = str_replace('.www.','.', $domain);
|
||||
return $domain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function absoluteBaseURL() {
|
||||
|
@ -168,15 +110,23 @@ class Subsite extends DataObject implements PermissionProvider {
|
|||
* Show the configuration fields for each subsite
|
||||
*/
|
||||
function getCMSFields() {
|
||||
$domainTable = new TableField("Domains", "SubsiteDomain",
|
||||
array("Domain" => "Domain (use * as a wildcard)", "IsPrimary" => "Primary domain?"),
|
||||
array("Domain" => "TextField", "IsPrimary" => "CheckboxField"),
|
||||
null, "SubsiteDomain.SubsiteID", $this->ID);
|
||||
|
||||
$domainTable->setExtraData(array(
|
||||
'SubsiteID' => $this->ID ? $this->ID : '$RecordID',
|
||||
));
|
||||
|
||||
$fields = new FieldSet(
|
||||
new TabSet('Root',
|
||||
new Tab('Configuration',
|
||||
new HeaderField($this->getClassName() . ' configuration', 2),
|
||||
new TextField('Title', 'Name of subsite:', $this->Title),
|
||||
new FieldGroup('URL',
|
||||
new TextField('Subdomain',"Subdomain <small>(without domain or protocol)</small>", $this->Subdomain),
|
||||
new DropdownField('Domain','.', ArrayLib::valuekey(self::allowed_domains()), $this->Domain)
|
||||
),
|
||||
|
||||
new HeaderField("Domains for this subsite"),
|
||||
$domainTable,
|
||||
// new TextField('RedirectURL', 'Redirect to URL', $this->RedirectURL),
|
||||
new CheckboxField('DefaultSite', 'Default site', $this->DefaultSite),
|
||||
new CheckboxField('IsPublic', 'Enable public access', $this->IsPublic),
|
||||
|
@ -303,37 +253,27 @@ JS;
|
|||
}
|
||||
|
||||
/**
|
||||
* Get a matching subsite for the domain defined in HTTP_HOST.
|
||||
* Get a matching subsite for the given host, or for the current HTTP_HOST.
|
||||
*
|
||||
* @param $host The host to find the subsite for. If not specified, $_SERVER['HTTP_HOST']
|
||||
* is used.
|
||||
*
|
||||
* @return int Subsite ID
|
||||
*/
|
||||
static function getSubsiteIDForDomain() {
|
||||
$domainNameParts = explode('.', $_SERVER['HTTP_HOST']);
|
||||
|
||||
if($domainNameParts[0] == 'www') array_shift($domainNameParts);
|
||||
|
||||
$SQL_subdomain = Convert::raw2sql(array_shift($domainNameParts));
|
||||
$SQL_domain = join('.', Convert::raw2sql($domainNameParts));
|
||||
static function getSubsiteIDForDomain($host = null) {
|
||||
if($host == null) $host = $_SERVER['HTTP_HOST'];
|
||||
|
||||
if(defined('DB::USE_ANSI_SQL'))
|
||||
$q="\"";
|
||||
else $q='`';
|
||||
|
||||
$subsite = null;
|
||||
if(self::$use_domain) {
|
||||
$subsite = DataObject::get_one('Subsite', "{$q}Subdomain{$q} = '$SQL_subdomain' AND {$q}Domain{$q} = '$SQL_domain' AND {$q}IsPublic{$q} = 1");
|
||||
}
|
||||
if(!$subsite) {
|
||||
$subsite = DataObject::get_one('Subsite', "{$q}Subdomain{$q} = '$SQL_subdomain' AND {$q}IsPublic{$q} = 1");
|
||||
}
|
||||
if(!$subsite) {
|
||||
$subsite = DataObject::get_one('Subsite', "{$q}DefaultSite{$q} = 1 AND {$q}IsPublic{$q} = 1");
|
||||
}
|
||||
$host = str_replace('www.','',$host);
|
||||
$SQL_host = Convert::raw2sql($host);
|
||||
|
||||
if($subsite) {
|
||||
// This will need to be updated to use the current theme system
|
||||
// SSViewer::setCurrentTheme($subsite->Theme);
|
||||
return $subsite->ID;
|
||||
$matchingDomains = DataObject::get("SubsiteDomain", "'$SQL_host' LIKE replace({$q}SubsiteDomain{$q}.{$q}Domain{$q},'*','%')",
|
||||
"{$q}IsPrimary{$q} DESC", "INNER JOIN {$q}Subsite{$q} ON {$q}Subsite{$q}.{$q}ID{$q} = {$q}SubsiteDomain{$q}.{$q}SubsiteID{$q} AND
|
||||
{$q}Subsite{$q}.{$q}IsPublic{$q}");
|
||||
|
||||
if($matchingDomains) {
|
||||
$subsiteIDs = array_unique($matchingDomains->column('SubsiteID'));
|
||||
if(sizeof($subsiteIDs) > 1) user_error("Multiple subsites match '$host'", E_USER_WARNING);
|
||||
return $subsiteIDs[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -543,14 +483,16 @@ class Subsite_Template extends Subsite {
|
|||
/**
|
||||
* Create an instance of this template, with the given title & subdomain
|
||||
*/
|
||||
function createInstance($title, $subdomain) {
|
||||
function createInstance($title, $domain) {
|
||||
$intranet = Object::create('Subsite');
|
||||
$intranet->Title = $title;
|
||||
$intranet->Domain = $this->Domain;
|
||||
$intranet->Subdomain = $subdomain;
|
||||
$intranet->TemplateID = $this->ID;
|
||||
$intranet->write();
|
||||
|
||||
|
||||
$intranetDomain = Object::create('SubsiteDomain');
|
||||
$intranetDomain->SubsiteID = $intranet->ID;
|
||||
$intranetDomain->Domain = $domain;
|
||||
$intranetDomain->write();
|
||||
|
||||
$oldSubsiteID = Session::get('SubsiteID');
|
||||
self::changeSubsite($this->ID);
|
||||
|
|
|
@ -68,7 +68,7 @@ class SubsiteAdmin extends GenericDataAdmin {
|
|||
$numIntranets++;
|
||||
$evenOdd = ($numIntranets % 2) ? 'odd':'even';
|
||||
$prefix = ($intranet instanceof Subsite_Template) ? " * " : "";
|
||||
$html .= "<tr class=\"$evenOdd\"><td><a class=\"show\" href=\"admin/subsites/show/{$intranet->ID}\">$prefix{$intranet->Title}</a></td><td><a class=\"show\" href=\"admin/subsites/show/{$intranet->ID}\">{$intranet->Subdomain}.{$intranet->Domain}</a></td></tr>";
|
||||
$html .= "<tr class=\"$evenOdd\"><td><a class=\"show\" href=\"admin/subsites/show/{$intranet->ID}\">$prefix{$intranet->Title}</a></td><td><a class=\"show\" href=\"admin/subsites/show/{$intranet->ID}\">{$intranet->domain()}</a></td></tr>";
|
||||
}
|
||||
$html .= "</tbody></table>";
|
||||
return $html;
|
||||
|
@ -88,7 +88,7 @@ class SubsiteAdmin extends GenericDataAdmin {
|
|||
|
||||
return new Form($this, 'AddSubsiteForm', new FieldSet(
|
||||
new TextField('Name', 'Name:'),
|
||||
new TextField('Subdomain', 'Subdomain:'),
|
||||
new TextField('Domain', 'Domain name:'),
|
||||
new DropdownField('Type', 'Type', array(
|
||||
'subsite' => 'New site',
|
||||
'template' => 'New template',
|
||||
|
@ -111,13 +111,13 @@ class SubsiteAdmin extends GenericDataAdmin {
|
|||
}
|
||||
|
||||
function addintranet($data, $form) {
|
||||
if($data['Name'] && ($data['Subdomain'] || $data['Type'] == 'template')) {
|
||||
if($data['Name'] && ($data['Domain'] || $data['Type'] == 'template')) {
|
||||
if(isset($data['TemplateID']) && $data['TemplateID']) {
|
||||
$template = DataObject::get_by_id('Subsite_Template', $data['TemplateID']);
|
||||
} else {
|
||||
$template = null;
|
||||
}
|
||||
|
||||
|
||||
// Create intranet from existing template
|
||||
switch($data['Type']) {
|
||||
case 'template':
|
||||
|
@ -130,12 +130,17 @@ class SubsiteAdmin extends GenericDataAdmin {
|
|||
|
||||
case 'subsite':
|
||||
default:
|
||||
if($template) $intranet = $template->createInstance($data['Name'], $data['Subdomain']);
|
||||
if($template) $intranet = $template->createInstance($data['Name'], $data['Domain']);
|
||||
else {
|
||||
$intranet = new Subsite();
|
||||
$intranet->Title = $data['Name'];
|
||||
$intranet->Subdomain = $data['Subdomain'];
|
||||
$intranet->write();
|
||||
|
||||
$newSubsiteDomain = new SubsiteDomain();
|
||||
$newSubsiteDomain->SubsiteID = $intranet->ID;
|
||||
$newSubsiteDomain->write();
|
||||
$newSubsiteDomain->Domain = $data['Domain'];
|
||||
$newSubsiteDomain->write();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -143,7 +148,7 @@ class SubsiteAdmin extends GenericDataAdmin {
|
|||
Director::redirect('admin/subsites/show/' . $intranet->ID);
|
||||
} else {
|
||||
if($data['Type'] == 'template') echo "You must provide a name for your new template.";
|
||||
else echo "You must provide a name and subdomain for your new site.";
|
||||
else echo "You must provide a name and domain for your new site.";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
11
code/SubsiteDomain.php
Normal file
11
code/SubsiteDomain.php
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
class SubsiteDomain extends DataObject {
|
||||
static $db = array(
|
||||
"Domain" => "Varchar(255)",
|
||||
"IsPrimary" => "Boolean",
|
||||
);
|
||||
static $has_one = array(
|
||||
"Subsite" => "Subsite",
|
||||
);
|
||||
}
|
|
@ -78,7 +78,7 @@ class SubsiteAdminTest extends SapphireTest {
|
|||
|
||||
$response = $form->testSubmission('addintranet', array(
|
||||
'Name' => 'Test Intranet',
|
||||
'Subdomain' => 'Test',
|
||||
'Domain' => 'test.example.com',
|
||||
'TemplateID' => 1,
|
||||
'AdminEmail' => '',
|
||||
'AdminName' => '',
|
||||
|
|
|
@ -58,13 +58,13 @@ class SubsiteTest extends SapphireTest {
|
|||
}
|
||||
|
||||
// Create a new site
|
||||
$subsite = $template->createInstance('My Site', 'something');
|
||||
$subsite = $template->createInstance('My Site', 'something.test.com');
|
||||
|
||||
// Check title
|
||||
$this->assertEquals($subsite->Title, 'My Site');
|
||||
|
||||
// Check that domain generation is working
|
||||
$this->assertEquals($subsite->domain(), 'something.test.com');
|
||||
$this->assertEquals('something.test.com', $subsite->domain());
|
||||
|
||||
// Another test that changeSubsite is working
|
||||
Subsite::changeSubsite($subsite->ID);
|
||||
|
@ -85,6 +85,50 @@ class SubsiteTest extends SapphireTest {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm that domain lookup is working
|
||||
*/
|
||||
function testDomainLookup() {
|
||||
$this->assertEquals($this->idFromFixture('Subsite','domaintest1'),
|
||||
Subsite::getSubsiteIDForDomain('one.example.org'));
|
||||
$this->assertEquals($this->idFromFixture('Subsite','domaintest1'),
|
||||
Subsite::getSubsiteIDForDomain('one.localhost'));
|
||||
|
||||
$this->assertEquals($this->idFromFixture('Subsite','domaintest2'),
|
||||
Subsite::getSubsiteIDForDomain('two.mysite.com'));
|
||||
$this->assertEquals($this->idFromFixture('Subsite','domaintest2'),
|
||||
Subsite::getSubsiteIDForDomain('other.mysite.com'));
|
||||
|
||||
$this->assertNull(Subsite::getSubsiteIDForDomain('other.example.com'));
|
||||
$this->assertNull(Subsite::getSubsiteIDForDomain('two.example.com'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the Subsite->domain() method
|
||||
*/
|
||||
function testDefaultDomain() {
|
||||
$this->assertEquals('one.example.org',
|
||||
$this->objFromFixture('Subsite','domaintest1')->domain());
|
||||
|
||||
$this->assertEquals('two.mysite.com',
|
||||
$this->objFromFixture('Subsite','domaintest2')->domain());
|
||||
|
||||
$originalHTTPHost = $_SERVER['HTTP_HOST'];
|
||||
|
||||
$_SERVER['HTTP_HOST'] = "www.example.org";
|
||||
$this->assertEquals('three.example.org',
|
||||
$this->objFromFixture('Subsite','domaintest3')->domain());
|
||||
|
||||
$_SERVER['HTTP_HOST'] = "mysite.example.org";
|
||||
$this->assertEquals('three.mysite.example.org',
|
||||
$this->objFromFixture('Subsite','domaintest3')->domain());
|
||||
|
||||
|
||||
$_SERVER['HTTP_HOST'] = $originalHTTPHost;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Only the published content from the template should publish.
|
||||
*/
|
||||
|
|
|
@ -1,13 +1,43 @@
|
|||
Subsite_Template:
|
||||
main:
|
||||
Title: Template
|
||||
Domain: test.com
|
||||
subsite1:
|
||||
Title: Subsite1 Template
|
||||
Subdomain: subsite1
|
||||
subsite2:
|
||||
Title: Subsite2 Template
|
||||
Subdomain: subsite2
|
||||
Subsite:
|
||||
domaintest1:
|
||||
Title: Test 1
|
||||
domaintest2:
|
||||
Title: Test 2
|
||||
domaintest3:
|
||||
Title: Test 3
|
||||
SubsiteDomain:
|
||||
subsite1:
|
||||
SubsiteID: =>Subsite_Template.subsite1
|
||||
Domain: subsite1.*
|
||||
subsite2:
|
||||
SubsiteID: =>Subsite_Template.subsite2
|
||||
Domain: subsite2.*
|
||||
dt1a:
|
||||
SubsiteID: =>Subsite.domaintest1
|
||||
Domain: one.example.org
|
||||
IsPrimary: 1
|
||||
dt1b:
|
||||
SubsiteID: =>Subsite.domaintest1
|
||||
Domain: one.*
|
||||
dt2a:
|
||||
SubsiteID: =>Subsite.domaintest2
|
||||
Domain: two.mysite.com
|
||||
IsPrimary: 1
|
||||
dt2b:
|
||||
SubsiteID: =>Subsite.domaintest2
|
||||
Domain: *.mysite.com
|
||||
dt3:
|
||||
SubsiteID: =>Subsite.domaintest3
|
||||
Domain: three.*
|
||||
IsPrimary: 1
|
||||
|
||||
SiteTree:
|
||||
home:
|
||||
Title: Home
|
||||
|
|
Loading…
Reference in New Issue
Block a user