📄 reader.php
字号:
<?PHP
/**
* Base class for patTemplate readers
*
* $Id: Reader.php 8287 2007-08-01 08:38:59Z eddieajau $
*
* This class is able to parse patTemplate tags from any string you hand it over
* It will emulate some kind of SAX parsing by calling start-, end- and CData-handlers.
*
* @package patTemplate
* @subpackage Readers
* @author Stephan Schmidt <schst@php.net>
*/
// Check to ensure this file is within the rest of the frameworkdefined('JPATH_BASE') or die();
/**
* No input
*/
define( 'PATTEMPLATE_READER_ERROR_NO_INPUT', 6000 );
/**
* Unknown tag
*/
define( 'PATTEMPLATE_READER_ERROR_UNKNOWN_TAG', 6001 );
/**
* Invalid tag (missing attribute)
*/
define( 'PATTEMPLATE_READER_ERROR_INVALID_TAG', 6002 );
/**
* Closing tag is missing
*/
define( 'PATTEMPLATE_READER_ERROR_NO_CLOSING_TAG', 6003 );
/**
* Invalid closing tag
*/
define( 'PATTEMPLATE_READER_ERROR_INVALID_CLOSING_TAG', 6004 );
/**
* Invalid condition specified
*/
define( 'PATTEMPLATE_READER_ERROR_INVALID_CONDITION', 6005 );
/**
* No name has been specified
*/
define( 'PATTEMPLATE_READER_ERROR_NO_NAME_SPECIFIED', 6010 );
/**
* CData in a conditional template
*/
define( 'PATTEMPLATE_READER_NOTICE_INVALID_CDATA_SECTION', 6050 );
/**
* template already exists
*/
define( 'PATTEMPLATE_READER_NOTICE_TEMPLATE_EXISTS', 6051 );
/**
* Base class for patTemplate readers
*
* This class is able to parse patTemplate tags from any string you hand it over
* It will emulate some kind of SAX parsing by calling start-, end- and CData-handlers.
*
* @abstract
* @package patTemplate
* @subpackage Readers
* @author Stephan Schmidt <schst@php.net>
*/
class patTemplate_Reader extends patTemplate_Module
{
/**
* reference to the patTemplate object that instantiated the module
*
* @access protected
* @var object
*/
var $_tmpl;
/**
* stack for all open elements
* @access private
* @var array
*/
var $_elStack;
/**
* stack for all open templates
* @access private
* @var array
*/
var $_tmplStack;
/**
* character data
* @access private
* @var array
*/
var $_data;
/**
* tag depth
* @access private
* @var integer
*/
var $_depth;
/**
* templates that have been found
* @access protected
* @var array
*/
var $_templates = array();
/**
* path to the template
* @access protected
* @var array
*/
var $_path = array();
/**
* start tag for variables
* @access private
* @var string
*/
var $_startTag;
/**
* end tag for variables
* @access private
* @var string
*/
var $_endTag;
/**
* default attributes
*
* @access private
* @var array
*/
var $_defaultAtts = array();
/**
* root attributes
*
* This is used when reading the template content
* from an external file.
*
* @access private
* @var array
*/
var $_rootAtts = array();
/**
* inherit attributes
*
* @access private
* @var array
*/
var $_inheritAtts = array();
/**
* name of the first template that has been found
*
* @access private
* @var string
*/
var $_root = null;
/**
* all data that has been processed
*
* @access private
* @var string
*/
var $_processedData = null;
/**
* current input
*
* @access private
* @var string
*/
var $_currentInput = null;
/**
* all loaded functions
*
* @access private
* @var array
*/
var $_functions = array();
/**
* function aliases
*
* @access private
* @var array
*/
var $_funcAliases = array();
/**
* options
*
* @access private
* @var array
*/
var $_options = array();
/**
* reader is in use
*
* @access private
* @var boolean
*/
var $_inUse = false;
/**
* set a reference to the patTemplate object that instantiated the reader
*
* @access public
* @param object patTemplate object
*/
function setTemplateReference( &$tmpl )
{
$this->_tmpl = &$tmpl;
}
/**
* read templates from any input
*
* @abstract must be implemented in the template readers
* @param mixed input to read from.
* This can be a string, a filename, a resource or whatever the derived class needs to read from
* @param array options, not implemented in current versions, but future versions will allow passing of options
* @return array template structure
*/
function readTemplates( $input, $options = array() )
{
return array();
}
/**
* load template from any input
*
* If the a template is loaded, the content will not get
* analyzed but the whole content is returned as a string.
*
* @abstract must be implemented in the template readers
* @param mixed input to load from.
* This can be a string, a filename, a resource or whatever the derived class needs to read from
* @param array options, not implemented in current versions, but future versions will allow passing of options
* @return string template content
*/
function loadTemplate( $input, $options = array() )
{
return $input;
}
/**
* set options
*
* @access public
* @param array array containing options
*/
function setOptions( $options )
{
$this->_startTag = $options['startTag'];
$this->_endTag = $options['endTag'];
$this->_options = $options;
if (isset($options['functionAliases'])) {
$this->_funcAliases = $options['functionAliases'];
}
array_map('strtolower', $this->_funcAliases);
}
/**
* add an alias for a function
*
* @access public
* @param string alias
* @param string function name
*/
function addFunctionAlias($alias, $function)
{
$this->_funcAliases[strtolower($alias)] = $function;
}
/**
* set the root attributes
*
* @access public
* @param array array containing options
*/
function setRootAttributes( $attributes )
{
$this->_rootAtts = $attributes;
}
/**
* parse templates from string
*
* @access private
* @param string string to parse
* @return array templates
*/
function parseString( $string )
{
$this->_inUse = true;
/**
* apply input filter before parsing
*/
$string = $this->_tmpl->applyInputFilters( $string );
$this->_inheritAtts = array();
$this->_elStack = array();
$this->_data = array( '' );
$this->_tmplStack = array();
$this->_depth = 0;
$this->_templates = array();
$this->_path = array();
$this->_processedData = '';
$this->_defaultAtts = $this->_tmpl->getDefaultAttributes();
if( !isset( $this->_defaultAtts['autoload'] ) ) {
$this->_defaultAtts['autoload'] = 'on';
}
/**
* create a special root template
*/
$attributes = $this->_rootAtts;
$attributes['name'] = '__ptroot';
$rootTemplate = $this->_initTemplate( $attributes );
$this->_root = null;
unset( $rootTemplate['isRoot'] );
array_push( $this->_tmplStack, $rootTemplate );
$patNamespace = $this->_tmpl->getNamespace();
if (is_array($patNamespace)) {
$patNamespace = array_map('strtolower', $patNamespace);
} else {
$patNamespace = array(strtolower( $patNamespace ));
}
/**
*start parsing
*/
$regexp = '/(<(\/?)([[:alnum:]]+):([[:alnum:]]+)[[:space:]]*([^>]*)>)/im';
$tokens = preg_split( $regexp, $string, -1, PREG_SPLIT_DELIM_CAPTURE );
/**
* the first token is always character data
* Though it could just be empty
*/
if( $tokens[0] != '' ) {
$this->_characterData( $tokens[0] );
}
$cnt = count( $tokens );
$i = 1;
// process all tokens
while( $i < $cnt ) {
$fullTag = $tokens[$i++];
$closing = $tokens[$i++];
$namespace = strtolower( $tokens[$i++] );
$tagname = strtolower( $tokens[$i++] );
$attString = $tokens[$i++];
$empty = substr( $attString, -1 );
$data = $tokens[$i++];
/**
* check, whether it's a known namespace
* currently only the template namespace is possible
*/
if( !in_array($namespace, $patNamespace) ) {
$this->_characterData( $fullTag );
$this->_characterData( $data );
continue;
}
/**
* is it a closing tag?
*/
if( $closing === '/' ) {
$result = $this->_endElement( $namespace, $tagname );
if( patErrorManager::isError( $result ) ) {
return $result;
}
$this->_characterData( $data );
continue;
}
/**
* Is empty or opening tag!
*/
if( $empty === '/' ) {
$attString = substr( $attString, 0, -1 );
}
$attributes = $this->_parseAttributes( $attString );
$result = $this->_startElement( $namespace, $tagname, $attributes );
if( patErrorManager::isError( $result ) ) {
return $result;
}
/**
* check, if the tag is empty
*/
if( $empty === '/' ) {
$result = $this->_endElement( $namespace, $tagname );
if( patErrorManager::isError( $result ) ) {
return $result;
}
}
$this->_characterData( $data );
}
$rootTemplate = array_pop( $this->_tmplStack );
$this->_closeTemplate( $rootTemplate, $this->_data[0] );
/**
* check for tags that are still open
*/
if( $this->_depth > 0 ) {
$el = array_pop( $this->_elStack );
return patErrorManager::raiseError(
PATTEMPLATE_READER_ERROR_NO_CLOSING_TAG,
$this->_createErrorMessage( "No closing tag for {$el['ns']}:{$el['name']} found" )
);
}
$this->_inUse = false;
return $this->_templates;
}
/**
* parse an attribute string and build an array
*
* @access private
* @param string attribute string
* @param array attribute array
*/
function _parseAttributes( $string )
{
static $entities = array(
'<' => '<',
'>' => '>',
'&' => '&',
'"' => '"',
''' => '\''
);
$attributes = array();
$match = array();
preg_match_all('/([a-zA-Z_0-9]+)="((?:\\\.|[^"\\\])*)"/U', $string, $match);
for ($i = 0; $i < count($match[1]); $i++) {
$attributes[strtolower( $match[1][$i] )] = strtr( (string)$match[2][$i], $entities );
}
return $attributes;
}
/**
* handle start element
*
* @access private
* @param string element name
* @param array attributes
*/
function _startElement( $ns, $name, $attributes )
{
array_push( $this->_elStack, array(
'ns' => $ns,
'name' => $name,
'attributes' => $attributes,
)
);
$this->_depth++;
$this->_data[$this->_depth] = '';
/**
* handle tag
*/
switch( $name )
{
/**
* template
*/
case 'tmpl':
$result = $this->_initTemplate( $attributes );
break;
/**
* sub-template
*/
case 'sub':
$result = $this->_initSubTemplate( $attributes );
break;
/**
* link
*/
case 'link':
$result = $this->_initLink( $attributes );
break;
/**
* variable
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -