Compare commits

..

2 Commits

Author SHA1 Message Date
Guy Sartorelli
7d4be94154
Merge d86064bee7 into 33929e2992 2024-10-07 22:48:52 +00:00
Guy Sartorelli
d86064bee7
API Refactor template layer into its own module
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
2024-10-08 11:48:43 +13:00
7 changed files with 26 additions and 20 deletions

View File

@ -91,7 +91,7 @@ class Controller extends RequestHandler implements TemplateGlobalProvider
'handleIndex', 'handleIndex',
]; ];
private ?TemplateEngine $templateEngine = null; protected ?TemplateEngine $templateEngine = null;
public function __construct() public function __construct()
{ {

View File

@ -1149,7 +1149,9 @@ class SSTemplateParser extends Parser implements TemplateParser
if ($res['ArgumentCount'] != 0) { if ($res['ArgumentCount'] != 0) {
throw new SSTemplateParseException('Base_tag takes no arguments', $this); throw new SSTemplateParseException('Base_tag takes no arguments', $this);
} }
return '$val .= \\SilverStripe\\View\\SSViewer::get_base_tag($val);'; $code = '$isXhtml = preg_match(\'/<!DOCTYPE[^>]+xhtml/i\', $val);';
$code .= PHP_EOL . '$val .= \\SilverStripe\\View\\SSViewer::get_base_tag($isXhtml);';
return $code;
} }
/** /**

View File

@ -4434,7 +4434,9 @@ class SSTemplateParser extends Parser implements TemplateParser
if ($res['ArgumentCount'] != 0) { if ($res['ArgumentCount'] != 0) {
throw new SSTemplateParseException('Base_tag takes no arguments', $this); throw new SSTemplateParseException('Base_tag takes no arguments', $this);
} }
return '$val .= \\SilverStripe\\View\\SSViewer::get_base_tag($val);'; $code = '$isXhtml = preg_match(\'/<!DOCTYPE[^>]+xhtml/i\', $val);';
$code .= PHP_EOL . '$val .= \\SilverStripe\\View\\SSViewer::get_base_tag($isXhtml);';
return $code;
} }
/** /**

View File

@ -413,20 +413,17 @@ PHP;
* Return an appropriate base tag for the given template. * Return an appropriate base tag for the given template.
* It will be closed on an XHTML document, and unclosed on an HTML document. * It will be closed on an XHTML document, and unclosed on an HTML document.
* *
* @param string $contentGeneratedSoFar The content of the template generated so far; it should contain * @param bool $isXhtml Whether the DOCTYPE is xhtml or not.
* the DOCTYPE declaration.
* @return string
*/ */
public static function get_base_tag($contentGeneratedSoFar) public static function get_base_tag(bool $isXhtml = false): string
{ {
// Base href should always have a trailing slash // Base href should always have a trailing slash
$base = rtrim(Director::absoluteBaseURL(), '/') . '/'; $base = rtrim(Director::absoluteBaseURL(), '/') . '/';
// Is the document XHTML? if ($isXhtml) {
if (preg_match('/<!DOCTYPE[^>]+xhtml/i', $contentGeneratedSoFar ?? '')) {
return "<base href=\"$base\" />"; return "<base href=\"$base\" />";
} else { } else {
return "<base href=\"$base\"><!--[if lte IE 6]></base><![endif]-->"; return "<base href=\"$base\">";
} }
} }

View File

@ -21,6 +21,8 @@ class ViewLayerData implements IteratorAggregate, Stringable, Countable
public const TYPE_METHOD = 'method'; public const TYPE_METHOD = 'method';
public const TYPE_ANY = 'any';
private object $data; private object $data;
public function __construct(mixed $data, mixed $source = null, string $name = '') public function __construct(mixed $data, mixed $source = null, string $name = '')
@ -42,18 +44,21 @@ class ViewLayerData implements IteratorAggregate, Stringable, Countable
*/ */
public function count(): int public function count(): int
{ {
if (ClassInfo::hasMethod($this->data, 'count')) {
$count = $this->callDataMethod($this->data, 'count', []);
if ($count !== null) {
return $count;
}
}
if (isset($this->data->count)) {
return $this->data->count;
}
if (is_countable($this->data)) { if (is_countable($this->data)) {
return count($this->data); return count($this->data);
} }
if (ClassInfo::hasMethod($this->data, 'getIterator')) { if (ClassInfo::hasMethod($this->data, 'getIterator')) {
return count($this->data->getIterator()); return count($this->data->getIterator());
} }
if (ClassInfo::hasMethod($this->data, 'count')) {
return $this->data->count();
}
if (isset($this->data->count)) {
return $this->data->count;
}
return 0; return 0;
} }
@ -133,9 +138,9 @@ class ViewLayerData implements IteratorAggregate, Stringable, Countable
// @TODO We need this publicly right now for the ss template engine method args, but need to check if // @TODO We need this publicly right now for the ss template engine method args, but need to check if
// we can rely on it, since twig won't be calling this at all // we can rely on it, since twig won't be calling this at all
public function getRawDataValue(string $name, string $type, array $arguments = []): mixed public function getRawDataValue(string $name, string $type = ViewLayerData::TYPE_ANY, array $arguments = []): mixed
{ {
if ($type !== ViewLayerData::TYPE_METHOD && $type !== ViewLayerData::TYPE_PROPERTY) { if ($type !== ViewLayerData::TYPE_ANY && $type !== ViewLayerData::TYPE_METHOD && $type !== ViewLayerData::TYPE_PROPERTY) {
throw new InvalidArgumentException('$type must be one of the TYPE_* constant values'); throw new InvalidArgumentException('$type must be one of the TYPE_* constant values');
} }

View File

@ -56,7 +56,7 @@ class TestComponent extends RequestHandler implements GridField_URLHandler
public function showform(GridField $gridField, HTTPRequest $request) public function showform(GridField $gridField, HTTPRequest $request)
{ {
$this->setRequest($request); $this->setRequest($request);
return "<head>" . SSViewer::get_base_tag("") . "</head>" . $this->Form($gridField, $request)->forTemplate(); return "<head>" . SSViewer::get_base_tag() . "</head>" . $this->Form($gridField, $request)->forTemplate();
} }
/** /**

View File

@ -36,7 +36,7 @@ class TestComponent_ItemRequest extends RequestHandler
public function showform() public function showform()
{ {
return "<head>" . SSViewer::get_base_tag("") . "</head>" . $this->Form()->forTemplate(); return "<head>" . SSViewer::get_base_tag() . "</head>" . $this->Form()->forTemplate();
} }
public function Form() public function Form()