There is a fundamental architecture choice to be made here which porting the module affords. The FBIA PHP SDK provides a component which allows you to create an Instant Article object in a domain specific language (DSL) that expresses all the elements, metadata and structure of the document, then call a render() method on that object to get guaranteed compliant FBIA documents. This is good, we want to use this. In D7 we use this by creating an instance of the InstantArticle object on node_load and setting it as a property of the node. Each field formatter then calls methods on the InstantArticle object instance to add it’s data to the instant article. Finally, the node is rendered via the theme system, and in order to output the FBIA markup, the render() method is called on the instance. This works, however is flawed. First it causes issues with render caching. The FBIA PHP SDK uses the PHP DOM API internally, and parts of it have problems being serialized/unserialized. Second, the API approach has a slightly awkward time of obtaining the markup as it has to invoke the theme API to render the markup needed, which ends up feeling odd and is not very performant. Third, the approach isn’t very performant regardless of API/RSS delivery. Finally, D7 also uses a custom view mode and hijacks the Manage Display form as a way of mapping fields to FBIA elements. This isn't what view modes are for really, they are really tied to HTML output.
This task is to research alternative architectures for using the FBIA PHP SDK within Drupal to serialize content entities into FBIA formatted documents for use in RSS/API delivery to FB.
The goal would be an architecture that:
- Uses the FBIA PHP SDK
- Allows for mapping fields to FBIA Elements
- Plays well with caching and is performant
- Appropriately leverages Drupal API's
Comments
Comment #2
m4oliveiI suspect that we could somehow leverage the Serialization API in Drupal 8 to do this (outputting content entities in alternate representations is what it was designed for). I did up a proof of concept that works nicely:
Need to think more about moving away from custom view mode.
Comment #3
m4oliveiComment #4
scottrigbyNotes from DrupalCon BoF:
display module convo:
- scott: rename to "entity" module? "Bundle" module?
- matt: don't use view mode?
- ryan: we bypassed the view mode for this reason. maybe use a separate config form?
- matt: maybe use serialization module? I made an initial POC.
- scott: maybe if we do this, we can have a new, separate API UI module
- scott: but is there any advantage to using the D8 serialization module as opposed to our standalone class?
- matt: one benefit is serialization automatically integrates with D8 Views, so you would have to do less for a separate FBIA Views module (for those who don't want to register a FB app ID for the
- scott & ryan: agree
Comment #5
m4oliveiComment #6
scottrigbyAbout naming… our discussion is leaning to refactor the Display module code & move to a new space, whose job it is to provide entity/field/properties mapping to FBIA HTML output. That output can then be used with the API submodule, or with Views (a separate module), etc. The new space could be a sub-module, or maybe better just it's own class inside the base module.
Comment #7
scottrigbyCon: this way you loose the functionality of all other field formatters :/
Comment #8
m4oliveiCorrection on the last point, we don't loose the functionality of all other field formatters b/c the only field formatters that are compatible with Facebook Instant Article view mode are the FBIA prefixed ones that ship with the module. Any field that is enabled without a FBIA prefixed formatter is ignored in the Facebook Instant Articles document.
Comment #9
m4oliveiOk, here's what I propose:
We keep the view mode, it's a nice simple way to get a mapping for which fields go into which regions and which FBIA Elements they should use.
We also use the serialization API to serialize entities (typically nodes) into FBIA documents, passing the config entity for the view mode so the mapping is in hand to guide the serialization. In case of the RSS approach, this make things very easy to integrate, b/c views and Serialization play nicely together. In case of the API approach, it makes it equally so, just `\Drupal::service('serializer')->serialize(\Drupal\node\Entity\Node::load(1), 'fbia')`. A standard approach instead of awkwardly invoking the theme system. Both approaches (for RSS and API) would take the exact same straightforward code path to generate FBIA document markup. It's also much more testable to use Serialization API, b/c you don't have to go through the the theme system. The Serialization API also nicely supports the concept of recursive serialization, which gives us a nice way to break up the code into discrete parts (see https://www.lullabot.com/articles/drupal-serialization-step-by-step)
The field formatters present would be so only in name, they wouldn't generate any output since we never want to see a FBIA markup on the website in the front end. It's strictly generated for the purpose of delivering to Facebook via RSS or API. Which isn't any different then the D7 module.
I said a lot of things. I owe a POC, which I'll build out over the next couple days.
Comment #10
m4oliveiThe other thing I'd like to see is fb_instant_articles_display merge into the base module. Seeing as you really need fb_instant_articles and fb_instant_articles_display in practice to do anything with the module, I think it makes sense. One less configuration step, less confusion, and we avoid the weird naming. If your not using the view mode you can simply not enable it (it'll be disabled by default). And also with Serialization, if you want to do your mapping in a completely custom way, you can provide a normalizer service to do that.
I'll start that merger over in: https://www.drupal.org/node/2872801
Comment #11
m4oliveiThe approach in #9 is fully implemented over in #2872807: Manage creation and rendering of InstantArticle object via the Serialization API. Marking this as done.