Last active
August 29, 2015 14:01
-
-
Save poison/27e1ffb71fc682ee4ec4 to your computer and use it in GitHub Desktop.
This patch enables you to loop over structures. See the test for more details
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 84b8814377c18e8ccdc3e6f1e4eb1e9d1828b212 Mon Sep 17 00:00:00 2001 | |
From: Nicolas Van Eenaeme <nicolas@netlog.com> | |
Date: Tue, 13 May 2014 19:55:18 +0200 | |
Subject: [PATCH] Enabled iteration over objects! | |
Fixed the test to check for mixed array contents | |
Added test for new loop | |
--- | |
blitz.c | 32 +++++++++++++++++++++----------- | |
tests/loop.phpt | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ | |
2 files changed, 69 insertions(+), 11 deletions(-) | |
create mode 100644 tests/loop.phpt | |
diff --git a/blitz.c b/blitz.c | |
index f4d57ab..3f684f7 100644 | |
--- a/blitz.c | |
+++ b/blitz.c | |
@@ -1262,11 +1262,11 @@ static inline void blitz_parse_call (char *text, unsigned int len_text, blitz_no | |
BLITZ_SKIP_BLANK(c,i_pos,pos); | |
i_len = i_pos = ok = 0; | |
p = buf; | |
- BLITZ_SCAN_ALNUM(c,p,i_len,i_symb); | |
+ BLITZ_SCAN_VAR(c,p,i_len,i_symb,is_path); | |
if (i_len!=0) { | |
ok = 1; | |
pos += i_len; | |
- ADD_CALL_ARGS(buf, i_len, i_type); | |
+ ADD_CALL_ARGS(buf, i_len, is_path ? BLITZ_ARG_TYPE_VAR_PATH : i_type); | |
state = BLITZ_CALL_STATE_FINISHED; | |
} else { | |
state = BLITZ_CALL_STATE_ERROR; | |
@@ -1276,7 +1276,7 @@ static inline void blitz_parse_call (char *text, unsigned int len_text, blitz_no | |
i_pos = 0; | |
BLITZ_SKIP_BLANK(c,i_pos,pos); i_pos = 0; symb = *c; | |
if (BLITZ_IS_ALPHA(symb)) { | |
- BLITZ_SCAN_ALNUM(c,p,i_pos,i_symb); pos += i_pos; i_pos = 0; | |
+ BLITZ_SCAN_VAR(c,p,i_pos,i_symb,is_path); pos += i_pos; i_pos = 0; | |
} | |
state = BLITZ_CALL_STATE_FINISHED; | |
break; | |
@@ -2327,7 +2327,11 @@ static inline unsigned int blitz_fetch_var_by_path(zval ***zparam, const char *l | |
/* try to get data by the key */ | |
if (0 == root_found) { /* globals or params? */ | |
- root_found = (params && (SUCCESS == zend_hash_find(Z_ARRVAL_P(params), key, key_len + 1, (void **) zparam))); | |
+ root_found = (params && ( | |
+ (IS_ARRAY == Z_TYPE_P(params) && SUCCESS == zend_hash_find(Z_ARRVAL_P(params), key, key_len + 1, (void **) zparam)) || | |
+ (IS_OBJECT == Z_TYPE_P(params) && SUCCESS == zend_hash_find(Z_OBJPROP_P(params), key, key_len + 1, (void **) zparam)) | |
+ )); | |
+ | |
if (!root_found) { | |
root_found = (tpl->hash_globals && (SUCCESS == zend_hash_find(tpl->hash_globals, key, key_len + 1, (void**)zparam))); | |
if (!root_found) { | |
@@ -2941,7 +2945,8 @@ static void blitz_exec_context(blitz_tpl *tpl, blitz_node *node, zval *parent_pa | |
char *key = NULL; | |
unsigned int key_len = 0; | |
unsigned long key_index = 0; | |
- int check_key = 0, not_empty = 0; | |
+ int check_key = 0, not_empty = 0, first_type = -1; | |
+ long predefined = -1; | |
zval **ctx_iterations = NULL; | |
zval **ctx_data = NULL; | |
call_arg *arg = node->args; | |
@@ -2962,8 +2967,7 @@ static void blitz_exec_context(blitz_tpl *tpl, blitz_node *node, zval *parent_pa | |
php_printf("checking key %s in parent_params...\n", arg->name); | |
} | |
- check_key = zend_hash_find(Z_ARRVAL_P(parent_params), arg->name, arg->len + 1, (void**)&ctx_iterations); | |
- if (check_key == FAILURE) { | |
+ if (blitz_extract_var(tpl, arg->name, arg->len, (arg->type == BLITZ_ARG_TYPE_VAR_PATH), parent_params, &predefined, &ctx_iterations TSRMLS_CC) == 0) { | |
if (BLITZ_DEBUG) { | |
php_printf("failed to find key %s in parent params\n", arg->name); | |
} | |
@@ -3009,14 +3013,16 @@ static void blitz_exec_context(blitz_tpl *tpl, blitz_node *node, zval *parent_pa | |
} else if (HASH_KEY_IS_LONG == check_key) { | |
if (BLITZ_DEBUG) php_printf("KEY_CHECK: %d <long>\n", key_index); | |
BLITZ_LOOP_INIT(tpl, zend_hash_num_elements(Z_ARRVAL_PP(ctx_iterations))); | |
+ first_type = -1; | |
while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(ctx_iterations),(void**) &ctx_data, NULL) == SUCCESS) { | |
+ if (first_type == -1) first_type = Z_TYPE_PP(ctx_data); | |
if (BLITZ_DEBUG) { | |
php_printf("GO subnode, params:\n"); | |
php_var_dump(ctx_data,0 TSRMLS_CC); | |
} | |
/* mix of num/str errors: array(0=>array(), 'key' => 'val') */ | |
- if (IS_ARRAY != Z_TYPE_PP(ctx_data)) { | |
+ if (first_type != Z_TYPE_PP(ctx_data)) { | |
blitz_error(tpl TSRMLS_CC, E_WARNING, | |
"ERROR: You have a mix of numerical and non-numerical keys in the iteration set " | |
"(context: %s, line %lu, pos %lu), key was ignored", | |
@@ -3066,8 +3072,12 @@ static inline unsigned int blitz_extract_var ( | |
if (is_path) { | |
return blitz_fetch_var_by_path(z, name, len, params, tpl TSRMLS_CC); | |
} else { | |
- if (params && SUCCESS == zend_hash_find(Z_ARRVAL_P(params), name, len_p1, (void**)z)) { | |
- return 1; | |
+ if (params) { | |
+ if (IS_ARRAY == Z_TYPE_P(params) && SUCCESS == zend_hash_find(Z_ARRVAL_P(params), name, len_p1, (void**)z)) { | |
+ return 1; | |
+ } else if (IS_OBJECT == Z_TYPE_P(params) && SUCCESS == zend_hash_find(Z_OBJPROP_P(params), name, len_p1, (void**)z)) { | |
+ return 1; | |
+ } | |
} | |
if (tpl->hash_globals && (SUCCESS == zend_hash_find(tpl->hash_globals, name, len_p1, (void**)z))) { | |
@@ -3391,7 +3401,7 @@ static int blitz_exec_nodes(blitz_tpl *tpl, blitz_node *first_child, | |
/* check parent data (once in the beginning) - user could put non-array here. */ | |
/* if we use hash_find on non-array - we get segfaults. */ | |
- if (parent_ctx_data && Z_TYPE_P(parent_ctx_data) == IS_ARRAY) { | |
+ if (parent_ctx_data && (Z_TYPE_P(parent_ctx_data) == IS_ARRAY || Z_TYPE_P(parent_ctx_data) == IS_OBJECT)) { | |
parent_params = parent_ctx_data; | |
} | |
diff --git a/tests/loop.phpt b/tests/loop.phpt | |
new file mode 100644 | |
index 0000000..c03aeca | |
--- /dev/null | |
+++ b/tests/loop.phpt | |
@@ -0,0 +1,48 @@ | |
+--TEST-- | |
+looping over struct | |
+--FILE-- | |
+<?php | |
+ | |
+include('common.inc'); | |
+ini_set('blitz.remove_spaces_around_context_tags', 1); | |
+ | |
+$body = <<<BODY | |
+Hi, I'm {{ user.name }}, and my friends are: | |
+{{ BEGIN user.friends }} | |
+ {{ name }} | |
+{{ END }} | |
+BODY; | |
+ | |
+class User { | |
+ var $name; | |
+ var $friends; | |
+ | |
+ function __construct($name) { | |
+ $this->name = $name; | |
+ } | |
+} | |
+ | |
+$u = new User("Nicolas"); | |
+$u->friends = array(new User("Maurus"), new User("Thibaut")); | |
+ | |
+$T = new Blitz(); | |
+$T->load($body); | |
+$T->set(array('user' => $u)); | |
+var_dump($T->getStruct()); | |
+$T->display(); | |
+ | |
+?> | |
+--EXPECT-- | |
+array(4) { | |
+ [0]=> | |
+ string(10) "/user.name" | |
+ [1]=> | |
+ string(14) "/user.friends/" | |
+ [2]=> | |
+ string(18) "/user.friends/name" | |
+ [3]=> | |
+ string(17) "/user.friends/END" | |
+} | |
+Hi, I'm Nicolas, and my friends are: | |
+ Maurus | |
+ Thibaut | |
-- | |
1.8.5.2 (Apple Git-48)+GitX |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 3c7cf6c3debe757abe874da76131981442fb9c0a Mon Sep 17 00:00:00 2001 | |
From: Nicolas Van Eenaeme <nicolas@netlog.com> | |
Date: Wed, 21 May 2014 22:40:37 +0200 | |
Subject: [PATCH] Fix segfault with scope_lookup if the item is an object + | |
added test | |
--- | |
blitz.c | 3 ++- | |
tests/scope3.phpt | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ | |
2 files changed, 53 insertions(+), 1 deletion(-) | |
create mode 100644 tests/scope3.phpt | |
diff --git a/blitz.c b/blitz.c | |
index 3f684f7..011c708 100644 | |
--- a/blitz.c | |
+++ b/blitz.c | |
@@ -2297,7 +2297,8 @@ static inline int blitz_scope_stack_find(blitz_tpl *tpl, char *key, unsigned lon | |
while (i <= lookup_limit) { | |
data = tpl->scope_stack[tpl->scope_stack_pos - i - 1]; | |
- if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), key, key_len, (void **) zparam)) { | |
+ if ((IS_ARRAY == Z_TYPE_P(data) && SUCCESS == zend_hash_find(Z_ARRVAL_P(data), key, key_len, (void **) zparam)) || | |
+ (IS_OBJECT == Z_TYPE_P(data) && SUCCESS == zend_hash_find(Z_OBJPROP_P(data), key, key_len, (void **) zparam))) { | |
return i; | |
} | |
i++; | |
diff --git a/tests/scope3.phpt b/tests/scope3.phpt | |
new file mode 100644 | |
index 0000000..a48449c | |
--- /dev/null | |
+++ b/tests/scope3.phpt | |
@@ -0,0 +1,51 @@ | |
+--TEST-- | |
+scope lookup test #3 (with objects) | |
+--FILE-- | |
+<?php | |
+ | |
+$T = new Blitz(); | |
+ | |
+$body = <<<BODY | |
+{{ BEGIN items }} | |
+flat variable lookup: {{ \$upper }} | |
+{{ BEGIN inner }} | |
+1-level lookup: {{ \$upper }} | |
+method if with 1-level lookup: {{ if(\$upper, 'OK', 'FAILED') }} | |
+context if with 1-level lookup: {{ IF \$upper }}OK{{ ELSE }}FAILED{{ END }} | |
+{{ END inner }} | |
+{{ END items }} | |
+=================================================================== | |
+ | |
+BODY; | |
+ | |
+$T->load($body); | |
+ | |
+$item = new stdClass(); | |
+$item->upper = 'OK'; | |
+$item->inner = array( | |
+ 'value' => true | |
+); | |
+ | |
+$data = array( | |
+ 'items' => array( | |
+ $item | |
+ ) | |
+); | |
+ | |
+ini_set('blitz.scope_lookup_limit', 0); | |
+$T->display($data); | |
+ini_set('blitz.scope_lookup_limit', 1); | |
+$T->display($data); | |
+ | |
+?> | |
+--EXPECT-- | |
+flat variable lookup: OK | |
+1-level lookup: | |
+method if with 1-level lookup: FAILED | |
+context if with 1-level lookup: FAILED | |
+=================================================================== | |
+flat variable lookup: OK | |
+1-level lookup: OK | |
+method if with 1-level lookup: OK | |
+context if with 1-level lookup: OK | |
+=================================================================== | |
-- | |
1.8.5.2 (Apple Git-48)+GitX |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment