diff --git a/CHANGELOG b/CHANGELOG index fca793530dd..42d2ca8be21 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -256,11 +256,16 @@ - Phalcon\Security::checkHash() now correctly handles non-bcrypt hashes (#1912) - Phalcon\Session: - Fix Phalcon\Session\Bag::remove() (#1637) + - Add remove() to Phalcon\Session\BagInterface (#1917) - Phalcon\Session\Adapter::get() may optionally remove the data from session (#1358) - Phalcon\Session\Adapter optimizations (#1624) - Phalcon\Session\Adapter::__destruct() now calls session_write_close() (#1624) - Phalcon\Session\AdapterInterface is compatible with SessionHandlerInterface (#1108) - Phalcon\Session\Adapter now implements Phalcon\Session\AdapterInterface (#1852) + - Phalcon\Session\Bag::__get() now returns by reference (unlike get()) (#1895) + - Phalcon\Session\Bag implements ArrayAccess, Countable, IteratorAggregate interfaces (#1917) + - Phalcon\Session\Adapter implements ArrayAccess, Countable, IteratorAggregate interfaces (#1917) + - Optimized Phalcon\Session\Adapter using object handlers (#1917) - Phalcon\Tag: - Fixed bugs (#903) - Fixed radio button generation (#947) diff --git a/ext/config.c b/ext/config.c index 0717346a71e..4fdb99c0106 100644 --- a/ext/config.c +++ b/ext/config.c @@ -403,9 +403,7 @@ static zend_object_value phalcon_config_object_ctor(zend_class_entry* ce TSRMLS_ zend_object_value retval; zend_object_std_init(&obj->obj, ce TSRMLS_CC); -#if PHP_VERSION_ID >= 50400 object_properties_init(&obj->obj, ce); -#endif ALLOC_HASHTABLE(obj->props); zend_hash_init(obj->props, 0, NULL, ZVAL_PTR_DTOR, 0); diff --git a/ext/di.c b/ext/di.c index 6451fa3e811..c033b2caf07 100644 --- a/ext/di.c +++ b/ext/di.c @@ -417,9 +417,7 @@ static zend_object_value phalcon_di_ctor(zend_class_entry* ce TSRMLS_DC) zend_object_value retval; zend_object_std_init(&obj->obj, ce TSRMLS_CC); -#if PHP_VERSION_ID >= 50400 object_properties_init(&obj->obj, ce); -#endif ALLOC_HASHTABLE(obj->services); ALLOC_HASHTABLE(obj->shared); diff --git a/ext/internal/arginfo.h b/ext/internal/arginfo.h new file mode 100644 index 00000000000..fd18aebf34e --- /dev/null +++ b/ext/internal/arginfo.h @@ -0,0 +1,126 @@ +/* + +------------------------------------------------------------------------+ + | Phalcon Framework | + +------------------------------------------------------------------------+ + | Copyright (c) 2011-2014 Phalcon Team (http://www.phalconphp.com) | + +------------------------------------------------------------------------+ + | This source file is subject to the New BSD License that is bundled | + | with this package in the file docs/LICENSE.txt. | + | | + | If you did not receive a copy of the license and are unable to | + | obtain it through the world-wide-web, please send an email | + | to license@phalconphp.com so we can send you a copy immediately. | + +------------------------------------------------------------------------+ + | Authors: Andres Gutierrez | + | Eduar Carvajal | + | Vladimir Kolesnikov | + +------------------------------------------------------------------------+ +*/ + +#ifndef PHALCON_INTERNAL_ARGINFO_H +#define PHALCON_INTERNAL_ARGINFO_H + +#include +#include + + +ZEND_BEGIN_ARG_INFO_EX(arginfo_empty, 0, 0, 0) +ZEND_END_ARG_INFO() + + +/** @brief & __get($property) */ +ZEND_BEGIN_ARG_INFO_EX(arginfo___getref, 0, 1, 1) + ZEND_ARG_INFO(0, property) +ZEND_END_ARG_INFO() + +/** @brief __get($property) */ +ZEND_BEGIN_ARG_INFO_EX(arginfo___get, 0, 0, 1) + ZEND_ARG_INFO(0, property) +ZEND_END_ARG_INFO() + +/** @brief __set($property, $value) */ +ZEND_BEGIN_ARG_INFO_EX(arginfo___set, 0, 0, 2) + ZEND_ARG_INFO(0, property) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + +/** @brief __isset($property) */ +ZEND_BEGIN_ARG_INFO_EX(arginfo___isset, 0, 0, 1) + ZEND_ARG_INFO(0, property) +ZEND_END_ARG_INFO() + +/** @brief __unset($property) */ +ZEND_BEGIN_ARG_INFO_EX(arginfo___unset, 0, 0, 1) + ZEND_ARG_INFO(0, property) +ZEND_END_ARG_INFO() + + +/** @brief IteratorAggregate::getIterator() */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_iteratoraggregate_getiterator, 0, 0, 0) +ZEND_END_ARG_INFO() + + +/** @brief Countable::count() */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_countable_count, 0, 0, 0) +ZEND_END_ARG_INFO() + + +/** @brief ArrayAccess::offsetGet($property) */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offsetget, 0, 0, 1) + ZEND_ARG_INFO(0, property) +ZEND_END_ARG_INFO() + +#if PHP_VERSION_ID >= 50304 + +/** @brief & ArrayAccess::offsetGet($property) */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offsetgetref, 0, 1, 1) + ZEND_ARG_INFO(0, property) +ZEND_END_ARG_INFO() + +#else + +/** @brief ArrayAccess::offsetGet($property) */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offsetgetref, 0, 0, 1) + ZEND_ARG_INFO(0, property) +ZEND_END_ARG_INFO() + +#endif + +/** @brief ArrayAccess::offsetSet($property, $value) */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offsetset, 0, 0, 2) + ZEND_ARG_INFO(0, property) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + +/** @brief ArrayAccess::offsetExists($property) */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offsetexists, 0, 0, 1) + ZEND_ARG_INFO(0, property) +ZEND_END_ARG_INFO() + +/** @brief ArrayAccess::offsetUnset($property) */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_arrayaccess_offsetunset, 0, 0, 1) + ZEND_ARG_INFO(0, property) +ZEND_END_ARG_INFO() + + +/** @brief Iterator::current() */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_iterator_current, 0, 0, 0) +ZEND_END_ARG_INFO() + +/** @brief Iterator::key() */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_iterator_key, 0, 0, 0) +ZEND_END_ARG_INFO() + +/** @brief Iterator::next() */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_iterator_next, 0, 0, 0) +ZEND_END_ARG_INFO() + +/** @brief Iterator::rewind() */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_iterator_rewind, 0, 0, 0) +ZEND_END_ARG_INFO() + +/** @brief Iterator::valid() */ +ZEND_BEGIN_ARG_INFO_EX(arginfo_iterator_valid, 0, 0, 0) +ZEND_END_ARG_INFO() + +#endif /* PHALCON_INTERNAL_ARGINFO_H */ diff --git a/ext/kernel/hash.c b/ext/kernel/hash.c index 1988106568b..9a0e861484f 100644 --- a/ext/kernel/hash.c +++ b/ext/kernel/hash.c @@ -256,7 +256,7 @@ zval** phalcon_hash_get(HashTable *ht, zval *key, int type) case BP_VAR_W: { zval *value; ALLOC_INIT_ZVAL(value); - zend_hash_index_update(ht, index, (void**)&value, sizeof(void*), NULL); + zend_hash_index_update(ht, index, (void**)&value, sizeof(void*), (void**)&ret); break; } } @@ -284,7 +284,7 @@ zval** phalcon_hash_get(HashTable *ht, zval *key, int type) case BP_VAR_W: { zval *value; ALLOC_INIT_ZVAL(value); - zend_symtable_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key)+1, (void**)&value, sizeof(void*), NULL); + zend_symtable_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key)+1, (void**)&value, sizeof(void*), (void**)&ret); break; } } diff --git a/ext/kernel/object.c b/ext/kernel/object.c index c94f8627135..7816ba6b0cc 100644 --- a/ext/kernel/object.c +++ b/ext/kernel/object.c @@ -1010,10 +1010,10 @@ int phalcon_update_property_array(zval *object, char *property, unsigned int pro if (Z_TYPE_P(index) == IS_STRING) { zend_symtable_update(Z_ARRVAL_P(tmp), Z_STRVAL_P(index), Z_STRLEN_P(index) + 1, &value, sizeof(zval*), NULL); - } else { - if (Z_TYPE_P(index) == IS_LONG) { - zend_hash_index_update(Z_ARRVAL_P(tmp), Z_LVAL_P(index), &value, sizeof(zval *), NULL); - } + } else if (Z_TYPE_P(index) == IS_LONG) { + zend_hash_index_update(Z_ARRVAL_P(tmp), Z_LVAL_P(index), &value, sizeof(zval *), NULL); + } else if (Z_TYPE_P(index) == IS_NULL) { + zend_hash_next_index_insert(Z_ARRVAL_P(tmp), (void**)&value, sizeof(zval*), NULL); } if (separated) { @@ -1454,3 +1454,23 @@ int phalcon_property_decr(zval *object, char *property_name, unsigned int proper return SUCCESS; } + +#if PHP_VERSION_ID < 50400 + +void object_properties_init(zend_object *object, zend_class_entry *class_type) +{ + zval *tmp; + + if (UNEXPECTED(!object->properties)) { + ALLOC_HASHTABLE(object->properties); + zend_hash_init(object->properties, zend_hash_num_elements(&class_type->default_properties), NULL, ZVAL_PTR_DTOR, 0); + } + +#if PHP_VERSION_ID < 50304 + zend_hash_copy(object->properties, &class_type->default_properties, (copy_ctor_func_t)zval_add_ref, (void*)&tmp, sizeof(zval*)); +#else + zend_hash_copy(object->properties, &class_type->default_properties, zval_copy_property_ctor(class_type), (void*)&tmp, sizeof(zval*)); +#endif +} + +#endif diff --git a/ext/kernel/object.h b/ext/kernel/object.h index 3a4f0d5c815..7f5337088c6 100644 --- a/ext/kernel/object.h +++ b/ext/kernel/object.h @@ -17,6 +17,9 @@ +------------------------------------------------------------------------+ */ +#ifndef PHALCON_KERNEL_OBJECT_H +#define PHALCON_KERNEL_OBJECT_H + /** Class Retrieving/Checking */ int phalcon_class_exists(const zval *class_name, int autoload TSRMLS_DC); int phalcon_class_exists_ex(zend_class_entry **zce, const zval *class_name, int autoload TSRMLS_DC); @@ -102,3 +105,8 @@ int phalcon_create_instance_params_ce(zval *return_value, zend_class_entry *ce, int phalcon_create_instance(zval *return_value, const zval *class_name TSRMLS_DC); int phalcon_create_instance_params(zval *return_value, const zval *class_name, zval *params TSRMLS_DC); +#if PHP_VERSION_ID < 50400 +void object_properties_init(zend_object *object, zend_class_entry *class_type); +#endif + +#endif /* PHALCON_KERNEL_OBJECT_H */ diff --git a/ext/mvc/model/row.c b/ext/mvc/model/row.c index 35c3f02a2a8..6b4770968db 100644 --- a/ext/mvc/model/row.c +++ b/ext/mvc/model/row.c @@ -240,9 +240,7 @@ static zend_object_value phalcon_mvc_model_row_object_ctor(zend_class_entry* ce zend_object_value retval; zend_object_std_init(&obj->obj, ce TSRMLS_CC); -#if PHP_VERSION_ID >= 50400 object_properties_init(&obj->obj, ce); -#endif ALLOC_HASHTABLE(obj->props); zend_hash_init(obj->props, 0, NULL, ZVAL_PTR_DTOR, 0); diff --git a/ext/session/adapter.c b/ext/session/adapter.c index ce9ed3faaa7..a941f95a2f4 100644 --- a/ext/session/adapter.c +++ b/ext/session/adapter.c @@ -19,12 +19,13 @@ #include "session/adapter.h" #include "session/adapterinterface.h" +#include "internal/arginfo.h" #include
+#include #include "kernel/main.h" #include "kernel/memory.h" - #include "kernel/fcall.h" #include "kernel/operators.h" #include "kernel/object.h" @@ -32,6 +33,7 @@ #include "kernel/array.h" #include "kernel/concat.h" #include "kernel/session.h" +#include "kernel/hash.h" /** * Phalcon\Session\Adapter @@ -40,6 +42,8 @@ */ zend_class_entry *phalcon_session_adapter_ce; +static zend_object_handlers phalcon_session_adapter_object_handlers; + PHP_METHOD(Phalcon_Session_Adapter, __construct); PHP_METHOD(Phalcon_Session_Adapter, __destruct); PHP_METHOD(Phalcon_Session_Adapter, start); @@ -52,23 +56,327 @@ PHP_METHOD(Phalcon_Session_Adapter, remove); PHP_METHOD(Phalcon_Session_Adapter, getId); PHP_METHOD(Phalcon_Session_Adapter, isStarted); PHP_METHOD(Phalcon_Session_Adapter, destroy); +PHP_METHOD(Phalcon_Session_Adapter, __get); +PHP_METHOD(Phalcon_Session_Adapter, count); +PHP_METHOD(Phalcon_Session_Adapter, getIterator); static const zend_function_entry phalcon_session_adapter_method_entry[] = { PHP_ME(Phalcon_Session_Adapter, __construct, arginfo_phalcon_session_adapterinterface___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) - PHP_ME(Phalcon_Session_Adapter, __destruct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_DTOR) - PHP_ME(Phalcon_Session_Adapter, start, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Session_Adapter, __destruct, arginfo_empty, ZEND_ACC_PUBLIC | ZEND_ACC_DTOR) + PHP_ME(Phalcon_Session_Adapter, start, arginfo_empty, ZEND_ACC_PUBLIC) PHP_ME(Phalcon_Session_Adapter, setOptions, arginfo_phalcon_session_adapterinterface_setoptions, ZEND_ACC_PUBLIC) - PHP_ME(Phalcon_Session_Adapter, getOptions, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Session_Adapter, getOptions, arginfo_empty, ZEND_ACC_PUBLIC) PHP_ME(Phalcon_Session_Adapter, get, arginfo_phalcon_session_adapterinterface_get, ZEND_ACC_PUBLIC) PHP_ME(Phalcon_Session_Adapter, set, arginfo_phalcon_session_adapterinterface_set, ZEND_ACC_PUBLIC) PHP_ME(Phalcon_Session_Adapter, has, arginfo_phalcon_session_adapterinterface_has, ZEND_ACC_PUBLIC) PHP_ME(Phalcon_Session_Adapter, remove, arginfo_phalcon_session_adapterinterface_remove, ZEND_ACC_PUBLIC) - PHP_ME(Phalcon_Session_Adapter, getId, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Phalcon_Session_Adapter, isStarted, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Session_Adapter, getId, arginfo_empty, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Session_Adapter, isStarted, arginfo_empty, ZEND_ACC_PUBLIC) PHP_ME(Phalcon_Session_Adapter, destroy, arginfo_phalcon_session_adapterinterface_destroy, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Session_Adapter, __get, arginfo___getref, ZEND_ACC_PUBLIC) + PHP_MALIAS(Phalcon_Session_Adapter, __set, set, arginfo___set, ZEND_ACC_PUBLIC) + PHP_MALIAS(Phalcon_Session_Adapter, __isset, has, arginfo___isset, ZEND_ACC_PUBLIC) + PHP_MALIAS(Phalcon_Session_Adapter, __unset, remove, arginfo___unset, ZEND_ACC_PUBLIC) + PHP_MALIAS(Phalcon_Session_Adapter, offsetGet, __get, arginfo_arrayaccess_offsetgetref, ZEND_ACC_PUBLIC) + PHP_MALIAS(Phalcon_Session_Adapter, offsetSet, set, arginfo_arrayaccess_offsetset, ZEND_ACC_PUBLIC) + PHP_MALIAS(Phalcon_Session_Adapter, offsetExists, has, arginfo_arrayaccess_offsetexists, ZEND_ACC_PUBLIC) + PHP_MALIAS(Phalcon_Session_Adapter, offsetUnset, remove, arginfo_arrayaccess_offsetunset, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Session_Adapter, count, arginfo_countable_count, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Session_Adapter, getIterator, arginfo_iteratoraggregate_getiterator, ZEND_ACC_PUBLIC) PHP_FE_END }; +static zval** phalcon_session_adapter_get_property_ptr_ptr_internal(zval *object, zval *member, int type TSRMLS_DC) +{ + zval *unique_id, *_SESSION, key = zval_used_for_init, *pkey = &key; + zval **value; + + unique_id = phalcon_fetch_nproperty_this(object, SL("_uniqueId"), PH_NOISY TSRMLS_CC); + + _SESSION = phalcon_get_global(SS("_SESSION") TSRMLS_CC); + if (Z_TYPE_P(_SESSION) != IS_ARRAY) { + if (type == BP_VAR_R || type == BP_VAR_RW) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Session is not started or $_SESSION is invalid"); + } + + return (type == BP_VAR_W || type == BP_VAR_RW) ? &EG(error_zval_ptr) : &EG(uninitialized_zval_ptr); + } + + phalcon_concat_vv(&pkey, unique_id, member, 0 TSRMLS_CC); + value = phalcon_hash_get(Z_ARRVAL_P(_SESSION), pkey, type); + zval_dtor(&key); + + return value; +} + +static int phalcon_session_adapter_has_property_internal(zval *object, zval *member, int has_set_exists TSRMLS_DC) +{ + zval *unique_id, *_SESSION, **tmp; + zval key = zval_used_for_init, *pkey = &key; + + unique_id = phalcon_fetch_nproperty_this(object, SL("_uniqueId"), PH_NOISY TSRMLS_CC); + + _SESSION = phalcon_get_global(SS("_SESSION") TSRMLS_CC); + if (Z_TYPE_P(_SESSION) != IS_ARRAY) { + return 0; + } + + phalcon_concat_vv(&pkey, unique_id, member, 0 TSRMLS_CC); + tmp = phalcon_hash_get(Z_ARRVAL_P(_SESSION), pkey, BP_VAR_NA); + zval_dtor(&key); + + if (!tmp) { + return 0; + } + + if (0 == has_set_exists) { + return Z_TYPE_PP(tmp) != IS_NULL; + } + + if (1 == has_set_exists) { + return zend_is_true(*tmp); + } + + return 1; +} + +static void phalcon_session_adapter_write_property_internal(zval *object, zval *member, zval *value TSRMLS_DC) +{ + zval *unique_id, *_SESSION; + zval key = zval_used_for_init, *pkey = &key; + + unique_id = phalcon_fetch_nproperty_this(object, SL("_uniqueId"), PH_NOISY TSRMLS_CC); + + _SESSION = phalcon_get_global(SS("_SESSION") TSRMLS_CC); + if (Z_TYPE_P(_SESSION) == IS_ARRAY) { + phalcon_concat_vv(&pkey, unique_id, member, 0 TSRMLS_CC); + Z_ADDREF_P(value); + phalcon_hash_update_or_insert(Z_ARRVAL_P(_SESSION), pkey, value); + zval_dtor(&key); + } +} + +static void phalcon_session_adapter_unset_property_internal(zval *object, zval *member TSRMLS_DC) +{ + zval *unique_id, *_SESSION; + zval key = zval_used_for_init, *pkey = &key; + + unique_id = phalcon_fetch_nproperty_this(object, SL("_uniqueId"), PH_NOISY TSRMLS_CC); + + _SESSION = phalcon_get_global(SS("_SESSION") TSRMLS_CC); + if (Z_TYPE_P(_SESSION) == IS_ARRAY) { + phalcon_concat_vv(&pkey, unique_id, member, 0 TSRMLS_CC); + phalcon_hash_unset(Z_ARRVAL_P(_SESSION), pkey); + zval_dtor(&key); + } +} + +#if PHP_VERSION_ID < 50500 + +static zval** phalcon_session_adapter_get_property_ptr_ptr(zval *object, zval *member ZLK_DC TSRMLS_DC) +{ + if (!is_phalcon_class(Z_OBJCE_P(object))) { + return zend_get_std_object_handlers()->get_property_ptr_ptr(object, member ZLK_CC TSRMLS_CC); + } + + return phalcon_session_adapter_get_property_ptr_ptr_internal(object, member, BP_VAR_W TSRMLS_CC); +} + +#else + +static zval** phalcon_session_adapter_get_property_ptr_ptr(zval *object, zval *member, int type ZLK_DC TSRMLS_DC) +{ + if (!is_phalcon_class(Z_OBJCE_P(object))) { + return zend_get_std_object_handlers()->get_property_ptr_ptr(object, member, type ZLK_CC TSRMLS_CC); + } + + return phalcon_session_adapter_get_property_ptr_ptr_internal(object, member, type TSRMLS_CC); +} + +#endif + +static int phalcon_session_adapter_has_property(zval *object, zval *member, int has_set_exists ZLK_DC TSRMLS_DC) +{ + if (!is_phalcon_class(Z_OBJCE_P(object))) { + return zend_get_std_object_handlers()->has_property(object, member, has_set_exists ZLK_CC TSRMLS_CC); + } + + return phalcon_session_adapter_has_property_internal(object, member, has_set_exists TSRMLS_CC); +} + +static void phalcon_session_adapter_write_property(zval *object, zval *member, zval *value ZLK_DC TSRMLS_DC) +{ + if (!is_phalcon_class(Z_OBJCE_P(object))) { + zend_get_std_object_handlers()->write_property(object, member, value ZLK_CC TSRMLS_CC); + } + else { + phalcon_session_adapter_write_property_internal(object, member, value TSRMLS_CC); + } +} + +static void phalcon_session_adapter_unset_property(zval *object, zval *member ZLK_DC TSRMLS_DC) +{ + if (!is_phalcon_class(Z_OBJCE_P(object))) { + zend_get_std_object_handlers()->unset_property(object, member ZLK_CC TSRMLS_CC); + } + else { + phalcon_session_adapter_unset_property_internal(object, member TSRMLS_CC); + } +} + +static zval* phalcon_session_adapter_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) +{ + zval **ret; + + if (!is_phalcon_class(Z_OBJCE_P(object))) { + return zend_get_std_object_handlers()->read_dimension(object, offset, type TSRMLS_CC); + } + + if (UNEXPECTED(!offset)) { + return EG(uninitialized_zval_ptr); + } + + ret = phalcon_session_adapter_get_property_ptr_ptr_internal(object, offset, type TSRMLS_CC); + + /* For write context we need to return a reference */ + if ((type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) && !Z_ISREF_PP(ret)) { + if ((type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) && !Z_ISREF_PP(ret)) { + zval *newval; + + MAKE_STD_ZVAL(newval); + *newval = **ret; + zval_copy_ctor(newval); + Z_SET_REFCOUNT_P(newval, 1); + + Z_DELREF_PP(ret); + *ret = newval; + } + + Z_SET_ISREF_PP(ret); + } + + return *ret; +} + +static void phalcon_session_adapter_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC) +{ + if (!is_phalcon_class(Z_OBJCE_P(object))) { + zend_get_std_object_handlers()->write_dimension(object, offset, value TSRMLS_CC); + return; + } + + if (!offset) { + offset = PHALCON_GLOBAL(z_null); + } + + phalcon_session_adapter_write_property_internal(object, offset, value TSRMLS_CC); +} + +static int phalcon_session_adapter_has_dimension(zval *object, zval *member, int check_empty TSRMLS_DC) +{ + zval **tmp; + + if (!is_phalcon_class(Z_OBJCE_P(object))) { + return zend_get_std_object_handlers()->has_dimension(object, member, check_empty TSRMLS_CC); + } + + tmp = phalcon_session_adapter_get_property_ptr_ptr_internal(object, member, BP_VAR_NA TSRMLS_CC); + + if (!tmp) { + return 0; + } + + if (0 == check_empty) { + return Z_TYPE_PP(tmp) != IS_NULL; + } + + if (1 == check_empty) { + return zend_is_true(*tmp); + } + + return 1; +} + +static void phalcon_session_adapter_unset_dimension(zval *object, zval *offset TSRMLS_DC) +{ + if (!is_phalcon_class(Z_OBJCE_P(object))) { + return zend_get_std_object_handlers()->unset_dimension(object, offset TSRMLS_CC); + } + + phalcon_session_adapter_unset_property_internal(object, offset TSRMLS_CC); +} + +static int phalcon_session_adapter_count_elements(zval *object, long *count TSRMLS_DC) +{ + int res; + zval *cnt = NULL; + + if (is_phalcon_class(Z_OBJCE_P(object))) { + zval *_SESSION = phalcon_get_global(SS("_SESSION") TSRMLS_CC); + if (Z_TYPE_P(_SESSION) == IS_ARRAY) { + *count = zend_hash_num_elements(Z_ARRVAL_P(_SESSION)); + return SUCCESS; + } + + return FAILURE; + } + + res = phalcon_call_method_params(cnt, &cnt, object, SL("count"), zend_inline_hash_func(SS("count")) TSRMLS_CC, 0); + if (res == SUCCESS) { + *count = (Z_TYPE_P(cnt) == IS_LONG) ? Z_LVAL_P(cnt) : phalcon_get_intval(cnt); + zval_ptr_dtor(&cnt); + } + + return res; +} + +static zend_object_value phalcon_session_adapter_object_ctor(zend_class_entry *ce TSRMLS_DC) +{ + zend_object *obj = emalloc(sizeof(zend_object)); + zend_object_value retval; + + zend_object_std_init(obj, ce TSRMLS_CC); + object_properties_init(obj, ce); + + retval.handlers = &phalcon_session_adapter_object_handlers; + retval.handle = zend_objects_store_put( + obj, + (zend_objects_store_dtor_t)zend_objects_destroy_object, + (zend_objects_free_object_storage_t)zend_objects_free_object_storage, + NULL + TSRMLS_CC + ); + + return retval; +} + +static zend_object_iterator* phalcon_session_adapter_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) +{ + zval *iterator; + zval *data; + zend_object_iterator *ret; + + data = phalcon_get_global(SS("_SESSION") TSRMLS_CC); + if (Z_TYPE_P(data) != IS_ARRAY) { + return NULL; + } + + MAKE_STD_ZVAL(iterator); + object_init_ex(iterator, spl_ce_ArrayIterator); + if (FAILURE == phalcon_call_method_params(NULL, NULL, iterator, SL("__construct"), zend_inline_hash_func(SS("__construct")) TSRMLS_CC, 1, data)) { + ret = NULL; + } + else if (Z_TYPE_P(iterator) == IS_OBJECT) { + ret = spl_ce_ArrayIterator->get_iterator(spl_ce_ArrayIterator, iterator, by_ref TSRMLS_CC); + } + else { + ret = NULL; + } + + zval_ptr_dtor(&iterator); + return ret; +} + /** * Phalcon\Session\Adapter initializer */ @@ -76,11 +384,32 @@ PHALCON_INIT_CLASS(Phalcon_Session_Adapter){ PHALCON_REGISTER_CLASS(Phalcon\\Session, Adapter, session_adapter, phalcon_session_adapter_method_entry, ZEND_ACC_EXPLICIT_ABSTRACT_CLASS); + phalcon_session_adapter_ce->create_object = phalcon_session_adapter_object_ctor; + zend_declare_property_null(phalcon_session_adapter_ce, SL("_uniqueId"), ZEND_ACC_PROTECTED TSRMLS_CC); zend_declare_property_bool(phalcon_session_adapter_ce, SL("_started"), 0, ZEND_ACC_PROTECTED TSRMLS_CC); zend_declare_property_null(phalcon_session_adapter_ce, SL("_options"), ZEND_ACC_PROTECTED TSRMLS_CC); - zend_class_implements(phalcon_session_adapter_ce TSRMLS_CC, 1, phalcon_session_adapterinterface_ce); + phalcon_session_adapter_object_handlers = *zend_get_std_object_handlers(); + phalcon_session_adapter_object_handlers.get_property_ptr_ptr = phalcon_session_adapter_get_property_ptr_ptr; + phalcon_session_adapter_object_handlers.has_property = phalcon_session_adapter_has_property; + phalcon_session_adapter_object_handlers.write_property = phalcon_session_adapter_write_property; + phalcon_session_adapter_object_handlers.unset_property = phalcon_session_adapter_unset_property; + phalcon_session_adapter_object_handlers.count_elements = phalcon_session_adapter_count_elements; + phalcon_session_adapter_object_handlers.read_dimension = phalcon_session_adapter_read_dimension; + phalcon_session_adapter_object_handlers.write_dimension = phalcon_session_adapter_write_dimension; + phalcon_session_adapter_object_handlers.has_dimension = phalcon_session_adapter_has_dimension; + phalcon_session_adapter_object_handlers.unset_dimension = phalcon_session_adapter_unset_dimension; + + phalcon_session_adapter_ce->get_iterator = phalcon_session_adapter_get_iterator; + + zend_class_implements( + phalcon_session_adapter_ce TSRMLS_CC, 4, + phalcon_session_adapterinterface_ce, + spl_ce_Countable, + zend_ce_aggregate, + zend_ce_arrayaccess + ); return SUCCESS; } @@ -181,39 +510,37 @@ PHP_METHOD(Phalcon_Session_Adapter, get){ zval *index, *default_value = NULL, *remove = NULL, *unique_id, *key, *_SESSION; zval *value; - PHALCON_MM_GROW(); - phalcon_fetch_params(1, 1, 2, &index, &default_value, &remove); + phalcon_fetch_params(0, 1, 2, &index, &default_value, &remove); if (!default_value) { default_value = PHALCON_GLOBAL(z_null); } - if (!remove) { - remove = PHALCON_GLOBAL(z_false); + if (!remove || !zend_is_true(remove)) { + /* Fast path */ + zval **value = phalcon_session_adapter_get_property_ptr_ptr_internal(getThis(), index, BP_VAR_NA TSRMLS_CC); + if (value) { + RETURN_ZVAL(*value, 1, 0); + } + + RETURN_ZVAL(default_value, 1, 0); } unique_id = phalcon_fetch_nproperty_this(this_ptr, SL("_uniqueId"), PH_NOISY_CC); + PHALCON_MM_GROW(); PHALCON_INIT_VAR(key); PHALCON_CONCAT_VV(key, unique_id, index); _SESSION = phalcon_get_global(SS("_SESSION") TSRMLS_CC); if (phalcon_array_isset_fetch(&value, _SESSION, key)) { - if (PHALCON_IS_NOT_EMPTY(value)) { - RETVAL_ZVAL(value, 1, 0); - } - else { - RETVAL_ZVAL(default_value, 1, 0); - } - - if (zend_is_true(remove)) { - phalcon_array_unset(&_SESSION, key, 0); - } - - PHALCON_MM_RESTORE(); - return; + RETVAL_ZVAL(value, 1, 0); + phalcon_array_unset(&_SESSION, key, 0); + } + else { + RETVAL_ZVAL(default_value, 1, 0); } - RETURN_CTOR(default_value); + PHALCON_MM_RESTORE(); } /** @@ -228,20 +555,10 @@ PHP_METHOD(Phalcon_Session_Adapter, get){ */ PHP_METHOD(Phalcon_Session_Adapter, set){ - zval *index, *value, *unique_id, *key, *_SESSION; - - PHALCON_MM_GROW(); + zval *index, *value; - phalcon_fetch_params(1, 2, 0, &index, &value); - - unique_id = phalcon_fetch_nproperty_this(this_ptr, SL("_uniqueId"), PH_NOISY_CC); - - PHALCON_INIT_VAR(key); - PHALCON_CONCAT_VV(key, unique_id, index); - _SESSION = phalcon_get_global(SS("_SESSION") TSRMLS_CC); - phalcon_array_update_zval(&_SESSION, key, &value, PH_COPY); - - PHALCON_MM_RESTORE(); + phalcon_fetch_params(0, 2, 0, &index, &value); + phalcon_session_adapter_write_property_internal(getThis(), index, value TSRMLS_CC); } /** @@ -256,19 +573,10 @@ PHP_METHOD(Phalcon_Session_Adapter, set){ */ PHP_METHOD(Phalcon_Session_Adapter, has){ - zval *index, *unique_id, *key, *_SESSION; - - PHALCON_MM_GROW(); + zval *index; - phalcon_fetch_params(1, 1, 0, &index); - - unique_id = phalcon_fetch_nproperty_this(this_ptr, SL("_uniqueId"), PH_NOISY_CC); - - PHALCON_INIT_VAR(key); - PHALCON_CONCAT_VV(key, unique_id, index); - _SESSION = phalcon_get_global(SS("_SESSION") TSRMLS_CC); - RETVAL_BOOL(phalcon_array_isset(_SESSION, key)); - PHALCON_MM_RESTORE(); + phalcon_fetch_params(0, 1, 0, &index); + RETURN_BOOL(phalcon_session_adapter_has_property_internal(getThis(), index, 2 TSRMLS_CC)); } /** @@ -282,20 +590,10 @@ PHP_METHOD(Phalcon_Session_Adapter, has){ */ PHP_METHOD(Phalcon_Session_Adapter, remove){ - zval *index, *unique_id, *key, *_SESSION; - - PHALCON_MM_GROW(); + zval *index; - phalcon_fetch_params(1, 1, 0, &index); - - unique_id = phalcon_fetch_nproperty_this(this_ptr, SL("_uniqueId"), PH_NOISY_CC); - - PHALCON_INIT_VAR(key); - PHALCON_CONCAT_VV(key, unique_id, index); - _SESSION = phalcon_get_global(SS("_SESSION") TSRMLS_CC); - phalcon_array_unset(&_SESSION, key, 0); - - PHALCON_MM_RESTORE(); + phalcon_fetch_params(0, 1, 0, &index); + phalcon_session_adapter_unset_property_internal(getThis(), index TSRMLS_CC); } /** @@ -342,3 +640,38 @@ PHP_METHOD(Phalcon_Session_Adapter, destroy){ RETURN_ON_FAILURE(phalcon_session_destroy(TSRMLS_C)); RETURN_TRUE; } + +PHP_METHOD(Phalcon_Session_Adapter, __get) +{ + zval **property, **retval; + + assert(return_value_ptr != NULL); + + phalcon_fetch_params_ex(1, 0, &property); + retval = phalcon_session_adapter_get_property_ptr_ptr_internal(getThis(), *property, BP_VAR_W TSRMLS_CC); + + zval_ptr_dtor(return_value_ptr); + *return_value_ptr = *retval; + Z_ADDREF_PP(return_value_ptr); + Z_SET_ISREF_PP(return_value_ptr); +} + +PHP_METHOD(Phalcon_Session_Adapter, count) +{ + long int count; + + if (SUCCESS == phalcon_session_adapter_count_elements(getThis(), &count TSRMLS_CC)) { + RETURN_LONG(count); + } + + RETURN_NULL(); +} + +PHP_METHOD(Phalcon_Session_Adapter, getIterator) +{ + zval *data; + + data = phalcon_get_global(SS("_SESSION") TSRMLS_CC); + object_init_ex(return_value, spl_ce_ArrayIterator); + RETURN_ON_FAILURE(phalcon_call_method_params(NULL, NULL, return_value, SL("__construct"), zend_inline_hash_func(SS("__construct")) TSRMLS_CC, 1, data)); +} diff --git a/ext/session/bag.c b/ext/session/bag.c index eff76da1d11..73a9d7abb1b 100644 --- a/ext/session/bag.c +++ b/ext/session/bag.c @@ -24,6 +24,9 @@ #include "di/injectionawareinterface.h" #include "di.h" #include "diinterface.h" +#include "internal/arginfo.h" + +#include #include "kernel/main.h" #include "kernel/memory.h" @@ -57,37 +60,78 @@ PHP_METHOD(Phalcon_Session_Bag, destroy); PHP_METHOD(Phalcon_Session_Bag, set); PHP_METHOD(Phalcon_Session_Bag, get); PHP_METHOD(Phalcon_Session_Bag, has); +PHP_METHOD(Phalcon_Session_Bag, __get); PHP_METHOD(Phalcon_Session_Bag, remove); +PHP_METHOD(Phalcon_Session_Bag, getIterator); +PHP_METHOD(Phalcon_Session_Bag, count); ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_session_bag___construct, 0, 0, 1) ZEND_ARG_INFO(0, name) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_session_bag___get, 0, 0, 1) - ZEND_ARG_INFO(0, property) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_session_bag_remove, 0, 0, 1) - ZEND_ARG_INFO(0, property) -ZEND_END_ARG_INFO() - static const zend_function_entry phalcon_session_bag_method_entry[] = { PHP_ME(Phalcon_Session_Bag, __construct, arginfo_phalcon_session_bag___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(Phalcon_Session_Bag, setDI, arginfo_phalcon_di_injectionawareinterface_setdi, ZEND_ACC_PUBLIC) PHP_ME(Phalcon_Session_Bag, getDI, arginfo_phalcon_di_injectionawareinterface_getdi, ZEND_ACC_PUBLIC) - PHP_ME(Phalcon_Session_Bag, initialize, NULL, ZEND_ACC_PUBLIC) - PHP_ME(Phalcon_Session_Bag, destroy, NULL, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Session_Bag, initialize, arginfo_empty, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Session_Bag, destroy, arginfo_empty, ZEND_ACC_PUBLIC) PHP_ME(Phalcon_Session_Bag, set, arginfo_phalcon_session_baginterface_set, ZEND_ACC_PUBLIC) - PHP_MALIAS(Phalcon_Session_Bag, __set, set, arginfo_phalcon_session_baginterface_set, ZEND_ACC_PUBLIC) PHP_ME(Phalcon_Session_Bag, get, arginfo_phalcon_session_baginterface_get, ZEND_ACC_PUBLIC) - PHP_MALIAS(Phalcon_Session_Bag, __get, get, arginfo_phalcon_session_bag___get, ZEND_ACC_PUBLIC) PHP_ME(Phalcon_Session_Bag, has, arginfo_phalcon_session_baginterface_has, ZEND_ACC_PUBLIC) - PHP_MALIAS(Phalcon_Session_Bag, __isset, has, arginfo_phalcon_session_baginterface_has, ZEND_ACC_PUBLIC) - PHP_ME(Phalcon_Session_Bag, remove, arginfo_phalcon_session_bag_remove, ZEND_ACC_PUBLIC) - PHP_MALIAS(Phalcon_Session_Bag, __unset, remove, arginfo_phalcon_session_bag_remove, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Session_Bag, remove, arginfo_phalcon_session_baginterface_remove, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Session_Bag, getIterator, arginfo_iteratoraggregate_getiterator, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Session_Bag, __get, arginfo___getref, ZEND_ACC_PUBLIC) + PHP_MALIAS(Phalcon_Session_Bag, __set, set, arginfo___set, ZEND_ACC_PUBLIC) + PHP_MALIAS(Phalcon_Session_Bag, __isset, has, arginfo___isset, ZEND_ACC_PUBLIC) + PHP_MALIAS(Phalcon_Session_Bag, __unset, remove, arginfo___unset, ZEND_ACC_PUBLIC) + PHP_MALIAS(Phalcon_Session_Bag, offsetGet, __get, arginfo_arrayaccess_offsetgetref, ZEND_ACC_PUBLIC) + PHP_MALIAS(Phalcon_Session_Bag, offsetSet, set, arginfo_arrayaccess_offsetset, ZEND_ACC_PUBLIC) + PHP_MALIAS(Phalcon_Session_Bag, offsetExists, has, arginfo_arrayaccess_offsetexists, ZEND_ACC_PUBLIC) + PHP_MALIAS(Phalcon_Session_Bag, offsetUnset, remove, arginfo_arrayaccess_offsetunset, ZEND_ACC_PUBLIC) + PHP_ME(Phalcon_Session_Bag, count, arginfo_countable_count, ZEND_ACC_PUBLIC) PHP_FE_END }; +static int phalcon_session_bag_maybe_initialize(zval *this_ptr TSRMLS_DC) +{ + zval *initialized; + + initialized = phalcon_fetch_nproperty_this(this_ptr, SL("_initialized"), PH_NOISY TSRMLS_CC); + if (PHALCON_IS_FALSE(initialized)) { + return phalcon_call_method_params(NULL, NULL, this_ptr, SL("initialize"), zend_inline_hash_func(SS("initialize")) TSRMLS_CC, 0); + } + + return SUCCESS; +} + +static zend_object_iterator* phalcon_session_bag_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) +{ + zval *iterator; + zval *data; + zend_object_iterator *ret; + + if (FAILURE == phalcon_session_bag_maybe_initialize(object TSRMLS_CC)) { + return NULL; + } + + data = phalcon_fetch_nproperty_this(object, SL("_data"), PH_NOISY TSRMLS_CC); + + MAKE_STD_ZVAL(iterator); + object_init_ex(iterator, spl_ce_ArrayIterator); + if (FAILURE == phalcon_call_method_params(NULL, NULL, iterator, SL("__construct"), zend_inline_hash_func(SS("__construct")) TSRMLS_CC, 1, data)) { + ret = NULL; + } + else if (Z_TYPE_P(iterator) == IS_OBJECT) { + ret = spl_ce_ArrayIterator->get_iterator(spl_ce_ArrayIterator, iterator, by_ref TSRMLS_CC); + } + else { + ret = NULL; + } + + zval_ptr_dtor(&iterator); + return ret; +} + /** * Phalcon\Session\Bag initializer */ @@ -101,7 +145,16 @@ PHALCON_INIT_CLASS(Phalcon_Session_Bag){ zend_declare_property_bool(phalcon_session_bag_ce, SL("_initialized"), 0, ZEND_ACC_PROTECTED TSRMLS_CC); zend_declare_property_null(phalcon_session_bag_ce, SL("_session"), ZEND_ACC_PROTECTED TSRMLS_CC); - zend_class_implements(phalcon_session_bag_ce TSRMLS_CC, 2, phalcon_di_injectionawareinterface_ce, phalcon_session_baginterface_ce); + phalcon_session_bag_ce->get_iterator = phalcon_session_bag_get_iterator; + + zend_class_implements( + phalcon_session_bag_ce TSRMLS_CC, 5, + phalcon_di_injectionawareinterface_ce, + phalcon_session_baginterface_ce, + zend_ce_aggregate, + zend_ce_arrayaccess, + spl_ce_Countable + ); return SUCCESS; } @@ -151,16 +204,15 @@ PHP_METHOD(Phalcon_Session_Bag, getDI){ PHP_METHOD(Phalcon_Session_Bag, initialize){ zval *session = NULL, *dependency_injector = NULL, *service; - zval *name, *data = NULL; + zval *name, **data; PHALCON_MM_GROW(); - PHALCON_OBS_VAR(session); - phalcon_read_property_this(&session, this_ptr, SL("_session"), PH_NOISY_CC); + session = phalcon_fetch_nproperty_this(this_ptr, SL("_session"), PH_NOISY TSRMLS_CC); if (Z_TYPE_P(session) != IS_OBJECT) { PHALCON_OBS_VAR(dependency_injector); - phalcon_read_property_this(&dependency_injector, this_ptr, SL("_dependencyInjector"), PH_NOISY_CC); + phalcon_read_property_this(&dependency_injector, this_ptr, SL("_dependencyInjector"), PH_NOISY TSRMLS_CC); if (Z_TYPE_P(dependency_injector) != IS_OBJECT) { PHALCON_OBSERVE_OR_NULLIFY_VAR(dependency_injector); @@ -175,30 +227,36 @@ PHP_METHOD(Phalcon_Session_Bag, initialize){ PHALCON_INIT_VAR(service); PHALCON_ZVAL_MAYBE_INTERNED_STRING(service, phalcon_interned_session); - PHALCON_INIT_NVAR(session); + PHALCON_INIT_VAR(session); phalcon_call_method_p1(session, dependency_injector, "getshared", service); PHALCON_VERIFY_INTERFACE(session, phalcon_session_adapterinterface_ce); phalcon_update_property_this(this_ptr, SL("_session"), session TSRMLS_CC); } - PHALCON_OBS_VAR(name); - phalcon_read_property_this(&name, this_ptr, SL("_name"), PH_NOISY_CC); - - PHALCON_INIT_VAR(data); - phalcon_call_method_p1(data, session, "get", name); - if (Z_TYPE_P(data) != IS_ARRAY) { - PHALCON_INIT_NVAR(data); - array_init(data); + name = phalcon_fetch_nproperty_this(this_ptr, SL("_name"), PH_NOISY TSRMLS_CC); + +#if PHP_VERSION_ID < 50500 + data = Z_OBJ_HANDLER_P(session, get_property_ptr_ptr)(session, name ZLK_NULL_CC TSRMLS_CC); +#else + data = Z_OBJ_HANDLER_P(session, get_property_ptr_ptr)(session, name, BP_VAR_W ZLK_NULL_CC TSRMLS_CC); +#endif + + if (Z_TYPE_PP(data) != IS_ARRAY) { + zval *empty_array; + PHALCON_ALLOC_GHOST_ZVAL(empty_array); + array_init(empty_array); + phalcon_update_property_this(this_ptr, SL("_data"), empty_array TSRMLS_CC); + } + else { + phalcon_update_property_this(this_ptr, SL("_data"), *data TSRMLS_CC); } - phalcon_update_property_this(this_ptr, SL("_data"), data TSRMLS_CC); phalcon_update_property_bool(this_ptr, SL("_initialized"), 1 TSRMLS_CC); - PHALCON_MM_RESTORE(); } /** - * Destroyes the session bag + * Destroys the session bag * * * $user->destroy(); @@ -206,24 +264,13 @@ PHP_METHOD(Phalcon_Session_Bag, initialize){ */ PHP_METHOD(Phalcon_Session_Bag, destroy){ - zval *initialized, *name, *session; + zval *name, *session; - PHALCON_MM_GROW(); - - PHALCON_OBS_VAR(initialized); - phalcon_read_property_this(&initialized, this_ptr, SL("_initialized"), PH_NOISY_CC); - if (PHALCON_IS_FALSE(initialized)) { - phalcon_call_method_noret(this_ptr, "initialize"); - } - - PHALCON_OBS_VAR(name); - phalcon_read_property_this(&name, this_ptr, SL("_name"), PH_NOISY_CC); + RETURN_ON_FAILURE(phalcon_session_bag_maybe_initialize(this_ptr TSRMLS_CC)); - PHALCON_OBS_VAR(session); - phalcon_read_property_this(&session, this_ptr, SL("_session"), PH_NOISY_CC); - phalcon_call_method_p1_noret(session, "remove", name); - - PHALCON_MM_RESTORE(); + name = phalcon_fetch_nproperty_this(this_ptr, SL("_name"), PH_NOISY TSRMLS_CC); + session = phalcon_fetch_nproperty_this(this_ptr, SL("_session"), PH_NOISY TSRMLS_CC); + Z_OBJ_HANDLER_P(session, unset_property)(session, name ZLK_NULL_CC TSRMLS_CC); } /** @@ -238,32 +285,18 @@ PHP_METHOD(Phalcon_Session_Bag, destroy){ */ PHP_METHOD(Phalcon_Session_Bag, set){ - zval *property, *value, *initialized, *name, *data; - zval *session; + zval *property, *value, *session, *name, *data; - PHALCON_MM_GROW(); - - phalcon_fetch_params(1, 2, 0, &property, &value); + phalcon_fetch_params(0, 2, 0, &property, &value); - PHALCON_OBS_VAR(initialized); - phalcon_read_property_this(&initialized, this_ptr, SL("_initialized"), PH_NOISY_CC); - if (PHALCON_IS_FALSE(initialized)) { - phalcon_call_method_noret(this_ptr, "initialize"); - } + RETURN_ON_FAILURE(phalcon_session_bag_maybe_initialize(this_ptr TSRMLS_CC)); phalcon_update_property_array(this_ptr, SL("_data"), property, value TSRMLS_CC); - PHALCON_OBS_VAR(name); - phalcon_read_property_this(&name, this_ptr, SL("_name"), PH_NOISY_CC); - - PHALCON_OBS_VAR(data); - phalcon_read_property_this(&data, this_ptr, SL("_data"), PH_NOISY_CC); - - PHALCON_OBS_VAR(session); - phalcon_read_property_this(&session, this_ptr, SL("_session"), PH_NOISY_CC); - phalcon_call_method_p2_noret(session, "set", name, data); - - PHALCON_MM_RESTORE(); + name = phalcon_fetch_nproperty_this(this_ptr, SL("_name"), PH_NOISY TSRMLS_CC); + data = phalcon_fetch_nproperty_this(this_ptr, SL("_data"), PH_NOISY TSRMLS_CC); + session = phalcon_fetch_nproperty_this(this_ptr, SL("_session"), PH_NOISY TSRMLS_CC); + Z_OBJ_HANDLER_P(session, write_property)(session, name, data ZLK_NULL_CC TSRMLS_CC); } /** @@ -292,46 +325,29 @@ PHALCON_DOC_METHOD(Phalcon_Session_Bag, __set); */ PHP_METHOD(Phalcon_Session_Bag, get){ - zval *property, *default_value = NULL, *initialized; + zval *property, *default_value = NULL; zval *data, *value; - PHALCON_MM_GROW(); - - phalcon_fetch_params(1, 1, 1, &property, &default_value); + phalcon_fetch_params(0, 1, 1, &property, &default_value); if (!default_value) { default_value = PHALCON_GLOBAL(z_null); } - /** - * Check first if the bag is initialized - */ - PHALCON_OBS_VAR(initialized); - phalcon_read_property_this(&initialized, this_ptr, SL("_initialized"), PH_NOISY_CC); - if (PHALCON_IS_FALSE(initialized)) { - phalcon_call_method_noret(this_ptr, "initialize"); - } - - /** - * Retrieve the data - */ - PHALCON_OBS_VAR(data); - phalcon_read_property_this(&data, this_ptr, SL("_data"), PH_NOISY_CC); - if (phalcon_array_isset(data, property)) { + /* Check first if the bag is initialized */ + RETURN_ON_FAILURE(phalcon_session_bag_maybe_initialize(this_ptr TSRMLS_CC)); - PHALCON_OBS_VAR(value); - phalcon_array_fetch(&value, data, property, PH_NOISY); - if (PHALCON_IS_NOT_EMPTY(value)) { - RETURN_CTOR(value); - } + /* Retrieve the data */ + data = phalcon_fetch_nproperty_this(this_ptr, SL("_data"), PH_NOISY TSRMLS_CC); + if (phalcon_array_isset_fetch(&value, data, property)) { + RETURN_ZVAL(value, 1, 0); } - - RETURN_CTOR(default_value); + + RETURN_ZVAL(default_value, 1, 0); } /** * Magic getter to obtain values from the session bag. - * Alias for Phalcon\Session\Bag::get() * * * echo $user->name; @@ -340,7 +356,35 @@ PHP_METHOD(Phalcon_Session_Bag, get){ * @param string $property * @return string */ -PHALCON_DOC_METHOD(Phalcon_Session_Bag, __get); +PHP_METHOD(Phalcon_Session_Bag, __get) +{ + zval *property, *data, *value; + + assert(return_value_ptr != NULL); + + phalcon_fetch_params(0, 1, 0, &property); + + /* Check first if the bag is initialized */ + RETURN_ON_FAILURE(phalcon_session_bag_maybe_initialize(this_ptr TSRMLS_CC)); + + /* Retrieve the data */ + data = phalcon_fetch_nproperty_this(this_ptr, SL("_data"), PH_NOISY TSRMLS_CC); + zval_ptr_dtor(return_value_ptr); + if (phalcon_array_isset_fetch(&value, data, property)) { + *return_value_ptr = value; + } + else { + zval *tmp; + ALLOC_INIT_ZVAL(tmp); + Z_DELREF_P(tmp); + phalcon_update_property_array(this_ptr, SL("_data"), property, tmp TSRMLS_CC); + *return_value_ptr = tmp; + } + + Z_ADDREF_PP(return_value_ptr); + Z_SET_ISREF_PP(return_value_ptr); +} + /** * Check whether a property is defined in the internal bag @@ -354,25 +398,14 @@ PHALCON_DOC_METHOD(Phalcon_Session_Bag, __get); */ PHP_METHOD(Phalcon_Session_Bag, has){ - zval *property, *initialized, *data; + zval *property, *data; - PHALCON_MM_GROW(); - - phalcon_fetch_params(1, 1, 0, &property); - - PHALCON_OBS_VAR(initialized); - phalcon_read_property_this(&initialized, this_ptr, SL("_initialized"), PH_NOISY_CC); - if (PHALCON_IS_FALSE(initialized)) { - phalcon_call_method_noret(this_ptr, "initialize"); - } + phalcon_fetch_params(0, 1, 0, &property); - PHALCON_OBS_VAR(data); - phalcon_read_property_this(&data, this_ptr, SL("_data"), PH_NOISY_CC); - if (phalcon_array_isset(data, property)) { - RETURN_MM_TRUE; - } + RETURN_ON_FAILURE(phalcon_session_bag_maybe_initialize(this_ptr TSRMLS_CC)); - RETURN_MM_FALSE; + data = phalcon_fetch_nproperty_this(this_ptr, SL("_data"), PH_NOISY TSRMLS_CC); + RETURN_BOOL(phalcon_array_isset(data, property)); } /** @@ -401,36 +434,23 @@ PHALCON_DOC_METHOD(Phalcon_Session_Bag, __isset); PHP_METHOD(Phalcon_Session_Bag, remove){ zval *property, *data = NULL, *name, *session; - zval *initialized; - PHALCON_MM_GROW(); + phalcon_fetch_params(0, 1, 0, &property); - phalcon_fetch_params(1, 1, 0, &property); + RETURN_ON_FAILURE(phalcon_session_bag_maybe_initialize(this_ptr TSRMLS_CC)); - PHALCON_OBS_VAR(initialized); - phalcon_read_property_this(&initialized, this_ptr, SL("_initialized"), PH_NOISY_CC); - if (PHALCON_IS_FALSE(initialized)) { - phalcon_call_method_noret(this_ptr, "initialize"); - } - - PHALCON_OBS_VAR(data); - phalcon_read_property_this(&data, this_ptr, SL("_data"), PH_NOISY_CC); + data = phalcon_fetch_nproperty_this(this_ptr, SL("_data"), PH_NOISY TSRMLS_CC); if (phalcon_array_isset(data, property)) { phalcon_unset_property_array(this_ptr, SL("_data"), property TSRMLS_CC); - - PHALCON_OBS_NVAR(data); - phalcon_read_property_this(&data, this_ptr, SL("_data"), PH_NOISY_CC); - - PHALCON_OBS_VAR(name); - phalcon_read_property_this(&name, this_ptr, SL("_name"), PH_NOISY_CC); - - PHALCON_OBS_VAR(session); - phalcon_read_property_this(&session, this_ptr, SL("_session"), PH_NOISY_CC); - phalcon_call_method_p2_noret(session, "set", name, data); - RETURN_MM_TRUE; + + data = phalcon_fetch_nproperty_this(this_ptr, SL("_data"), PH_NOISY TSRMLS_CC); + name = phalcon_fetch_nproperty_this(this_ptr, SL("_name"), PH_NOISY TSRMLS_CC); + session = phalcon_fetch_nproperty_this(this_ptr, SL("_session"), PH_NOISY TSRMLS_CC); + Z_OBJ_HANDLER_P(session, write_property)(session, name, data ZLK_NULL_CC TSRMLS_CC); + RETURN_TRUE; } - RETURN_MM_FALSE; + RETURN_FALSE; } /** @@ -445,3 +465,26 @@ PHP_METHOD(Phalcon_Session_Bag, remove){ * @return boolean */ PHALCON_DOC_METHOD(Phalcon_Session_Bag, __unset); + +PHP_METHOD(Phalcon_Session_Bag, getIterator) +{ + zval *data; + + RETURN_ON_FAILURE(phalcon_session_bag_maybe_initialize(this_ptr TSRMLS_CC)); + + data = phalcon_fetch_nproperty_this(getThis(), SL("_data"), PH_NOISY TSRMLS_CC); + object_init_ex(return_value, spl_ce_ArrayIterator); + RETURN_ON_FAILURE(phalcon_call_method_params(NULL, NULL, return_value, SL("__construct"), zend_inline_hash_func(SS("__construct")) TSRMLS_CC, 1, data)); +} + +PHP_METHOD(Phalcon_Session_Bag, count) +{ + zval *data; + long int count; + + RETURN_ON_FAILURE(phalcon_session_bag_maybe_initialize(this_ptr TSRMLS_CC)); + + data = phalcon_fetch_nproperty_this(getThis(), SL("_data"), PH_NOISY TSRMLS_CC); + count = (Z_TYPE_P(data) == IS_ARRAY) ? zend_hash_num_elements(Z_ARRVAL_P(data)) : 0; + RETURN_LONG(count); +} diff --git a/ext/session/baginterface.c b/ext/session/baginterface.c index 1b47b0bcf94..cc1a45484c9 100644 --- a/ext/session/baginterface.c +++ b/ext/session/baginterface.c @@ -28,6 +28,7 @@ static const zend_function_entry phalcon_session_baginterface_method_entry[] = { PHP_ABSTRACT_ME(Phalcon_Session_BagInterface, set, arginfo_phalcon_session_baginterface_set) PHP_ABSTRACT_ME(Phalcon_Session_BagInterface, get, arginfo_phalcon_session_baginterface_get) PHP_ABSTRACT_ME(Phalcon_Session_BagInterface, has, arginfo_phalcon_session_baginterface_has) + PHP_ABSTRACT_ME(Phalcon_Session_BagInterface, remove, arginfo_phalcon_session_baginterface_remove) PHP_FE_END }; @@ -75,3 +76,10 @@ PHALCON_DOC_METHOD(Phalcon_Session_BagInterface, get); * @return boolean */ PHALCON_DOC_METHOD(Phalcon_Session_BagInterface, has); + +/** + * Unset property + * + * @param string $property + */ +PHALCON_DOC_METHOD(Phalcon_Session_BagInterface, remove); diff --git a/ext/session/baginterface.h b/ext/session/baginterface.h index ea123963550..7c3de68fe4f 100644 --- a/ext/session/baginterface.h +++ b/ext/session/baginterface.h @@ -40,4 +40,8 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_session_baginterface_has, 0, 0, 1) ZEND_ARG_INFO(0, property) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_phalcon_session_baginterface_remove, 0, 0, 1) + ZEND_ARG_INFO(0, property) +ZEND_END_ARG_INFO() + #endif /* PHALCON_SESSION_BAGINTERFACE_H */ diff --git a/ext/tests/issue-1226.phpt b/ext/tests/issue-1226.phpt index ff930e81670..df240f2b1f5 100644 --- a/ext/tests/issue-1226.phpt +++ b/ext/tests/issue-1226.phpt @@ -2,6 +2,7 @@ Default values in Phalcon\Http\Request::getQuery() - https://github.com/phalcon/cphalcon/issues/1226 --SKIPIF-- + --GET-- id=1&num=a1a&age=aa&phone= --POST-- diff --git a/ext/tests/issue-1265.phpt b/ext/tests/issue-1265.phpt index 4ed50f2a7af..cf3a51a2681 100644 --- a/ext/tests/issue-1265.phpt +++ b/ext/tests/issue-1265.phpt @@ -2,6 +2,7 @@ MongoDB Request Injection Attacks (getQuery/getPost) - https://github.com/phalcon/cphalcon/issues/1265 --SKIPIF-- + --GET-- string=hello&array[string]=world --POST-- diff --git a/ext/tests/issue-1342.phpt b/ext/tests/issue-1342.phpt index 5f4e33c0dcd..5dc90f3b049 100644 --- a/ext/tests/issue-1342.phpt +++ b/ext/tests/issue-1342.phpt @@ -2,6 +2,7 @@ Implement Phalcon\Flash\Session::isset() - https://github.com/phalcon/cphalcon/issues/1342 --SKIPIF-- + --GET-- dummy --FILE-- diff --git a/ext/tests/issue-1575.phpt b/ext/tests/issue-1575.phpt index 22b1e0d7ba1..1394ee7c173 100644 --- a/ext/tests/issue-1575.phpt +++ b/ext/tests/issue-1575.phpt @@ -4,6 +4,7 @@ flashSession->getMessages(type, BOOLEAN remove) removed all messages - https://g dummy=1 --SKIPIF-- + --FILE-- + --GET-- dummy=1 --FILE-- @@ -35,7 +36,7 @@ class Test extends \Phalcon\Di\Injectable public function dump($v) { - echo $v, '=', var_dump($this->persistent->$v); + echo $v, '=', var_dump($this->persistent->get($v)); echo 'has(', $v, ')=', var_dump($this->persistent->has($v)); echo 'isset(', $v, ')=', var_dump(isset($this->persistent->$v)); echo PHP_EOL; diff --git a/ext/tests/issue-1895.phpt b/ext/tests/issue-1895.phpt new file mode 100644 index 00000000000..6a6acf43381 --- /dev/null +++ b/ext/tests/issue-1895.phpt @@ -0,0 +1,40 @@ +--TEST-- +'Indirect modification of overloaded property' notice in Phalcon\Session\Bag - https://github.com/phalcon/cphalcon/issues/1895 +--SKIPIF-- + + +--GET-- +dummy=1 +--FILE-- +start(); +$namespace = new \Phalcon\Session\Bag('test'); +$namespace->{'prop1'}['prop2'] = 'my value'; +var_dump($namespace->{'prop1'}); +$namespace['prop3']['prop4'] = 'your value'; +var_dump($namespace['prop3']); +var_dump(count($namespace)); +foreach ($namespace as $key => $value) { + echo $key, ' => '; + var_dump($value); +} +?> +--EXPECT-- +array(1) { + ["prop2"]=> + string(8) "my value" +} +array(1) { + ["prop4"]=> + string(10) "your value" +} +int(2) +prop1 => array(1) { + ["prop2"]=> + string(8) "my value" +} +prop3 => array(1) { + ["prop4"]=> + string(10) "your value" +}