Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch '2.1' of github.com:OPL/Open-Power-Template into 2.1

  • Loading branch information...
commit 36627db75ad4c321d0e80376e1457b50b426d6dd 2 parents c45cd91 + 8bff7c1
@zyxist zyxist authored
Showing with 628 additions and 15,376 deletions.
  1. +9 −11 lib/Opt/Class.php
  2. +44 −15 lib/Opt/Expression/Standard.php
  3. +0 −10 lib/Opt/Format/Abstract.php
  4. +75 −0 lib/Opt/Format/Block.php
  5. +96 −0 lib/Opt/Format/Component.php
  6. +1 −1  lib/Opt/Format/StaticGenerator.php
  7. +0 −20 lib/Opt/Function.php
  8. +0 −1  lib/Opt/Instruction/Abstract.php
  9. +27 −38 lib/Opt/Instruction/Block.php
  10. +57 −74 lib/Opt/Instruction/Component.php
  11. +2 −2 lib/Opt/Instruction/Grid.php
  12. +4 −3 lib/Opt/Instruction/Selector.php
  13. +4 −9 lib/Opt/Instruction/Snippet.php
  14. +53 −7 lib/Opt/Instruction/Tag.php
  15. +6 −1 lib/Opt/Xml/Cdata.php
  16. +1 −1  lib/Opt/Xml/Element.php
  17. +4 −3 lib/Opt/Xml/Scannable.php
  18. +2 −2 tests/Package/Instruction/AllTests.php
  19. +1 −0  tests/Package/Instruction/ComponentTest.php
  20. +60 −0 tests/Package/Instruction/TagTest.php
  21. +26 −0 tests/Package/Instruction/Tests/Component/component_id.txt
  22. +2 −2 tests/Package/Instruction/Tests/Tag/{tag_1.txt → tag_basic.txt}
  23. +3 −3 tests/Package/Instruction/Tests/Tag/{tag_2.txt → tag_dynamic_attr.txt}
  24. +3 −3 tests/Package/Instruction/Tests/Tag/{tag_5.txt → tag_name.txt}
  25. +27 −0 tests/Package/Instruction/Tests/Tag/tag_name_attr.txt
  26. +27 −0 tests/Package/Instruction/Tests/Tag/tag_name_attr_ns.txt
  27. +27 −0 tests/Package/Instruction/Tests/Tag/tag_namespaces.txt
  28. +2 −2 tests/Package/Instruction/Tests/Tag/{tag_4.txt → tag_single.txt}
  29. +3 −3 tests/Package/Instruction/Tests/Tag/{tag_3.txt → tag_special_attr.txt}
  30. +56 −0 tests/Package/ViewTest.php
  31. +4 −0 tests/Package/templates/dummy.tpl
  32. +2 −0  tests/run-single.php
  33. +0 −504 tools/lexer/expression_lexer.php
  34. +0 −12,512 tools/lexer/expression_parser.out
  35. +0 −2,149 tools/lexer/expression_parser.php
