Skip to content

Commit 6b33b5a

Browse files
API Refactor template layer (#11405)
Includes the following large-scale changes: - Impoved barrier between model and view layers - Improved casting of scalar to relevant DBField types - Improved capabilities for rendering arbitrary data in templates
1 parent 57ae271 commit 6b33b5a

File tree

187 files changed

+6173
-4755
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

187 files changed

+6173
-4755
lines changed

_config/view.yml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
Name: view-config
3+
---
4+
SilverStripe\Core\Injector\Injector:
5+
SilverStripe\View\TemplateEngine:
6+
class: 'SilverStripe\View\SSTemplateEngine'

src/Control/ContentNegotiator.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ public function html(HTTPResponse $response)
225225
// Fix base tag
226226
$content = preg_replace(
227227
'/<base href="([^"]*)" \/>/',
228-
'<base href="$1"><!--[if lte IE 6]></base><![endif]-->',
228+
'<base href="$1">',
229229
$content ?? ''
230230
);
231231

src/Control/Controller.php

+29-7
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
namespace SilverStripe\Control;
44

55
use SilverStripe\Core\ClassInfo;
6+
use SilverStripe\Core\Injector\Injector;
67
use SilverStripe\Dev\Debug;
8+
use SilverStripe\Model\ModelData;
79
use SilverStripe\ORM\FieldType\DBHTMLText;
810
use SilverStripe\Security\Member;
911
use SilverStripe\Security\Security;
1012
use SilverStripe\View\SSViewer;
13+
use SilverStripe\View\TemplateEngine;
1114
use SilverStripe\View\TemplateGlobalProvider;
1215

1316
/**
@@ -87,6 +90,8 @@ class Controller extends RequestHandler implements TemplateGlobalProvider
8790
'handleIndex',
8891
];
8992

93+
protected ?TemplateEngine $templateEngine = null;
94+
9095
public function __construct()
9196
{
9297
parent::__construct();
@@ -400,7 +405,7 @@ public function getViewer($action)
400405
$templates = array_unique(array_merge($actionTemplates, $classTemplates));
401406
}
402407

403-
return SSViewer::create($templates);
408+
return SSViewer::create($templates, $this->getTemplateEngine());
404409
}
405410

406411
/**
@@ -452,9 +457,10 @@ protected function definingClassForAction($action)
452457
}
453458

454459
$class = static::class;
455-
while ($class != 'SilverStripe\\Control\\RequestHandler') {
460+
$engine = $this->getTemplateEngine();
461+
while ($class !== RequestHandler::class) {
456462
$templateName = strtok($class ?? '', '_') . '_' . $action;
457-
if (SSViewer::hasTemplate($templateName)) {
463+
if ($engine->hasTemplate($templateName)) {
458464
return $class;
459465
}
460466

@@ -486,17 +492,25 @@ public function hasActionTemplate($action)
486492
$parentClass = get_parent_class($parentClass ?? '');
487493
}
488494

489-
return SSViewer::hasTemplate($templates);
495+
$engine = $this->getTemplateEngine();
496+
return $engine->hasTemplate($templates);
497+
}
498+
499+
public function renderWith($template, ModelData|array $customFields = []): DBHTMLText
500+
{
501+
// Ensure template engine is used, unless the viewer was already explicitly instantiated
502+
if (!($template instanceof SSViewer)) {
503+
$template = SSViewer::create($template, $this->getTemplateEngine());
504+
}
505+
return parent::renderWith($template, $customFields);
490506
}
491507

492508
/**
493509
* Render the current controller with the templates determined by {@link getViewer()}.
494510
*
495511
* @param array $params
496-
*
497-
* @return string
498512
*/
499-
public function render($params = null)
513+
public function render($params = null): DBHTMLText
500514
{
501515
$template = $this->getViewer($this->getAction());
502516

@@ -735,4 +749,12 @@ public static function get_template_global_variables()
735749
'CurrentPage' => 'curr',
736750
];
737751
}
752+
753+
protected function getTemplateEngine(): TemplateEngine
754+
{
755+
if (!$this->templateEngine) {
756+
$this->templateEngine = Injector::inst()->create(TemplateEngine::class);
757+
}
758+
return $this->templateEngine;
759+
}
738760
}

src/Control/Email/Email.php

