Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOC Document changes to template layer #591

Open
wants to merge 1 commit into
base: 6
Choose a base branch
from

Conversation

GuySartorelli
Copy link
Member

@GuySartorelli GuySartorelli marked this pull request as draft September 26, 2024 04:27
@GuySartorelli GuySartorelli force-pushed the pulls/6/refactor-template-layer branch 3 times, most recently from 94d90fe to 827cb70 Compare October 4, 2024 00:21
@GuySartorelli GuySartorelli force-pushed the pulls/6/refactor-template-layer branch 8 times, most recently from a6f45e5 to fd791b5 Compare October 14, 2024 02:57
@GuySartorelli GuySartorelli marked this pull request as ready for review October 23, 2024 02:37
Comment on lines -72 to +71
$Foo(param)
$Foo("param")
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mostly-unrelated update to promote best practice

$Foo.Bar
```

These variables will call a method / field on the object and insert the returned value as a string into the template.

Arguments don't have to be literals - you can pass template variables as arguments as well.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is new and was mostly just a natural consequence of how we're wrapping data now. Very useful though, I'm already gonna use it in the CMSMain refactor.

Comment on lines -79 to +80
> If you wish to pass arguments to getter functions, you must use the full method name. e.g. `$Thing` will try to access `Thing` as a property, which will ultimately result in `getThing()` being called with no arguments To pass arguments you must use `$getThing('param')`.
>
> Also, arguments must be literals, and cannot be other template variables (`$getThing($variable)` will pass the literal string `'$variable'` to the `getThing()` method).
> Arguments cannot be literal arrays (e.g `$myMethod(["val1", "val2"])`). The behaviour for this is currently undefined.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was mostly saying "you can't pass template variables as arguments" which as noted above is no longer the case. It's just array literals you can't do now.

> Arguments passed into methods can be any non-array literal type (not just strings), e.g:
> Arguments passed into methods can be almost any type (not just strings), e.g:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At first glance you might think to leave as-is cause we still can't do arrays - but it doesn't have to be a literal anymore which the old text said it does.


public function UsersIpAddress()
public function usersIpAddress()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated change to promote best practice. Also updated casing on the below.

Comment on lines -9 to +10
All objects that are being rendered in a template should be a [ModelData](api:SilverStripe\Model\ModelData) instance such as `DataObject`,
`DBField` or `Controller`. From these objects, the template can include any method from the object in [scope](syntax#scope).
Classes that subclass [`ModelData`](api:SilverStripe\Model\ModelData) (such as `DataObject`,
`DBField` or `Controller`) can define how their values should be cast or escaped when used in a template.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can pass basically anything into templates, doesn't have to be ModelData - but the ability to define casting like this is unique to ModelData and its subclasses.

Comment on lines -275 to -294
The `forTemplate` method will probably look something like this:

```php
namespace App\Model;

use SilverStripe\ORM\CMSPreviewable;
use SilverStripe\ORM\DataObject;

