Class to automate parsing Joomla Content Plugin tags.
Easy operation, define your tag name, and if it is a self-closing tag
Update 4-23-2013 - Added option to use an alternate closing tag. Namespaced DOMDocument, so the class can itself be namespaced, should the application require it.
$content = '{plugin param yoyoyo param1="param with a string value containing spaces" param2="2" param3="3" unquotedinteger=4 param4=unquotedstring}plugin content{/plugin}'; $content.= '{plugin}contents{/plugin}'; $parser = new TagParser('plugin'); $parser->parse($content); foreach($parser->tags as $key=>$tag) { $param1 = $tag->getParam('param1','default value'); echo $tag->getContent('default content'); /* of course, you'll want to do something with the tags */ $content = $tag->replace($content,'<p class="param1 or whatever">'.$param1.'</p>'); } /* appending the previous $content and using the previous $parser * (adjusting it for a slightly different tag, with an alternate closing tag), * this tag is appended to the taglist of the previous instance */ $content.= "{plugin:detail param1=2 param2=3 param3=1}plugin content2{/plugin}"; $parser->setIdentifier('plugin:detail'); $parser->setOptions(array('alternateclose'=>'plugin')); $parser->parse($content); foreach($parser->tags as $key=>$tag) { echo $tag->getParam('param1','default value'); echo $tag->getContent('default content'); /* we did something else, so we just get rid of this tag entirely */ $content = $tag->replace($content,''); } $content2 = '{plugin2 param param1=1 param2=2 param3=3}'; $parser2 = new TagParser('plugin2',array('selfclosing'=>true)); $parser2->parse($content2); foreach($parser2->tags as $key=>$tag) { echo $tag->getParam('param1','default value'); } $content3 = '[plugin3 param param1=1 param2=2 param3=3]<a href="#">plugin content</a>[/plugin3]'; $parser3 = new TagParser('plugin3',array('bracket'=>'[]')); $parser3->parse($content3); foreach($parser3->tags as $key=>$tag) { echo $tag->getParam('param1','default value'); echo $tag->getContent('default content'); }
And here's the class:
<!--?php /** * @package library TagParser * @copyright (C) 2010-2013 RicheyWeb - www.richeyweb.com * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL */ // no direct access defined( '_JEXEC' ) or die( 'Restricted access' ); class TagParser { protected static $instances = array(); private $identifier = ''; private $options = array( 'bracket'=>'{}', 'alternateclose'=>false, 'selfclosing'=>false ); public $tags = array(); public $total = 0; public function __construct($identifier=false,$options=false) { if($identifier) { $this->setIdentifier($identifier); if($options) $this->setOptions($options); } } public static function getInstance($identifier=false,$options=false) { $instanceid = $identifier?$identifier:''; if(empty(self::$instances[$instanceid])) { self::$instances[$instanceid] = new TagParser($identifier,$options); } return self::$instances[$instanceid]; } public function setIdentifier($identifier=false) { if($identifier) $this->identifier = $identifier; } public function setOptions($options=false) { if(is_array($options)) { foreach($options as $key=>$option) $this->options[$key]=$option; } if(strlen($this->options['bracket']) == 1) $this->options['bracket'] = $this->options['bracket'].$this->options['bracket']; } public function parse($content) { $regex ='/'.$this->bracket('open').$this->identifier.'\s*?(?<params>.*?)'.$this->bracket('close'); if(!$this->options['selfclosing']) $regex.='(?<content>.*?)(?<closetag>'.$this->bracket('open').'\/'.($this->options['alternateclose']?$this->options['alternateclose']:$this->identifier).$this->bracket('close').')'; $regex.='/'; $matches = array(); preg_match_all($regex,$content,$matches); foreach($matches[0] as $key=>$match) { $this->total++; $this->tags[$key]=new TagParserItem($match); $this->tags[$key]->tagid = $this->total; if(strlen($matches['params'][$key])) { $params = new \DOMDocument; $params->loadHTML('<br '.trim($matches['params'][$key]).' />'); $paramsxml = simplexml_import_dom($params->documentElement); if(count($paramsxml->body->br->attributes())) { $this->tags[$key]->params = array(); foreach($paramsxml->body->br->attributes() as $attribute=>$value) { $this->tags[$key]->params[$attribute]=(strlen($value->__toString())?$value->__toString():true); } } } if(!$this->options['selfclosing']) $this->tags[$key]->content = $matches['content'][$key]; } } private function bracket($type='open') { return preg_quote(($type=='open')?$this->options['bracket'][0]:$this->options['bracket'][1]); } } class TagParserItem { public $tag; public $tagid=0; public $params = false; public $content = false; public function __construct($tag) { $this->tag = $tag; } public function getParam($name,$default) { return isset($this->params[$name])?$this->params[$name]:$default; } public function getContent($default='') { return $this->content?$this->content:$default; } public function replace($content,$replacement='') { $regex='/'.preg_quote($this->tag,'/').'/'; return preg_replace($regex,$replacement,$content,1); } }