FIX: VirtualPage not using target page's template (fixes #2039) (#2041)

* FIX: VirtualPage refreshFromCopied creates duplicate URLSegments on first write

* FIX: VirtualPage not using target page's template (fixes #2039)
This commit is contained in:
Loz Calver 2017-12-05 22:59:30 +00:00 committed by Damian Mooyman
parent 363fea3de0
commit 7efe667a48
4 changed files with 50 additions and 12 deletions

View File

@ -440,16 +440,24 @@ HTML;
$action = '_' . $action;
}
$templates = array_merge(
// Find templates by dataRecord
SSViewer::get_templates_by_class(get_class($this->dataRecord), $action, "SilverStripe\\CMS\\Model\\SiteTree"),
// Next, we need to add templates for all controllers
SSViewer::get_templates_by_class(static::class, $action, "SilverStripe\\Control\\Controller"),
// Fail-over to the same for the "index" action
SSViewer::get_templates_by_class(get_class($this->dataRecord), "", "SilverStripe\\CMS\\Model\\SiteTree"),
SSViewer::get_templates_by_class(static::class, "", "SilverStripe\\Control\\Controller")
);
$templatesFound = [];
// Find templates for the record + action together - e.g. Page_action.ss
if ($this->dataRecord instanceof SiteTree) {
$templatesFound[] = $this->dataRecord->getViewerTemplates($action);
}
// Find templates for the controller + action together - e.g. PageController_action.ss
$templatesFound[] = SSViewer::get_templates_by_class(static::class, $action, Controller::class);
// Find templates for the record without an action - e.g. Page.ss
if ($this->dataRecord instanceof SiteTree) {
$templatesFound[] = $this->dataRecord->getViewerTemplates();
}
// Find the templates for the controller without an action - e.g. PageController.ss
$templatesFound[] = SSViewer::get_templates_by_class(static::class, "", Controller::class);
$templates = array_merge(...$templatesFound);
return SSViewer::create($templates);
}

View File

@ -2,6 +2,7 @@
namespace SilverStripe\CMS\Model;
use Page;
use SilverStripe\Core\Convert;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\LiteralField;
@ -9,9 +10,9 @@ use SilverStripe\Forms\ReadonlyTransformation;
use SilverStripe\Forms\TreeDropdownField;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\ValidationResult;
use SilverStripe\Versioned\Versioned;
use SilverStripe\Security\Member;
use Page;
use SilverStripe\Versioned\Versioned;
use SilverStripe\View\SSViewer;
/**
* Virtual Page creates an instance of a page, with the same fields that the original page had, but readonly.
@ -277,8 +278,8 @@ class VirtualPage extends Page
public function onBeforeWrite()
{
parent::onBeforeWrite();
$this->refreshFromCopied();
parent::onBeforeWrite();
}
/**
@ -368,6 +369,22 @@ class VirtualPage extends Page
return parent::CMSTreeClasses() . ' VirtualPage-' . $this->CopyContentFrom()->ClassName;
}
/**
* Use the target page's class name for fetching templates - as we need to take on its appearance
*
* @param string $suffix
* @return array
*/
public function getViewerTemplates($suffix = '')
{
$copy = $this->CopyContentFrom();
if ($copy && $copy->exists()) {
return $copy->getViewerTemplates($suffix);
}
return parent::getViewerTemplates($suffix);
}
/**
* Allow attributes on the master page to pass
* through to the virtual page

View File

@ -632,6 +632,18 @@ class VirtualPageTest extends FunctionalTest
$this->assertEquals(200, $response->getStatusCode());
$this->assertContains('TestContent', $response->getBody());
$this->assertNotContains('NotThisContent', $response->getBody());
// VirtualPageTest_ClassB doesn't have an associated controller for
// ModelAsController::controller_for() to find
$page = new VirtualPageTest_ClassB();
$page->Title = 'Test Page B';
$page->write();
$vp = new VirtualPage();
$vp->CopyContentFromID = $page->ID;
$vp->write();
$response = $this->get($vp->Link());
$this->assertEquals(200, $response->getStatusCode());
$this->assertContains('Test Page B', $response->getBody());
});
}