Version 4 > Developer Guides > Content Model > How a page is made

How a page is made

Basic page skeleton

The page skeleton is the basic HTML framework for the page, containing CMS tags to insert other content into appropriate places.

In V3, the system looks for a content object named page to get the basic HTML skeleton for the page. In V4, there is no longer a page content object; the page itself can hold its own revisions directly. If a page object has its own revision, it uses that as the page skeleton.

If a page does not have its own skeleton, it looks to its template to provide the skeleton. The template can hold a page skeleton in the same way (ie. in its own revisions). Templates can inherit from other templates, so the page skeleton may be further inherited from more basic or lower-level templates.

If a page does not declare a template, the system will look to its parent page(s) to see what they do. If they also do nothing, it will eventually fall back on the page skeleton of the section.

Expanding the skeleton

The skeleton HTML will include special CMS markup to insert other content objects. This is the same as V3, ie.:

CMS tag result 
[[name]] replaced with URL to content "name"
replaced with link to page "name"
<!--content(name)--> replaced with HTML of content "name"
<!--&Plugin(options)--> replaced with output from Plugin
<!--$name--> replaced with metadata "name"

The rules for finding matching content under "name" are a bit different. We search the following locations, in order:

    1. search the children of the current node
    2. search the children of the current page
    3. search the children of our templates and their parent(s)
    4. search the children of the current page’s templates and their parent(s)
    5. search all of our descendant nodes
    6. search the children of our section’s template(s)
    7. search the libraries of this section and its parent sections

The italicised rules are different from V3. They have the effect of allowing for contextual searches. That is, if there are multiple pieces of content in a site called "name", it will prefer ones that are in the same area of the site. For example, if you link to , it will prefer to link to a sub-page called "contact" than one that is located in a different sub-menu.

The content expansion is done by ExSite::Content::expand(), which works using similar principles to v3’s expand().

Content URLs

Tags of the form [[name]] link to direct view of a content object. That is, you will get the raw content, which is usually what you want in cases like images, scripts, and stylesheets.

In place of name, you can also specify the content ID directly. Linking by ID ensures the link will continue to work even if the content is renamed. Linking by name ensures the link will continue to work if the original content is renamed or deleted, but another one exists that can take over.

You can optionally link to specific views (eg. thumbnail, small, or large) by appending the view:

[[name:large]]

You can also force a dynamic view by appending a query string. Dynamic content views go through ex.cgi/view, for example:

[[name]]

will link to the draft revision of the content, instead of the published revision.

Page URLs

Tags of the form link to a formatted page view of the content. If the content is already a page, this is just the regular page view. If the content is not a page, this will wrap the content up into a pseudo-page view before showing it to the viewer.

In place of "name" you can specify

(blank) link to self
(number)  link to that page ID 
! link to self, but a dynamic URL
?query_string dynamically link to self, with query string parameters
name? link to name, but a dynamic URL
name?query_string dynamically link to name, with query string parameters
&Plugin link to the service page for Plugin
&Plugin?query_string link to the service page for Plugin, with query string parameters

For example, you can link direct to shopping cart checkout using {{&Pay?cart=checkout}}

Content substitutions

Tags of the form <!--content(name)--> insert the HTML representation of the content into that position in the skeleton.

In place of "name" you can specify name:view to get a different view of the content.

If the user is not permitted to view content "name", they will see a permission denied error where the content would normally go if the content is the primary content of the page view (ie. equivalent to the page body). Secondary content will simply not be displayed if the user is not permitted to see it.

If the container page is static, but the referenced content is dynamic or restricted access, the actual substitution will be a javascript to fetch the content dynamically. That allows you to construct static member-only pages by making the page static, but setting the specific member-only content objects to a higher level of access.

Plugins

Plugin substitutions work the same way as in V3, including running in AJAX mode with && and &&& forms of plugin call.

Metadata

The meta tags <!--$page_header--> and <!--$page_footer--> will be replaced with the contents of $share{page_header} and $share{page_footer}. The intention is that these tags should be placed in the <head> section and after the </body> in the template. Things like scripts and stylesheets can be placed there for better document structuring. Best to append to these variables, so you don’t wipe out anything already placed there by other objects/modules.

The meta tag <!--$metadata--> will attempt to bulk insert all of the relevant metadata for the page view, as a block of meta tags. Any defined metadata with a show attribute set to 1 will be included in this output. This includes implicit metadata, so you don't even have to set the metadata explicitly to get output here. For example, to automatically include Twitter card metadata in the page, set the following configuration options:

content.metadata._.twitter:card.show = 1
content.metadata._.twitter:title.show = 1
content.metadata._.twitter:description.show = 1
content.metadata._.twitter:image.show = 1
content.metadata._.article:tag.show = 1

(The "_" in the above refers to the generic metadata vocabulary. You can include ExSite metadata as well, for example:

content.metadata.product.product:price:amount.show = 1

 

Non-pages

Any content type with a display type of "template" will follow similar rules with regard to page construction from a base HTML skeleton; the revisions of the object will be used as a template for the page. (In the base install, this includes pages, sections, and templates.)

Pseudo-pages

Non-page content types can be displayed like pages simply by running them through the page method:

http://my_website.com/cgi/ex.cgi/page/path/to/content

When viewed this way, the CMS will pick an appropriate template to start from, and substitute the selected content object into the body of that pseudo-page.

To do this programattically, use:

$out = $my_content->show_templated();

To write out a file that has your content formatted like a page, use:

my $file = new ExSite::Diskfile( base=>$base_path, path=>$web_path,filename=>$fname, contents=>$this->show_templated() );
$file->publish();

where $base_path is your DOCROOT, $web_path is the path in the URL, $filename is the HTML filename (eg. something.html), and contents is the complete HTML for the document.