3. Constructing the main template

Usually, the websites do not use complete, separate templates for each page but rather construct the output from a couple of smaller files. The footer and header remain the same across the pages, so they are loaded from a common file, where the module-specific content is embedded. While creating the main template in Open Power Template 2, we must pay attention to the XML prolog and DTD. If we type them directly, OPT keeps them for itself and does not display them in the output code. To simplify working with them, we may use the two instructions: opt:prolog and opt:dtd. Furthermore, we will make use of a "container" opt:root which provides a root node for the XML document and the rest of the content. Our template may look like this:

<?xml version="1.0" ?>
<opt:root>
<opt:prolog />
<opt:dtd template="xhtml10" />
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pl" lang="pl">
  <head>
    <title>My website</title>
    <!-- remaining tags -->
  </head>
  <body>
    <!-- header layout -->
 
    <!-- beginning of the code for displaying modules -->
    <opt:section name="modules">
      <opt:include from="modules" />
    </opt:section>
    <!-- end of the code for displaying modules -->
 
    <!-- footer layout -->
  </body>
</html>
</opt:root>

The prolog visible at the beginning of the document is not sent to the browser, but parsed by OPT for internal purposes. The "visible" prolog is generated by opt:prolog instruction. It accepts the same arguments, as the original problog, but if we do not provide any, it uses the default values for them. Another simplification is opt:dtd instruction, where the DTD block is enclosed. We can write everything manually:

<opt:dtd><![CDATA[
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
]]></opt:dtd>

Manual DTD declaration requires it to be enclosed within a CDATA section. You do not have to worry about that, opt:dtd and OPT take care of it and do everything to make it correctly displayed for the browser.

However, this is not enough. As we already have an instruction, we get a couple of predefined DTD templates for the most common Document Type Definitions. They are selected with an template attribute and have simple, intuitive names such as xhtml10, html4 or html5.

After those two tags, we are allowed to put the opening <html> and start defining the website layout. By the way we should notice the way we display the module-dependent content. As we are supposed to know, in OPT we work with objects called 'views'. Each view is a template with the corresponding script data, so that each file has its own variable space and avoids naming collisions. The modules may generate their own view objects and pass them as their results to the controller:

public function action()
{
  $view = new Opt_View('module_index.tpl');
  $view->zmienna = 'foo';
 
  return $view;
} // end action();

Then they can be packed into a section and assigned to the main template. The opt:include instruction renders the view objects, and what is more - it can read them directly from a section. It is illustrated by the sample codes. Below we can see, how to obtain a view from a module and append it to a section.

$moduleViews = array();
foreach($this->currentModules as $module)
{
  $view = $module->action();
  if($view instanceof Opt_View)
  {
    $moduleViews[] = array('view' => $view);
  }
}
 
$layout = new Opt_View('layout.tpl');
$layout->modules = $moduleViews;
 
$output->render($layout);

Now we have both the main template and the PHP code to prepare it.