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

Improve view engines and their integration in the Admin #70

Open
wants to merge 15 commits into
base: main
Choose a base branch
from

Conversation

veve40
Copy link
Contributor

@veve40 veve40 commented Oct 13, 2022

The View package's primary API elements are the render() (for template files: path/to /view.mustache) and renderTemplate() (for template strings: {{ person.name }}) methods. Their somewhat vague names caused widespread misuse because Mustache (for a long time the default and only supported template engine) provides a single method render() for rendering both. This caused a lot of trouble during the initial integration of Twig 3 (#44).

This pull request attempts to resolve most of the leftover issues in supporting both Mustache and Twig and their mixed use within the Admin (for features such as content blocks).

Breaking Changes

  • Replaced all inconsistent use of render() and renderTemplate() with the appropriate function call for the given circumstance.

    If a renderable value was previously a template file path (path/to /view.mustache) it may need to be converted to a template include tag ({{> path/to/view }}) and vice versa.

    For example, renderable elements in Selectize (SelectizeRenderer) now require a template string.

  • In classes such as NestedWidgetFormGroup and FormGroupWidget:

    The description and notes are localized and rendered in their setter methods instead of their getter methods. This avoids recursion with templating engines such as Twig which require the view data to be serialized unlike Mustache which accepts objects.

  • In the View package, the in-memory cache of registered dynamic templates now static to share templates across view loader classes.

View

View Aggregator

Added a new view adapter: ViewAggregator. This is now the default adapter and uses Mustache, PHP, and Twig (in that order).

The aggregator is used to register several engines to either use a specific engine later on or to dynamically resolve which engine to render any given template file or template string.

The get() method allows you to retrieve a view adapter for an engine by its name. This is useful in situations where a single portion may need rendering in a specific engine.

$mustache = $container['view']->get('mustache');
$html = $mustache->render('<h1>{{ title }}</h1>', [ 'title' => $title ]);

The using() method allows you to change the default engine to use by its name. This is useful in situations where the overall kind of templates being rendered changes dramatically.

$container['view']->using('mustache');
$html = $container['view']->render('<h1>{{ title }}</h1>', [ 'title' => $title ]);

Note that the default engine is only used if the templating file or tag syntax can not be determined during the dynamic resolution process.

$view = new ViewAggregator([
    'engines'               => $container['view/engines'],
    'engine'                => $container['view/engine'],
    'file_engine_decider'   => $container['view/engine/decider/file'],
    'string_engine_decider' => $container['view/engine/decider/string'],
]);

The deciders are functions that receive the given template, context, available engines, and the default engine, and handle which engine to should be used. For example:

$renderTemplateStringEngineDecider = function (string $templateString, $context, array $engines, EngineInterface $defaultEngine): EngineInterface {
    foreach ($engines as $engine) {
        $string = $engine->loader()->resolveDynamicTemplate($templateString);
        if ($engine->loader()->isTemplateString($string)) {
            return $engine;
        }
    }
    return $defaultEngine;
}

Changed

  • Improve error handling of JSON serialization of $context parameter in PhpEngine and TwigEngine. Classes now throw an exception instead rendering with a bad value (false).
  • Changed visibility of method setEngine() from private to protected in AbstractEngine.
  • Changed visibility of method loader() from protected to public in AbstractEngine.
  • Changed visibility of methods isTemplateString() and findTemplateFile() from protected to public in AbstractLoader.
  • Added public method resolveDynamicTemplate() in AbstractLoader.

Admin

Changed

Email

Changed

…ckage

Uses a container admin/view set with Mustache engine only for admin package. Resolves issues with
default view from different contexts. Add custom Admin TemplateRoute extending App TemplateRoute
with the overwriting view container. Overwrite model/dependencies to set the admin/view container.
@mcaskill mcaskill changed the title Pulling feature/admin-view into main Add dedicated view engine for the Admin Oct 13, 2022
Xavier added 3 commits October 31, 2022 11:19
Replace email/factory for admin/email/factory in admin module in order to force using mustache view
engine for emails. Offer the possibilty to keep using the default view engine (ie front) even for
sending email from backend.
Xavier added 2 commits November 1, 2022 15:26
Use an email/dependencies container overwritten in admin module to use specific view engine
…il/provider and Admin Template Route. Fix the calls of render and renderTemplate in admin section
packages/view/src/Charcoal/View/Twig/TwigEngine.php Outdated Show resolved Hide resolved
packages/view/src/Charcoal/View/Twig/TwigEngine.php Outdated Show resolved Hide resolved
packages/view/src/Charcoal/View/Twig/TwigEngine.php Outdated Show resolved Hide resolved
packages/view/src/Charcoal/View/Twig/TwigEngine.php Outdated Show resolved Hide resolved
packages/view/src/Charcoal/View/ViewAggregator.php Outdated Show resolved Hide resolved
packages/view/src/Charcoal/View/ViewAggregator.php Outdated Show resolved Hide resolved
packages/view/src/Charcoal/View/ViewAggregator.php Outdated Show resolved Hide resolved
packages/view/src/Charcoal/View/ViewAggregator.php Outdated Show resolved Hide resolved
packages/view/src/Charcoal/View/ViewServiceProvider.php Outdated Show resolved Hide resolved
veve40 and others added 4 commits November 7, 2022 10:55
Co-authored-by: Chauncey McAskill <[email protected]>
…ring engine decider

Rename file decider and string decider for file engine decider and string engine decider for
ViewAggregator
@mcaskill mcaskill changed the title Add dedicated view engine for the Admin Improve view engines and their integration in the Admin Nov 9, 2022
The 'view' service is provided by the parent class `AbstractWidget`.
Remove unused and duplicate imports.
A viewable object does not have a context parameter.
Changed:
- Moved logic irrelevant to JSON serialization outside of try/catch.
- Added `JsonException` handling to `PhpEngine` to match `TwigEngine`.
- Sorted namespace imports.
Copy link
Collaborator

@mcaskill mcaskill left a comment

Choose a reason for hiding this comment

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

I reread this pull request and I think there's a few improvements we can make:

  • Rename decider to resolver.
  • Replace the JSON re-encoding of the context as an associative array in PhpEngine and TwigEngine with a better approach that does not lose access to objects.

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