How WebPal Sites Work

Intro

Now that you have created a basic site, it's time to look a little under the hood. This chapter explains the inner workings of how pages of a WebPal Site are rendered and presented to the browser. This is very useful information if you are planning to extend the site's functionality with your own custom extensions.

Laravel Framework

WebPal uses Laravel as the model-view-controller (MVC) framework to handle all rendering, routing, and composition of pages within the site. So basically, a WebPal Site is a single, stand-alone Laravel Application. The code and resources for this application are all contained in a single extension called webpal-core, which is the cornerstone of every WebPal Site. Every site has this extension at a minimum.

Webpal-core contains a single core controller, routes, filters, resources, and a few other goodies that are explained further below. Although you can, you typically don't want to modify the webpal-core extension, as each of its functions can be extended or overridden using your own separate custom extension node. This approach will enable you to receive future updates to webpal-core without losing your own code.

XML Content Storage

In general, all content of a site is stored in hierarchical XML format, which creates a tree structure of nodes that can each be edited individually. Depending on the node's schema-type and other attributes, WebPal opens different editors to accommodate different content structures. What's important to note is that at all times, WebPal maintains nodes and content in perfectly valid XML. This enables us to always parse and transform the content using standard XSL transformations, but later more about that.

Attachments, such as images or other binary files, are stored as documents and referred to by the document file ID as generated by WebPal. This ID is generated every time a new attachment is inserted, pasted, copied or updated. 

Editors

As mentioned above, all node types have an attribute edittype that determines which editor UI is presented to the user when opening a node for editing. Currently, WebPal supports the following types: html, text, code, form, sheet, data-table, image, string, attributes.

data?command=webpalimage.download&web_na

Node Schemas

The webpal-core extension contains the schema which defines the structure of a basic WebPal Site:

<web>
 <pages>
  <page name="home">
  <html><h1>Home Page</h1><p>some text</p></html>
  </page>
 </pages>
 <extensions>
  <extension name="webpal-core">...</extension>
 </extensions>
</web>

This schema is defined by standard XML Schema Definition (XSD) language, which is stored in the extension's core-xsd node.

<element name="web" type="wpWeb"/>

<complexType name="wpWeb" edittype="sheet" icon="world.png" lockable="yes">
  <attribute name="name" use="required" type="wpName"/>
  <element name="settings" type="wpWebsettings" minOccurs="1" maxOccurs="1"/>
  <element name="pages" type="wpPageList" maxOccurs="1"/>
  <element name="extensions" type="wpExtensions" maxOccurs="1"/>
</complexType>

<complexType name="wpWebsettings" edittype="sheet" icon="wrench.png" lockable="yes">
  <element name="title" type="wpStringL"  minOccurs="1" />
  <element name="shorttitle" type="wpShorttitle"  minOccurs="1" />
  <element name="author" type="wpString"/>
  <element name="classification" type="wpStringL"/>
   ...
</complexType>

<complexType name="wpPageList" edittype="sheet" icon="folder_page.png">
  <element name="page" type="wpPage"/>
</complexType>

<complexType name="wpPage" edittype="sheet" icon="folder_page.png" lockable="yes">
  <attribute name="id" use="auto" type="wpString" value="chap"/>
  <attribute name="name" use="required" type="wpPageName"/>
  <attribute name="design" use="optional"  type="wpString"/>
  <attribute name="show-in-menu" use="oneof"  type="wpString" value="yes,no,sub-pages-only"/>
  <element name="page" type="wpPage"/>
  <element name="title" type="wpStringL"/>
  <element name="shorttitle" type="wpShorttitle" minOccurs="1"/>
  <element name="html" type="wpPageHtml"/>
   <!-- other possible child nodes here -->
</complexType>

 

It is thus possible to define entirely new node schemas that allow you to create virtually any content structure 

Transformations

Finally, webpal-core contains two nodes core-xsl and core-theme, which contain XSLT transformation stylesheets. XSL is a language which defines templates for transforming XML from one structure to another. XSL is a rule-based, not a functional language, and as such is ideally suited for the hierarchical nature of transforming XML content. It also offers convenient output switches to produce HTML and XHTML output formats.

