diff --git a/.travis.yml b/.travis.yml index 92baae9a..1e03dd40 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,8 @@ language: php +sudo: false + php: - 5.4 diff --git a/code/extensions/SiteTreeSubsites.php b/code/extensions/SiteTreeSubsites.php index 540f6656..1ae8301f 100644 --- a/code/extensions/SiteTreeSubsites.php +++ b/code/extensions/SiteTreeSubsites.php @@ -104,12 +104,17 @@ public function updateCMSFields(FieldList $fields) // replace readonly link prefix $subsite = $this->owner->Subsite(); $nested_urls_enabled = Config::inst()->get('SiteTree', 'nested_urls'); - if ($subsite && $subsite->ID) { - $baseUrl = Director::protocol() . $subsite->domain() . '/'; - $baseLink = Controller::join_links( - $baseUrl, - ($nested_urls_enabled && $this->owner->ParentID ? $this->owner->Parent()->RelativeLink(true) : null) - ); + 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( + $baseLink, + $this->owner->Parent()->RelativeLink(true) + ); + } $urlsegment = $fields->dataFieldByName('URLSegment'); $urlsegment->setURLPrefix($baseLink); diff --git a/code/forms/WildcardDomainField.php b/code/forms/WildcardDomainField.php new file mode 100644 index 00000000..2a02d805 --- /dev/null +++ b/code/forms/WildcardDomainField.php @@ -0,0 +1,43 @@ +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'; + } +} diff --git a/code/model/Subsite.php b/code/model/Subsite.php index 01574c1c..ba8649fb 100644 --- a/code/model/Subsite.php +++ b/code/model/Subsite.php @@ -758,26 +758,27 @@ public function onAfterWrite() */ public function domain() { - if ($this->ID) { - $domains = DataObject::get("SubsiteDomain", "\"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; - } - - // SubsiteID = 0 is often used to refer to the main site, just return $_SERVER['HTTP_HOST'] - } else { - return $_SERVER['HTTP_HOST']; + // Get best SubsiteDomain object + $domainObject = $this->getPrimarySubsiteDomain(); + if ($domainObject) { + return $domainObject->SubstitutedDomain; } + + // 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(); } /** @@ -790,12 +791,19 @@ public function getPrimaryDomain() } /** - * + * 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(); } /** diff --git a/code/model/SubsiteDomain.php b/code/model/SubsiteDomain.php index 11439e02..e976a1e6 100644 --- a/code/model/SubsiteDomain.php +++ b/code/model/SubsiteDomain.php @@ -1,8 +1,12 @@ "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 @@ -24,14 +54,24 @@ class SubsiteDomain extends DataObject ); /** - * + * @config * @var array */ - private static $summary_fields=array( + private static $summary_fields = array( 'Domain', 'IsPrimary', ); + /** + * @config + * @var array + */ + private static $casting = array( + 'SubstitutedDomain' => 'Varchar', + 'FullProtocol' => 'Varchar', + 'AbsoluteLink' => 'Varchar', + ); + /** * Whenever a Subsite Domain is written, rewrite the hostmap * @@ -48,9 +88,29 @@ public function onAfterWrite() */ public function getCMSFields() { + $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( - new TextField('Domain', $this->fieldLabel('Domain'), null, 255), - new CheckboxField('IsPrimary', $this->fieldLabel('IsPrimary')) + 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.
' . + '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); @@ -66,20 +126,90 @@ public function fieldLabels($includerelations = true) { $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; } /** - * Before writing the Subsite Domain, strip out any HTML the user has entered. - * @return void + * Get the link to this subsite + * + * @return string */ - public function onBeforeWrite() + public function Link() { - parent::onBeforeWrite(); + return $this->getFullProtocol() . $this->Domain; + } - //strip out any HTML to avoid XSS attacks - $this->Domain = Convert::html2raw($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" 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 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() + ); } } diff --git a/tests/FileSubsitesTest.php b/tests/FileSubsitesTest.php index a465dee7..1ab22f90 100644 --- a/tests/FileSubsitesTest.php +++ b/tests/FileSubsitesTest.php @@ -3,6 +3,18 @@ class FileSubsitesTest extends BaseSubsiteTest { public static $fixture_file = 'subsites/tests/SubsiteTest.yml'; + + /** + * Disable other file extensions + * + * @var array + */ + protected $illegalExtensions = array( + 'File' => array( + 'SecureFileExtension', + 'VersionedFileExtension' + ) + ); public function testTrivialFeatures() { @@ -68,12 +80,14 @@ public function testSubsitesFolderDropdown() $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)); } } diff --git a/tests/SubsiteTest.php b/tests/SubsiteTest.php index fd128e99..9add45f8 100644 --- a/tests/SubsiteTest.php +++ b/tests/SubsiteTest.php @@ -3,20 +3,37 @@ class SubsiteTest extends BaseSubsiteTest { public static $fixture_file = 'subsites/tests/SubsiteTest.yml'; + + /** + * Original value of {@see SubSite::$strict_subdomain_matching} + * + * @var bool + */ + protected $origStrictSubdomainMatching = null; + + /** + * Original value of $_REQUEST + * + * @var array + */ + protected $origServer = array(); public function setUp() { parent::setUp(); + Config::inst()->update('Director', 'alternate_base_url', '/'); $this->origStrictSubdomainMatching = Subsite::$strict_subdomain_matching; + $this->origServer = $_SERVER; Subsite::$strict_subdomain_matching = false; } public function tearDown() { - parent::tearDown(); - + $_SERVER = $this->origServer; Subsite::$strict_subdomain_matching = $this->origStrictSubdomainMatching; + + parent::tearDown(); } /** @@ -238,9 +255,7 @@ public function testDefaultDomain() $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()); @@ -251,8 +266,51 @@ public function testDefaultDomain() $this->assertEquals($_SERVER['HTTP_HOST'], singleton('Subsite')->PrimaryDomain); $this->assertEquals('http://'.$_SERVER['HTTP_HOST'].Director::baseURL(), singleton('Subsite')->absoluteBaseURL()); - - $_SERVER['HTTP_HOST'] = $originalHTTPHost; + } + + /** + * Tests that Subsite and SubsiteDomain both respect http protocol correctly + */ + public function testDomainProtocol() { + // domaintest2 has 'protocol' + $subsite2 = $this->objFromFixture('Subsite', 'domaintest2'); + $domain2a = $this->objFromFixture('SubsiteDomain', 'dt2a'); + $domain2b = $this->objFromFixture('SubsiteDomain', 'dt2b'); + + // domaintest4 is 'https' (primary only) + $subsite4 = $this->objFromFixture('Subsite', 'domaintest4'); + $domain4a = $this->objFromFixture('SubsiteDomain', 'dt4a'); + $domain4b = $this->objFromFixture('SubsiteDomain', 'dt4b'); // secondary domain is http only though + + // domaintest5 is 'http' + $subsite5 = $this->objFromFixture('Subsite', 'domaintest5'); + $domain5a = $this->objFromFixture('SubsiteDomain', '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() @@ -265,7 +323,9 @@ public function testAllSites() array('Title' =>'Subsite2 Template'), array('Title' =>'Test 1'), array('Title' =>'Test 2'), - array('Title' =>'Test 3') + array('Title' =>'Test 3'), + array('Title' => 'Test Non-SSL'), + array('Title' => 'Test SSL') ), $subsites, 'Lists all subsites'); } @@ -301,10 +361,14 @@ public function testAccessibleSites() '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('Member', 'subsite1member2')); + $member2Sites = Subsite::accessible_sites( + "CMS_ACCESS_CMSMain", false, null, + $this->objFromFixture('Member', 'subsite1member2') + ); $member2SiteTitles = $member2Sites->column("Title"); sort($member2SiteTitles); $this->assertEquals('Subsite1 Template', $member2SiteTitles[0], 'Member can get to subsite via a group role'); diff --git a/tests/SubsiteTest.yml b/tests/SubsiteTest.yml index e4b0ef63..f888474b 100644 --- a/tests/SubsiteTest.yml +++ b/tests/SubsiteTest.yml @@ -1,184 +1,208 @@ Subsite: - main: - Title: Template - subsite1: - Title: Subsite1 Template - subsite2: - Title: Subsite2 Template - domaintest1: - Title: Test 1 - domaintest2: - Title: Test 2 - domaintest3: - Title: Test 3 + main: + Title: Template + subsite1: + Title: Subsite1 Template + subsite2: + Title: Subsite2 Template + domaintest1: + Title: Test 1 + domaintest2: + Title: Test 2 + domaintest3: + Title: Test 3 + domaintest4: + Title: 'Test SSL' + domaintest5: + Title: 'Test Non-SSL' SubsiteDomain: - subsite1: - SubsiteID: =>Subsite.subsite1 - Domain: subsite1.* - subsite2: - SubsiteID: =>Subsite.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 + subsite1: + SubsiteID: =>Subsite.subsite1 + Domain: subsite1.* + Protocol: automatic + subsite2: + SubsiteID: =>Subsite.subsite2 + Domain: subsite2.* + Protocol: automatic + dt1a: + SubsiteID: =>Subsite.domaintest1 + Domain: one.example.org + Protocol: automatic + IsPrimary: 1 + dt1b: + SubsiteID: =>Subsite.domaintest1 + Domain: one.* + Protocol: automatic + dt2a: + SubsiteID: =>Subsite.domaintest2 + Domain: two.mysite.com + Protocol: automatic + IsPrimary: 1 + dt2b: + SubsiteID: =>Subsite.domaintest2 + Domain: *.mysite.com + Protocol: automatic + dt3: + SubsiteID: =>Subsite.domaintest3 + Domain: three.* + Protocol: automatic + IsPrimary: 1 + dt4a: + SubsiteID: =>Subsite.domaintest4 + Domain: www.primary.com + Protocol: https + dt4b: + SubsiteID: =>Subsite.domaintest4 + Domain: www.secondary.com + Protocol: http + dt5: + SubsiteID: =>Subsite.domaintest5 + Domain: www.tertiary.com + Protocol: http + IsPrimary: 1 Page: - mainSubsitePage: - Title: MainSubsitePage - SubsiteID: 0 - home: - Title: Home - SubsiteID: =>Subsite.main - about: - Title: About - SubsiteID: =>Subsite.main - linky: - Title: Linky - SubsiteID: =>Subsite.main - staff: - Title: Staff - ParentID: =>Page.about - SubsiteID: =>Subsite.main - contact: - Title: Contact Us - SubsiteID: =>Subsite.main - importantpage: - Title: Important Page - SubsiteID: =>Subsite.main - subsite1_home: - Title: Home (Subsite 1) - SubsiteID: =>Subsite.subsite1 - subsite1_contactus: - Title: Contact Us (Subsite 1) - SubsiteID: =>Subsite.subsite1 - subsite1_staff: - Title: Staff - SubsiteID: =>Subsite.subsite1 - subsite2_home: - Title: Home (Subsite 2) - SubsiteID: =>Subsite.subsite2 - subsite2_contactus: - Title: Contact Us (Subsite 2) - SubsiteID: =>Subsite.subsite2 + mainSubsitePage: + Title: MainSubsitePage + SubsiteID: 0 + home: + Title: Home + SubsiteID: =>Subsite.main + about: + Title: About + SubsiteID: =>Subsite.main + linky: + Title: Linky + SubsiteID: =>Subsite.main + staff: + Title: Staff + ParentID: =>Page.about + SubsiteID: =>Subsite.main + contact: + Title: Contact Us + SubsiteID: =>Subsite.main + importantpage: + Title: Important Page + SubsiteID: =>Subsite.main + subsite1_home: + Title: Home (Subsite 1) + SubsiteID: =>Subsite.subsite1 + subsite1_contactus: + Title: Contact Us (Subsite 1) + SubsiteID: =>Subsite.subsite1 + subsite1_staff: + Title: Staff + SubsiteID: =>Subsite.subsite1 + subsite2_home: + Title: Home (Subsite 2) + SubsiteID: =>Subsite.subsite2 + subsite2_contactus: + Title: Contact Us (Subsite 2) + SubsiteID: =>Subsite.subsite2 PermissionRoleCode: - roleCode1: - Code: CMS_ACCESS_CMSMain + roleCode1: + Code: CMS_ACCESS_CMSMain PermissionRole: - role1: - Title: role1 - Codes: =>PermissionRoleCode.roleCode1 + role1: + Title: role1 + Codes: =>PermissionRoleCode.roleCode1 Group: - admin: - Title: Admin - Code: admin - AccessAllSubsites: 1 - editor: - Title: Editor - Code: editor - AccessAllSubsites: 1 - subsite1_group: - Title: subsite1_group - Code: subsite1_group - AccessAllSubsites: 0 - Subsites: =>Subsite.subsite1 - subsite2_group: - Title: subsite2_group - Code: subsite2_group - AccessAllSubsites: 0 - Subsites: =>Subsite.subsite2 - subsite1admins: - Title: subsite1admins - Code: subsite1admins - AccessAllSubsites: 0 - Subsites: =>Subsite.subsite1 - allsubsitesauthors: - Title: allsubsitesauthors - Code: allsubsitesauthors - AccessAllSubsites: 1 - subsite1_group_via_role: - Title: subsite1_group_via_role - Code: subsite1_group_via_role - AccessAllSubsites: 1 - Roles: =>PermissionRole.role1 + admin: + Title: Admin + Code: admin + AccessAllSubsites: 1 + editor: + Title: Editor + Code: editor + AccessAllSubsites: 1 + subsite1_group: + Title: subsite1_group + Code: subsite1_group + AccessAllSubsites: 0 + Subsites: =>Subsite.subsite1 + subsite2_group: + Title: subsite2_group + Code: subsite2_group + AccessAllSubsites: 0 + Subsites: =>Subsite.subsite2 + subsite1admins: + Title: subsite1admins + Code: subsite1admins + AccessAllSubsites: 0 + Subsites: =>Subsite.subsite1 + allsubsitesauthors: + Title: allsubsitesauthors + Code: allsubsitesauthors + AccessAllSubsites: 1 + subsite1_group_via_role: + Title: subsite1_group_via_role + Code: subsite1_group_via_role + AccessAllSubsites: 1 + Roles: =>PermissionRole.role1 Permission: - admin: - Code: ADMIN - GroupID: =>Group.admin - editor1: - Code: CMS_ACCESS_CMSMain - GroupID: =>Group.editor - editor2: - Code: SITETREE_VIEW_ALL - GroupID: =>Group.editor - editor3: - Code: VIEW_DRAFT_CONTENT - GroupID: =>Group.editor - accesscmsmain1: - Code: CMS_ACCESS_CMSMain - GroupID: =>Group.subsite1_group - accesscmsmain2: - Code: CMS_ACCESS_CMSMain - GroupID: =>Group.subsite2_group - accesscmsmain3: - Code: CMS_ACCESS_CMSMain - GroupID: =>Group.subsite1admins - accesscmsmain4: - Code: CMS_ACCESS_CMSMain - GroupID: =>Group.allsubsitesauthors - securityaccess1: - Code: CMS_ACCESS_SecurityAdmin - GroupID: =>Group.subsite1_group - securityaccess2: - Code: CMS_ACCESS_SecurityAdmin - GroupID: =>Group.subsite2_group - adminsubsite1: - Code: ADMIN - GroupID: =>Group.subsite1admins + admin: + Code: ADMIN + GroupID: =>Group.admin + editor1: + Code: CMS_ACCESS_CMSMain + GroupID: =>Group.editor + editor2: + Code: SITETREE_VIEW_ALL + GroupID: =>Group.editor + editor3: + Code: VIEW_DRAFT_CONTENT + GroupID: =>Group.editor + accesscmsmain1: + Code: CMS_ACCESS_CMSMain + GroupID: =>Group.subsite1_group + accesscmsmain2: + Code: CMS_ACCESS_CMSMain + GroupID: =>Group.subsite2_group + accesscmsmain3: + Code: CMS_ACCESS_CMSMain + GroupID: =>Group.subsite1admins + accesscmsmain4: + Code: CMS_ACCESS_CMSMain + GroupID: =>Group.allsubsitesauthors + securityaccess1: + Code: CMS_ACCESS_SecurityAdmin + GroupID: =>Group.subsite1_group + securityaccess2: + Code: CMS_ACCESS_SecurityAdmin + GroupID: =>Group.subsite2_group + adminsubsite1: + Code: ADMIN + GroupID: =>Group.subsite1admins Member: - admin: - FirstName: Admin - Surname: User - Email: admin@test.com - Password: rangi - Groups: =>Group.admin - editor: - FirstName: Editor - Surname: User - Email: editor@test.com - Password: rangi - Groups: =>Group.editor - subsite1member: - Email: subsite1member@test.com - Groups: =>Group.subsite1_group - subsite2member: - Email: subsite2member@test.com - Groups: =>Group.subsite2_group - subsite1admin: - Email: subsite1admin@test.com - Groups: =>Group.subsite1admins - allsubsitesauthor: - Email: allsubsitesauthor@test.com - Groups: =>Group.allsubsitesauthors - subsite1member2: - Email: subsite1member2@test.com - Groups: =>Group.subsite1_group_via_role + admin: + FirstName: Admin + Surname: User + Email: admin@test.com + Password: rangi + Groups: =>Group.admin + editor: + FirstName: Editor + Surname: User + Email: editor@test.com + Password: rangi + Groups: =>Group.editor + subsite1member: + Email: subsite1member@test.com + Groups: =>Group.subsite1_group + subsite2member: + Email: subsite2member@test.com + Groups: =>Group.subsite2_group + subsite1admin: + Email: subsite1admin@test.com + Groups: =>Group.subsite1admins + allsubsitesauthor: + Email: allsubsitesauthor@test.com + Groups: =>Group.allsubsitesauthors + subsite1member2: + Email: subsite1member2@test.com + Groups: =>Group.subsite1_group_via_role SiteConfig: - config: - CanCreateTopLevelType: LoggedInUsers \ No newline at end of file + config: + CanCreateTopLevelType: LoggedInUsers diff --git a/tests/WildcardDomainFieldTest.php b/tests/WildcardDomainFieldTest.php new file mode 100644 index 00000000..87361446 --- /dev/null +++ b/tests/WildcardDomainFieldTest.php @@ -0,0 +1,72 @@ +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('*') + ); + } + +}