/includes/Opl/Opt/Instruction/Snippet.php
PHP | 329 lines | 187 code | 28 blank | 114 comment | 15 complexity | 61fcaaf1d945084cfc6a959505afaba9 MD5 | raw file
Possible License(s): GPL-3.0, MIT
- <?php
- /*
- * OPEN POWER LIBS <http://www.invenzzia.org>
- *
- * This file is subject to the new BSD license that is bundled
- * with this package in the file LICENSE. It is also available through
- * WWW at this URL: <http://www.invenzzia.org/license/new-bsd>
- *
- * Copyright (c) Invenzzia Group <http://www.invenzzia.org>
- * and other contributors. See website for details.
- *
- * $Id: Snippet.php 272 2009-12-23 08:42:26Z zyxist $
- */
- /**
- * The snippet instruction processor.
- */
- class Opt_Instruction_Snippet extends Opt_Compiler_Processor
- {
- /**
- * The processor name required by the parent.
- * @internal
- * @var string
- */
- protected $_name = 'snippet';
- /**
- * The list of available snippets.
- * @internal
- * @var array
- */
- protected $_snippets = array();
- /**
- * The currently inserted snippet stack used for detecting the infinite recursion.
- * @internal
- * @var array
- */
- protected $_current = array();
- /**
- * Configures the instruction processor.
- *
- * @internal
- */
- public function configure()
- {
- $this->_addInstructions(array('opt:snippet', 'opt:insert', 'opt:parent'));
- $this->_addAttributes(array('opt:use'));
- } // end configure();
- /**
- * Resets the processor after the finished compilation and frees the
- * memory taken by the snippets.
- *
- * @internal
- */
- public function reset()
- {
- foreach($this->_snippets as &$snippetList)
- {
- foreach($snippetList as $snippet)
- {
- $snippet->dispose();
- }
- }
- $this->_snippets = array();
- $this->_current = array();
- } // end reset();
- /*
- public function processNode(Opt_Xml_Node $node)
- {
- $name = '_process'.ucfirst($node->getName());
- $this->$name($node);
- } // end processNode();
-
- public function postprocessNode(Opt_Xml_Node $node)
- {
- $name = '_postprocess'.ucfirst($node->getName());
- $this->$name($node);
- } // end postprocessNode();
- */
- /**
- * Processes the opt:use attribute.
- *
- * @internal
- * @param Opt_Xml_Node $node The node the attribute is added to
- * @param Opt_Xml_Attribute $attr The found attribute.
- */
- public function processAttribute(Opt_Xml_Node $node, Opt_Xml_Attribute $attr)
- {
- if(isset($this->_snippets[$attr->getValue()]))
- {
- array_push($this->_current, $attr->getValue());
- $snippet = &$this->_snippets[$attr->getValue()];
-
- // Move all the stuff to the fake node.
- if($node->hasChildren())
- {
- $newNode = new Opt_Xml_Element('opt:_');
- $newNode->moveChildren($node);
-
- $size = sizeof($snippet);
- $snippet[$size] = $newNode;
- $attr->set('snippetObj', $snippet);
- $attr->set('size', $size);
- }
- $node->removeChildren();
-
- // Process the snippets
- $node->set('escaping', $this->_compiler->get('escaping'));
- $this->_compiler->set('escaping', $snippet[0]->get('escaping'));
- foreach($snippet[0] as $subnode)
- {
- $node->appendChild(clone $subnode);
- }
- $node->set('call:use', $attr->getValue());
- $attr->set('postprocess', true);
- }
- } // end processAttribute();
- /**
- * A postprocessing routine for opt:use
- * @internal
- * @param Opt_Xml_Node $node
- * @param Opt_Xml_Attribute $attr
- */
- public function postprocessAttribute(Opt_Xml_Node $node, Opt_Xml_Attribute $attr)
- {
- if(!is_null($attr->get('size')))
- {
- $snippet = $attr->get('snippetObj');
- unset($snippet[$attr->get('size')]);
- }
- // Restore the original escaping state
- $this->_compiler->set('escaping', $node->get('escaping'));
- array_pop($this->_current);
- } // end postprocessAttribute();
- /**
- * Processes the opt:snippet element.
- * @internal
- * @param Opt_Xml_Element $node The found snippet.
- */
- public function _processSnippet(Opt_Xml_Element $node)
- {
- $params = array(
- 'name' => array(0 => self::REQUIRED, self::ID)
- );
- $this->_extractAttributes($node, $params);
-
- // Assign this snippet
- if(!isset($this->_snippets[$params['name']]))
- {
- $this->_snippets[$params['name']] = array(0 => $node);
- $current = 0;
- }
- else
- {
- $current = sizeof($this->_snippets[$params['name']]);
- $this->_snippets[$params['name']][] = $node;
- }
- if($node->getParent()->removeChild($node) == 0)
- {
- throw new Opl_Debug_Exception();
- }
- // Remember the template state of escaping for this snippet.
- // This is necessary to make per-template escaping work with
- // the inheritance.
- $node->set('escaping', $this->_compiler->get('escaping'));
-
- // Link "opt:parent" with the parent
- $parentTags = $node->getElementsByTagNameNS('opt', 'parent');
- foreach($parentTags as $parent)
- {
- $parent->set('snippetName', $params['name']);
- $parent->set('snippetId', $current + 1);
- }
- } // end _processSnippet();
- /**
- * Processes the opt:parent element.
- * @internal
- * @param Opt_Xml_Element $node The found element.
- */
- public function _processParent(Opt_Xml_Element $node)
- {
- $n = $node->get('snippetName');
- $i = $node->get('snippetId');
- // If there is a parent, append it here and execute.
- if(isset($this->_snippets[$n][$i]))
- {
- $node->set('escaping', $this->_compiler->get('escaping'));
- $node->set('single', false);
- $this->_compiler->set('escaping', $this->_snippets[$n][$i]->get('escaping'));
- $master = $node->getParent();
- foreach($this->_snippets[$n][$i] as $subnode)
- {
- $master->insertBefore($cloned = clone $subnode, $node);
- $this->_enqueue($cloned);
- }
- $master->removeChild($node);
- $node->set('postprocess', true);
- }
- } // end _processParent();
- /**
- * A postprocessing routine for opt:parent
- * @internal
- * @param Opt_Xml_Element $node The found element
- */
- public function _postprocessParent(Opt_Xml_Element $node)
- {
- $this->_compiler->set('escaping', $node->get('escaping'));
- } // end _postprocessParent();
- /**
- * Processes the opt:insert element.
- * @internal
- * @param Opt_Xml_Element $node The found element
- */
- public function _processInsert(Opt_Xml_Element $node)
- {
- // A support for the dynamically chosen part captured by opt:capture
- if($node->getAttribute('captured') !== NULL)
- {
- $params = array(
- 'captured' => array(0 => self::REQUIRED, self::EXPRESSION)
- );
- $this->_extractAttributes($node, $params);
- if($node->hasChildren())
- {
- $node->addBefore(Opt_Xml_Buffer::TAG_BEFORE, 'if(!isset(self::$_capture['.$params['captured'].'])){ ');
- $node->addAfter(Opt_Xml_Buffer::TAG_AFTER, '} else { echo self::$_capture['.$params['captured'].']; } ');
- $this->_process($node);
- }
- else
- {
- $node->addBefore(Opt_Xml_Buffer::TAG_BEFORE, 'if(isset(self::$_capture['.$params['captured'].'])){ echo self::$_capture['.$params['captured'].']; } ');
- }
- }
- else
- {
- // Snippet insertion
- $params = array(
- 'snippet' => array(0 => self::REQUIRED, self::ID),
- 'ignoredefault' => array(0 => self::OPTIONAL, self::BOOL, false)
- );
- $this->_extractAttributes($node, $params);
- if(in_array($params['snippet'], $this->_current))
- {
- array_push($this->_current, $params['snippet']);
- $err = new Opt_SnippetRecursion_Exception($params['snippet']);
- throw $err->setData($this->_current);
- }
- if(isset($this->_snippets[$params['snippet']]))
- {
- array_push($this->_current, $params['snippet']);
- $snippet = &$this->_snippets[$params['snippet']];
- // Move all the stuff to the fake node.
- if($node->hasChildren() && $params['ignoredefault'] == false)
- {
- $newNode = new Opt_Xml_Element('opt:_');
- $newNode->set('escaping', $this->_compiler->get('escaping'));
- $newNode->moveChildren($node);
- $size = sizeof($snippet);
- $snippet[$size] = $newNode;
- $node->set('insertSize', $size);
- }
- // We must do the cleaning for the inserted node.
- $node->removeChildren();
- // Process the snippets
- $node->set('escaping', $this->_compiler->get('escaping'));
- $this->_compiler->set('escaping', $snippet[0]->get('escaping'));
- foreach($snippet[0] as $subnode)
- {
- $node->appendChild(clone $subnode);
- }
- $this->_process($node);
- $node->set('insertSnippet', $params['snippet']);
- $node->set('postprocess', true);
- }
- else
- {
- // Processing the default content - snippet not found.
- $this->_process($node);
- }
- }
- } // end _processInsert();
- /**
- * Postprocesses the opt:insert element.
- * @internal
- * @param Opt_Xml_Element $node The found element.
- */
- public function _postprocessInsert(Opt_Xml_Element $node)
- {
- // Freeing the fake node, if necessary.
- if(!is_null($node->get('insertSize')))
- {
- $this->_snippets[$node->get('insertSnippet')][$node->get('insertSize')]->dispose();
- unset($this->_snippets[$node->get('insertSnippet')][$node->get('insertSize')]);
- }
- // Restore the original escaping state
- $this->_compiler->set('escaping', $node->get('escaping'));
-
- array_pop($this->_current);
- } // end _postprocessInsert();
- /**
- * Returns true, if the snippet with the given name is defined.
- * @param string $name The snippet name
- * @return boolean
- */
- public function isSnippet($name)
- {
- return isset($this->_snippets[$name]);
- } // end isSnippet();
- } // end Opt_Instruction_Snippet;