From 3485ee77ea0fb14aa485cf7adcba9b59abb6849c Mon Sep 17 00:00:00 2001 From: Charles Date: Thu, 20 Sep 2012 18:29:21 +0700 Subject: [PATCH] Native extension: handle dynamic properties defined in the get_properties handler in a per instance fashion. --- ext/twig/twig.c | 30 ++++++------------------------ test/Twig/Tests/NativeExtensionTest.php | 26 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 24 deletions(-) create mode 100644 test/Twig/Tests/NativeExtensionTest.php diff --git a/ext/twig/twig.c b/ext/twig/twig.c index f8fc859..f464faf 100644 --- a/ext/twig/twig.c +++ b/ext/twig/twig.c @@ -612,26 +612,6 @@ static int twig_add_property_to_class(void *pDest APPLY_TSRMLS_DC, int num_args, return 0; } -/* {{{ _adddynproperty */ -static int twig_add_dyn_property_to_class(void *pDest APPLY_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) -{ - APPLY_TSRMLS_FETCH(); - zend_class_entry *ce = *va_arg(args, zend_class_entry**); - zval *retval = va_arg(args, zval*), member; - char *class_name, *prop_name; - - if (hash_key->nKeyLength < 1 || hash_key->arKey[0] == '\0') { - return 0; /* non public cannot be dynamic */ - } - - ZVAL_STRINGL(&member, hash_key->arKey, hash_key->nKeyLength-1, 0); - if (zend_get_property_info(ce, &member, 1 TSRMLS_CC) == &EG(std_property_info)) { - zend_unmangle_property_name((&EG(std_property_info))->name, (&EG(std_property_info))->name_length, &class_name, &prop_name); - add_assoc_string(retval, prop_name, prop_name, 1); - } - return 0; -} - static void twig_add_class_to_cache(zval *cache, zval *object, char *class_name TSRMLS_DC) { zval *class_info, *class_methods, *class_properties; @@ -649,10 +629,6 @@ static void twig_add_class_to_cache(zval *cache, zval *object, char *class_name zend_hash_apply_with_arguments(&class_ce->function_table APPLY_TSRMLS_CC, twig_add_method_to_class, 1, class_methods); zend_hash_apply_with_arguments(&class_ce->properties_info APPLY_TSRMLS_CC, twig_add_property_to_class, 2, &class_ce, class_properties); - if (object && Z_OBJ_HT_P(object)->get_properties) { - HashTable *properties = Z_OBJ_HT_P(object)->get_properties(object TSRMLS_CC); - zend_hash_apply_with_arguments(properties APPLY_TSRMLS_CC, twig_add_dyn_property_to_class, 2, &class_ce, class_properties); - } add_assoc_zval(class_info, "methods", class_methods); add_assoc_zval(class_info, "properties", class_properties); add_assoc_zval(cache, class_name, class_info); @@ -853,6 +829,12 @@ PHP_FUNCTION(twig_template_get_attributes) efree(class_name); + // An object property can be dynamically created in the get_properties handler of the object, + // so if the property is not found and the object has a custom get_properties_handler, then call it first. + if (! tmp_item && ! TWIG_HAS_PROPERTY(object, &zitem TSRMLS_CC) && Z_OBJ_HT_P(object)->get_properties && Z_OBJ_HT_P(object)->get_properties != zend_std_get_properties) { + Z_OBJ_HT_P(object)->get_properties(object TSRMLS_CC); + } + if (tmp_item || TWIG_HAS_PROPERTY(object, &zitem TSRMLS_CC) || TWIG_ARRAY_KEY_EXISTS(object, item, item_len) // FIXME: Array key? is that array access here? ) { if (isDefinedTest) { diff --git a/test/Twig/Tests/NativeExtensionTest.php b/test/Twig/Tests/NativeExtensionTest.php new file mode 100644 index 0000000..936c127 --- /dev/null +++ b/test/Twig/Tests/NativeExtensionTest.php @@ -0,0 +1,26 @@ + true, + 'cache' => false, + 'autoescape' => array($this, 'escapingStrategyCallback'), + )); + + // If it fails, PHP will crash. + } +} -- 1.7.2.5