For example, let's say we have a simple web site with this structure:

data?command=webpalimage.download&web_na  

<pages name="pages">
 <page name="home">
  <shorttitle>Home</shorttitle>
  <html>
   <h1>Home</h1>
   <p>Lorem ipsum dolor sit amet... </p>
  </html>
 </page>
 <page name="offers">
  <shorttitle>Our Offers</shorttitle>
  <page name="offer1">
   <shorttitle>Offer 1</shorttitle>
  </page>
  <page name="offer2">
   <shorttitle>Offer 2</shorttitle>
  </page>
  <page name="offer3">
   <shorttitle>Offer 3</shorttitle>
  </page>
 </page>
 <page name="contactus">
  <shorttitle>Contact Us</shorttitle>
 </page>
 <page name="common">
  <shorttitle>Common</shorttitle>
 </page>
</pages>

Then the following templates will render a basic navigation for this site. This template can be invoked in a number of different ways, later more about this. For now, let's assume that any XML content can be accessed and re-purposed for any page that is presented to the browser.

 <xsl:template match="page" mode="navigation">
  <xsl:param name="path" select="''"/>
  <li>
    <a href="{$path}/{@name}"><xsl:value-of select="shorttitle"/></a>
  </li>
  <xsl:if test="page">
   <ul>
    <xsl:apply-templates select="page" mode="navigation">
     <xsl:with-param name="path" select="concat($path, '/', @name)"/>
    </xsl:apply-templates>
   </ul>
  </xsl:if>
 </xsl:template>

 

For more information on XSLT processing, we recommend you check out http://www.w3schools.com/xml/xsl_intro.asp 

Accessing Nodes

By default, all XSL transformations start with the root node of any input XML document as their main entry point of template matching. WebPal-core changes that by injecting any desired context node as the node to be processed. This node is located using an XPath expression. 

For example, let's say we want to render the home page of the sample site above. The corresponding XPath expression for the page to be rendered would thus be:

/web/pages/page[@name='home']

Webpal-core provides a single controller that bundles a number of methods for basic page-rendering functions. Among these is the Core::render() method which can be invoked as such:

\WebpalCore\Controllers\Core::render(
    array(
       'xpath' => "/web/pages/page[@name='home']"
      ));

Pre-processing and Caching

Generally, WebPal tries to store the entire web site in a single XML document for convenient XSLT processing. Naturally, for large web sites, this document can become rather large. This scaling concern is even larger for multi-lingual web sites which house duplicate version of the same content in different web sites or for different localities.

WebPal Sites use a multi-level caching cascade to optimize rendering performance of the final end-product, the page views. Additionally, the XML content is pre-processed, splitting the content into multiple copies for different languages. This pre-process is actually done by an XSLT transformation, too.

Lastly, the end-result of the final view computation is cacheable again by Laravel or edge-side proxy mechanisms, such as squid, redis, memcached, or mod_proxy.

Summarizing

Summarizing, the Core::render() method follows these steps:

1. Pre-processing

  • invoked whenever a new version of the site XML is published
  • splits the site XML into content, code, and separate attachment documents
  • splits the site XML into a version for each language
  • stores the results in Cache A

2. Transformation

  • invoked whenever a needed view is not in Cache B
  • retrieves the appropriate version of XML from Cache A, if present
  • extracts XSLT templates from the site XML and builds an XSLT processor from these
  • applies the XSLT to the XML, starting with the injected context node
  • stores the result in Cache B under a unique view name

3. Page Generation

  • invoked whenever a requested page is not in Cache C
  • identifies correct view name and retrieves the view from Cache B, if present
  • interprets the view as a Laravel Blade view
  • evaluates the view and substitutes variables
  • stores the result in Cache C (redis, proxy, or memcached)
  • presents the result page to the browser

4. Page Presentation

  • invoked whenever a page is requested
  • responds with page content from Cache C, if present

data?command=webpalimage.download&web_na