This commit is contained in:
Tom Rix 2010-03-01 02:48:45 +00:00
parent 4635b8d3de
commit 9a556a31f9
6 changed files with 153 additions and 121 deletions

View File

@ -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);

View File

@ -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
View File

@ -0,0 +1,11 @@
<?php
class SubsiteDomain extends DataObject {
static $db = array(
"Domain" => "Varchar(255)",
"IsPrimary" => "Boolean",
);
static $has_one = array(
"Subsite" => "Subsite",
);
}

View File

@ -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' => '',

View File

@ -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.
*/

View File

@ -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