summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xext/spl/php_spl.c8
-rwxr-xr-xext/spl/php_spl.h1
-rwxr-xr-xext/spl/spl_array.c60
-rwxr-xr-xext/spl/spl_array.h1
-rwxr-xr-xext/spl/tests/array_access_001.phpt41
-rwxr-xr-xext/spl/tests/array_access_002.phpt4
6 files changed, 112 insertions, 3 deletions
diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c
index 6634e156b5..9704fe261d 100755
--- a/ext/spl/php_spl.c
+++ b/ext/spl/php_spl.c
@@ -95,6 +95,7 @@ static void spl_init_globals(zend_spl_globals *spl_globals)
#ifdef SPL_ARRAY_WRITE
ZEND_EXECUTE_HOOK(ZEND_ASSIGN_DIM);
+ ZEND_EXECUTE_HOOK(ZEND_UNSET_DIM_OBJ);
#endif /* SPL_ARRAY_WRITE */
}
/* }}} */
@@ -106,13 +107,13 @@ PHP_FUNCTION(spl_abstract) {}
static
ZEND_BEGIN_ARG_INFO(arginfo_one_param, 0)
- ZEND_ARG_PASS_INFO(0)
+ ZEND_ARG_INFO(0, index)
ZEND_END_ARG_INFO();
static
ZEND_BEGIN_ARG_INFO(arginfo_two_params, 0)
- ZEND_ARG_PASS_INFO(0)
- ZEND_ARG_PASS_INFO(0)
+ ZEND_ARG_INFO(0, index)
+ ZEND_ARG_INFO(0, value)
ZEND_END_ARG_INFO();
function_entry spl_funcs_iterator[] = {
@@ -148,6 +149,7 @@ function_entry spl_funcs_array_read[] = {
function_entry spl_funcs_array_access[] = {
SPL_ABSTRACT_FE(array_access, set, arginfo_two_params)
+ SPL_ABSTRACT_FE(array_access, del, arginfo_one_param)
{NULL, NULL, NULL}
};
diff --git a/ext/spl/php_spl.h b/ext/spl/php_spl.h
index 7591ef8c50..b8de833022 100755
--- a/ext/spl/php_spl.h
+++ b/ext/spl/php_spl.h
@@ -71,6 +71,7 @@ ZEND_BEGIN_MODULE_GLOBALS(spl)
#endif
#ifdef SPL_ARRAY_WRITE
ZEND_EXECUTE_HOOK_PTR(ZEND_ASSIGN_DIM);
+ ZEND_EXECUTE_HOOK_PTR(ZEND_UNSET_DIM_OBJ);
#endif
ZEND_END_MODULE_GLOBALS(spl)
diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c
index 55be32069a..d728942a49 100755
--- a/ext/spl/spl_array.c
+++ b/ext/spl/spl_array.c
@@ -240,6 +240,66 @@ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_ASSIGN_DIM)
#endif
/* }}} */
+/* {{{ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_UNSET_DIM_OBJ) */
+#ifdef SPL_ARRAY_WRITE
+ZEND_EXECUTE_HOOK_FUNCTION(ZEND_UNSET_DIM_OBJ)
+{
+ zval **obj;
+ zend_class_entry *obj_ce;
+ spl_is_a is_a;
+
+ if (EX(opline)->extended_value != ZEND_UNSET_DIM) {
+ ZEND_EXECUTE_HOOK_ORIGINAL(ZEND_UNSET_DIM_OBJ);
+ }
+
+ obj = spl_get_obj_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), 0 TSRMLS_CC);
+
+ if (!obj || (obj_ce = spl_get_class_entry(*obj TSRMLS_CC)) == NULL) {
+ ZEND_EXECUTE_HOOK_ORIGINAL(ZEND_UNSET_DIM_OBJ);
+ }
+
+ is_a = spl_implements(obj_ce);
+
+ if (is_a & SPL_IS_A_ARRAY_ACCESS) {
+ znode *op2 = &EX(opline)->op2;
+ zval *index = spl_get_zval_ptr(op2, EX(Ts), &EG(free_op2), BP_VAR_R);
+ zval tmp;
+ zval *retval;
+
+ spl_unlock_zval_ptr_ptr(&EX(opline)->op1, EX(Ts) TSRMLS_CC);
+
+ /* here we are sure we are dealing with an object */
+ switch (op2->op_type) {
+ case IS_CONST:
+ /* already a constant string */
+ break;
+ case IS_VAR:
+ tmp = *index;
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ index = &tmp;
+ break;
+ case IS_TMP_VAR:
+ convert_to_string(index);
+ break;
+ }
+
+ spl_begin_method_call_arg_ex1(obj, obj_ce, NULL, "del", sizeof("del")-1, &retval, index TSRMLS_CC);
+
+ if (index == &tmp) {
+ zval_dtor(index);
+ }
+
+ FREE_OP(Ts, op2, EG(free_op2));
+ DELETE_RET_ZVAL(retval);
+
+ NEXT_OPCODE();
+ }
+ ZEND_EXECUTE_HOOK_ORIGINAL(ZEND_UNSET_DIM_OBJ);
+}
+#endif
+/* }}} */
+
SPL_CLASS_FUNCTION(array, __construct);
SPL_CLASS_FUNCTION(array, new_iterator);
SPL_CLASS_FUNCTION(array, rewind);
diff --git a/ext/spl/spl_array.h b/ext/spl/spl_array.h
index 3aa194c8cc..840a9627eb 100755
--- a/ext/spl/spl_array.h
+++ b/ext/spl/spl_array.h
@@ -30,6 +30,7 @@ ZEND_EXECUTE_HOOK_FUNCTION(ZEND_FETCH_DIM_RW);
#ifdef SPL_ARRAY_WRITE
ZEND_EXECUTE_HOOK_FUNCTION(ZEND_ASSIGN_DIM);
+ZEND_EXECUTE_HOOK_FUNCTION(ZEND_UNSET_DIM_OBJ);
#endif
#endif /* SPL_ARRAY_H */
diff --git a/ext/spl/tests/array_access_001.phpt b/ext/spl/tests/array_access_001.phpt
index 4aea3d90f4..2292749db2 100755
--- a/ext/spl/tests/array_access_001.phpt
+++ b/ext/spl/tests/array_access_001.phpt
@@ -22,6 +22,10 @@ class c implements spl_array_access {
echo __METHOD__ . "($index,$newval)\n";
return $this->a[$index] = $newval;
}
+ function del($index) {
+ echo __METHOD__ . "($index)\n";
+ unset($this->a[$index]);
+ }
}
$obj = new c();
@@ -55,6 +59,14 @@ $x = $obj[6] = 'changed 6';
var_dump($obj[6]);
var_dump($x);
+echo "===unset===\n";
+var_dump($obj->a);
+unset($obj[2]);
+unset($obj['4th']);
+unset($obj[7]);
+unset($obj['8th']);
+var_dump($obj->a);
+
print "Done\n";
?>
--EXPECTF--
@@ -119,4 +131,33 @@ c::exists(6)
c::get(6)
string(9) "changed 6"
string(9) "changed 6"
+===unset===
+array(6) {
+ [0]=>
+ string(3) "1st"
+ [1]=>
+ string(9) "Changed 1"
+ [2]=>
+ string(3) "3rd"
+ ["4th"]=>
+ string(11) "Changed 4th"
+ ["5th"]=>
+ string(9) "Added 5th"
+ [6]=>
+ string(9) "changed 6"
+}
+c::del(2)
+c::del(4th)
+c::del(7)
+c::del(8th)
+array(4) {
+ [0]=>
+ string(3) "1st"
+ [1]=>
+ string(9) "Changed 1"
+ ["5th"]=>
+ string(9) "Added 5th"
+ [6]=>
+ string(9) "changed 6"
+}
Done
diff --git a/ext/spl/tests/array_access_002.phpt b/ext/spl/tests/array_access_002.phpt
index e6616ea658..133e6f3f4a 100755
--- a/ext/spl/tests/array_access_002.phpt
+++ b/ext/spl/tests/array_access_002.phpt
@@ -23,6 +23,10 @@ class c implements spl_array_access {
echo __METHOD__ . "($index,$newval)\n";
/* return */ $this->a[$index] = $newval;
}
+ function del($index) {
+ echo __METHOD__ . "($index)\n";
+ unset($this->a[$index]);
+ }
}
$obj = new c();