Merge remote-tracking branch 'origin/3.0' into 3.1.0

Conflicts:
	code/controllers/ContentController.php
	code/model/SiteTree.php
	tests/search/SearchFormTest.php
This commit is contained in:
Ingo Schommer 2013-08-20 20:48:24 +02:00
commit ba57d42349
3 changed files with 43 additions and 38 deletions

View File

@ -101,15 +101,25 @@ class ContentController extends Controller {
if($this->redirectedTo()) return; if($this->redirectedTo()) return;
// Check page permissions // Draft/Archive security check - only CMS users should be able to look at stage/archived content
if($this->dataRecord && $this->URLSegment != 'Security' && !$this->dataRecord->canView()) { if(
$permissionMessage = null; $this->URLSegment != 'Security'
&& !Session::get('unsecuredDraftSite')
// Check if we could view the live version, offer redirect if so && (
if($this->canViewStage('Live')) { Versioned::current_archived_date()
|| (Versioned::current_stage() && Versioned::current_stage() != 'Live')
)
) {
if(!$this->dataRecord->canViewStage(Versioned::current_archived_date() ? 'Stage' : Versioned::current_stage())) {
$link = $this->Link();
$message = _t(
"ContentController.DRAFT_SITE_ACCESS_RESTRICTION",
'You must log in with your CMS password in order to view the draft or archived content. ' .
'<a href="%s">Click here to go back to the published site.</a>'
);
Session::clear('currentStage'); Session::clear('currentStage');
Session::clear('archiveDate'); Session::clear('archiveDate');
$permissionMessage = sprintf( $permissionMessage = sprintf(
_t( _t(
"ContentController.DRAFT_SITE_ACCESS_RESTRICTION", "ContentController.DRAFT_SITE_ACCESS_RESTRICTION",
@ -215,7 +225,7 @@ class ContentController extends Controller {
$response = $this->request->isMedia() ? null : ErrorPage::response_for($code); $response = $this->request->isMedia() ? null : ErrorPage::response_for($code);
// Failover to $message if the HTML response is unavailable / inappropriate // Failover to $message if the HTML response is unavailable / inappropriate
parent::httpError($code, $response ? $response : $message); parent::httpError($code, $response ? $response : $message);
} }
/** /**
* Get the project name * Get the project name

View File

@ -218,7 +218,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
* Determines if the system should avoid orphaned pages * Determines if the system should avoid orphaned pages
* by deleting all children when the their parent is deleted (TRUE), * by deleting all children when the their parent is deleted (TRUE),
* or rather preserve this data even if its not reachable through any navigation path (FALSE). * or rather preserve this data even if its not reachable through any navigation path (FALSE).
* *
* @deprecated 3.2 Use the "SiteTree.enforce_strict_hierarchy" config setting instead * @deprecated 3.2 Use the "SiteTree.enforce_strict_hierarchy" config setting instead
* @param boolean * @param boolean
*/ */
@ -409,7 +409,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
) { ) {
return; // There were no suitable matches at all. return; // There were no suitable matches at all.
} }
$link = Convert::raw2att($page->Link()); $link = Convert::raw2att($page->Link());
if($content) { if($content) {
@ -445,7 +445,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
return Director::absoluteURL($this->Link($action)); return Director::absoluteURL($this->Link($action));
} }
} }
/** /**
* Base link used for previewing. Defaults to absolute URL, * Base link used for previewing. Defaults to absolute URL,
* in order to account for domain changes, e.g. on multi site setups. * in order to account for domain changes, e.g. on multi site setups.
@ -841,8 +841,8 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
} }
if(!$fromLive if(!$fromLive
&& !Session::get('unsecuredDraftSite') && !Session::get('unsecuredDraftSite')
&& !Permission::checkMember($member, array('CMS_ACCESS_CMSMain', 'VIEW_DRAFT_CONTENT'))) { && !Permission::checkMember($member, array('CMS_ACCESS_CMSMain', 'VIEW_DRAFT_CONTENT'))) {
// If we weren't definitely loaded from live, and we can't view non-live content, we need to // If we weren't definitely loaded from live, and we can't view non-live content, we need to
// check to make sure this version is the live version and so can be viewed // check to make sure this version is the live version and so can be viewed
if (Versioned::get_versionnumber_by_stage($this->class, 'Live', $this->ID) != $this->Version) return false; if (Versioned::get_versionnumber_by_stage($this->class, 'Live', $this->ID) != $this->Version) return false;
@ -876,11 +876,11 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
return false; return false;
} }
/** /**
* Determines canView permissions for the latest version of this Page on a specific stage (see {@link Versioned}). * Determines canView permissions for the latest version of this Page on a specific stage (see {@link Versioned}).
* Usually the stage is read from {@link Versioned::current_stage()}. * Usually the stage is read from {@link Versioned::current_stage()}.
* *
* @todo Implement in CMS UI. * @todo Implement in CMS UI.
* *
* @param String $stage * @param String $stage
@ -892,7 +892,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
Versioned::reading_stage($stage); Versioned::reading_stage($stage);
$versionFromStage = DataObject::get($this->class)->byID($this->ID); $versionFromStage = DataObject::get($this->class)->byID($this->ID);
Versioned::set_reading_mode($oldMode); Versioned::set_reading_mode($oldMode);
return $versionFromStage ? $versionFromStage->canView($member) : false; return $versionFromStage ? $versionFromStage->canView($member) : false;
} }
@ -1335,7 +1335,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
if($this->ExtraMeta) { if($this->ExtraMeta) {
$tags .= $this->ExtraMeta . "\n"; $tags .= $this->ExtraMeta . "\n";
} }
if(Permission::check('CMS_ACCESS_CMSMain') && in_array('CMSPreviewable', class_implements($this)) && !$this instanceof ErrorPage) { if(Permission::check('CMS_ACCESS_CMSMain') && in_array('CMSPreviewable', class_implements($this)) && !$this instanceof ErrorPage) {
$tags .= "<meta name=\"x-page-id\" content=\"{$this->ID}\" />\n"; $tags .= "<meta name=\"x-page-id\" content=\"{$this->ID}\" />\n";
$tags .= "<meta name=\"x-cms-edit-link\" content=\"" . $this->CMSEditLink() . "\" />\n"; $tags .= "<meta name=\"x-cms-edit-link\" content=\"" . $this->CMSEditLink() . "\" />\n";
@ -1605,10 +1605,10 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
'SiteTree', 'SiteTree',
"\"URLSegment\" = '$this->URLSegment' $IDFilter $parentFilter" "\"URLSegment\" = '$this->URLSegment' $IDFilter $parentFilter"
); );
return !($existingPage); return !($existingPage);
} }
/** /**
* Generate a URL segment based on the title provided. * Generate a URL segment based on the title provided.
* *
@ -1712,7 +1712,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
foreach($contentLinks as $item) { foreach($contentLinks as $item) {
$item->DependentLinkType = 'Content link'; $item->DependentLinkType = 'Content link';
$linkList->push($item); $linkList->push($item);
} }
$items->merge($linkList); $items->merge($linkList);
} }
@ -1724,9 +1724,9 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
foreach($virtuals as $item) { foreach($virtuals as $item) {
$item->DependentLinkType = 'Virtual page'; $item->DependentLinkType = 'Virtual page';
$virtualList->push($item); $virtualList->push($item);
}
$items->merge($virtualList);
} }
$items->merge($virtualList);
}
} }
// Redirector pages // Redirector pages
@ -1736,7 +1736,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
foreach($redirectors as $item) { foreach($redirectors as $item) {
$item->DependentLinkType = 'Redirector page'; $item->DependentLinkType = 'Redirector page';
$redirectorList->push($item); $redirectorList->push($item);
} }
$items->merge($redirectorList); $items->merge($redirectorList);
} }
@ -1999,9 +1999,9 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
->setAttribute( ->setAttribute(
'data-placeholder', 'data-placeholder',
_t('SiteTree.GroupPlaceholder', 'Click to select group') _t('SiteTree.GroupPlaceholder', 'Click to select group')
)
) )
) )
)
); );
$visibility->setTitle($this->fieldLabel('Visibility')); $visibility->setTitle($this->fieldLabel('Visibility'));
@ -2226,14 +2226,14 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
// Set up the initial state of the button to reflect the state of the underlying SiteTree object. // Set up the initial state of the button to reflect the state of the underlying SiteTree object.
if($this->stagesDiffer('Stage', 'Live')) { if($this->stagesDiffer('Stage', 'Live')) {
$publish->addExtraClass('ss-ui-alternate'); $publish->addExtraClass('ss-ui-alternate');
}
} }
}
$actions = new FieldList(array($majorActions, $rootTabSet)); $actions = new FieldList(array($majorActions, $rootTabSet));
// Hook for extensions to add/remove actions. // Hook for extensions to add/remove actions.
$this->extend('updateCMSActions', $actions); $this->extend('updateCMSActions', $actions);
return $actions; return $actions;
} }
@ -2666,7 +2666,7 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
if(!$this->canEdit() && !$this->canAddChildren()) { if(!$this->canEdit() && !$this->canAddChildren()) {
if (!$this->canView()) { if (!$this->canView()) {
$classes .= " disabled"; $classes .= " disabled";
} else { } else {
$classes .= " edit-disabled"; $classes .= " edit-disabled";
} }

View File

@ -11,7 +11,7 @@
class ZZZSearchFormTest extends FunctionalTest { class ZZZSearchFormTest extends FunctionalTest {
protected static $fixture_file = 'SearchFormTest.yml'; protected static $fixture_file = 'SearchFormTest.yml';
protected $mockController; protected $mockController;
public function waitUntilIndexingFinished() { public function waitUntilIndexingFinished() {
@ -37,7 +37,7 @@ class ZZZSearchFormTest extends FunctionalTest {
$this->waitUntilIndexingFinished(); $this->waitUntilIndexingFinished();
} }
/** /**
* @return Boolean * @return Boolean
*/ */
@ -101,7 +101,7 @@ class ZZZSearchFormTest extends FunctionalTest {
'Unpublished pages are not found by searchform' 'Unpublished pages are not found by searchform'
); );
} }
public function testPagesRestrictedToLoggedinUsersNotIncluded() { public function testPagesRestrictedToLoggedinUsersNotIncluded() {
if(!$this->checkFulltextSupport()) return; if(!$this->checkFulltextSupport()) return;
@ -109,7 +109,6 @@ class ZZZSearchFormTest extends FunctionalTest {
$page = $this->objFromFixture('SiteTree', 'restrictedViewLoggedInUsers'); $page = $this->objFromFixture('SiteTree', 'restrictedViewLoggedInUsers');
$page->publish('Stage', 'Live'); $page->publish('Stage', 'Live');
$results = $sf->getResults(null, array('Search'=>'restrictedViewLoggedInUsers')); $results = $sf->getResults(null, array('Search'=>'restrictedViewLoggedInUsers'));
$this->assertNotContains( $this->assertNotContains(
$page->ID, $page->ID,
@ -135,7 +134,6 @@ class ZZZSearchFormTest extends FunctionalTest {
$page = $this->objFromFixture('SiteTree', 'restrictedViewOnlyWebsiteUsers'); $page = $this->objFromFixture('SiteTree', 'restrictedViewOnlyWebsiteUsers');
$page->publish('Stage', 'Live'); $page->publish('Stage', 'Live');
$results = $sf->getResults(null, array('Search'=>'restrictedViewOnlyWebsiteUsers')); $results = $sf->getResults(null, array('Search'=>'restrictedViewOnlyWebsiteUsers'));
$this->assertNotContains( $this->assertNotContains(
$page->ID, $page->ID,
@ -165,16 +163,13 @@ class ZZZSearchFormTest extends FunctionalTest {
} }
public function testInheritedRestrictedPagesNotIncluded() { public function testInheritedRestrictedPagesNotIncluded() {
if(!$this->checkFulltextSupport()) return;
$sf = new SearchForm($this->mockController, 'SearchForm'); $sf = new SearchForm($this->mockController, 'SearchForm');
$parent = $this->objFromFixture('SiteTree', 'restrictedViewLoggedInUsers'); $parent = $this->objFromFixture('SiteTree', 'restrictedViewLoggedInUsers');
$parent->publish('Stage', 'Live'); $parent->publish('Stage', 'Live');
$page = $this->objFromFixture('SiteTree', 'inheritRestrictedView'); $page = $this->objFromFixture('SiteTree', 'inheritRestrictedView');
$page->publish('Stage', 'Live'); $page->publish('Stage', 'Live');
$results = $sf->getResults(null, array('Search'=>'inheritRestrictedView')); $results = $sf->getResults(null, array('Search'=>'inheritRestrictedView'));
$this->assertNotContains( $this->assertNotContains(
$page->ID, $page->ID,