class Product extends DataObject implements CMSPreviewable
{
// ...

public function forTemplate(): string
{
// If the template for this DataObject is not an "Include" template, use the appropriate type here
// e.g. "Layout".
return $this->renderWith(['type' => 'Includes', self::class]);
}
}
```
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove unnecessary example now that the default implementation in ModelData does this for you.

Comment on lines -408 to +386
> $preview = SSViewer::create('PreviewBase')->process(ArrayData::create(['Preview' => $preview]));
> $preview = SSViewer::create('PreviewBase')->process(['Preview' => $preview]);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to wrap them anymore. I'd argue it's even best practice to not wrap them.

@@ -526,12 +582,12 @@ You can change the level of entropy required by passing one of the valid [minSco

### Other new features

- Native indexed PHP arrays can now be passed into templates and iterated over with `<% loop $MyArray %>`. Under the hood they are wrapped in [`ArrayList`](api:SilverStripe\Model\List\ArrayList), so you can get the count using `$Count` and use `<% if $ArrayList %>` as a shortcut for `<% if $ArrayList.Count %>`. Other functionality from `ArrayList` such as filtering and sorting cannot be used on arrays since they don't have keys to filter or sort against.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved this into the template changes section

- Modules no longer need to have a root level `_config.php` or `_config` directory to be recognised as a Silverstripe CMS module. They will now be recognised as a module if they have a `composer.json` file with a `type` of `silverstripe-vendormodule` or `silverstripe-theme`.
- A new [`DataObject::getCMSEditLink()`](api:SilverStripe\ORM\DataObject::getCMSEditLink()) method has been added, which returns `null` by default. This provides more consistency for that method which has previously been inconsistently applied to various subclasses of `DataObject`. See [managing records](/developer_guides/model/managing_records/#getting-an-edit-link) for more details about providing sane values for this method in your own subclasses.
- The `CMSEditLink()` method on many `DataObject` subclasses has been renamed to `getCMSEditLink()`.
- The [`UrlField`](api:SilverStripe\Forms\UrlField) class has some new API for setting which protocols are allowed for valid URLs.
- The [`EmailField`](api:SilverStripe\Forms\EmailField) class now uses `symfony/validator` to handle its validation logic, where previously this was validated with a custom regex.
- [`ArrayData`](api:SilverStripe\Model\ArrayData) can now be serialised using [`json_encode()`](https://www.php.net/manual/en/function.json-encode.php).
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't directly related to templates so adding here instead.


Just like in PHP, method names are case insensitive, but property names are case sensitive.

Using `$MyValue` in a template will successfully call a `myValue()` method, or a `getMyvalue()` method even though the case doesn't match what you used in the template. But it *will not* match a `myValue` property or database field because the case doesn't match.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Using `$MyValue` in a template will successfully call a `myValue()` method, or a `getMyvalue()` method even though the case doesn't match what you used in the template. But it *will not* match a `myValue` property or database field because the case doesn't match.
Using `$MyValue` in a template will successfully call a `myValue()` method, or a `getMyValue()` method even though the case doesn't match what you used in the template. But it *will not* match a `myValue` property or database field because the case doesn't match.

@@ -459,6 +459,62 @@ Note that the `SilverStripe\View\ViewableData` class has been renamed to [`Silve

See [many renamed classes](#renamed-classes) for more information about this change.

#### Improved separation between the view and model layers {#view-layer-separation}

Historically the `ModelData` class did double-duty as being the base class for most models as well as being the presumed class wrapping data for the template layer. Part of this included methods like `XML_val()` being called on any object in the template layer, despite being methods very specifically implemented on `ModelData`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Historically it's been called ViewableData ? Maybe mention that ModelData used to be called ViewableData

@@ -6,6 +6,9 @@ icon: code

# Rendering data to a template

> [!NOTE]
> The template syntax, file extensions, and specifics about which tempaltes are chosen from a set as described on this page are specific to the default [`SSTemplateEngine`](api:SilverStripe\View\SSTemplateEngine) - but many of the concepts here (especially the PHP code) should work with any template engine you choose to use.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
> The template syntax, file extensions, and specifics about which tempaltes are chosen from a set as described on this page are specific to the default [`SSTemplateEngine`](api:SilverStripe\View\SSTemplateEngine) - but many of the concepts here (especially the PHP code) should work with any template engine you choose to use.
> The template syntax, file extensions, and specifics about which templates are chosen from a set as described on this page are specific to the default [`SSTemplateEngine`](api:SilverStripe\View\SSTemplateEngine) - but many of the concepts here (especially the PHP code) should work with any template engine you choose to use.

@@ -194,5 +203,62 @@ class MyPageController extends PageController
}
```

> [!WARNING]
> A common mistake is trying to loop over an array directly in a template - this won't work. You'll need to wrap the array in some `ModelData` instance as mentioned above.
Or wrap the data in a `ModelData` subclass:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Or wrap the data in a `ModelData` subclass:
Or wrap the data in a `ModelData` subclass such as `ArrayList`:


Every time a raw template file is processed, some PHP code is generated from it which is then executed to produce the final rendered result.

That PHP code is stored in the filesystem so that the raw template file doesn't need to be processed again until either the cache is flushed or the raw template file is updated.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
That PHP code is stored in the filesystem so that the raw template file doesn't need to be processed again until either the cache is flushed or the raw template file is updated.
That PHP code is cached in the filesystem so that the raw template file doesn't need to be processed again until either the cache is flushed or the raw template file is updated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just ties it together a little better

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants