Compare commits

...

6 Commits

Author SHA1 Message Date
Guy Sartorelli
6157338e59
ENH Improve type safety to support refactored template layer 2024-10-22 13:39:10 +13:00
github-actions
b05a24d5d1 Merge branch '5' into 6 2024-10-21 23:57:32 +00:00
Guy Sartorelli
42aed2b72e
API Deprecations for template layer (#3012) 2024-10-22 12:53:07 +13:00
Steve Boyd
84740116a9
Merge pull request #3015 from creative-commoners/pulls/6/new-admincontroller
API Update method signature to match parent class
2024-10-21 11:55:30 +13:00
Guy Sartorelli
b07789db44
API Update method signature to match parent class 2024-10-15 12:53:02 +13:00
Guy Sartorelli
2fa2aa356f
ENH Use config instead of runtime code to remove menu items 2024-10-15 12:51:55 +13:00
10 changed files with 108 additions and 40 deletions

View File

@ -1,10 +1,5 @@
<?php <?php
use SilverStripe\Admin\CMSMenu;
use SilverStripe\CMS\Controllers\CMSMain;
use SilverStripe\CMS\Controllers\CMSPageAddController;
use SilverStripe\CMS\Controllers\CMSPageEditController;
use SilverStripe\CMS\Controllers\CMSPageSettingsController;
use SilverStripe\CMS\Model\SiteTree; use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Core\Manifest\ModuleLoader; use SilverStripe\Core\Manifest\ModuleLoader;
use SilverStripe\Forms\HTMLEditor\TinyMCEConfig; use SilverStripe\Forms\HTMLEditor\TinyMCEConfig;
@ -31,8 +26,3 @@ ShortcodeParser::get('default')->register(
'sitetree_link', 'sitetree_link',
[SiteTree::class, 'link_shortcode_handler'] [SiteTree::class, 'link_shortcode_handler']
); );
CMSMenu::remove_menu_class(CMSMain::class);
CMSMenu::remove_menu_class(CMSPageEditController::class);
CMSMenu::remove_menu_class(CMSPageSettingsController::class);
CMSMenu::remove_menu_class(CMSPageAddController::class);

View File

