<?php
/**
* Wapple Architect WAPL Builder class
*
* This class allows you to build WAPL ensuring that it's always valid and
* always is in line with the schema at http://wapl.wapple.net/wapl.xsd
*
* @author Rich Gubby
* @version 1.0
* @package WappleArchitect
*/
class waplBuilder
{
/**
* Any universal attributes that apply to all elements
* @access public
* @var array
*/
public $universalAttributes = array('class', 'id');
/**
* The current tag we're building
* @access public
* @var string
*/
public $tag;
/**
* Tag prefix - used when a "link" becomes an "externalLink"
* @access public
* @var string
*/
public $tagPrefix;
/**
* Parent tag
* @access public
* @var string
*/
public $parentTag;
/**
* WAPL schema
* @access public
* @var array
* @todo Make sure it's up to date!
*/
public $schema = array(
'head' => array(
'children' => array('title')
),
'title' => array(
'direct' => true,
'parent' => 'head'
),
'layout' => array(
),
'meta' => array(
'attributes' => array('name', 'content'),
'parent' => 'head',
'selfClosing' => true
),
'css' => array(
'children' => array('url'),
'parent' => 'head'
),
'link' => array(
'children' => array('url', 'label', 'prefix', 'linkVars', 'insertion', 'suffix', 'prefix', 'externalImage', 'accessKey')
),
'chars' => array(
'attributes' => array('make_safe'),
'children' => array('value')
),
'linkVars' => array(
'parent' => 'link',
'children' => array('var')
),
'var' => array(
'children' => array('name', 'value'),
'parent' => 'linkVars'
),
'externalLink' => array(
'children' => array('url', 'label', 'prefix', 'suffix', 'externalImage')
),
'externalImage' => array(
'attributes' => array('filetype', 'scale', 'quality', 'alt'),
'children' => array('url', 'transcol', 'safe_mode')
),
'form' => array(
'children' => array('action', 'formItem', 'url')
),
'formItem' => array(
'parent' => 'form',
'attributes' => array('item_type', 'default', 'menu_id'),
'children' => array('name', 'label', 'value', 'possibility', 'input_mask')
),
'possibility' => array(
'parent' => 'formItem',
'children' => array('label', 'value')
),
'rule' => array(
'attributes' => array('type', 'criteria', 'condition')
),
'phonecallChunk' => array(
'children' => array('phone_number', 'show_label')
),
'phonebookChunk' => array(
'children' => array('phone_number', 'contact_name', 'show_label')
),
'rssChunk' => array(
'children' => array('url', 'max_items', 'items_per_page', 'graphic_scale', 'icon_scale', 'tease_length', 'show_no_tease',
'do_channel_title', 'do_channel_image', 'do_channel_link', 'do_channel_description', 'do_channel_language',
'do_channel_copyright', 'do_channel_managing_editor', 'do_channel_webmaster', 'do_channel_publish_date',
'do_channel_last_build_date', 'do_channel_category', 'do_channel_generator', 'do_channel_documentation',
'do_channel_cloud', 'do_channel_ttl', 'do_channel_rating', 'do_channel_text_input', 'do_channel_skip_hours',
'do_channel_skip_days', 'do_item_title', 'do_item_link', 'do_item_description', 'do_item_author',
'do_item_category', 'do_item_comment', 'do_item_comments', 'do_item_enclosure', 'do_item_guid',
'do_item_publish_date', 'do_item_source'
)
),
'rubberduckChunk' => array(
'children' => array('rubberduck_client_id', 'rubberduck_set_id', 'graphic_scale', 'delivery_performance',
'display_mode')
),
'jumpChunk' => array(
'children' => array('destination_page', 'url')
),
'waplChunk' => array(
'children' => array('url')
),
'wordsChunk' => array(
'children' => array('display_as', 'quick_text')
),
'spacemakerChunk' => array(
'children' => array('scale')
),
'hrChunk' => array(),
'admobChunk' => array(
'children' => array('mobile_site_id', 'iphone_site_id', 'iphone_background_color', 'iphone_text_color')
),
'admodaChunk' => array(
'children' => array('admoda_mode', 'admoda_zoneid', 'admoda_showhousebanner', 'admoda_housebannerid')
),
'decktradeChunk' => array(
'children' => array('decktrade_siteid')
),
'adsenseChunk' => array(
'children' => array('channel_id', 'client_id', 'items_per_page', 'col_border', 'col_bg', 'col_link', 'col_text', 'col_url')
),
'mbrandChunk' => array(
'children' => array('mbrand_placement_id', 'mbrand_ad_server')
),
'mkhojChunk' => array(
'children' => array('mkhoj_site_id')
),
'mobilecommercemmsChunk' => array(
'children' => array('client_id', 'items_per_page', 'backfill', 'filter_out_adult', 'use_page_keywords',
'ad_keyword', 'do_search', 'test_mode'
)
),
'mpressionChunk' => array(
'children' => array('adslot_id', 'ad_category', 'ad_keyword')
),
'nokiaadsChunk' => array(
'children' => array('nokiaads_spot_name', 'nokiaads_ad_server')
),
'stampChunk' => array(
'children' => array('stamp_si', 'stamp_al', 'stamp_mode', 'items_per_page', 'graphic_scale')
),
'zestadzChunk' => array(
'children' => array('zestadz_cid', 'zestadz_meta')
),
'settings' => array(
'children' => array('bangoPageTrackingId', 'iphoneTextSizeAdjust', 'iphoneUserScaleable', 'iphoneInitalScale', 'iphoneMinScale', 'iphoneMaxScale', 'iphoneMagicWidth')
)
);
/**
* List of tags that don't have rows or cells
* @access public
* @var array
*/
public $noRowTags = array(
'head', 'title', 'meta', 'css', 'linkVars', 'var', 'formItem', 'possibility',
'rule', 'phonecallChunk', 'phonebookChunk', 'rssChunk', 'rubberduckChunk',
'jumpChunk', 'waplChunk', 'wordsChunk', 'spacemakerChunk', 'hrChunk', 'admobChunk',
'decktradeChunk', 'adsenseChunk', 'mbrandChunk', 'mkhojChunk', 'mobilecommercemmsChunk',
'mpressionChunk', 'nokiaadsChunk', 'stampChunk', 'zestadzChunk', 'settings', 'row', 'cell', 'layout'
);
/**
* Number of pages in an article
* @access public
* @var array
*/
public $pages = array();
/**
* The current page we're on
* @access public
* @var integer
*/
public $currentPage;
/**
* Build the page header
*
* @access public
* @return string
*/
public function start()
{
return '<' . '?xml version="1.0" encoding="utf-8" ?'.'><wapl xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://wapl.wapple.net/wapl.xsd">';
}
/**
* Build the page layout
*
* @access public
* @param array $options
* @return unknown_type
*/
public function layout($options = array())
{
$this->tag = 'layout';
$this->tagPrefix = null;
return $this->__do_tag($options);
}
/**
* Build the page footer
*
* @access public
* @return string
*/
public function end()
{
return '</wapl>';
}
/**
* Build a WAPL head element
* @param array $options
* @access public
* @return string
*/
public function head($options = array())
{
$this->tag = 'head';
$this->tagPrefix = null;
return $this->__do_tag($options);
}
/**
* Build a META element
* @param array $options
* @access public
* @return string
*/
public function meta($options = array())
{
$this->tag = 'meta';
$this->tagPrefix = null;
return $this->__do_tag($options);
}
/**
* Build a CSS element
* @param array $options
* @access public
* @return string
*/
public function css($options = array())
{
$this->tag = 'css';
$this->tagPrefix = null;
return $this->__do_tag($options);
}
/**
* Build a WAPL link element
* @param array $options
* @access public
* @return string
*/
public function link($options = array())
{
$this->tag = 'link';
$this->__doExternal($options);
return $this->__do_tag($options);
}
/**
* Build a WAPL image element
*
* @param array $options
* @access public
* @return string
*/
public function image($options = array())
{
$this->tag = 'image';
$this->__doExternal($options);
return $this->__do_tag($options);
}
/**
* Build a WAPL chars element
* @param array $options
* @access public
* @return string
*/
public function chars($options = array())
{
$this->tag = 'chars';
$this->tagPrefix = null;
return $this->__do_tag($options);
}
/**
* Build a WAPL chunk element
* @param string $type
* @param array $options
* @return string
*/
public function chunk($type, $options)
{
$this->tag = $type.'Chunk';
$this->tagPrefix = null;
return $this->__do_tag($options);
}
/**
* Build a WAPL form element (includes all form item elements)
* @param array $options
* @access public
* @return string
*/
public function form($options = array())
{
$this->tag = 'form';
$this->tagPrefix = null;
return $this->__do_tag($options);
}
/**
* Build a WAPL formItem element
* @param array $options
* @access public
* @return string
*/
public function formItem($options = array())
{
$this->tag = 'formItem';
$this->tagPrefix = null;
return $this->__do_tag($options);
}
/**
* Build a WAPL rule
* @param array $options
* @access public
* @return string
*/
public function rule($options)
{
$this->tag = 'rule';
return $this->__do_tag($options);
}
/**
* Build any page settings
* @param array $options
* @access public
* @return string
*/
public function settings($options)
{
$this->tag = 'settings';
$this->tagPrefix = null;
return $this->__do_tag($options);
}
/**
* Build a row start tag
* @param array $options
* @access public
* @return string
*/
public function rowStart($options = array())
{
$this->tag = 'row';
$this->tagPrefix = null;
$options['end'] = false;
$options['row'] = false;
$options['cell'] = false;
return $this->__do_tag_start($options);
}
/**
* Build a row end tag
* @param array $options
* @access public
* @return string
*/
public function rowEnd($options = array())
{
$this->tag = 'row';
$this->tagPrefix = null;
$options['start'] = false;
$options['row'] = false;
$options['cell'] = false;
return $this->__do_tag_end($options);
}
/**
* Build a cell start tag
* @param array $options
* @access public
* @return string
*/
public function cellStart($options = array())
{
$this->tag = 'cell';
$options['end'] = false;
$options['row'] = false;
$options['cell'] = false;
return $this->__do_tag_start($options);
}
/**
* Build a cell end tag
* @param array $options
* @access public
* @return string
*/
public function cellEnd($options = array())
{
$this->tag = 'cell';
$options['start'] = false;
$options['row'] = false;
$options['cell'] = false;
return $this->__do_tag_end($options);
}
/**
* Format content into WAPL readable format
* @param string $content
* @param integer $imagescale
* @param integer $imagequality
* @param string $class
* @param integer $length
* @access public
* @return string
*/
public function format_text($content, $imagescale = 95, $imagequality = 90, $class = '', $length = null)
{
// Remove newlines and tabs
$content = str_replace(array("\r", "\n", "\t", "\r\n"), ' ', $content);
$this->pages = array();
// Replace p tags with a new wordsChunk element
$content = preg_replace('/<p class="(.*?)">(.*?)<\/p>/is', '</quick_text></wordsChunk><wordsChunk class="${1}"><quick_text>${2}</quick_text></wordsChunk><wordsChunk class="'.$class.'"><quick_text>', $content);
$content = preg_replace('/<p>(.*?)<\/p>/is', '</quick_text></wordsChunk><wordsChunk class="'.$class.'"><quick_text>${1}</quick_text></wordsChunk><wordsChunk class="'.$class.'"><quick_text>', $content);
// Remove images with WAPL versions
//$content = preg_replace('/<img(.*?)src=\"(.*?)(\.)(jpeg|png|jpg|bmp|gif)\".*?\/>/i', '</quick_text></wordsChunk><row><cell><externalImage filetype="${4}" scale="'.$imagescale.'" quality="'.$imagequality.'"><url>${2}.${4}</url></externalImage></cell></row><wordsChunk class="'.$class.'"><quick_text>', $content);
preg_match_all('/<img(.*?)src=\"(.*?)(\.)*(jpeg|png|jpg|bmp|gif)*\"(.*?)(\/>|><\/img>)/i', $content, $imageMatches);
foreach($imageMatches[2] as $key => $val)
{
if(isset($imageMatches[3][$key]) AND $imageMatches[3][$key] == '.')
{
$content = str_replace($imageMatches[0][$key], '</quick_text></wordsChunk><row><cell><externalImage filetype="'.$imageMatches[4][$key].'" scale="'.$imagescale.'" quality="'.$imagequality.'"><url>'.$val.'.'.$imageMatches[4][$key].'</url></externalImage></cell></row><wordsChunk class="'.$class.'"><quick_text>', $content);
}
}
// Replace any strong tags with WTF [b] tags
$content = preg_replace('/<strong>(.*?)<\/strong>/i', '[b]${1}[/b]', $content);
// Replace any h* tags
$content = preg_replace('/<h(.*?)>(.*?)<\/h(.*?)>/i', '</quick_text></wordsChunk><wordsChunk class="'.$class.'"><display_as>h${1}</display_as><quick_text>${2}</quick_text></wordsChunk><wordsChunk class="'.$class.'"><quick_text>', $content);
// Lists
$content = preg_replace('/<ul(.*?)>/', '[list]', $content);
$content = preg_replace('/<\/ul>/', '[/list]', $content);
// List items
$content = preg_replace('/<li(.*?)>(.*?)<\/li>/i', '[*]${2}[/*]', $content);
// Replace any links
$content = preg_replace('/<a(.*?)href="(.*?)"(.*?)>(.*?)<\/a>/i', '[url=${2}]${4}[/url]', $content);
// Replace any form tags - upgrade this later!
$content = preg_replace('/<form(.*?)>/i', '', $content);
$content = preg_replace('/<\/form>/i', '', $content);
$content = preg_replace('/<script(.*?)>.*<\/script>/', '', $content);
// Replace any rogue wordsChunk chars
$content = preg_replace('/<\/wordsChunk><quick_text>(.*?)<\/quick_text><\/wordsChunk>/i', '', $content);
$content = preg_replace('/<\/wordsChunk><quick_text>(.*?)<\/quick_text><\/wordsChunk>/i', '', $content);
$content = preg_replace('/<wordsChunk><quick_text>([\s\t])+<\/quick_text><\/wordsChunk>/i', '', $content);
$content = str_replace('</wordsChunk><quick_text>', '', $content);
$content = str_replace('</externalLink></quick_text></wordsChunk>', '', $content);
// Lastly strip any other tags
$stripTagExclude = array();
foreach($this->schema as $key => $val)
{
$stripTagExclude[$key] = $key;
if(isset($val['children']))
{
foreach($val['children'] as $child)
{
$stripTagExclude[$child] = $child;
}
}
}
$stripTagExcludeString = '';
foreach($stripTagExclude as $tag)
{
$stripTagExcludeString .= '<'.$tag.'>';
}
$stripTagExcludeString.= '<row><cell>';
// Strip any remaining html
$content = strip_tags($content, $stripTagExcludeString);
// Remove multiple BR and make a new wordschunk
$content = preg_replace('/(<br \/>\s){2,}/', '</quick_text></wordsChunk><wordsChunk class="'.$class.'"><quick_text>', $content);
// Clean up any empty wordsChunk elements
$content = preg_replace('/<wordsChunk class="'.$class.'"><quick_text><\/quick_text><\/wordsChunk>/i', '', $content);
if($length)
{
$this->getPages($content, $length);
$tidyContent = $this->pages[($this->currentPage - 1)];
if((strpos($tidyContent, '<row>') === 0) OR (strpos($tidyContent, '<wordsChunk') === 0))
{
$tidyContent = '</quick_text></wordsChunk>'.$tidyContent;
}
if(strrpos($tidyContent, '</quick_text></wordsChunk>') === (strlen($tidyContent) - strlen('</quick_text></wordsChunk>')))
{
$tidyContent = substr($tidyContent, 0, strrpos($tidyContent, '</quick_text></wordsChunk'));
}
return $tidyContent;
} else
{
$this->pages = array('page');
$this->currentPage = 1;
return $content;
}
}
/**
* Get the number of pages
* @param string $content
* @access public
* @return unknown_type
*/
public function getPages($content, $length)
{
$chunks = preg_split('/<\/quick_text><\/wordsChunk>/', $content, -1);
$r = 0;
$tmpPages = array();
for($i = 0; $i < count($chunks); $i++)
{
if (strlen($this->pages[$r] . $chunks[$i].' ') < $length)
{
$tmpPages[$r] .= $chunks[$i] . '</quick_text></wordsChunk>';
} else
{
$r++;
$tmpPages[$r] .= $chunks[$i] . '</quick_text></wordsChunk>';
}
}
// Order pages correctly
foreach($tmpPages as $val)
{
$this->pages[] = $val;
}
// which page are we on?
if(isset($_GET['page']))
{
$this->currentPage = $_GET['page'];
} else
{
$this->currentPage = 1;
}
}
/**
* Main function to build a tag
* @param array $options
* @access private
* @return string
*/
private function __do_tag($options)
{
if(in_array($this->__getTag(), $this->noRowTags))
{
$options['row'] = false;
$options['cell'] = false;
}
$string = '';
$string .= $this->__do_tag_start($options);
$string .= $this->__do_tag_contents($options);
$string .= $this->__do_tag_end($options);
return $string;
}
/**
* Start an element off by building a row and cell if needed and setting up a tag prefix
* @param array $options
* @access private
* @return string
*/
private function __do_tag_start($options)
{
if(isset($options['start']) AND $options['start'] == false)
{
return;
}
$string = null;
if(!isset($options['row']) OR $options['row'] !== false)
{
$string .= $this->__do_tag_row_start($options);
}
if(!isset($options['cell']) OR $options['cell'] !== false)
{
$string .= $this->__do_tag_cell_start($options);
}
$string .= '<'.$this->tagPrefix;
if($this->tagPrefix)
{
$tag = $this->tagPrefix.ucwords($this->tag);
$string .= ucwords($this->tag);
} else
{
$tag = $this->tag;
$string .= $this->tag;
}
foreach($this->universalAttributes as $val)
{
if(isset($options[$val]))
{
$string .= ' '.$val.'="'.$options[$val].'"';
}
}
if(isset($this->schema[$tag]['attributes']))
{
foreach($this->schema[$tag]['attributes'] as $val)
{
if(isset($options[trim($val)]))
{
$string .= ' '.trim($val).'="'.$options[trim($val)].'"';
}
}
}
if(!isset($this->schema[$tag]['selfClosing']) OR $this->schema[$tag]['selfClosing'] == false)
{
$string .= '>';
}
return $string;
}
/**
* Build the internal contents of an element
* @param array $options
* @access private
* @return string
*/
private function __do_tag_contents($options)
{
if(isset($options['contents']) AND $options['contents'] == false)
{
return;
}
$string = null;
$tag = $this->__getTag();
if(isset($this->schema[$tag]['children']) AND !empty($this->schema[$tag]['children']))
{
foreach($this->schema[$tag]['children'] as $val)
{
if((isset($this->schema[$val]['parent']) AND ($this->schema[$val]['parent'] == $this->__getTag())) OR !isset($this->schema[$val]['parent']))
{
if(isset($options[$val]))
{
$string .= '<'.$val.'>'.$options[$val].'</'.$val.'>';
}
}
}
}
if(isset($options['children']))
{
$childString = null;
$this->parentTag = $this->tag;
$tmpTagPrefix = $this->tagPrefix;
foreach($options['children'] as $child)
{
if(isset($child['tag']))
{
$this->tag = $child['tag'];
$options = array();
// Build up any attributes
if(isset($this->schema[$this->tag]['attributes']))
{
foreach($this->schema[$this->tag]['attributes'] as $attVal)
{
if(isset($child[$attVal]))
{
$options[$attVal] = $child[$attVal];
}
}
}
if(isset($child['options']))
{
$options = array_merge($options, $child['options']);
}
if(method_exists($this, $this->tag))
{
$childString .= $this->{$this->tag}($options);
} else
{
$childString .= $this->__do_tag($options);
}
}
}
$this->tagPrefix = $tmpTagPrefix;
$this->tag = $this->parentTag;
$string .= $childString;
}
// Set a direct value into a tag
if(isset($this->schema[$tag]['direct']) AND $this->schema[$tag]['direct'] == true)
{
$string .= $options['value'];
}
return $string;
}
/**
* Close elements properly
* @param array $options
* @access private
* @return string
*/
private function __do_tag_end($options)
{
if(isset($options['end']) AND $options['end'] == false)
{
return;
}
$string = '';
if(isset($this->schema[$this->tag]['selfClosing']) AND $this->schema[$this->tag]['selfClosing'] == true)
{
$string .= ' />';
} else
{
$string .= '</'.$this->tagPrefix;
if($this->tagPrefix)
{
$string .= ucwords($this->tag);
} else
{
$string .= $this->tag;
}
$string .= '>';
if(!isset($options['cell']) OR $options['cell'] !== false)
{
$string .= $this->__do_tag_cell_end($options);
}
if(!isset($options['row']) OR $options['row'] !== false)
{
$string .= $this->__do_tag_row_end($options);
}
}
return $string;
}
/**
* Open an elements row
* @param array $options
* @access private
* @return string
*/
private function __do_tag_row_start($options)
{
$string = '<row';
if(isset($options['rowClass']))
{
$string .= ' class="'.$options['rowClass'].'"';
}
if(isset($options['rowId']))
{
$string .= ' id="'.$options['rowId'].'"';
}
$string .= '>';
return $string;
}
/**
* Close a row
* @access private
* @return string
*/
private function __do_tag_row_end()
{
return '</row>';
}
/**
* Open an elements cell
* @param array $options
* @access private
* @return string
*/
private function __do_tag_cell_start($options)
{
$string = '<cell';
if(isset($options['cellClass']))
{
$string .= ' class="'.$options['cellClass'].'"';
}
if(isset($options['cellId']))
{
$string .= ' id="'.$options['cellId'].'"';
}
$string .= '>';
return $string;
}
/**
* Close a cell
* @param array $options
* @access private
* @return string
*/
private function __do_tag_cell_end($options)
{
return '</cell>';
}
/**
* Get proper tag
* @access private
* @return string
*/
private function __getTag()
{
if($this->tagPrefix)
{
return $this->tagPrefix.ucwords($this->tag);
} else
{
return $this->tag;
}
}
/**
* Work out external link
* @param array $options
* @access private
* @return void
*/
private function __doExternal($options)
{
$this->tagPrefix = null;
if(!isset($options['external']) || $options['external'] == true)
{
$this->tagPrefix = 'external';
}
}
}
?>
|