Decoupling decisions and compatibility¶
This is a historical elaboration on some details when this project has been
decoupled form TYPO3.Flow
and made a standalone library. Isn't of too much
help nowadays anymore, but can be helpful for some insight on why things
materialized as is.
In order to decouple this package from TYPO3.Flow
a few necessary but
implication-filled decisions had to be made.
No more dependency injection¶
It is simply gone and will not be implemented again in any shape or form. The DI
concept from TYPO3.Flow
does not apply on a wider scale and it is every bit as
possible to achieve the same results through the constructor methods. While DI
is a nice concept for usability, it is better to sacrifice it for more universal
class support.
No more widget support¶
It is also gone and will not be implemented again. However: because of the nature of Fluid and ViewHelpers, recreating the implementation that behaves like Widgets but does so in the context of the framework in which it gets used is the correct way to achieve this behavior.
As an added benefit, all translated labels and a lot of functional tests and fixtures can and have been removed.
ViewHelpers can't use render method arguments¶
Although still technically feasible to implement, a decision was made to
sacrifice the support for render()
method arguments in ViewHelpers
(as opposed to using registerArgument
inside initializeArguments
).
The following reasons are given:
Render method type hinting beyond strict types is impossible without analysing phpdoc comments which implies Reflection as well as a dependency on the
TYPO3.Flow
annotation parser.Performance and testability is exactly the same.
A single method to register arguments now exists and
ArgumentDefinition
can be reduced in complexity.Having only one method to check in every instance means better performance overall.
Overriding these capabilites is possible and implies a custom
ViewHelperInvoker
returned from a custom ViewHelperResolver
.
The View consumes TemplatePaths¶
Rather than allow the View class to be aware of the Request via the ControllerContext, both the Request and ControllerContext concepts have been completely removed. A new strategy has taken the place of these: the TemplatePaths.
In order to instantiate a View instance, a special TemplatePaths instance must now be passed as first argument. This TemplatePaths instance is then responsible for all the resolving and retrieval of template files. This means that replacing the TemplatePaths instance that gets used will allow another implementation to effectively change how Fluid resolves template files.
This also means that the View itself no longer has any file resolving capabilities. Instead, it relies on the provided instance to resolve every file and template source. For usability, there are dedicated methods to set template path and filename as well as layout path and filename.
Because of this the path treatments are now completely decoupled and no longer
uses expression expansions to create arrays of expected paths. Instead, each
path is iterated and the epected filename checked and returned if found. In
order to potentially re-implement this decoupled package into TYPO3.Flow
as
well as TYPO3.CMS
this means that these paths can then be generated by the MVC
and simply passed along to the View - or, íf more complex behavior is required,
a custom TemplatePaths implementation can be created.
As a side effect of this, the View no longer supports any options. Where
before a user was able to pass paths, filenames and other settings as options
on the View, such behavior is no longer required due to the use of
TemplatePaths. However, such behavior can be restored by subclassing the
TemplateView and adding options
support which simply delegates to
TemplatePaths to change root paths etc.
Obviously your paths can no longer use any custom syntax or markers for
replacement such as EXT:...
paths or @marker
patterns. To use such
expressions make sure you convert the paths before you pass them to the View;
e.g. do so inside your custom TemplatePaths or before you pass the paths to the
built-in TemplatePaths object.
Deprecated code has been evicted¶
This includes all and every support for the legacy path name conventions - only arrays of paths are now accepted except when specifying the full template- or layout path and filename on the View.
Note about injecting functionality¶
It is possible to restore almost all of the removed features by creating custom implementations of the following classes:
https://github.com/TYPO3Fluid/Fluid/blob/main/src/View/TemplatePaths.php to change how template files are resolved.
https://github.com/TYPO3Fluid/Fluid/blob/main/src/Core/ViewHelper/ViewHelperResolver.php to change how each ViewHelper is resolved, how its arguments are retrieved, which namespaces are available and expected class names of ViewHelpers.
When combined in a package that implements TYPO3.Fluid
in a framework, these
two classes together make it possible to change all the behaviors that were
changed to make TYPO3.Fluid
more portable. The solutions are, in order:
Dependency injection in ViewHelpers can be restored by overriding the
createViewHelperClassInstance
method of the ViewHelperResolver implementation. The View itself can of course also be loaded by an object manager that does injection.Widgets can be reintroduced as a framework-specific feature by making the ViewHelperResolver return the desired class names when the TemplateParser tries to load the ViewHelpers that were removed. This includes all of the other ViewHelpers which were sacrificed for portability because they had too strong dependencies on the framework; for example the
f:form
helpers known from TYPO3 CMS and Flow.The arguments of each ViewHelper can be adjusted - or the class itself can be replaced. This allows the framework to replace those ViewHelpers that have been "dumbed down" (for example the debug ViewHelper which in CMS or Flow would use the DebuggerUtility to display variables but in this standalone version uses a plain
var_dump
).The TemplatePaths implementation can be replaced by one that supports the necessary folder structures and path treatments, for example allowing the
EXT:....
syntax in paths and making it possible to "bubble sub package" or whatever special feature the template file resolving should support.Deprecated code and support for legacy class names can be introduced by overriding the ViewHelperResolver. The aliases can be defined any way desired - as long as the ViewHelperResolver is aware of them and will return the new class as replacement.
The way the ViewHelpers are themselves executed can be overridden via a custom ViewHelperInvoker returned from the custom ViewHelperResolver. Overriding this part allows, among other things, restoring the
render()
method argument support.