@ -32,6 +32,8 @@ class CMSPageAddController extends CMSPageEditController
private static $menu_title = 'Add page'; private static $menu_title = 'Add page';
private static $required_permission_codes = 'CMS_ACCESS_CMSMain'; private static $required_permission_codes = 'CMS_ACCESS_CMSMain';
private static $ignore_menuitem = true;
private static $allowed_actions = [ private static $allowed_actions = [
'AddForm', 'AddForm',
'doAdd', 'doAdd',

View File

@ -28,11 +28,13 @@ class CMSPageEditController extends CMSMain
private static $required_permission_codes = 'CMS_ACCESS_CMSMain'; private static $required_permission_codes = 'CMS_ACCESS_CMSMain';
private static $ignore_menuitem = true;
private static $allowed_actions = [ private static $allowed_actions = [
'AddToCampaignForm', 'AddToCampaignForm',
]; ];
public function getClientConfig() public function getClientConfig(): array
{ {
return ArrayLib::array_merge_recursive(parent::getClientConfig(), [ return ArrayLib::array_merge_recursive(parent::getClientConfig(), [
'form' => [ 'form' => [

View File

@ -15,6 +15,8 @@ class CMSPageSettingsController extends CMSMain
private static $required_permission_codes = 'CMS_ACCESS_CMSMain'; private static $required_permission_codes = 'CMS_ACCESS_CMSMain';
private static $ignore_menuitem = true;
public function getEditForm($id = null, $fields = null) public function getEditForm($id = null, $fields = null)
{ {
$record = $this->getRecord($id ?: $this->currentPageID()); $record = $this->getRecord($id ?: $this->currentPageID());

View File

@ -289,14 +289,6 @@ class ContentController extends Controller
return new ArrayList($visible); return new ArrayList($visible);
} }
/**
* @return ArrayList<SiteTree>
*/
public function Menu($level)
{
return $this->getMenu($level);
}
/** /**
* Returns the default log-in form. * Returns the default log-in form.
* *
@ -413,23 +405,23 @@ HTML;
$action = $action === 'index' ? '' : '_' . $action; $action = $action === 'index' ? '' : '_' . $action;
$templatesFound = []; $templatesFound = [];
// Find templates for the record + action together - e.g. Page_action.ss // Find templates for the record + action together - e.g. Page_action
if ($this->dataRecord instanceof SiteTree) { if ($this->dataRecord instanceof SiteTree) {
$templatesFound[] = $this->dataRecord->getViewerTemplates($action); $templatesFound[] = $this->dataRecord->getViewerTemplates($action);
} }
// Find templates for the controller + action together - e.g. PageController_action.ss // Find templates for the controller + action together - e.g. PageController_action
$templatesFound[] = SSViewer::get_templates_by_class(static::class, $action, Controller::class); $templatesFound[] = SSViewer::get_templates_by_class(static::class, $action ?? '', Controller::class);
// Find templates for the record without an action - e.g. Page.ss // Find templates for the record without an action - e.g. Page
if ($this->dataRecord instanceof SiteTree) { if ($this->dataRecord instanceof SiteTree) {
$templatesFound[] = $this->dataRecord->getViewerTemplates(); $templatesFound[] = $this->dataRecord->getViewerTemplates();
} }
// Find the templates for the controller without an action - e.g. PageController.ss // Find the templates for the controller without an action - e.g. PageController
$templatesFound[] = SSViewer::get_templates_by_class(static::class, "", Controller::class); $templatesFound[] = SSViewer::get_templates_by_class(static::class, '', Controller::class);
$templates = array_merge(...$templatesFound); $templates = array_merge(...$templatesFound);
return SSViewer::create($templates); return SSViewer::create($templates, $this->getTemplateEngine());
} }
} }

View File

@ -1454,7 +1454,7 @@ class SiteTree extends DataObject implements PermissionProvider, i18nEntityProvi
$tags['title'] = [ $tags['title'] = [
'tag' => 'title', 'tag' => 'title',
'content' => $this->obj('Title')->forTemplate() 'content' => $this->obj('Title')?->forTemplate()
]; ];
$generator = $this->getGenerator(); $generator = $this->getGenerator();
@ -1601,7 +1601,7 @@ class SiteTree extends DataObject implements PermissionProvider, i18nEntityProvi
$tagString = implode("\n", $tags); $tagString = implode("\n", $tags);
if ($this->ExtraMeta) { if ($this->ExtraMeta) {
$tagString .= $this->obj('ExtraMeta')->forTemplate(); $tagString .= $this->obj('ExtraMeta')?->forTemplate();
} }
$this->extend('updateMetaTags', $tagString); $this->extend('updateMetaTags', $tagString);

View File

@ -33,7 +33,7 @@ class ThemeContext implements Context
} }
/** /**
* Create a template within a test theme * Create a template within a test theme. Only ss templates are supported.
* *
* @Given /^a template "(?<template>[^"]+)" in theme "(?<theme>[^"]+)" with content "(?<content>[^"]+)"/ * @Given /^a template "(?<template>[^"]+)" in theme "(?<theme>[^"]+)" with content "(?<content>[^"]+)"/
* @param string $template * @param string $template

View File

@ -5,6 +5,8 @@ namespace SilverStripe\CMS\Tests\Controllers;
use SilverStripe\CMS\Controllers\ContentController; use SilverStripe\CMS\Controllers\ContentController;
use SilverStripe\CMS\Controllers\RootURLController; use SilverStripe\CMS\Controllers\RootURLController;
use SilverStripe\CMS\Model\SiteTree; use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\CMS\Tests\Controllers\ContentControllerTest\DummyTemplateContentController;
use SilverStripe\CMS\Tests\Controllers\ContentControllerTest\DummyTemplateEngine;
use SilverStripe\Control\Director; use SilverStripe\Control\Director;
use SilverStripe\Control\HTTPResponse_Exception; use SilverStripe\Control\HTTPResponse_Exception;
use SilverStripe\Core\Config\Config; use SilverStripe\Core\Config\Config;
@ -162,7 +164,7 @@ class ContentControllerTest extends FunctionalTest
{ {
$this->useTestTheme(__DIR__, 'controllertest', function () { $this->useTestTheme(__DIR__, 'controllertest', function () {
// Test a page without a controller (ContentControllerTest_PageWithoutController.ss) // Test a page without a controller (ContentControllerTest_PageWithoutController)
$page = new ContentControllerTestPageWithoutController(); $page = new ContentControllerTestPageWithoutController();
$page->URLSegment = "test"; $page->URLSegment = "test";
$page->write(); $page->write();
@ -171,7 +173,7 @@ class ContentControllerTest extends FunctionalTest
$response = $this->get($page->RelativeLink()); $response = $this->get($page->RelativeLink());
$this->assertEquals("ContentControllerTestPageWithoutController", trim($response->getBody() ?? '')); $this->assertEquals("ContentControllerTestPageWithoutController", trim($response->getBody() ?? ''));
// This should fall over to user Page.ss // This should fall over to use Page
$page = new ContentControllerTestPage(); $page = new ContentControllerTestPage();
$page->URLSegment = "test"; $page->URLSegment = "test";
$page->write(); $page->write();
@ -191,20 +193,27 @@ class ContentControllerTest extends FunctionalTest
$this->assertEquals("ContentControllerTestPage_test", trim($response->getBody() ?? '')); $this->assertEquals("ContentControllerTestPage_test", trim($response->getBody() ?? ''));
// Test that an action without a template will default to the index template, which is // Test that an action without a template will default to the index template, which is
// to say the default Page.ss template // to say the default Page template
$response = $this->get($page->RelativeLink("testwithouttemplate")); $response = $this->get($page->RelativeLink("testwithouttemplate"));
$this->assertEquals("Page", trim($response->getBody() ?? '')); $this->assertEquals("Page", trim($response->getBody() ?? ''));
// Test that an action with a template will render the both action template *and* the // Test that an action with a template will render both the action template *and* the
// correct parent template // correct parent template
$controller = new ContentController($page); $controller = new DummyTemplateContentController($page);
$viewer = $controller->getViewer('test'); $viewer = $controller->getViewer('test');
$this->assertEquals( /** @var DummyTemplateEngine $engine */
__DIR__ $engine = $viewer->getTemplateEngine();
. '/themes/controllertest/templates/SilverStripe/CMS/Tests/Controllers/' $templateCandidates = $engine->getTemplates();
. 'ContentControllerTestPage_test.ss', // Check for the action templates
$viewer->templates()['main'] $this->assertContains('SilverStripe\CMS\Tests\Controllers\ContentControllerTestPage_test', $templateCandidates);
); $this->assertContains('SilverStripe\CMS\Model\SiteTree_test', $templateCandidates);
$this->assertContains('SilverStripe\CMS\Tests\Controllers\ContentControllerTest\DummyTemplateContentController_test', $templateCandidates);
$this->assertContains('SilverStripe\CMS\Controllers\ContentController_test', $templateCandidates);
// Check for the parent templates
$this->assertContains('SilverStripe\CMS\Tests\Controllers\ContentControllerTestPage', $templateCandidates);
$this->assertContains('SilverStripe\CMS\Model\SiteTree', $templateCandidates);
$this->assertContains('SilverStripe\CMS\Tests\Controllers\ContentControllerTest\DummyTemplateContentController', $templateCandidates);
$this->assertContains('SilverStripe\CMS\Controllers\ContentController', $templateCandidates);
}); });
} }
} }

View File

@ -0,0 +1,15 @@
<?php
namespace SilverStripe\CMS\Tests\Controllers\ContentControllerTest;
use SilverStripe\CMS\Controllers\ContentController;
use SilverStripe\Dev\TestOnly;
use SilverStripe\View\TemplateEngine;
class DummyTemplateContentController extends ContentController implements TestOnly
{
protected function getTemplateEngine(): TemplateEngine
{
return new DummyTemplateEngine();
}
}

View File

@ -0,0 +1,56 @@
<?php
namespace SilverStripe\CMS\Tests\Controllers\ContentControllerTest;
use SilverStripe\Dev\TestOnly;
use SilverStripe\View\TemplateEngine;
use SilverStripe\View\ViewLayerData;
/**
* A dummy template renderer that doesn't actually render any templates.
*/
class DummyTemplateEngine implements TemplateEngine, TestOnly
{
private string $output = '<html><head></head><body></body></html>';
private string|array $templates;
public function __construct(string|array $templateCandidates = [])
{
$this->templates = $templateCandidates;
}
public function setTemplate(string|array $templateCandidates): static
{
$this->templates = $templateCandidates;
return $this;
}
public function hasTemplate(string|array $templateCandidates): bool
{
return true;
}
public function renderString(string $template, ViewLayerData $model, array $overlay = [], bool $cache = true): string
{
return $this->output;
}
public function render(ViewLayerData $model, array $overlay = []): string
{
return $this->output;
}
public function setOutput(string $output): void
{
$this->output = $output;
}
/**
* Returns the template candidates that were passed to the constructor or to setTemplate()
*/
public function getTemplates(): array
{
return $this->templates;
}
}