+7-14
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class Email extends SymfonyEmail
4646
private static string|array $admin_email = '';
4747

4848
/**
49-
* The name of the HTML template to render the email with (without *.ss extension)
49+
* The name of the HTML template to render the email with
5050
*/
5151
private string $HTMLTemplate = '';
5252

@@ -398,26 +398,21 @@ public function removeData(string $name)
398398
return $this;
399399
}
400400

401-
public function getHTMLTemplate(): string
401+
public function getHTMLTemplate(): string|array
402402
{
403403
if ($this->HTMLTemplate) {
404404
return $this->HTMLTemplate;
405405
}
406406

407-
return ThemeResourceLoader::inst()->findTemplate(
408-
SSViewer::get_templates_by_class(static::class, '', Email::class),
409-
SSViewer::get_themes()
410-
);
407+
return SSViewer::get_templates_by_class(static::class, '', Email::class);
411408
}
412409

413410
/**
414-
* Set the template to render the email with
411+
* Set the template to render the email with.
412+
* Do not include a file extension unless you are referencing a full absolute file path.
415413
*/
416414
public function setHTMLTemplate(string $template): static
417415
{
418-
if (substr($template ?? '', -3) == '.ss') {
419-
$template = substr($template ?? '', 0, -3);
420-
}
421416
$this->HTMLTemplate = $template;
422417
return $this;
423418
}
@@ -431,13 +426,11 @@ public function getPlainTemplate(): string
431426
}
432427

433428
/**
434-
* Set the template to render the plain part with
429+
* Set the template to render the plain part with.
430+
* Do not include a file extension unless you are referencing a full absolute file path.
435431
*/
436432
public function setPlainTemplate(string $template): static
437433
{
438-
if (substr($template ?? '', -3) == '.ss') {
439-
$template = substr($template ?? '', 0, -3);
440-
}
441434
$this->plainTemplate = $template;
442435
return $this;
443436
}

src/Control/HTTPResponse.php

-2
Original file line numberDiff line numberDiff line change
@@ -444,8 +444,6 @@ public function isRedirect()
444444

