Skip to content

Data output POC

czheng edited this page Jun 3, 2011 · 1 revision

Overview

In the latest working build of Symphony 3, front-end output is generated in the following way:

  1. The view instantiates its source document and template, both DOMDocument objects
  2. The view and its data sources and events append various DOMElements to the source document
  3. The view uses its template to transform the source document into string output

What I'm proposing is that we abstract this process ever so slightly by creating a Data Output API by means of which a pluggable output engine manages and transforms the source data and builds output itself. So:

  1. The view initializes its output engine
  2. The output engine instantiates its own source document and template
  3. The view and its data sources and events append output elements to the source document via the Data Output API
  4. The output engine uses its template to transform the source document into string output

Example: The Old Way

STEP 1: When a View is instantiated, its __construct() method is responsible for initializing its source document and stylesheet:

<?php
    $this->document = new XMLDocument;

    $this->document->appendChild(
      $this->document->createElement('data')
    );

    $this->stylesheet = new XMLDocument;
    // $this->stylesheet is later populated by loading in the content from the view's template file

STEP 2: Now as the view builds its output, it creates elements and appends them to the source document:

<?php
    $root = $this->document->documentElement;

    $my_element = $this->document->createElement('ninja-star');
    $root->appendChild($my_element);

STEP 3: Once the source document is complete, the View transforms it and returns the output:

<?php
    $output = XSLProc::transform(
      $this->document->saveXML(),
      $this->stylesheet->saveXML(),
      XSLProc::XML,
      array(), array()
    );

    return $output();

Example: The Proposed Way

The proposed Data Output API would change things only slightly.

STEP 1: When a View is instantiated, its __construct() method is responsible for initializing its output engine. Something like:

<?php
    $engine_name = Crane::Config()->load('output-engine');
    $engine = new $engine_name;

STEP 2: This in turn calls the output engine's own __construct() method, which instantiates a source document (among other things):

<?php
    Class SomeEngine extends OutputEngine {

      public function __construct() {
        $this->document = new SomeOutputDocument;
        // ... etc.
      }
    }

STEP 3: Now view output can be built as before, only the actual implementation is abstracted out to the output engine. Something like this:

<?php

    $my_element = $engine->createElement('ninja-star');
    $engine->appendElement($my_element);

It's up to the output engine to decide what createElement() does. The system doesn't need to know as long as the API's properly implemented.

STEP 4: Finally, when all's said and done, each output engine would take its source document and its view template and create the output however it liked. The XSLTEngine would do something very similar to what we saw above. Another engine might do something more like:

<?php
    $template = $this->loadTemplate();
    $variables = $this->documentToVars($this->document);
    return $template->render($variables);

API Structure

Overview

I'm imagining the API consisting of a series of abstract classes or interfaces like:

  • OutputEngine
  • OutputDocument
  • OutputElement

The latter two would be heavily inspired by DOMDocument and DOMElement because we need to be able to pretty closely replicate existing capabilities when it comes to working with output data. This would mean that the default XSLT output engine included in core could be fairly lightweight and serve mostly as an interface for DOMDoc.

Other output engines would be provided by extensions, and would be required to fully implement the Data Output API so that the system and other extensions (field types, data source types) could be completely agnostic when building output.

This would mean that more simplistic templating systems would need to support the full range of object operations that something like DOMDoc does (addAttribute() and so on) and decide for themselves how to translate that into whatever sort of source data they need for their templates (often just a multidimensional array).

View Templates

The view templates system would have to be tweaked ever so slightly in order to accommodate other kinds of templates (HTML, PHP, etc).

Scope

Again, this is only for front-end output. The back end will continue to be powered solely by XML/XSLT. We'd have to decide whether output engine is a system-wide preference or something that can be specified on a per-View basis.

Debugging

If output engines are allowed to build their own source data, this has implications for the debug view. It may be necessary to account for this in the API (maybe an OutputDebug class?). At the very least, the engine has to figure out how to render its source document. It may also be necessary for engines to account for dynamic traversal (á la the XPath selector we have now).

Data Source Filtering

We've discussed many times the possibility of using XPath in data source filtering. It's still unclear how that would work (mostly in terms of ordering and dependency) but obviously if we implement a data output API then each output engine would need to parse the filter expressions itself.

Clone this wiki locally