Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #19 from ziggys/nested-callback-parameters-fix

Nested callback parameters fix.
  • Loading branch information...
commit 587e6a2e1050cf89d1f113512d0745666a0f0134 2 parents 9632d69 + a024188
@philsturgeon philsturgeon authored
Showing with 61 additions and 11 deletions.
  1. +1 −1  example/template.lex
  2. +60 −10 lib/Lex/Parser.php
View
2  example/template.lex
@@ -16,7 +16,7 @@
{{ endif }}
<ul id="navigation">
- {{template:partial name="navigation" group="{{nav_group}}"}}
+ {{template:partial name="navigation" group=nav_group}}
{{/template:partial}}
</ul>
View
70 lib/Lex/Parser.php
@@ -35,7 +35,10 @@ class Lex_Parser
protected static $extractions = array(
'noparse' => array(),
);
-
+
+ protected static $data = null;
+ protected static $callback_data = array();
+
/**
* The main Lex parser method. Essentially acts as dispatcher to
* all of the helper parser methods.
@@ -49,6 +52,24 @@ public function parse($text, $data = array(), $callback = false, $allow_php = fa
{
$this->setup_regex();
+ // Is this the first time parse() is called?
+ if (Lex_Parser::$data === null)
+ {
+ // Let's store the local data array for later use.
+ Lex_Parser::$data = $data;
+ }
+ else
+ {
+ // Let's merge the current data array with the local scope variables
+ // So you can call local variables from within blocks.
+ $data = array_merge(Lex_Parser::$data, $data);
+
+ // Since this is not the first time parse() is called, it's most definately a callback,
+ // let's store the current callback data with the the local data
+ // so we can use it straight after a callback is called.
+ Lex_Parser::$callback_data = $data;
+ }
+
// The parse_conditionals method executes any PHP in the text, so clean it up.
if ( ! $allow_php)
{
@@ -57,19 +78,20 @@ public function parse($text, $data = array(), $callback = false, $allow_php = fa
$text = $this->parse_comments($text);
$text = $this->extract_noparse($text);
- $text = $this->extract_looped_tags($text);
+ $text = $this->extract_looped_tags($text, $data, $callback);
// Order is important here. We parse conditionals first as to avoid
// unnecessary code from being parsed and executed.
$text = $this->parse_conditionals($text, $data, $callback);
$text = $this->inject_extractions($text, 'looped_tags');
$text = $this->parse_variables($text, $data, $callback);
-
+ $text = $this->inject_extractions($text, 'callback_blocks');
+
if ($callback)
{
$text = $this->parse_callback_tags($text, $data, $callback);
}
-
+
// To ensure that {{ noparse }} is never parsed even during consecutive parse calls
// set $cumulative_noparse to true and use Lex_Parser::inject_noparse($text); immediately
// before the final output is sent to the browser
@@ -104,6 +126,7 @@ public function parse_comments($text)
public function parse_variables($text, $data, $callback = null)
{
$this->setup_regex();
+
/**
* $data_matches[][0][0] is the raw data loop tag
* $data_matches[][0][1] is the offset of raw data loop tag
@@ -131,6 +154,12 @@ public function parse_variables($text, $data, $callback = null)
}
$text = preg_replace('/'.preg_quote($match[0][0], '/').'/m', addcslashes($looped_text, '\\$'), $text, 1);
}
+ else // It's a callback block.
+ {
+ // Let's extract it so it doesn't conflict
+ // with the local scope variables in the next step.
+ $text = $this->create_extraction('callback_blocks', $match[0][0], $match[0][0], $text);
+ }
}
}
@@ -190,7 +219,7 @@ public function parse_callback_tags($text, $data, $callback)
if (isset($match[2]))
{
$raw_params = $this->inject_extractions($match[2][0], '__cond_str');
- $parameters = $this->parse_parameters($raw_params, $data, $callback);
+ $parameters = $this->parse_parameters($raw_params, array_merge($data, Lex_Parser::$callback_data), $callback);
}
$content = '';
@@ -201,6 +230,13 @@ public function parse_callback_tags($text, $data, $callback)
{
$content = substr($temp_text, 0, $match[0][1]);
$tag .= $content.$match[0][0];
+
+ // Is there a nested block under this one existing with the same name?
+ if (preg_match($this->callback_block_regex, $content.$match[0][0], $nested_matches))
+ {
+ $nested_content = preg_replace('/\{\{\s*\/'.preg_quote($name, '/').'\s*\}\}/m', '', $nested_matches[0]);
+ $content = $this->create_extraction('nested_looped_tags', $nested_content, $nested_content, $content);
+ }
}
$replacement = call_user_func_array($callback, array($name, $parameters, $content));
@@ -210,7 +246,7 @@ public function parse_callback_tags($text, $data, $callback)
$replacement = $this->value_to_literal($replacement);
}
$text = preg_replace('/'.preg_quote($tag, '/').'/m', addcslashes($replacement, '\\$'), $text, 1);
-
+ $text = $this->inject_extractions($text, 'nested_looped_tags');
}
return $text;
@@ -461,14 +497,14 @@ protected function extract_noparse($text)
return $text;
}
-
+
/**
* Extracts the looped tags so that we can parse conditionals then re-inject.
*
* @param string $text The text to extract from
* @return string
*/
- protected function extract_looped_tags($text)
+ protected function extract_looped_tags($text, $data = array(), $callback = null)
{
/**
* $matches[][0] is the raw match
@@ -477,7 +513,17 @@ protected function extract_looped_tags($text)
{
foreach ($matches as $match)
{
- $text = $this->create_extraction('looped_tags', $match[0], $match[0], $text);
+ // Does this callback block contain parameters?
+ if ($this->parse_parameters($match[2], $data, $callback))
+ {
+ // Let's extract it so it doesn't conflict with local variables when
+ // parse_variables() is called.
+ $text = $this->create_extraction('callback_blocks', $match[0], $match[0], $text);
+ }
+ else
+ {
+ $text = $this->create_extraction('looped_tags', $match[0], $match[0], $text);
+ }
}
}
@@ -583,6 +629,10 @@ protected function get_variable($key, $data, $default = null)
$data = $data->{$key_part};
}
+ else
+ {
+ return $default;
+ }
}
return $data;
@@ -656,4 +706,4 @@ protected function parse_parameters($parameters, $data, $callback)
return array();
}
-}
+}
Please sign in to comment.
Something went wrong with that request. Please try again.