445445
/**
446446
* The HTTP response represented as a raw string
447-
*
448-
* @return string
449447
*/
450448
public function __toString()
451449
{

src/Control/RSS/RSSFeed_Entry.php

+5-5
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class RSSFeed_Entry extends ModelData
4747
*/
4848
public function __construct($entry, $titleField, $descriptionField, $authorField)
4949
{
50-
$this->failover = $entry;
50+
$this->setFailover($entry);
5151
$this->titleField = $titleField;
5252
$this->descriptionField = $descriptionField;
5353
$this->authorField = $authorField;
@@ -58,7 +58,7 @@ public function __construct($entry, $titleField, $descriptionField, $authorField
5858
/**
5959
* Get the description of this entry
6060
*
61-
* @return DBField Returns the description of the entry.
61+
* @return DBField|null Returns the description of the entry.
6262
*/
6363
public function Title()
6464
{
@@ -68,7 +68,7 @@ public function Title()
6868
/**
6969
* Get the description of this entry
7070
*
71-
* @return DBField Returns the description of the entry.
71+
* @return DBField|null Returns the description of the entry.
7272
*/
7373
public function Description()
7474
{
@@ -85,7 +85,7 @@ public function Description()
8585
/**
8686
* Get the author of this entry
8787
*
88-
* @return DBField Returns the author of the entry.
88+
* @return DBField|null Returns the author of the entry.
8989
*/
9090
public function Author()
9191
{
@@ -96,7 +96,7 @@ public function Author()
9696
* Return the safely casted field
9797
*
9898
* @param string $fieldName Name of field
99-
* @return DBField
99+
* @return DBField|null
100100
*/
101101
public function rssField($fieldName)
102102
{

src/Core/Manifest/ModuleResource.php

-2
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,6 @@ public function exists()
114114

115115
/**
116116
* Get relative path
117-
*
118-
* @return string
119117
*/
120118
public function __toString()
121119
{

src/Dev/Backtrace.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,11 @@ public static function full_func_name($item, $showArgs = false, $argCharLimit =
149149
if ($showArgs && isset($item['args'])) {
150150
$args = [];
151151
foreach ($item['args'] as $arg) {
152-
if (!is_object($arg) || method_exists($arg, '__toString')) {
152+
if (is_object($arg)) {
153+
$args[] = get_class($arg);
154+
} else {
153155
$sarg = is_array($arg) ? 'Array' : strval($arg);
154156
$args[] = (strlen($sarg ?? '') > $argCharLimit) ? substr($sarg, 0, $argCharLimit) . '...' : $sarg;
155-
} else {
156-
$args[] = get_class($arg);
157157
}
158158
}
159159

src/Dev/TestSession.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Exception;
66
use InvalidArgumentException;
7+
use LogicException;
78
use SilverStripe\Control\Controller;
89
use SilverStripe\Control\Cookie_Backend;
910
use SilverStripe\Control\Director;
@@ -214,7 +215,7 @@ public function submitForm(string $formID, string $button = null, array $data =
214215
$formCrawler = $page->filterXPath("//form[@id='$formID']");
215216
$form = $formCrawler->form();
216217
} catch (InvalidArgumentException $e) {
217-
user_error("TestSession::submitForm failed to find the form {$formID}");
218+
throw new LogicException("TestSession::submitForm failed to find the form '{$formID}'");
218219
}
219220

220221
foreach ($data as $fieldName => $value) {
@@ -235,7 +236,7 @@ public function submitForm(string $formID, string $button = null, array $data =
235236
if ($button) {
236237
$btnXpath = "//button[@name='$button'] | //input[@name='$button'][@type='button' or @type='submit']";
237238
if (!$formCrawler->children()->filterXPath($btnXpath)->count()) {
238-
throw new Exception("Can't find button '$button' to submit as part of test.");
239+
throw new LogicException("Can't find button '$button' to submit as part of test.");
239240
}
240241
$values[$button] = true;
241242
}

src/Forms/DropdownField.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
* DropdownField::create(
6969
* 'Country',
7070
* 'Country',
71-
* singleton(MyObject::class)->dbObject('Country')->enumValues()
71+
* singleton(MyObject::class)->dbObject('Country')?->enumValues()
7272
* );
7373
* </code>
7474
*

src/Forms/FieldGroup.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ public function getMessage()
154154
/** @var FormField $subfield */
155155
$messages = [];
156156
foreach ($dataFields as $subfield) {
157-
$message = $subfield->obj('Message')->forTemplate();
157+
$message = $subfield->obj('Message')?->forTemplate();
158158
if ($message) {
159159
$messages[] = rtrim($message ?? '', ".");
160160
}

src/Forms/Form.php

+6-6
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class Form extends ModelData implements HasRequestHandler
8282
const ENC_TYPE_MULTIPART = 'multipart/form-data';
8383

8484
/**
85-
* Accessed by Form.ss.
85+
* Accessed by Form template.
8686
* A performance enhancement over the generate-the-form-tag-and-then-remove-it code that was there previously
8787
*
8888
* @var bool
@@ -159,7 +159,7 @@ class Form extends ModelData implements HasRequestHandler
159159
/**
160160
* Legend value, to be inserted into the
161161
* <legend> element before the <fieldset>
162-
* in Form.ss template.
162+
* in Form template.
163163
*
164164
* @var string|null
165165
*/
@@ -888,7 +888,7 @@ public function setTarget($target)
888888

889889
/**
890890
* Set the legend value to be inserted into
891-
* the <legend> element in the Form.ss template.
891+
* the <legend> element in the Form template.
892892
* @param string $legend
893893
* @return $this
894894
*/
@@ -899,10 +899,10 @@ public function setLegend($legend)
899899
}
900900

901901
/**
902-
* Set the SS template that this form should use
902+
* Set the template or template candidates that this form should use
903903
* to render with. The default is "Form".
904904
*
905-
* @param string|array $template The name of the template (without the .ss extension) or array form
905+
* @param string|array $template The name of the template (without the file extension) or array of candidates
906906
* @return $this
907907
*/
908908
public function setTemplate($template)
@@ -1234,7 +1234,7 @@ public function getRecord()
12341234

12351235
/**
12361236
* Get the legend value to be inserted into the
1237-
* <legend> element in Form.ss
1237+
* <legend> element in Form template
12381238
*
12391239
* @return string
12401240
*/

0 commit comments

Comments
 (0)