View
20 lib/Opt/Class.php
@@ -185,6 +185,8 @@ class Opt_Class extends Opl_Class
public $defaultFormat = 'Array';
public $containerFormat = 'Container';
public $treeFormat = 'DepthTree';
+ public $componentFormat = 'Component';
+ public $blockFormat = 'Block';
/**
* The compiler object
@@ -289,6 +291,7 @@ class Opt_Class extends Opl_Class
'Objective' => 'Opt_Format_Objective',
'Global' => 'Opt_Format_Global',
'SingleArray' => 'Opt_Format_SingleArray',
+ 'SplDatastructure' => 'Opt_Format_SplDatastructure',
'StaticGenerator' => 'Opt_Format_StaticGenerator',
'RuntimeGenerator' => 'Opt_Format_RuntimeGenerator',
'System' => 'Opt_Format_System',
@@ -296,7 +299,9 @@ class Opt_Class extends Opl_Class
'SwitchContains' => 'Opt_Format_SwitchContains',
'Container' => 'Opt_Format_Container',
'DepthTree' => 'Opt_Format_DepthTree',
- 'NestedTree' => 'Opt_Format_NestedTree'
+ 'NestedTree' => 'Opt_Format_NestedTree',
+ 'Component' => 'Opt_Format_Component',
+ 'Block' => 'Opt_Format_Block'
);
/**
* The extra entities replaced by OPT
@@ -594,17 +599,10 @@ public function _getList($name)
protected function _pluginLoader($directory, SplFileInfo $file)
{
$ns = explode('.', $file->getFilename());
- if(end($ns) == 'php')
+ $filename = $file->getFilename();
+ if(strpos($filename, '.php') === (strlen($filename) - 4))
{
- switch($ns[0])
- {
- case 'instruction':
- return 'Opl_Loader::mapAbsolute(\'Opt_Instruction_'.$ns[1].'\', \''.$directory.$file->getFilename().'\'); $this->register(Opt_Class::OPT_INSTRUCTION, \''.$ns[1].'\'); ';
- case 'format':
- return 'Opl_Loader::mapAbsolute(\'Opt_Format_'.$ns[1].'\', \''.$directory.$file->getFilename().'\'); $this->register(Opt_Class::OPT_FORMAT, \''.$ns[1].'\'); ';
- default:
- return ' require(\''.$directory.$file->getFilename().'\'); ';
- }
+ return ' require(\''.$directory.$filename.'\'); ';
}
} // end _pluginLoader();
View
59 lib/Opt/Expression/Standard.php
@@ -279,7 +279,10 @@ public function _prepareTemplateVar($name)
} // end _prepareTemplateVar();
/**
- * Compiles a language variable.
+ * Compiles a language variable. If the language variable call is not
+ * supported, an exception is thrown.
+ *
+ * @throws Opt_Compiler_Exception
* @param string $group The group name
* @param string $id The message ID name
* @param int $weight The token weight
@@ -289,7 +292,7 @@ public function _compileLanguageVar($group, $id, $weight)
{
if($this->_tpl->getTranslationInterface() == null)
{
- throw new Opt_NotSupported_Exception('language variable call', 'no translation interface installed');
+ throw new Opt_Compiler_Exception('The language variable call is not supported: no translation interface installed');
}
$array = new SplFixedArray(4);
@@ -560,7 +563,7 @@ public function _compileVariable(array $variable, $type, $weight, $context = 0,
if($context > 0 && !$format->property($hook))
{
- throw new Opt_OperationNotSupported_Exception($path, $this->_dfCalls[$context]);
+ throw new Opt_Compiler_Exception('Unsupported operation for '.$path.': '.$this->_dfCalls[$context]);
}
$code .= $format->get($hook);
}
@@ -897,6 +900,30 @@ public function _makeFunctional($identifier, array $arguments)
*/
public function _makeFunction(SplFixedArray $functional)
{
+ // Assign() special function.
+ if($functional[0] == 'assign')
+ {
+ if(sizeof($functional[1]) > 1 && preg_match('/\\(\'([a-zA-Z0-9\_]+)\',\'([a-zA-Z0-9\_]+)\'\\)/', $functional[1][0][0], $matches))
+ {
+ $code = '$this->_tf->assign(\''.$matches[1].'\',\''.$matches[2].'\'';
+ $size = sizeof($functional[1]);
+ for($i = 1; $i < $size; $i++)
+ {
+ $code .= ','.$functional[1][$i][0];
+ }
+ $obj = new SplFixedArray(4);
+ $obj[0] = $code.')';
+ $obj[1] = self::FUNCTIONAL_OP_WEIGHT;
+ $obj[3] = 0;
+ return $obj;
+ }
+ else
+ {
+ throw new Opt_Expression_Exception('assign() expects a language variable as the first argument.');
+ }
+ }
+
+ // Normal functions go here
if(($name = $this->_compiler->isFunction($functional[0])) === null)
{
throw new Opt_Expression_Exception('Function '.$functional[0].' cannot be used in templates.');
@@ -985,8 +1012,10 @@ public function _buildObjectFieldDynamic(SplFixedArray $variable, $current)
} // end _buildObjectFieldDynamic();
/**
- * Processes the object access operator from a static class.
+ * Processes the object access operator from a static class. An exception
+ * is thrown, if the direct object access is disabled.
*
+ * @throws Opt_Compiler_Exception
* @param string $className The static class name
* @param string $current The class field name
* @return SplFixedArray
@@ -995,12 +1024,12 @@ public function _buildObjectFieldStatic($className, $current)
{
if(!$this->_tpl->allowObjects)
{
- throw new Opt_NotSupported_Exception('direct object access', 'disabled by the configuration');
+ throw new Opt_Compiler_Exception('Unsupported direct object access: disabled by the configuration');
}
if(($compiled = $this->_compiler->isClass($token)) !== null)
{
- throw new Opt_ItemNotAllowed_Exception('Class', $className);
+ throw new Opt_Compiler_Exception('The class \''.$className.'\' is not allowed to be used in templates.');
}
$variable = new SplFixedArray(4);
$variable[0] = $compiled.'::$'.(string)$current;
@@ -1021,7 +1050,7 @@ public function _buildObjectFieldNext(SplFixedArray $variable, $current)
{
if(!$this->_tpl->allowObjects)
{
- throw new Opt_NotSupported_Exception('direct object access', 'disabled by the configuration');
+ throw new Opt_Compiler_Exception('Unsupported direct object access: disabled by the configuration');
}
$variable[0] .= '->'.(string)$current;
@@ -1041,7 +1070,7 @@ public function _buildMethodDynamic(SplFixedArray $variable, $current)
{
if(!$this->_tpl->allowObjects)
{
- throw new Opt_NotSupported_Exception('direct object access', 'disabled by the configuration');
+ throw new Opt_Compiler_Exception('Unsupported direct object access: disabled by the configuration');
}
$variable = $this->_compileVariable($variable[0], $variable[1], 0);
@@ -1078,12 +1107,12 @@ public function _buildMethodStatic($className, $current)
{
if(!$this->_tpl->allowObjects)
{
- throw new Opt_NotSupported_Exception('direct class access', 'disabled by the configuration');
+ throw new Opt_Compiler_Exception('Unsupported direct class access: disabled by the configuration');
}
if(($compiled = $this->_compiler->isClass($className)) === null)
{
- throw new Opt_ItemNotAllowed_Exception('Class', $className);
+ throw new Opt_Compiler_Exception('The class \''.$className.'\' is not allowed to be used in templates.');
}
$variable = new SplFixedArray(4);
$variable[0] = $compiled.'::'.(string)$current[0].'(';
@@ -1120,7 +1149,7 @@ public function _buildMethodNext(SplFixedArray $variable, $current)
{
if(!$this->_tpl->allowObjects)
{
- throw new Opt_NotSupported_Exception('direct object access', 'disabled by the configuration');
+ throw new Opt_Compiler_Exception('Unsupported direct object access: disabled by the configuration');
}
$variable[0] .= '->'.(string)$current[0].'(';
@@ -1156,7 +1185,7 @@ public function _buildArrayDynamic(SplFixedArray $variable, SplFixedArray $curre
{
if(!$this->_tpl->allowArrays)
{
- throw new Opt_NotSupported_Exception('direct array access', 'disabled by the configuration');
+ throw new Opt_Compiler_Exception('Unsupported direct array access: disabled by the configuration');
}
$variable = $this->_compileVariable($variable[0], $variable[1], 0);
@@ -1180,7 +1209,7 @@ public function _buildArrayNext(SplFixedArray $variable, SplFixedArray $current)
{
if(!$this->_tpl->allowArrays)
{
- throw new Opt_NotSupported_Exception('direct array access', 'disabled by the configuration');
+ throw new Opt_Compiler_Exception('Unsupported direct array access: disabled by the configuration');
}
$variable[0] .= '['.(string)$current[0].']';
@@ -1201,7 +1230,7 @@ public function _objective($action, $what, $weight)
{
if(!$this->_tpl->allowObjects || !$this->_tpl->allowObjectCreation)
{
- throw new Opt_NotSupported_Exception('object creation', 'disabled by the configuration');
+ throw new Opt_Compiler_Exception('Unsupported object creation: disabled by the configuration');
}
switch($action)
{
@@ -1214,7 +1243,7 @@ public function _objective($action, $what, $weight)
case 'new':
if(($compiled = $this->_compiler->isClass($what[0])) === null)
{
- throw new Opt_ItemNotAllowed_Exception('Class', $what[0]);
+ throw new Opt_Compiler_Exception('The class \''.$what[0].'\' is not allowed to be used in templates.');
}
$answer = new SplFixedArray(4);
$answer[0] = 'new '.$compiled;
View
10 lib/Opt/Format/Abstract.php
@@ -208,16 +208,6 @@ public function dispose()
}
else
{
- /*
- * DO NOT REMOVE THE LINE BELOW UNLESS YOU WANT A SEGMENTATION FAULT!
- *
- * This piece of code activates the issue known as PHP Bug #40479 open
- * since 2007 related to the corrupted zend_mm_heap. I do not know, why
- * throwing an exception in this place causes this after a while (the
- * segfault occurs, when this exception is captured in the compile() method
- * to clean the compiler state).
- */
- // die('Opt_APIHookNotDefined_Exception: Invalid hook name: '.$hookName.' in '.get_class($this));
throw new Opt_Format_Exception('Invalid hook name: '.$hookName.' in '.get_class($this));
}
}
View
75 lib/Opt/Format/Block.php
@@ -0,0 +1,75 @@
+<?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.
+ */
+
+/**
+ * The data format for blocks.
+ *
+ * @author Tomasz Jędrzejewski
+ * @copyright Invenzzia Group <http://www.invenzzia.org/> and contributors.
+ * @license http://www.invenzzia.org/license/new-bsd New BSD License
+ * @package Formats
+ */
+class Opt_Format_Block extends Opt_Format_Abstract
+{
+ /**
+ * The list of supported hook types.
+ * @var array
+ */
+ protected $_supports = array(
+ 'block'
+ );
+
+ /**
+ * Build a PHP code for the specified hook name.
+ *
+ * @internal
+ * @param string $hookName The hook name
+ * @return string The output PHP code
+ */
+ protected function _build($hookName)
+ {
+ switch($hookName)
+ {
+ case 'block:init':
+ return ' '.$this->_getVar('variable').'->setView($this); ';
+ case 'block:done':
+ return '';
+ case 'block:valid':
+ return ' '.$this->_getVar('variable').' instanceof Opt_Block_Interface';
+ case 'block:build':
+ return ' '.$this->_getVar('variable').' = new '.$this->_getVar('className').'; ';
+ case 'block:on-single':
+ $argList = 'array( ';
+ foreach($this->_getVar('arguments') as $name=>$value)
+ {
+ $argList .= '\''.$name.'\' => '.$value.', ';
+ }
+ $argList .= ')';
+ return ' '.$this->_getVar('variable').'->onSingle('.$argList.'); ';
+ case 'block:on-open':
+ $argList = 'array( ';
+ foreach($this->_getVar('arguments') as $name=>$value)
+ {
+ $argList .= '\''.$name.'\' => '.$value.', ';
+ }
+ $argList .= ')';
+ return ' if('.$this->_getVar('variable').'->onOpen('.$argList.')){ ';
+ case 'block:on-close':
+ return ' } '.$this->_getVar('variable').'->onClose(); ';
+ case 'block:set':
+ return ' '.$this->_getVar('variable').'->__set('.$this->_getVar('name').', '.$this->_getVar('value').') ';
+ case 'block:get':
+ return ' '.$this->_getVar('variable').'->__get('.$this->_getVar('name').') ';
+ }
+ } // end _build();
+
+} // end Opt_Format_Block;
View
96 lib/Opt/Format/Component.php
@@ -0,0 +1,96 @@
+<?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.
+ */
+
+/**
+ * The data format for components.
+ *
+ * @author Tomasz Jędrzejewski
+ * @copyright Invenzzia Group <http://www.invenzzia.org/> and contributors.
+ * @license http://www.invenzzia.org/license/new-bsd New BSD License
+ * @package Formats
+ */
+class Opt_Format_Component extends Opt_Format_Abstract
+{
+ /**
+ * The list of supported hook types.
+ * @var array
+ */
+ protected $_supports = array(
+ 'component'
+ );
+
+ /**
+ * Build a PHP code for the specified hook name.
+ *
+ * @internal
+ * @param string $hookName The hook name
+ * @return string The output PHP code
+ */
+ protected function _build($hookName)
+ {
+ switch($hookName)
+ {
+ case 'component:init':
+ return ' '.$this->_getVar('variable').'->setView($this); ';
+ case 'component:done':
+ return '';
+ case 'component:valid':
+ return ' '.$this->_getVar('variable').' instanceof Opt_Component_Interface';
+ case 'component:build':
+ return ' '.$this->_getVar('variable').' = new '.$this->_getVar('className').'; ';
+ case 'component:datasource':
+ return ' '.$this->_getVar('variable').'->setDatasource('.$this->_getVar('datasource').'); ';
+ case 'component:event-open':
+ return ' if('.$this->_getVar('variable').'->processEvent('.$this->_getVar('eventName').')){ ';
+ case 'component:event-close':
+ return ' } ';
+ case 'component:display':
+ $attrs = $this->_getVar('attributes');
+ $subCode = '';
+ if(sizeof($attrs) > 0)
+ {
+ $subCode = 'array(';
+ foreach($attrs as $name => $value)
+ {
+ $subCode .= '\''.$name.'\' => '.$value.',';
+ }
+ $subCode .= ')';
+ }
+ return ' '.$this->_getVar('variable').'->display('.$subCode.'); ';
+ case 'component:inject-open':
+ return ' '.$this->_getVar('variable').'->setInjection(';
+ case 'component:inject-close':
+ return '); ';
+ case 'component:manage-attributes':
+ $attrs = $this->_getVar('attributes');
+ $subCode = 'array()';
+ if(sizeof($attrs) > 0)
+ {
+ $subCode = 'array(';
+ foreach($attrs as $name => $value)
+ {
+ $subCode .= '\''.$name.'\' => '.$value.',';
+ }
+ $subCode .= ')';
+ }
+
+ return ' $out = '.$this->_getVar('variable').'->manageAttributes(\''.$this->_getVar('tag').'\', '.$subCode.'); ';
+ case 'component:manage-attributes-apply':
+ return ' if(is_array($out)){ foreach($out as $name=>$value){ echo \' \'.$name.\'="\'.$value.\'"\'; } } ';
+ case 'component:set':
+ return ' '.$this->_getVar('variable').'->__set('.$this->_getVar('name').', '.$this->_getVar('value').') ';
+ case 'component:get':
+ return ' '.$this->_getVar('variable').'->__get('.$this->_getVar('name').') ';
+ }
+ } // end _build();
+
+} // end Opt_Format_Component;
View
2  lib/Opt/Format/StaticGenerator.php
@@ -67,7 +67,7 @@ protected function _build($hookName)
// of "section" namespace.
if(!is_object($this->_decorated))
{
- throw new Opt_FormatNotDecorated_Exception('StaticGenerator');
+ throw new Opt_Format_Exception('The StaticGenerator format must be decorated.');
}
return ' $_sect'.$section['name'].'_vals = array(); if('.$ds.' instanceof Opt_Generator_Interface){ $_sect'.$section['name'].'_vals = '.$ds.'->generate(\''.$section['name'].'\'); } ';
View
20 lib/Opt/Function.php
@@ -782,24 +782,4 @@ static public function buildAttributes($attributes, $ignoreList = array(), $prep
}
return rtrim($prepend);
} // end buildAttributes();
-
- /**
- * Performs a safe template procedure call. Before that, it checks for
- * the existence of a procedure and if it does not exist, it throws
- * an exception.
- *
- * @throws Opt_ObjectNotExists_Exception
- * @param Opt_View $view The current view instance.
- * @param string $name The procedure name
- * @param array $arguments The list of procedure argument values
- */
- static public function call(Opt_InternalContext $ctx, $name, array $arguments)
- {
- if(function_exists('__optFunc_'.$name))
- {
- $arguments[0] = $ctx;
- return call_user_func_array('__optFunc_'.$name, $arguments);
- }
- throw new Opt_ObjectNotExists_Exception('template procedure', $name);
- } // end call();
} // end Opt_Function;
View
1  lib/Opt/Instruction/Abstract.php
@@ -630,7 +630,6 @@ public function processSystemVar($opt)
if(strlen(trim($value)) == 0)
{
throw new Opt_Instruction_Exception('The attribute "'.$attr->getXmlName().'" in '.$item->getXmlName().' is empty.');
- throw new Opt_AttributeEmpty_Exception($attr->getXmlName(), $item->getXmlName());
}
// if(preg_match('/^([a-zA-Z0-9\_]{2,})\:([^\:].*)$/', $value, $found))
// {
View
65 lib/Opt/Instruction/Block.php
@@ -77,16 +77,20 @@ public function processNode(Opt_Xml_Node $node)
// Undefined block processing
$params = array(
'from' => array(self::REQUIRED, self::EXPRESSION, null),
+ 'id' => array(self::OPTIONAL, self::STRING, null),
'__UNKNOWN__' => array(self::OPTIONAL, self::EXPRESSION, null)
);
$vars = $this->_extractAttributes($node, $params);
- $this->_stack->push($params['from']);
- $mainCode = ' if(is_object('.$params['from'].') && '.$params['from'].' instanceof Opt_Block_Interface){ '.$params['from'].'->setView($this); ';
- $mainCode .= $this->_commonProcessing($node, $params['from'], $vars);
+ $format = $this->_compiler->getFormat('block#'.$params['id'], false, $this->_tpl->blockFormat);
+ $format->assign('variable', $params['from']);
+ $this->_stack->push(array($params['from'], $format));
+
+ $mainCode = ' if(is_object('.$params['from'].') && '.$format->get('block:valid').'){ '.$format->get('block:init');
+ $mainCode .= $this->_commonProcessing($node, $params['from'], $vars, $format);
$node->addBefore(Opt_Xml_Buffer::TAG_BEFORE, $mainCode);
- $node->addAfter(Opt_Xml_Buffer::TAG_AFTER, ' } ');
+ $node->addAfter(Opt_Xml_Buffer::TAG_AFTER, $format->get('block:done').' } ');
$node->set('postprocess', true);
} // end processNode();
@@ -111,36 +115,25 @@ public function processBlock(Opt_Xml_Element $node)
{
// Defined block processing
$params = array(
+ 'id' => array(self::OPTIONAL, self::STRING, null),
'__UNKNOWN__' => array(self::OPTIONAL, self::EXPRESSION, null)
);
$vars = $this->_extractAttributes($node, $params);
- // Get the real class name
- $cn = '$_block_'.($this->_unique++);
- $this->_stack->push($cn);
-
- $class = $this->_compiler->block($node->getXmlName());
- // Check, if there are any conversions that may take control over initializing
- // the component object. We are allowed to capture only particular component
- // creation or all of them.
- if((($to = $this->_compiler->convert('##block_'.$class)) != '##block_'.$class))
- {
- $ccode = str_replace(array('%CLASS%', '%TAG%'), array($class, $node->getXmlName()), $to);
- }
- elseif((($to = $this->_compiler->convert('##block')) != '##block'))
- {
- $ccode = str_replace(array('%CLASS%', '%TAG%'), array($class, $node->getXmlName()), $to);
- }
- else
- {
- $ccode = 'new '.$class;
- }
+ // Initialize block structures
+ $cn = '$_block_'.($this->_unique++);
+ $format = $this->_compiler->getFormat('block#'.$params['id'], false, $this->_tpl->blockFormat);
+ $format->assign('variable', $cn);
+ $this->_stack->push(array($cn, $format));
- $mainCode = $cn.' = '.$ccode.'; '.$cn.'->setView($this); ';
+ // Generate the initialization code
+ $format->assign('className', $this->_compiler->block($node->getXmlName()));
+ $mainCode = $format->get('block:build').$format->get('block:init');
- $this->_commonProcessing($node, $cn, $vars);
+ $this->_commonProcessing($node, $cn, $vars, $format);
$node->addBefore(Opt_Xml_Buffer::TAG_BEFORE, $mainCode);
+ $node->addAfter(Opt_Xml_Buffer::TAG_AFTER, $format->get('block:done'));
} // end processBlock();
/**
@@ -167,24 +160,18 @@ public function postprocessBlock(Opt_Xml_Node $node)
* @param array $args The array of custom block attributes.
* @return string
*/
- private function _commonProcessing(Opt_Xml_Element $node, $blockVariable, array $args)
+ private function _commonProcessing(Opt_Xml_Element $node, $blockVariable, array $args, Opt_Format_Abstract $format)
{
// Common part of the component processing
- $argList = 'array( ';
- foreach($args as $name=>$value)
- {
- $argList .= '\''.$name.'\' => '.$value.', ';
- }
- $argList .= ')';
-
+ $format->assign('arguments', $args);
if($node->get('single'))
{
- $node->addAfter(Opt_Xml_Buffer::TAG_SINGLE_BEFORE, $blockVariable.'->onSingle('.$argList.'); ');
+ $node->addAfter(Opt_Xml_Buffer::TAG_SINGLE_BEFORE, $format->get('block:on-single'));
}
else
{
- $node->addAfter(Opt_Xml_Buffer::TAG_BEFORE, ' if('.$blockVariable.'->onOpen('.$argList.')){ ');
- $node->addBefore(Opt_Xml_Buffer::TAG_AFTER, ' } '.$blockVariable.'->onClose(); ');
+ $node->addAfter(Opt_Xml_Buffer::TAG_BEFORE, $format->get('block:on-open'));
+ $node->addBefore(Opt_Xml_Buffer::TAG_AFTER, $format->get('block:on-close'));
}
$this->_process($node);
@@ -204,6 +191,8 @@ public function processSystemVar($opt)
{
throw new Opt_Instruction_Exception('opt:block error: cannot process $'.implode('.',$opt).': no blocks active.');
}
- return $this->_stack->top().'->get(\''.$opt[2].'\')';
+ list($variable, $format) = $this->_stack->top();
+ $format->assign('name', $opt[2]);
+ return $format->get('block:get');
} // end processSystemVar();
} // end Opt_Instruction_Block;
View
131 lib/Opt/Instruction/Component.php
@@ -84,21 +84,25 @@ public function processNode(Opt_Xml_Node $node)
'from' => array(self::REQUIRED, self::EXPRESSION, null),
'datasource' => array(self::OPTIONAL, self::EXPRESSION, null),
'template' => array(self::OPTIONAL, self::ID, null),
+ 'id' => array(self::OPTIONAL, self::STRING, null),
'__UNKNOWN__' => array(self::OPTIONAL, self::EXPRESSION, null)
);
$vars = $this->_extractAttributes($node, $params);
- $this->_stack->push($params['from']);
+ $format = $this->_compiler->getFormat('component#'.$params['id'], false, $this->_tpl->componentFormat);
+ $format->assign('variable', $params['from']);
+ $this->_stack->push(array($params['from'], $format));
- $mainCode = ' if(is_object('.$params['from'].') && '.$params['from'].' instanceof Opt_Component_Interface){ '.$params['from'].'->setView($this); ';
+ $mainCode = ' if(is_object('.$params['from'].') && '.$format->get('component:valid').'){ '.$format->get('component:init');
if($params['datasource'] !== null)
{
- $mainCode .= $params['from'].'->setDatasource('.$params['datasource'].'); ';
+ $format->assign('datasource', $params['datasource']);
+ $mainCode .= $format->get('component:datasource');
}
- $mainCode .= $this->_commonProcessing($node, $params['from'], $params, $vars);
+ $mainCode .= $this->_commonProcessing($node, $params['from'], $params, $vars, $format);
$node->addBefore(Opt_Xml_Buffer::TAG_BEFORE, $mainCode);
- $node->addAfter(Opt_Xml_Buffer::TAG_AFTER, ' } ');
+ $node->addAfter(Opt_Xml_Buffer::TAG_AFTER, $format->get('component:done').' } ');
break;
case 'on-event':
if($this->_stack->count() == 0)
@@ -110,9 +114,12 @@ public function processNode(Opt_Xml_Node $node)
'name' => array(self::REQUIRED, self::EXPRESSION)
);
+ list($variable, $format) = $this->_stack->top();
+
$this->_extractAttributes($node, $tagParams);
- $node->addAfter(Opt_Xml_Buffer::TAG_BEFORE, ' if('.$this->_stack->top().'->processEvent('.$tagParams['name'].')){ ');
- $node->addAfter(Opt_Xml_Buffer::TAG_AFTER, ' } ');
+ $format->assign('eventName', $tagParams['name']);
+ $node->addAfter(Opt_Xml_Buffer::TAG_BEFORE, $format->get('component:event-open'));
+ $node->addAfter(Opt_Xml_Buffer::TAG_AFTER, $format->get('component:event-close'));
$this->_process($node);
break;
@@ -121,6 +128,7 @@ public function processNode(Opt_Xml_Node $node)
{
throw new Opt_Instruction_Exception('Component error: invalid use of "opt:display": no active component.');
}
+ list($variable, $format) = $this->_stack->top();
$node->set('hidden', false);
$node->removeChildren();
// The opt:display attributes must be packed into array and sent
@@ -132,20 +140,20 @@ public function processNode(Opt_Xml_Node $node)
'__UNKNOWN__' => array(self::OPTIONAL, self::EXPRESSION, null)
);
$vars = $this->_extractAttributes($node, $params);
- $subCode = 'array(';
- foreach($vars as $name => $value)
- {
- $subCode .= '\''.$name.'\' => '.$value.',';
- }
- $subCode .= ')';
+ $format->assign('attributes', $vars);
}
- $node->addAfter(Opt_Xml_Buffer::TAG_BEFORE, $this->_stack->top().'->display('.$subCode.'); ');
+ else
+ {
+ $format->assign('attributes', array());
+ }
+ $node->addAfter(Opt_Xml_Buffer::TAG_BEFORE, $format->get('component:display'));
break;
case 'inject':
if($this->_stack->count() == 0)
{
throw new Opt_Instruction_Exception('Component error: invalid use of "opt:inject": no active component.');
}
+ list($variable, $format) = $this->_stack->top();
$code = 'function() use($ctx){ ';
if($node->getAttribute('procedure') !== null)
@@ -157,7 +165,7 @@ public function processNode(Opt_Xml_Node $node)
$code .= ' $args = func_get_args(); array_unshift($args, $ctx); '.PHP_EOL;
$code .= $this->_compiler->processor('procedure')->callProcedure($params['procedure'], '$args', true).PHP_EOL;
$code .= '}'.PHP_EOL;
- $node->addAfter(Opt_Xml_Buffer::TAG_BEFORE, $this->_stack->top().'->setInjection('.$code.'); ');
+ $node->addAfter(Opt_Xml_Buffer::TAG_BEFORE, $format->get('component:inject-open').$code.$format->get('component:inject-close'));
}
else
{
@@ -174,7 +182,7 @@ public function processNode(Opt_Xml_Node $node)
{
if($value == 'required')
{
- $code .= 'if(!isset($args['.$i.'])){ throw new Opt_SnippetArgumentNotDefined_Exception(\''.$name.'\', \''.$params['snippet'].'\'); } '.PHP_EOL;
+ $code .= 'if(!isset($args['.$i.'])){ throw new Opt_Runtime_Exception(\'Snippet argument not defined: '.$name.' in '.$params['snippet'].'\'); } '.PHP_EOL;
}
else
{
@@ -182,8 +190,8 @@ public function processNode(Opt_Xml_Node $node)
}
$value = '$args['.($i++).']';
}
- $node->addAfter(Opt_Xml_Buffer::TAG_BEFORE, $this->_stack->top().'->setInjection('.$code);
- $node->addBefore(Opt_Xml_Buffer::TAG_AFTER, ' }); ');
+ $node->addAfter(Opt_Xml_Buffer::TAG_BEFORE, $format->get('component:inject-open').$code);
+ $node->addBefore(Opt_Xml_Buffer::TAG_AFTER, ' } '.$format->get('component:inject-close'));
$this->_compiler->processor('snippet')->useSnippet($node, $params['snippet'], $snippetArgs, false, true);
$this->_process($node);
}
@@ -223,56 +231,32 @@ public function processComponent(Opt_Xml_Element $node)
{
// Defined component processing
$params = array(
+ 'id' => array(self::OPTIONAL, self::STRING, null),
'datasource' => array(self::OPTIONAL, self::EXPRESSION, null),
'template' => array(self::OPTIONAL, self::ID, null),
'__UNKNOWN__' => array(self::OPTIONAL, self::EXPRESSION, null)
);
$vars = $this->_extractAttributes($node, $params);
- // Get the real class name
+ // Initialize component structures
$cn = '$_component_'.($this->_unique++);
-
- $this->_stack->push($cn);
-
- $class = $this->_compiler->component($node->getXmlName());
-
- // Check, if there are any conversions that may take control over initializing
- // the component object. We are allowed to capture only particular component
- // creation or all of them.
- if((($to = $this->_compiler->convert('##component_'.$class)) != '##component_'.$class))
- {
- $attributes = 'array(';
- foreach($vars as $name => $value)
- {
- $attributes .= '\''.$name.'\' => '.$value.', ';
- }
- $attributes .= ')';
- $ccode = str_replace(array('%CLASS%', '%TAG%', '%ATTRIBUTES%'), array($class, $node->getXmlName(), $attributes), $to);
- }
- elseif((($to = $this->_compiler->convert('##component')) != '##component'))
- {
- $attributes = 'array(';
- foreach($vars as $name => $value)
- {
- $attributes .= '\''.$name.'\' => '.$value.', ';
- }
- $attributes .= ')';
- $ccode = str_replace(array('%CLASS%', '%TAG%', '%ATTRIBUTES%'), array($class, $node->getXmlName(), $attributes), $to);
- }
- else
- {
- $ccode = 'new '.$class;
- }
+ $format = $this->_compiler->getFormat('component#'.$params['id'], false, $this->_tpl->componentFormat);
+ $format->assign('variable', $cn);
+ $this->_stack->push(array($cn, $format));
// Generate the initialization code
- $mainCode = $cn.' = '.$ccode.'; '.$cn.'->setView($this); ';
+ $format->assign('className', $this->_compiler->component($node->getXmlName()));
+ $mainCode = $format->get('component:build').$format->get('component:init');
+
if($params['datasource'] !== null)
{
- $mainCode .= $cn.'->setDatasource('.$params['datasource'].'); ';
+ $format->assign('datasource', $params['datasource']);
+ $mainCode .= $format->get('component:datasource');
}
- $mainCode .= $this->_commonProcessing($node, $cn, $params, $vars);
+ $mainCode .= $this->_commonProcessing($node, $cn, $params, $vars, $format).$format->get('component:done');
$node->addAfter(Opt_Xml_Buffer::TAG_BEFORE, $mainCode);
+ $node->addBefore(Opt_Xml_Buffer::TAG_AFTER, $format->get('component:done'));
} // end processComponent();
/**
@@ -305,9 +289,10 @@ public function postprocessComponent(Opt_Xml_Node $node)
* @param string $componentVariable The PHP component variable name.
* @param array $params The array of standard component attributes.
* @param array $args The array of custom component attributes.
+ * @param Opt_Format_Abstract $format The component data format.
* @return string
*/
- private function _commonProcessing(Opt_Xml_Element $node, $componentVariable, array $params, array $args)
+ private function _commonProcessing(Opt_Xml_Element $node, $componentVariable, array $params, array $args, Opt_Format_Abstract $format)
{
// Common part of the component processing
$set2 = array();
@@ -345,33 +330,29 @@ private function _commonProcessing(Opt_Xml_Element $node, $componentVariable, ar
);
$this->_extractAttributes($set, $tagParams);
- $code .= $componentVariable.'->__set('.$tagParams['name']['bare'].', '.$tagParams['value'].'); ';
+ $format->assign('name', $tagParams['name']['bare']);
+ $format->assign('value', $tagParams['value']);
+ $code .= $format->get('component:set');
}
foreach($args as $name => $value)
{
- $code .= $componentVariable.'->__set(\''.$name.'\', '.$value.'); ';
+ $format->assign('name', $name);
+ $format->assign('value', $value);
+ $code .= $format->get('component:set');
}
// opt:component-attributes
foreach($everything[1] as $wtf)
{
- $id = $wtf->getAttribute('opt:component-attributes')->getValue();
- $subCode = ' $out = '.$componentVariable.'->manageAttributes(\''.$wtf->getName().'#'.$id.'\', array(';
- // $wtf->removeAttribute('opt:component-attributes');
+ $params = array(
+ '__UNKNOWN__' => array(self::OPTIONAL, self::EXPRESSION, null, 'str')
+ );
+ $vars = $this->_extractAttributes($wtf, $params);
+ $format->assign('tag', $wtf->getName().'#'.$wtf->getAttribute('opt:component-attributes')->getValue());
+ $format->assign('attributes', $vars);
- // foreach($wtf->getAttributes() as $attribute)
- // {
- $params = array(
- '__UNKNOWN__' => array(self::OPTIONAL, self::EXPRESSION, null, 'str')
- );
- $vars = $this->_extractAttributes($wtf, $params);
- foreach($vars as $name => $value)
- {
- $subCode .= '\''.$name.'\' => '.$value.',';
- }
- // }
$wtf->removeAttributes();
- $wtf->addAfter(Opt_Xml_Buffer::TAG_BEFORE, $subCode.')); ');
- $wtf->addAfter(Opt_Xml_Buffer::TAG_ENDING_ATTRIBUTES, ' if(is_array($out)){ foreach($out as $name=>$value){ echo \' \'.$name.\'="\'.$value.\'"\'; } } ');
+ $wtf->addAfter(Opt_Xml_Buffer::TAG_BEFORE, $format->get('component:manage-attributes'));
+ $wtf->addAfter(Opt_Xml_Buffer::TAG_ENDING_ATTRIBUTES, $format->get('component:manage-attributes-apply'));
}
$node->set('postprocess', true);
@@ -398,7 +379,9 @@ public function processSystemVar($opt)
{
throw new Opt_Instruction_Exception('Component error: invalid use of $'.implode('.',$opt).': no active component.');
}
- return $this->_stack->top().'->'.$opt[2];
+ list($variable, $format) = $this->_stack->top();
+ $format->assign('name', $opt[2]);
+ return $format->get('component:get');
} // end processSystemVar();
/**
View
4 lib/Opt/Instruction/Grid.php
@@ -150,7 +150,7 @@ protected function _processItem(Opt_Xml_Node $node)
{
if(is_null($node->get('priv:section')))
{
- throw new Opt_InstructionInvalidLocation_Exception('opt:item', 'opt:grid');
+ throw new Opt_Instruction_Exception('opt:item should be located in opt:grid.');
}
// We're at home. For this particular node we have to activate the section.
@@ -180,7 +180,7 @@ protected function _processEmptyitem(Opt_Xml_Node $node)
{
if(is_null($node->get('priv:section')))
{
- throw new Opt_InstructionInvalidLocation_Exception('opt:item', 'opt:grid');
+ throw new Opt_Instruction_Exception('opt:item should be located in opt:grid.');
}
$section = $node->get('priv:section');
$node->addAfter(Opt_Xml_Buffer::TAG_BEFORE, ' if($_'.$section['name'].'_remain > 0 && !'.$node->get('priv:valid').') { for($_'.$section['name'].'_k = 0; $_'.$section['name'].'_k < $_'.$section['name'].'_remain; $_'.$section['name'].'_k++) { ');
View
7 lib/Opt/Instruction/Selector.php
@@ -176,7 +176,7 @@ protected function _postprocessSelector(Opt_Xml_Node $node)
* Processes the opt:selectorelse element.
* @internal
* @param Opt_Xml_Element $node
- * @throws Opt_InstructionInvalidParent_Exception
+ * @throws Opt_Instruction_Exception
*/
protected function _processElse(Opt_Xml_Element $node)
{
@@ -194,9 +194,10 @@ protected function _processElse(Opt_Xml_Element $node)
}
else
{
- throw new Opt_InstructionInvalidParent_Exception($node->getXmlName(), 'opt:section');
+ // Perhaps unreachable, unless some bug in the code occurs.
+ throw new Opt_Instruction_Exception('Invalid parent of \'opt:else\' node: '.$node->getXmlName());
}
- } // end _processSelectorelse();
+ } // end _processElse();
/**
* Processes the attribute version of opt:selector
View
13 lib/Opt/Instruction/Snippet.php
@@ -210,12 +210,7 @@ public function _processSnippet(Opt_Xml_Element $node)
$this->_snippets[$params['name']][] = $node;
}
$node->unmount();
- /*
- 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.
@@ -364,7 +359,7 @@ public function useSnippet(Opt_Xml_Node $node, $snippetName, array $arguments, $
if($it == $snippetName)
{
$this->_current->push($snippetName);
- $err = new Opt_SnippetRecursion_Exception($snippetName);
+ $err = new Opt_Compiler_Recursion_Exception('Infinite snippet recursion detected in \''.$snippetName.'\' snippet.');
throw $err->setData($this->_current);
}
}
@@ -513,7 +508,7 @@ public function postuseSnippet(Opt_Xml_Node $node)
/**
* Returns the list of arguments of the specified snippet.
*
- * @throws Opt_SnippetNotFound_Exception
+ * @throws Opt_Instrcution_Exception
* @param string $snippetName The snippet name.
* @return array
*/
@@ -521,7 +516,7 @@ public function getArguments($snippetName)
{
if(!isset($this->_arguments[$snippetName]))
{
- throw new Opt_SnippetNotFound_Exception($snippetName);
+ throw new Opt_Instrcution_Exception('The requested snippet \''.$snippetName.'\' is not defined.');
}
return $this->_arguments[$snippetName];
} // end getArguments();
View
60 lib/Opt/Instruction/Tag.php
@@ -49,7 +49,7 @@ class Opt_Instruction_Tag extends Opt_Instruction_Abstract
public function configure()
{
$this->_addInstructions('opt:tag');
- $this->_addAttributes('opt:single');
+ $this->_addAttributes(array('opt:single', 'opt:tag-name'));
if($this->_tpl->backwardCompatibility)
{
$this->_addAttributes($this->_deprecatedAttributes);
@@ -156,19 +156,19 @@ public function postprocessNode(Opt_Xml_Node $node)
* @internal
* @param Opt_Xml_Node $node XML node.
* @param Opt_Xml_Attribute $attr XML attribute.
- * @throws Opt_AttributeInvalidNamespace_Exception
+ * @throws Opt_Instruction_Exception
*/
- public function processAttribute(Opt_Xml_Node $node, Opt_Xml_Attribute $attr)
+ public function _processAttrSingle(Opt_Xml_Node $node, Opt_Xml_Attribute $attr)
{
if($this->_compiler->isNamespace($node->getNamespace()))
{
- throw new Opt_AttributeInvalidNamespace_Exception($node->getXmlName());
+ throw new Opt_Instruction_Exception('The attribute \''.$node->getXmlName().'\' uses the invalid namespace.');
}
if($attr->getValue() == 'yes')
{
$attr->set('postprocess', true);
}
- } // end processAttribute();
+ } // end _processAttrSingle();
/**
* Postprocesses the opt:single instruction attribute.
@@ -177,12 +177,58 @@ public function processAttribute(Opt_Xml_Node $node, Opt_Xml_Attribute $attr)
* @param Opt_Xml_Node $node XML node.
* @param Opt_Xml_Attribute $attr XML attribute.
*/
- public function postprocessAttribute(Opt_Xml_Node $node, Opt_Xml_Attribute $attr)
+ public function _postprocessAttrSingle(Opt_Xml_Node $node, Opt_Xml_Attribute $attr)
{
if($attr->getValue() == 'yes')
{
$node->set('single', true);
$node->removeChildren();
}
- } // end processAttribute();
+ } // end _postprocessAttrSingle();
+
+ /**
+ * Processes the opt:tag-name instruction attribute.
+ *
+ * @internal
+ * @param Opt_Xml_Node $node XML node.
+ * @param Opt_Xml_Attribute $attr XML attribute.
+ * @throws Opt_Instruction_Exception
+ */
+ public function _processAttrTagname(Opt_Xml_Node $node, Opt_Xml_Attribute $attr)
+ {
+ if($this->_compiler->isNamespace($node->getNamespace()))
+ {
+ throw new Opt_Instruction_Exception('Cannot use opt:tag-name with special OPT namespaces.');
+ }
+
+ $found = $this->_compiler->detectExpressionEngine($attr->getValue(), $this->_tpl->expressionEngine);
+ if($found === null)
+ {
+ $found = array($this->_tpl->expressionEngine, $attr->getValue());
+ }
+ $result = $this->_compiler->parseExpression($found[1], $found[0]);
+
+ if($result['complexity'] > 10)
+ {
+ if($node->getNamespace() !== null)
+ {
+ $node->addAfter(Opt_Xml_Buffer::TAG_NAME, 'if(($__tmp = '.$result['bare'].') !== null){ echo \''.$node->getNamespace().':\'.$__tmp; } else { echo \''.$node->getXmlName().'\'; }');
+ }
+ else
+ {
+ $node->addAfter(Opt_Xml_Buffer::TAG_NAME, 'if(($__tmp = '.$result['bare'].') !== null){ echo $__tmp; } else { echo \''.$node->getXmlName().'\'; }');
+ }
+ }
+ else
+ {
+ if($node->getNamespace() !== null)
+ {
+ $node->addAfter(Opt_Xml_Buffer::TAG_NAME, 'if('.$result['bare'].' !== null){ echo \''.$node->getNamespace().':\'.'.$result['bare'].'; } else { echo \''.$node->getXmlName().'\'; }');
+ }
+ else
+ {
+ $node->addAfter(Opt_Xml_Buffer::TAG_NAME, 'if('.$result['bare'].' !== null){ echo '.$result['bare'].'; } else { echo \''.$node->getXmlName().'\'; }');
+ }
+ }
+ } // end _processAttrTagname();
} // end Opt_Instruction_Tag;
View
7 lib/Opt/Xml/Cdata.php
@@ -107,6 +107,11 @@ public function __toString()
/**
* Validates the inserted text.
+ *
+ * Throws an exception, if the validated text contains special <> XML
+ * symbols.
+ *
+ * @throws Opt_Xml_Exception
* @param String $text The text to validate
* @return Boolean
*/
@@ -119,7 +124,7 @@ protected function _validate(&$text)
}
if(strcspn($text, '<>') != strlen($text))
{
- throw new Opt_XmlInvalidCharacter_Exception(htmlspecialchars($text));
+ throw new Opt_Xml_Exception('Invalid symbols in the character data: '.htmlspecialchars($text));
}
return true;
} // end _validate();
View
2  lib/Opt/Xml/Element.php
@@ -759,7 +759,7 @@ protected function _linkAttributes(Opt_Compiler_Class $compiler)
$code .= ($attribute->bufferSize(Opt_Xml_Buffer::ATTRIBUTE_BEGIN) == 0 ? ' ' : '').$attribute->buildCode(Opt_Xml_Buffer::ATTRIBUTE_BEGIN, ' ', Opt_Xml_Buffer::ATTRIBUTE_NAME);
break;
default:
- throw new Opt_CompilerCodeBufferConflict_Exception(1, 'ATTRIBUTE_NAME', $this->getXmlName());
+ throw new Opt_Xml_Exception('Compiler code buffer conflict: the buffer \'ATTRIBUTE_NAME\' in '.$this->getXmlName().' can contain at most one code block.');
}
if($attribute->bufferSize(Opt_Xml_Buffer::ATTRIBUTE_VALUE) == 0)
View
7 lib/Opt/Xml/Scannable.php
@@ -290,6 +290,7 @@ public function moveChildren(Opt_Xml_Scannable $node)
* Replaces the child with the new node. The reference node can be
* identified either by the number or by the object.
*
+ * @throws Opt_Xml_Exception
* @param Opt_Xml_Node $newnode The new node.
* @param integer|Opt_Xml_Node $refnode The old node.
* @return boolean
@@ -322,7 +323,7 @@ public function replaceChild(Opt_Xml_Node $newnode, $refnode)
// Now, do the replacement.
if($refnode->_parent !== $this)
{
- throw new Opt_APIInvalidBorders_Exception;
+ throw new Opt_Xml_Exception('Cannot perform replaceChild(): invalid referenced node.');
}
if($this->_iterator === $refnode)
@@ -921,9 +922,9 @@ public function key()
/**
* Checks whether the node can be added to this collection. If the specified
* node cannot be inserted into a collection, the method is supposed to
- * return 'Opt_APIInvalidNodeType_Exception'
+ * throw 'Opt_Xml_Exception'
*
- * @throws Opt_APIInvalidNodeType_Exception
+ * @throws Opt_Xml_Exception
* @param Opt_Xml_Node $node The node to test
*/
protected function _testNode(Opt_Xml_Node $node)
View
4 tests/Package/Instruction/AllTests.php
@@ -36,7 +36,7 @@
//require_once('SingleTest.php');
require_once('SnippetTest.php');
require_once('SwitchTest.php');
-//require_once('TagTest.php');
+require_once('TagTest.php');
require_once('TreeTest.php');
class Package_Instruction_AllTests extends PHPUnit_Framework_TestSuite
@@ -78,7 +78,7 @@ public static function suite()
//$suite->addTestSuite('Package_Instruction_SingleTest');
$suite->addTestSuite('Package_Instruction_SnippetTest');
$suite->addTestSuite('Package_Instruction_SwitchTest');
- //$suite->addTestSuite('Package_Instruction_TagTest');
+ $suite->addTestSuite('Package_Instruction_TagTest');
$suite->addTestSuite('Package_Instruction_TreeTest');
return $suite;
View
1  tests/Package/Instruction/ComponentTest.php
@@ -53,6 +53,7 @@ public static function dataProvider()
array('Component/component_nesting.txt'),
array('Component/component_template.txt'),
array('Component/component_template_missing.txt'),
+ array('Component/component_id.txt'),
);
} // end dataProvider();
View
60 tests/Package/Instruction/TagTest.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * The tests for opt:switch instruction.
+ *
+ * @author Tomasz "Zyx" Jędrzejewski
+ * @copyright Copyright (c) 2009 Invenzzia Group
+ * @license http://www.invenzzia.org/license/new-bsd New BSD License
+ */
+
+require_once('./Extra/TestFS.php');
+require_once('./Extra/TestFSBase.php');
+
+/**
+ * @covers Opt_Compiler_Class
+ * @covers Opt_Compiler_Format
+ * @covers Opt_Compiler_Processor
+ * @covers Opt_Instruction_Tag
+ * @runTestsInSeparateProcesses
+ */
+class Package_Instruction_TagTest extends Extra_TestFSBase
+{
+
+ /**
+ * Configuration method.
+ * @param Opt_Class $tpl
+ */
+ public function configure(Opt_Class $tpl)
+ {
+ $tpl->parser = 'Opt_Parser_Xml';
+ $tpl->register(Opt_Class::OPT_COMPONENT, 'opt:myComponent', 'Extra_Mock_Component');
+ $tpl->register(Opt_Class::OPT_BLOCK, 'opt:myBlock', 'Extra_Mock_Block');
+ } // end configure();
+
+ /**
+ * Provides the list of test cases.
+ * @return array
+ */
+ public static function dataProvider()
+ {
+ return array(0 =>
+ array('Tag/tag_basic.txt'),
+ array('Tag/tag_single.txt'),
+ array('Tag/tag_dynamic_attr.txt'),
+ array('Tag/tag_special_attr.txt'),
+ array('Tag/tag_name.txt'),
+ array('Tag/tag_namespaces.txt'),
+ array('Tag/tag_name_attr.txt'),
+ array('Tag/tag_name_attr_ns.txt'),
+ );
+ } // end dataProvider();
+
+ /**
+ * @dataProvider dataProvider
+ * @runInSeparateProcess
+ */
+ public function testInstructions($testCase)
+ {
+ return $this->_checkTest(dirname(__FILE__).'/Tests/'.$testCase);
+ } // end testInstructions();
+} // end Package_Instruction_TagTest;
View
26 tests/Package/Instruction/Tests/Component/component_id.txt
@@ -0,0 +1,26 @@
+Checking working with data formats.
+
+>>>>templates/test.tpl
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<opt:root xmlns:opt="http://xml.invenzzia.org/opt">
+
+<opt:component from="$component" id="foo">
+<opt:set name="foo" value="str:bar" />
+{$system.component.foo}
+</opt:component>
+
+</opt:root>
+
+>>>>data.php
+
+$view->setFormat('component#foo', 'Component');
+$view->component = new Extra_Mock_Component;
+
+>>>>expected.txt
+OUTPUT
+
+>>>>result.txt
+VIEW PASSED
+PARAM foo PASSED
+PARAM foo RETURNED
+bar
View
4 tests/Package/Instruction/Tests/Tag/tag_1.txt → tests/Package/Instruction/Tests/Tag/tag_basic.txt
@@ -1,8 +1,8 @@
The test checks the basic opt:tag functionality.
>>>>templates/test.tpl
-<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
-<opt:root>
+<?xml version="1.0" ?>
+<opt:root xmlns:opt="http://xml.invenzzia.org/opt">
<opt:tag name="foo">
bar
</opt:tag>
View
6 tests/Package/Instruction/Tests/Tag/tag_2.txt → ...ackage/Instruction/Tests/Tag/tag_dynamic_attr.txt
@@ -1,10 +1,10 @@
The test checks the basic opt:tag functionality with the "name" attribute added.
>>>>templates/test.tpl
-<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
-<opt:root>
+<?xml version="1.0" ?>
+<opt:root xmlns:opt="http://xml.invenzzia.org/opt">
<opt:tag name="foo">
-<opt:attribute str:name="name" str:value="bar" />
+<opt:attribute name="str:name" value="str:bar" />
bar
</opt:tag>
</opt:root>
View
6 tests/Package/Instruction/Tests/Tag/tag_5.txt → tests/Package/Instruction/Tests/Tag/tag_name.txt
@@ -1,10 +1,10 @@
The test checks the single tag creation with extra attributes.
>>>>templates/test.tpl
-<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
-<opt:root>
+<?xml version="1.0" ?>
+<opt:root xmlns:opt="http://xml.invenzzia.org/opt">
<opt:tag name="foo" single="yes">
-<opt:attribute str:name="name" str:value="bar" />
+<opt:attribute name="str:name" value="str:bar" />
bar
</opt:tag>
</opt:root>
View
27 tests/Package/Instruction/Tests/Tag/tag_name_attr.txt
@@ -0,0 +1,27 @@
+Testing the opt:tag-name special attribute.
+
+>>>>templates/test.tpl
+<?xml version="1.0" ?>
+<opt:root xmlns:opt="http://xml.invenzzia.org/opt">
+<div opt:tag-name="$nonexistingName">
+bar
+</div>
+<div opt:tag-name="$existingName">
+bar
+</div>
+</opt:root>
+
+>>>>data.php
+$view->nonexistingName = null;
+$view->existingName = 'span';
+
+>>>>expected.txt
+OUTPUT
+
+>>>>result.txt
+<div>
+bar
+</div>
+<span>
+bar
+</span>
View
27 tests/Package/Instruction/Tests/Tag/tag_name_attr_ns.txt
@@ -0,0 +1,27 @@
+Testing the opt:tag-name special attribute with namespaces.
+
+>>>>templates/test.tpl
+<?xml version="1.0" ?>
+<opt:root xmlns:opt="http://xml.invenzzia.org/opt" xmlns:xyz="http://www.example.com/xml/xyz">
+<xyz:div opt:tag-name="$nonexistingName">
+bar
+</xyz:div>
+<xyz:div opt:tag-name="$existingName">
+bar
+</xyz:div>
+</opt:root>
+
+>>>>data.php
+$view->nonexistingName = null;
+$view->existingName = 'span';
+
+>>>>expected.txt
+OUTPUT
+
+>>>>result.txt
+<xyz:div>
+bar
+</xyz:div>
+<xyz:span>
+bar
+</xyz:span>
View
27 tests/Package/Instruction/Tests/Tag/tag_namespaces.txt
@@ -0,0 +1,27 @@
+Checks if opt:tag correctly generates tags with dynamic namespaces.
+
+>>>>templates/test.tpl
+<?xml version="1.0" ?>
+<opt:root xmlns:opt="http://xml.invenzzia.org/opt">
+<opt:tag name="foo" ns="$existingNs">
+bar
+</opt:tag>
+<opt:tag name="foo" ns="$nonexistingNs">
+bar
+</opt:tag>
+</opt:root>
+
+>>>>data.php
+$view->existingNs = 'xyz';
+$view->nonexistingNs = null;
+
+>>>>expected.txt
+OUTPUT
+
+>>>>result.txt
+<xyz:foo>
+bar
+</xyz:foo>
+<foo>
+bar
+</foo>
View
4 tests/Package/Instruction/Tests/Tag/tag_4.txt → tests/Package/Instruction/Tests/Tag/tag_single.txt
@@ -1,8 +1,8 @@
The test checks the single tag creation.
>>>>templates/test.tpl
-<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
-<opt:root>
+<?xml version="1.0" ?>
+<opt:root xmlns:opt="http://xml.invenzzia.org/opt">
<opt:tag name="foo" single="yes">
bar
</opt:tag>
View
6 tests/Package/Instruction/Tests/Tag/tag_3.txt → ...ackage/Instruction/Tests/Tag/tag_special_attr.txt
@@ -1,10 +1,10 @@
The test checks the basic opt:tag functionality with the "single" attribute added.
>>>>templates/test.tpl
-<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
-<opt:root>
+<?xml version="1.0" ?>
+<opt:root xmlns:opt="http://xml.invenzzia.org/opt">
<opt:tag name="foo">
-<opt:attribute str:name="single" str:value="bar" />
+<opt:attribute name="str:single" value="str:bar" />
bar
</opt:tag>
</opt:root>
View
56 tests/Package/ViewTest.php
@@ -298,4 +298,60 @@ public function testNoNoticesOnUnexistingVars()
ob_end_clean();
} // end testNoNoticesOnUnexistingVars();
+ /**
+ * @covers Opt_View::setCache
+ * @covers Opt_View::getCache
+ * @covers Opt_View::_parse
+ */
+ public function testCacheRebuild()
+ {
+ $view = new Opt_View('dummy.tpl');
+
+ $mock = $this->getMock('Opt_Caching_Interface');
+ $mock->expects($this->once())
+ ->method('templateCacheStart')
+ ->with($view)
+ ->will($this->returnValue(false));
+ $mock->expects($this->once())
+ ->method('templateCacheStop')
+ ->with($view);
+
+ $view->setCache($mock);
+ $this->assertSame($mock, $view->getCache());
+
+ $output = $this->getMock('Opt_Output_Interface');
+ ob_start();
+ $view->_parse($output);
+ ob_end_clean();
+ } // end testCacheRebuild();
+
+ /**
+ * @covers Opt_View::setCache
+ * @covers Opt_View::getCache
+ * @covers Opt_View::_parse
+ */
+ public function testCacheRestore()
+ {
+ $view = new Opt_View('dummy.tpl');
+ file_put_contents('./Cache/cache.txt', 'DUPA');
+
+ $mock = $this->getMock('Opt_Caching_Interface');
+ $mock->expects($this->once())
+ ->method('templateCacheStart')
+ ->with($view)
+ ->will($this->returnValue('./Cache/cache.txt'));
+ $mock->expects($this->never())
+ ->method('templateCacheStop');
+
+ $view->setCache($mock);
+ $this->assertSame($mock, $view->getCache());
+
+ $output = $this->getMock('Opt_Output_Interface');
+ ob_start();
+ $view->_parse($output);
+ $data = ob_get_clean();
+
+ $this->assertEquals('DUPA', $data);
+ } // end testCacheRestore();
+
} // end Package_ViewTest;
View
4 tests/Package/templates/dummy.tpl
@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<opt:root xmlns:opt="http://xml.invenzzia.org/opt">
+DUMMY
+</opt:root>
View
2  tests/run-single.php
@@ -37,6 +37,8 @@ public function init()
$tpl->parser = Opt_Class::XML_MODE;
$tpl->stripWhitespaces = false;
$tpl->prologRequired = true;
+ $tpl->register(Opt_Class::OPT_COMPONENT, 'opt:myComponent', 'Extra_Mock_Component');
+ $tpl->register(Opt_Class::OPT_BLOCK, 'opt:myBlock', 'Extra_Mock_Block');
$tpl->setup();
$this->tpl = $tpl;
} // end init();
View
504 tools/lexer/expression_lexer.php
@@ -1,504 +0,0 @@
-<?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.
- *
- */
-
-/**
- * The lexer class for the expression parser. Note: this file
- * is automatically generated by PHP Parser Generator lexer
- * by Gregory Beaver. Do not modify it manually. Instead,
- * use the file /tools/lexer/expression_lexer.plex and parse
- * it with /tools/lexer/generateExpression.php.
- */
-class Opt_Expression_Standard_Lexer
-{
- /**
- * The data field for the lexical analyzer.
- */
- private $_data;
- /**
- * The token counter for the lexical analyzer.
- */
- private $_counter;
- /**
- * The line counter for the lexical analyzer.
- */
- private $_line;
-
- /**
- * The recognized token number for parser.
- * @var integer
- */
- public $token;
-
- /**
- * The recognized token value for parser.
- * @var string
- */
- public $value;
-
- /**
- * Constructs the lexer object for parsing the specified
- * expression.
- *
- * @param string $expression The expression to parse.
- */
- public function __construct($expression)
- {
- $this->_data = $expression;
- $this->_line = 1;
- $this->_counter = 0;
- } // end __construct();
-
-
-
- private $_yy_state = 1;
- private $_yy_stack = array();
-
- function yylex()
- {
- return $this->{'yylex' . $this->_yy_state}();
- }
-
- function yypushstate($state)
- {
- array_push($this->_yy_stack, $this->_yy_state);
- $this->_yy_state = $state;
- }
-
- function yypopstate()
- {
- $this->_yy_state = array_pop($this->_yy_stack);
- }
-
- function yybegin($state)
- {
- $this->_yy_state = $state;
- }
-
-
-
- function yylex1()
- {
- $tokenMap = array (
- 1 => 0,
- 2 => 1,
- 4 => 0,
- 5 => 0,
- 6 => 0,
- 7 => 0,
- 8 => 0,
- 9 => 0,
- 10 => 0,
- 11 => 0,
- 12 => 0,
- 13 => 0,
- 14 => 0,
- 15 => 0,
- 16 => 0,
- 17 => 0,
- 18 => 0,
- 19 => 0,
- 20 => 0,
- 21 => 0,
- 22 => 0,
- 23 => 0,
- 24 => 0,
- 25 => 0,
- 26 => 0,
- 27 => 0,
- 28 => 0,
- 29 => 0,
- 30 => 0,
- 31 => 0,
- 32 => 0,
- 33 => 0,
- 34 => 0,
- 35 => 0,
- 36 => 0,
- 37 => 0,
- 38 => 0,
- 39 => 0,
- 40 => 0,
- 41 => 0,
- 42 => 0,
- 43 => 0,
- 44 => 0,
- 45 => 0,
- );
- if ($this->_counter >= strlen($this->_data)) {
- return false; // end of input
- }
- $yy_global_pattern = "/^(\\s+)|^((\\+\\+|--))|^(\\+)|^(-)|^(\\*)|^(\/)|^(%)|^(\\^)|^(!)|^(==)|^(===)|^(!=)|^(!=)|^(~)|^(is\\s+between)|^(is\\s+not\\s+between)|^(is\\s+either)|^(is\\s+neither)|^(contains\\s+both)|^(contains\\s+either)|^(contains\\s+neither)|^(is\\s+in)|^(is\\s+not\\s+in)|^(is\\s+in\\s+both)|^(is\\s+in\\s+either)|^(is\\s+in\\s+neither)|^(\\$)|^(@)|^(\\.)|^(=)|^(\\()|^(\\))|^(<)|^(>)|^(\\[)|^(\\])|^(::)|^(,)|^(:)|^([a-zA-Z_][a-zA-Z0-9_]*)|^('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')|^(`[^`\\\\]*(?:\\\\.[^`\\\\]*)*`)|^([0-9]+\\.?[0-9]*)|^(0[xX][0-9a-fA-F]+)/";
-
- do {
- if (preg_match($yy_global_pattern, substr($this->_data, $this->_counter), $yymatches)) {
- $yysubmatches = $yymatches;
- $yymatches = array_filter($yymatches, 'strlen'); // remove empty sub-patterns
- if (!count($yymatches)) {
- throw new Exception('Error: lexing failed because a rule matched' .
- 'an empty string. Input "' . substr($this->_data,
- $this->_counter, 5) . '... state CODE');
- }
- next($yymatches); // skip global match
- $this->token = key($yymatches); // token number
- if ($tokenMap[$this->token]) {
- // extract sub-patterns for passing to lex function
- $yysubmatches = array_slice($yysubmatches, $this->token + 1,
- $tokenMap[$this->token]);
- } else {
- $yysubmatches = array();
- }
- $this->value = current($yymatches); // token value
- $r = $this->{'yy_r1_' . $this->token}($yysubmatches);
- if ($r === null) {
- $this->_counter += strlen($this->value);
- $this->_line += substr_count($this->value, "\n");
- // accept this token
- return true;
- } elseif ($r === true) {
- // we have changed state
- // process this token in the new state
- return $this->yylex();
- } elseif ($r === false) {
- $this->_counter += strlen($this->value);
- $this->_line += substr_count($this->value, "\n");
- if ($this->_counter >= strlen($this->_data)) {
- return false; // end of input
- }
- // skip this token
- continue;
- } } else {
- throw new Exception('Unexpected input at line' . $this->_line .
- ': ' . $this->_data[$this->_counter]);
- }
- break;
- } while (true);
-
- } // end function
-
-
- const CODE = 1;
- function yy_r1_1($yy_subpatterns)
- {
-
- $this->token = 'w';
- }
- function yy_r1_2($yy_subpatterns)
- {
-
- if($this->value == '++')
- {
- $this->token = Opt_Expression_Standard_Parser::T_INCREMENT;
- }
- else
- {
- $this->token = Opt_Expression_Standard_Parser::T_DECREMENT;
- }
- }
- function yy_r1_4($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_ADD;
- }
- function yy_r1_5($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_MINUS;
- }
- function yy_r1_6($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_MUL;
- }
- function yy_r1_7($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_DIV;
- }
- function yy_r1_8($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_MOD;
- }
- function yy_r1_9($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_EXP;
- }
- function yy_r1_10($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_NOT;
- }
- function yy_r1_11($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_EQUALS;
- }
- function yy_r1_12($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_EQUALS_T;
- }
- function yy_r1_13($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_NEQUALS;
- }
- function yy_r1_14($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_NEQUALS_T;
- }
- function yy_r1_15($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_CONCAT;
- }
- function yy_r1_16($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_IS_BETWEEN;
- }
- function yy_r1_17($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_IS_NOT_BETWEEN;
- }
- function yy_r1_18($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_IS_EITHER;
- }
- function yy_r1_19($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_IS_NEITHER;
- }
- function yy_r1_20($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_CONTAINS_BOTH;
- }
- function yy_r1_21($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_CONTAINS_EITHER;
- }
- function yy_r1_22($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_CONTAINS_NEITHER;
- }
- function yy_r1_23($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_IS_IN;
- }
- function yy_r1_24($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_IS_NOT_IN;
- }
- function yy_r1_25($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_IS_BOTH_IN;
- }
- function yy_r1_26($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_IS_EITHER_IN;
- }
- function yy_r1_27($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_IS_NEITHER_IN;
- }
- function yy_r1_28($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_DOLLAR;
- }
- function yy_r1_29($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_AT;
- }
- function yy_r1_30($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_DOT;
- }
- function yy_r1_31($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_ASSIGN;
- }
- function yy_r1_32($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_L_BRACKET;
- }
- function yy_r1_33($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_R_BRACKET;
- }
- function yy_r1_34($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_DLSQ_BRACKET;
- }
- function yy_r1_35($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_DRSQ_BRACKET;
- }
- function yy_r1_36($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_LSQ_BRACKET;
- }
- function yy_r1_37($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_RSQ_BRACKET;
- }
- function yy_r1_38($yy_subpatterns)
- {
-
- $this->token = Opt_Expression_Standard_Parser::T_OBJECT_OPERATOR;
- }
- function yy_r1_39($yy_subpatterns)
- {
-