Commit 170592ae by Seldaek

+ Added parsing of {foo->methodCall('with' params)->propertyRead}

git-svn-id: svn://dwoo.org/dwoo/trunk@132 0598d79b-80c4-4d41-97ba-ac86fbbd088b
parent b5cb4682
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
hook into the compiler's plugin subsystem to provide your own plugin calls. hook into the compiler's plugin subsystem to provide your own plugin calls.
Thanks to Denis Arh for the patch Thanks to Denis Arh for the patch
=> http://forum.dwoo.org/viewtopic.php?id=70 => http://forum.dwoo.org/viewtopic.php?id=70
+ Syntax: It is now possible to use a plugin's result as an object and call
a method or read a property from it, i.e. {fetchObject()->doStuff()}
* Syntax: Math expressions in strings are now only allowed when the entire * Syntax: Math expressions in strings are now only allowed when the entire
expression is delimited, e.g. {"/$foo/$bar"} evaluates as just that while expression is delimited, e.g. {"/$foo/$bar"} evaluates as just that while
{"/`$foo/$bar`"} will result in "/".($foo/$bar), therefore processing the / {"/`$foo/$bar`"} will result in "/".($foo/$bar), therefore processing the /
......
...@@ -1122,6 +1122,7 @@ class Dwoo_Compiler implements Dwoo_ICompiler ...@@ -1122,6 +1122,7 @@ class Dwoo_Compiler implements Dwoo_ICompiler
} elseif (preg_match('/^[a-z][a-z0-9_]*(?:::[a-z][a-z0-9_]*)?('.(is_array($parsingParams)||$curBlock!='root'?'':'\s+[^(]|').'\s*\(|\s*'.$this->rdr.'|\s*;)/i', $substr)) { } elseif (preg_match('/^[a-z][a-z0-9_]*(?:::[a-z][a-z0-9_]*)?('.(is_array($parsingParams)||$curBlock!='root'?'':'\s+[^(]|').'\s*\(|\s*'.$this->rdr.'|\s*;)/i', $substr)) {
// func // func
$out = $this->parseFunction($in, $from, $to, $parsingParams, $curBlock, $pointer); $out = $this->parseFunction($in, $from, $to, $parsingParams, $curBlock, $pointer);
$parsed = 'func';
} elseif ($first === ';') { } elseif ($first === ';') {
// instruction end // instruction end
if ($this->debug) echo 'END OF INSTRUCTION<br />'; if ($this->debug) echo 'END OF INSTRUCTION<br />';
...@@ -1190,6 +1191,22 @@ class Dwoo_Compiler implements Dwoo_ICompiler ...@@ -1190,6 +1191,22 @@ class Dwoo_Compiler implements Dwoo_ICompiler
} }
} }
} }
if (isset($parsed) && $parsed==='func' && preg_match('#^->[a-z0-9_]+\s*\(.+#s', $substr, $match)) {
$ptr = 0;
if (is_array($parsingParams)) {
$output = $this->parseMethodCall($out[1], $match[0], $curBlock, $ptr);
$out[count($out)-1][0] .= substr($match[0], 0, $ptr);
$out[count($out)-1][1] .= $output;
} else {
$out = $this->parseMethodCall($out, $match[0], $curBlock, $ptr);
}
$pointer += $ptr;
}
if ($curBlock === 'root' && substr($out, 0, strlen(self::PHP_OPEN)) !== self::PHP_OPEN) { if ($curBlock === 'root' && substr($out, 0, strlen(self::PHP_OPEN)) !== self::PHP_OPEN) {
return self::PHP_OPEN .'echo '.$out.';'. self::PHP_CLOSE; return self::PHP_OPEN .'echo '.$out.';'. self::PHP_CLOSE;
} else { } else {
...@@ -1445,6 +1462,9 @@ class Dwoo_Compiler implements Dwoo_ICompiler ...@@ -1445,6 +1462,9 @@ class Dwoo_Compiler implements Dwoo_ICompiler
} else { } else {
$output = 'call_user_func(array($this->getObjectPlugin(\''.$callback[0].'\'), \''.$callback[1].'\'), '.$params.')'; $output = 'call_user_func(array($this->getObjectPlugin(\''.$callback[0].'\'), \''.$callback[1].'\'), '.$params.')';
} }
if (empty($params)) {
$output = substr($output, 0, -3).')';
}
} else { } else {
$output = '$this->classCall(\''.$func.'\', array('.$params.'))'; $output = '$this->classCall(\''.$func.'\', array('.$params.'))';
} }
...@@ -1733,45 +1753,8 @@ class Dwoo_Compiler implements Dwoo_ICompiler ...@@ -1733,45 +1753,8 @@ class Dwoo_Compiler implements Dwoo_ICompiler
// methods // methods
if ($hasMethodCall) { if ($hasMethodCall) {
$ptr = 0; $ptr = 0;
$len = strlen($methodCall);
while ($ptr < $len) { $output = $this->parseMethodCall($output, $methodCall, $curBlock, $ptr);
if (strpos($methodCall, '->', $ptr) === $ptr) {
$ptr += 2;
}
if (in_array($methodCall[$ptr], array(';', '/', ' ', "\t", "\r", "\n", ')', '+', '*', '%', '=', '-')) || substr($methodCall, $ptr, strlen($this->rd)) === $this->rd) {
// break char found
break;
}
if(!preg_match('/^([a-z0-9_]+)(\(.*?\))?/i', substr($methodCall, $ptr), $methMatch)) {
throw new Dwoo_Compilation_Exception($this, 'Invalid method name : '.substr($methodCall, $ptr, 20));
}
if (empty($methMatch[2])) {
// property
if ($curBlock === 'root') {
$output .= '->'.$methMatch[1];
} else {
$output = '(($tmp = '.$output.') ? $tmp->'.$methMatch[1].' : null)';
}
$ptr += strlen($methMatch[1]);
} else {
// method
if (substr($methMatch[2], 0, 2) === '()') {
$parsedCall = '->'.$methMatch[1].'()';
$ptr += strlen($methMatch[1]) + 2;
} else {
$parsedCall = '->'.$this->parseFunction($methodCall, $ptr, strlen($methodCall), false, 'method', $ptr);
}
if ($curBlock === 'root') {
$output .= $parsedCall;
} else {
$output = '(($tmp = '.$output.') ? $tmp'.$parsedCall.' : null)';
}
}
}
if ($pointer !== null) { if ($pointer !== null) {
$pointer += $ptr; $pointer += $ptr;
...@@ -1877,6 +1860,62 @@ class Dwoo_Compiler implements Dwoo_ICompiler ...@@ -1877,6 +1860,62 @@ class Dwoo_Compiler implements Dwoo_ICompiler
} }
/** /**
* parses any number of chained method calls/property reads
*
* @param string $output the variable or whatever upon which the method are called
* @param string $methodCall method call source, starting at "->"
* @param string $curBlock the current parser-block being processed
* @param int $pointer a reference to a pointer that will be increased by the amount of characters parsed
* @return string parsed call(s)/read(s)
*/
protected function parseMethodCall($output, $methodCall, $curBlock, &$pointer)
{
$ptr = 0;
$len = strlen($methodCall);
while ($ptr < $len) {
if (strpos($methodCall, '->', $ptr) === $ptr) {
$ptr += 2;
}
if (in_array($methodCall[$ptr], array(';', '/', ' ', "\t", "\r", "\n", ')', '+', '*', '%', '=', '-')) || substr($methodCall, $ptr, strlen($this->rd)) === $this->rd) {
// break char found
break;
}
if(!preg_match('/^([a-z0-9_]+)(\(.*?\))?/i', substr($methodCall, $ptr), $methMatch)) {
throw new Dwoo_Compilation_Exception($this, 'Invalid method name : '.substr($methodCall, $ptr, 20));
}
if (empty($methMatch[2])) {
// property
if ($curBlock === 'root') {
$output .= '->'.$methMatch[1];
} else {
$output = '(($tmp = '.$output.') ? $tmp->'.$methMatch[1].' : null)';
}
$ptr += strlen($methMatch[1]);
} else {
// method
if (substr($methMatch[2], 0, 2) === '()') {
$parsedCall = '->'.$methMatch[1].'()';
$ptr += strlen($methMatch[1]) + 2;
} else {
$parsedCall = '->'.$this->parseFunction($methodCall, $ptr, strlen($methodCall), false, 'method', $ptr);
}
if ($curBlock === 'root') {
$output .= $parsedCall;
} else {
$output = '(($tmp = '.$output.') ? $tmp'.$parsedCall.' : null)';
}
}
}
$pointer += $ptr;
return $output;
}
/**
* parses a constant variable (a variable that doesn't contain another variable) and preprocesses it to save runtime processing time * parses a constant variable (a variable that doesn't contain another variable) and preprocesses it to save runtime processing time
* *
* @param string $key the variable to parse * @param string $key the variable to parse
...@@ -2496,7 +2535,7 @@ class Dwoo_Compiler implements Dwoo_ICompiler ...@@ -2496,7 +2535,7 @@ class Dwoo_Compiler implements Dwoo_ICompiler
} catch (Exception $e) { } catch (Exception $e) {
if (isset($phpFunc)) { if (isset($phpFunc)) {
$pluginType = Dwoo::NATIVE_PLUGIN; $pluginType = Dwoo::NATIVE_PLUGIN;
} elseif ($this->dwoo->getPluginProxy() && $this->dwoo->getPluginProxy()->loadPlugin($name)) { } elseif (is_object($this->dwoo->getPluginProxy()) && $this->dwoo->getPluginProxy()->loadPlugin($name)) {
$pluginType = Dwoo::PROXY_PLUGIN; $pluginType = Dwoo::PROXY_PLUGIN;
break; break;
} else { } else {
......
...@@ -536,6 +536,16 @@ replace="BAR" ...@@ -536,6 +536,16 @@ replace="BAR"
$this->assertEquals('-BAZBAR-', $this->dwoo->get($tpl, array(), $this->compiler)); $this->assertEquals('-BAZBAR-', $this->dwoo->get($tpl, array(), $this->compiler));
} }
public function testFunctionCallsChaining()
{
$tpl = new Dwoo_Template_String('{getobj()->foo()->bar("hoy")}');
$tpl->forceCompilation();
$dwoo = new Dwoo();
$dwoo->addPlugin('getobj', array(new PluginHelper(), 'call'));
$this->assertEquals('HOY', $dwoo->get($tpl, array(), $this->compiler));
}
public function testPluginProxy() public function testPluginProxy()
{ {
$proxy = new ProxyHelper('baz',true,3); $proxy = new ProxyHelper('baz',true,3);
...@@ -571,7 +581,31 @@ class ProxyHelper implements Dwoo_IPluginProxy ...@@ -571,7 +581,31 @@ class ProxyHelper implements Dwoo_IPluginProxy
} }
} }
class MethodCallsHelper { class PluginHelper
{
public function callWithDwoo(Dwoo $dwoo)
{
return $this;
}
public function call()
{
return $this;
}
public function foo()
{
return $this;
}
public function bar($a)
{
return strtoupper($a);
}
}
class MethodCallsHelper
{
public function __construct($int=0) { public function __construct($int=0) {
$this->int = $int; $this->int = $int;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment