- Issue created by @Chi
- π·πΊRussia Chi
Meanwhile, we can use a render element to gradually migrate from render arrays to DOM.
/** * Provides a render element to build markup using document object model. * * Properties: * - #dom: Document Object Model * * Usage Example: * @code * $build['dom'] = [ * '#type' => 'dom', * '#dom' => $dom, * ]; * @endcode * * @RenderElement("dom") * * @see https://www.php.net/manual/en/book.dom.php */ final class Dom extends RenderElementBase { /** * {@inheritdoc} */ public function getInfo(): array { return [ '#pre_render' => $this->preRenderEntityElement(...), '#dom' => NULL, ]; } /** * Pre-render callback. */ public static function preRenderEntityElement(array $element): array { $dom = $element['#dom'] ?? NULL; if (!$dom instanceof \DOMDocument) { throw new \InvalidArgumentException('#dom property must contain instance of DOMDocument'); } // Instead of using saveHtml, it should traverse the tree recursively, // rendering child nodes while respecting theme hooks and bubbling attached // metadata. return ['#markup' => $dom->saveHTML()]; } }
- πΊπΈUnited States effulgentsia
Interesting idea!
$time_el->setAttribute('class', 'example__time');
How would this work for #attributes values that aren't strings, such as arrays and objects?
- πΊπΈUnited States effulgentsia
How's the performance of creating and calling methods on
DOMElement
and its subclasses relative to PHP arrays? It's possible that modern PHP versions are fast enough with this, but I think it used to be that something like your suggestion would incur a lot of overhead for the size of render element trees we typically see in Drupal. - π·πΊRussia Chi
Actually, I think, having a full-fledged DOM implementation is not needed. We only need DOM as backing store for content tree. From this point, it's better to create a lightweight element tree with a few helper methods to simplify manipulation and traversal.
PHPβs built-in DOM extension feels overly complex for such tasks and has some pitfalls when dealing with multiple DOMDocument objects. On the other hand, it offers some cool features that could be nice to have, such as traversing in the upward direction, XPath, and CSS selectors (introduced in PHP 8.4) for finding elements. However, none of these features are essential for Drupal's rendering system.
- π·πΊRussia Chi
Re #5
That requires benchmarks. My guess is that manipulating an object tree costs almost nothing compared to other operations performed by Drupal's theme layer, such as preprocessing variables and rendering Twig templates. - π©πͺGermany geek-merlin Freiburg, Germany
Yay, this impulse may set some energy free in the community. For me it certainly does.
Some thoughts:
1) For all i know, objects having performenca penalty is long ago (php5?).
2) I'm maintaining RenderArrayTool Library β and have gotten to love that approach, for building, but much more for altering render arrays.
3) So this is an interesting approach: to have the Renderer eat render arrays OR RenderableObjectInterface. If the render elements then have typed properties, altering would be a lot more fun.
4) Another win of this approach: It would finally allow evolution. A RenderableObjectInterface (which is different to RenderElementBase or its interfaces) is something that spits out a html string in the end, BubbleableMetadata (roughly cacheability plus libraries) and may or may not use a render array in between (so it is also not RenderableInterface).
5) Hacking together a ComponentRenderElement would be trivial.
6) A RenderableFormElementInterface for form elements would need a bit more bells and whistles, as it has to interact with the form workflow.
7) We may even have a DrupalFormElement and other form elements, which would allow using other form libraries like symfony forms (though i strongly doubt they will ever be interoparable.)8) As of the API: There are lots of properties and methods (especially for forms) that have no relation to the DOM. But without doubt, having the dom related methods resemble DomExtension, has a lot of charm.
9) Yes, we don't want to extend DomNode for a variety of reasons. Whether the New-Dom empty marker interfaces \DOM\ParentNode and \DOM\ChildNode should play a role here, is up to debate.So in the end, for me it boils down to opening a core issue like "Add RenderableObjectInterface and allow it in render arrays".
WDYT?
- π·πΊRussia Chi
Re #8 That make sense.
Technically, the Drupal already has sort of DOM based on render arrays (should we call it DAM?). The issue merely about replacing associative arrays with objects.
it's better to create a lightweight element tree with a few helper methods to simplify manipulation and traversal
nicmart/tree seems like the right tool for this, at first glance.
- π¬π§United Kingdom joachim
What's the benefit of using DOMElement as our base?
How do we handle BC, especially with alter hooks that expect to find arrays?
> hard to find documentation for available properties.
I'm not against this direction of movement at all, but that is a reason to **fix our documentation**, not to replace a system with a new system that will need just as much documentation. People have been saying for years that form/render arrays need documentation.
- π·πΊRussia Chi
Re #10
By "documentation," I mean a list of available properties with their types and a brief description. This documentation may already exist somewhere, but you would need to look it up yourself. For objects with typed properties and methods, IDE can provide that information for you. See β¨ Use the builder pattern to make it easier to create render arrays Needs work for details.
How do we handle BC, especially with alter hooks that expect to find arrays?
I've no idea at this moment. Another hook? Anyway, this needs some brainstorming.
- π¬π§United Kingdom joachim
> By "documentation," I mean a list of available properties with their types and a brief description. This documentation may already exist somewhere, but you would need to look it up yourself. For objects with typed properties and methods, IDE can provide that information for you.
In both cases, people need to write the documentation.
Though I get your point that with named parameters or object properties, IDEs will more easily provide information. But it has to actually be there!
- π¬π§United Kingdom jonathanshaw Stroud, UK
We already have an issue for something like this: #2602368: Allow objects that implement RenderableInterface to used interchangeably with render arrays. β
And it can be achieved in a fairly BC way.
- π·πΊRussia Chi
#2602368: Allow objects that implement RenderableInterface to used interchangeably with render arrays. β indeed is very close to this one. Though the proposed approach is a bit different.
Here we aim to completely remove render arrays.
In #2602368 the render arrays will remain as intermediate layer between elements (objects) and renderer service. That is much easier to implement. The submitted patch is actually a tree-lines change.As of BC, we don't have to implement it imminently. Custom projects can benefit from this change right now. Contributed projects may start using element objects in major releases where BC breaks are allowed.
- π¬π§United Kingdom catch
I think this should be in the core queue - it's an API proposal not a product change.
- π¬π§United Kingdom joachim
DomDocument is still pretty verbose.
I'd love to see something inspired by perl's CGI (https://perldoc.perl.org/5.12.1/CGI#CREATING-STANDARD-HTML-ELEMENTS), which allows you to nest things:
$q->blockquote( "Many years ago on the island of", $q->a({href=>"http://crete.org/"},"Crete"), "there lived a Minotaur named", $q->strong("Fred."), ), $q->hr;
- π«π·France andypost
Looking ahead it sounds like good idea, moreover in a light of new HTML 5 DOM in PHP 8.4