The present page controller implementation creates a DOM tree while parsing templates. The functionality of each DOM node is defined within a taglib class. These taglib classes are based on the class Document that inherits from the central class coreObject. The class Document features the central parser method __extractTagLibTags() that searches a template file for known taglibs. Every XML tag generates another child node of the current DOM node. The XML attributes are added to the attribute list of the taglib implementation so that the taglib class can make use of them.
Every XML tag listed under Standard taglibs is represented by a taglib class. This class implements the interface methods defined in the class Document or coreObject respectively.
Every taglib class name must contain the part "_taglib_" between the prefix and the class description. If the developer is likely to introduce the XML tag
<shop:basket />shop_taglib_basketThe part of the name that is marked with green color is called prefix the blue one is named class. Both parts can be choosen freely. Though it is recommended to structure the tags according to their dependency. Given the fact that the <shop:basket /> tag contains various subtags these subtags should have the prefix basket. The following example shows this naming convention:
<shop:basket>
<basket:title />
<basket:products>
<products:listing />
<products:sum />
</basket:products>
</shop:basket>The example implies, that during parsing of the <shop:basket /> tag, the subtags should be parsed into child DOM objects, too. For this reason the constructor of the taglib implementation of the shop_taglib_basket must contain the definition of the known subtaglibs:
class shop_taglib_basket extends Document {
function shop_taglib_basket(){
$this->__TagLibs[] = new TagLib('namespace::to::taglib','basket','title');
$this->__TagLibs[] = new TagLib('namespace::to::taglib','basket','products');
}
[..]
}Same rule applies for the implementation of the <basket:products /> tag (taglib class basket_taglib_products). Here the constructor must declare the tags <products:listing /> and <products:sum />.
During parsing of the XML / HTML code within the template files known tags will be mapped to DOM objects. The content of the
<php:hightlight>
$var = 'value';
</php:hightlight>tag will be stored in the private class member variable $this->__Content. The attributes of the tag are stored in the associative array $this->__Attributes. Due to that behavior the developer can access the attributes and content of the tag easily and the tags can be configured using XML / HTML attributes. Another advantage is that the tags can be configured with any attributes such as "class" or "style". This lightens the formating of UI elements such as text fields or buttons independent of the PHP code.
The private member variable $this->__ParentObject stores the reference to the parent object of the current node. Due to the fact, that the parent object inherits from coreObjects, using the methods get(), set(), getAttribute() and setAttribute() can be used to gather properties of the parent class instance. The public methods getByReference() and setByReference() allows to get access to any object within the DOM tree. The detailed documentation of these methods can be seen in the API documentation. Here the classes Document and coreObject are importent.
To implement functionality to a present taglib class there are several interface methods that are executed concerning a special page controller timing model. These functions have different meaning, too. Beside the interface methods, the developer can design the class methods freely. Please attend to the following points:
Each taglib class must inherit from the Document class, because this class is the interface class that serves the central parser method. The class name depends on the XML tag name as described above. To have an XML tag that is named "php:highlight", the first part of the name (prefix) must be "php", the middle part the common string "_taglib_" and the XML class string is "highlight". This leads to the taglib class namephp_taglib_highlight. If this taglib is announced using the <core:addtaglib /> tag the parser searches for this tag in the currend template file. Moreover, it is important that the file name is identical to the class name.
The constructor is intended to contain initializing of member variables or things like that. The constructor is given no argument. When no inizializing must happen there must not be a constructor.
In common the constructor should be uses to define known taglibs to the current DOM node, that are added as child nodes during DOM construction (see example above). For a detailed implemenation example, please consult the API documentation for the class html_taglib_template or html_taglib_form.
The methode onParseTime() is executed by the page controller when the properties
are set. At this time the taglib class has access to it's attributes and content and operations concerning this properties can be implemented. During execution of the method the node is not added to the DOM tree yet. If the developer must be able to access father or child nodes the function onAfterAppend() should be taken instead.
<{OBJECT_ID} />As all children of the currend DOM node are added to the DOM tree the method onAfterAppend() is executed on them. At this moment a DOM node can access every neighbour node by the $this->__ParentObject or $this->__Children member variable. As mentioned above the methods get(), set() and so an grant access to the attributes of these neighbour nodes.
The methods discussed above all are used to generate and process a DOM tree out of XML / HTML code. The function transform() is to produce XML / HTML code out of the object tree instead. Merely the implementation of the class Document can be taken for a newly created taglib class. For special purpose this method must be overridden be be present class. To generate an attribute string out of the attributes of the current node, the method __getAttributesAsString() can be taken.
foreach($this->__Children as $objectId => $DUMMY){
$this->__Content = str_replace(
'<'.$objectId.' />',
$this->__Children[$objectId]->transform(),
$this->__Content
);
}As already mentioned above the following example describes how to highight and colorize the string between the tags
<php:highlight>
[..]
</php:highlight>The implementation of this task is taken over by the class php_taglib_hightlight. For this reason the method transform() is added to the class to modify the content contained in the property $this->__Content with aid of the highlight_string() PHP function. The code box shows how the class must look like:
class phpphp_taglib_highlight extends Document {
function phpphp_taglib_highlight(){
}
function transform(){
// count lines
$LineCount = substr_count($this->__Content,"\n") - 1;
// highlight source code
// - Remove new lines at the beginning
// - Remove new lines and blanks at the end
// - Remove new lines and blanks around the whole text
$HighlightedContent = highlight_string(trim('<?php '.ltrim(rtrim($this->__Content),"\x0A..\x0D").' ?>'),true);
// replace php start tags
$HighlightedContent = str_replace('<font color="#007700"><?</font>','',$HighlightedContent);
$HighlightedContent = str_replace('<font color="#0000BB"><?php ','<font color="#0000BB">',$HighlightedContent);
$HighlightedContent = str_replace('<font color="#0000BB">php','<font color="#0000BB">',$HighlightedContent);
$HighlightedContent = str_replace('<font color="#0000BB"> </font>','',$HighlightedContent);
// enhancement to the PHP5 support
$HighlightedContent = str_replace('<span style="color: #0000BB"><?php ','<span style="color: #0000BB">',$HighlightedContent);
$HighlightedContent = str_replace('<span style="color: #0000BB"><?php','<span style="color: #0000BB">',$HighlightedContent);
$HighlightedContent = str_replace('<span style="color: #0000BB">?></span>','',$HighlightedContent);
// replace php end tags
$HighlightedContent = str_replace('<font color="#0000BB">?></font>','',$HighlightedContent);
// return div enclodes source code with height limit if necessary
if($LineCount > 27){
return '<div class="phpcode" style="height: 400px; overflow: auto;">'.$HighlightedContent.'</div>';
}
else{
return '<div class="phpcode">'.$HighlightedContent.'</div>';
}
}
}The taglib html:entityencode provides a basis to convert text into HTML entities. This functionality can be used to encode e-mail addresses to protect them from getting crawled and used for spam. To provide this feature a new taglib class must be created using the method encodeCharactersToHTML of the class stringAssistant to do the encoding. After announcing the taglib via
<core:addtaglib namespace="path::to::namespace" prefix="html" class="entityencode" /><html:entityencode>nobody@example.com</html:entityencode>nobody@example.comSince the core functionality is not included in the taglib class itself this operation can be reused in components like guestbook controllers. The code box shows how the class must look like:
import('tools::string','stringAssistant');
class html_taglib_entityencode extends Document {
function html_taglib_entityencode(){
}
function transform(){
return stringAssistant::encodeCharactersToHTML($this->__Content);
}
}Giving another example the taglib <doc:createobject /> may be described here. This taglib is used to generate the content of this documentation page taking care of the choosen language and the content included there. The content is read from HTML files containing pure text, HTML code and XML strings that give advice to the page controller to include special modules. During parsing the source code is scanned to find known taglibs and new child nodes are created if a known taglib is found. To use this taglib it must be announced by using
<core:addtaglib namespace="tools::html::taglib" prefix="doc" class="createobject" /><doc:createobject requestparam="Seite" defaultvalue="Startseite" />Taking a closer look into the source code the following logic is encapsulated there:
import('tools::request','RequestHandler');
class doc_taglib_createobject extends Document {
function doc_taglib_createobject(){
parent::Document();
}
function onParseTime(){
// get tag attributes
$RequestParameter = $this->__Attributes['requestparam'];
$DefaultValue = $this->__Attributes['defaultvalue'];
// initialize request params
$_LOCALS = RequestHandler::getValues(array($RequestParameter => $DefaultValue));
// gather current param value
$CurrentRequestParameter = $_LOCALS[$RequestParameter];
// fill the content of the tag
$this->__Content = $this->__getContent($CurrentRequestParameter);
// extract tags
$this->__extractTagLibTags();
// check for document controller
$this->__extractDocumentController();
}
function __getContent($Page){
$File = './frontend/content/c_'.$this->__Language.'_'.strtolower($Page).'.html';
if(!file_exists($File)){
$File = './frontend/content/c_'.$this->__Language.'_404.html';
}
return file_get_contents($File);
}
}For continuing application examples the form taglibs can be studied. This taglib classes are stored in the apps/tools/form/taglib/ folder.