📄 reader.php
字号:
<?PHP/** * Base class for patTemplate readers * * $Id: Reader.php 10381 2008-06-01 03:35:53Z pasamio $ * * 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 + -