Merge remote-tracking branch 'origin/3.1'

This commit is contained in:
Damian Mooyman 2014-04-22 12:10:49 +12:00
commit 61ebe08437
3 changed files with 78 additions and 1 deletions

View File

@ -754,7 +754,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
$columns->setDisplayFields($fields); $columns->setDisplayFields($fields);
$columns->setFieldCasting(array( $columns->setFieldCasting(array(
'Created' => 'Datetime->Ago', 'Created' => 'Datetime->Ago',
'LastEdited' => 'Datetime->Ago', 'LastEdited' => 'Datetime->FormatFromSettings',
'getTreeTitle' => 'HTMLText' 'getTreeTitle' => 'HTMLText'
)); ));

View File

@ -586,6 +586,22 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
); );
} }
/**
* Check if the parent of this page has been removed (or made otherwise unavailable), and
* is still referenced by this child. Any such orphaned page may still require access via
* the cms, but should not be shown as accessible to external users.
*
* @return bool
*/
public function isOrphaned() {
// Always false for root pages
if(empty($this->ParentID)) return false;
// Parent must exist and not be an orphan itself
$parent = $this->Parent();
return !$parent || !$parent->exists() || $parent->isOrphaned();
}
/** /**
* Return "link" or "current" depending on if this is the {@link SiteTree::isCurrent()} current page. * Return "link" or "current" depending on if this is the {@link SiteTree::isCurrent()} current page.
* *
@ -886,6 +902,9 @@ class SiteTree extends DataObject implements PermissionProvider,i18nEntityProvid
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;
} }
// Orphaned pages (in the current stage) are unavailable, except for admins via the CMS
if($this->isOrphaned()) return false;
// Standard mechanism for accepting permission changes from extensions // Standard mechanism for accepting permission changes from extensions
$extended = $this->extendedCan('canView', $member); $extended = $this->extendedCan('canView', $member);
if($extended !== null) return $extended; if($extended !== null) return $extended;

View File

@ -944,6 +944,64 @@ class SiteTreeTest extends SapphireTest {
Config::inst()->update('SiteTree', 'meta_generator', $generator); Config::inst()->update('SiteTree', 'meta_generator', $generator);
} }
/**
* Test that orphaned pages are handled correctly
*/
public function testOrphanedPages() {
$origStage = Versioned::get_reading_mode();
// Setup user who can view draft content, but lacks cms permission.
// To users such as this, orphaned pages should be inaccessible. canView for these pages is only
// necessary for admin / cms users, who require this permission to edit / rearrange these pages.
$permission = new Permission();
$permission->Code = 'VIEW_DRAFT_CONTENT';
$group = new Group(array('Title' => 'Staging Users'));
$group->write();
$group->Permissions()->add($permission);
$member = new Member();
$member->Email = 'someguy@example.com';
$member->write();
$member->Groups()->add($group);
// both pages are viewable in stage
Versioned::reading_stage('Stage');
$about = $this->objFromFixture('Page', 'about');
$staff = $this->objFromFixture('Page', 'staff');
$this->assertFalse($about->isOrphaned());
$this->assertFalse($staff->isOrphaned());
$this->assertTrue($about->canView($member));
$this->assertTrue($staff->canView($member));
// Publishing only the child page to live should orphan the live record, but not the staging one
$staff->publish('Stage', 'Live');
$this->assertFalse($staff->isOrphaned());
$this->assertTrue($staff->canView($member));
Versioned::reading_stage('Live');
$staff = $this->objFromFixture('Page', 'staff'); // Live copy of page
$this->assertTrue($staff->isOrphaned()); // because parent isn't published
$this->assertFalse($staff->canView($member));
// Publishing the parent page should restore visibility
Versioned::reading_stage('Stage');
$about = $this->objFromFixture('Page', 'about');
$about->publish('Stage', 'Live');
Versioned::reading_stage('Live');
$staff = $this->objFromFixture('Page', 'staff');
$this->assertFalse($staff->isOrphaned());
$this->assertTrue($staff->canView($member));
// Removing staging page should not prevent live page being visible
$about->deleteFromStage('Stage');
$staff->deleteFromStage('Stage');
$staff = $this->objFromFixture('Page', 'staff');
$this->assertFalse($staff->isOrphaned());
$this->assertTrue($staff->canView($member));
// Cleanup
Versioned::set_reading_mode($origStage);
}
} }
/**#@+ /**#@+