Skip to content

Commit 0e259a6

Browse files
committed
Reintroduce Count handler
1 parent b5eb544 commit 0e259a6

File tree

3 files changed

+51
-7
lines changed

3 files changed

+51
-7
lines changed

Zend/zend_vm_def.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8396,6 +8396,14 @@ ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMPVAR|CV, UNUSED)
83968396
zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval);
83978397
count = zval_get_long(&retval);
83988398
zval_ptr_dtor(&retval);
8399+
/* Else if the object has a count handler defined */
8400+
} else if (zobj->handlers->count_elements) {
8401+
if (FAILURE == zobj->handlers->count_elements(zobj, &count)) {
8402+
zend_type_error("Parameter must be an array or an object that implements Countable");
8403+
}
8404+
if (UNEXPECTED(EG(exception))) {
8405+
count = 0;
8406+
}
83998407
} else {
84008408
zend_type_error("Parameter must be an array or an object that implements Countable");
84018409
}

Zend/zend_vm_execute.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9238,6 +9238,14 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CONST_
92389238
zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval);
92399239
count = zval_get_long(&retval);
92409240
zval_ptr_dtor(&retval);
9241+
/* Else if the object has a count handler defined */
9242+
} else if (zobj->handlers->count_elements) {
9243+
if (FAILURE == zobj->handlers->count_elements(zobj, &count)) {
9244+
zend_type_error("Parameter must be an array or an object that implements Countable");
9245+
}
9246+
if (UNEXPECTED(EG(exception))) {
9247+
count = 0;
9248+
}
92419249
} else {
92429250
zend_type_error("Parameter must be an array or an object that implements Countable");
92439251
}
@@ -16245,6 +16253,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMPVAR_UNUSED_HANDL
1624516253
zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval);
1624616254
count = zval_get_long(&retval);
1624716255
zval_ptr_dtor(&retval);
16256+
/* Else if the object has a count handler defined */
16257+
} else if (zobj->handlers->count_elements) {
16258+
if (FAILURE == zobj->handlers->count_elements(zobj, &count)) {
16259+
zend_type_error("Parameter must be an array or an object that implements Countable");
16260+
}
16261+
if (UNEXPECTED(EG(exception))) {
16262+
count = 0;
16263+
}
1624816264
} else {
1624916265
zend_type_error("Parameter must be an array or an object that implements Countable");
1625016266
}
@@ -44794,6 +44810,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CV_UNUSED_HANDLER(Z
4479444810
zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval);
4479544811
count = zval_get_long(&retval);
4479644812
zval_ptr_dtor(&retval);
44813+
/* Else if the object has a count handler defined */
44814+
} else if (zobj->handlers->count_elements) {
44815+
if (FAILURE == zobj->handlers->count_elements(zobj, &count)) {
44816+
zend_type_error("Parameter must be an array or an object that implements Countable");
44817+
}
44818+
if (UNEXPECTED(EG(exception))) {
44819+
count = 0;
44820+
}
4479744821
} else {
4479844822
zend_type_error("Parameter must be an array or an object that implements Countable");
4479944823
}

ext/standard/array.c

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -776,24 +776,36 @@ PHP_FUNCTION(count)
776776
return;
777777
}
778778
RETURN_LONG(count);
779+
}
780+
779781
/* Remove possibility to specify $mode when passing object? */
780-
} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "O|l",
782+
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "O|l",
781783
&countable, zend_ce_countable, &mode) == SUCCESS) {
782784
if (mode != COUNT_NORMAL && mode != COUNT_RECURSIVE) {
783785
zend_value_error("Mode value is invalid");
784786
return;
785787
}
786788
zval retval;
787-
zend_call_method_with_0_params(Z_OBJ_P(countable), NULL, NULL, "count", &retval);
788-
if (Z_TYPE(retval) != IS_UNDEF) {
789-
RETVAL_LONG(zval_get_long(&retval));
789+
/* First, we check if the count handler is defined */
790+
if (Z_OBJ_HT_P(countable)->count_elements) {
791+
RETVAL_LONG(1);
792+
if (SUCCESS == Z_OBJ_HT(*countable)->count_elements(Z_OBJ_P(countable), &Z_LVAL_P(return_value))) {
793+
return;
794+
}
795+
if (EG(exception)) {
796+
return;
797+
}
798+
} else {
799+
zend_call_method_with_0_params(Z_OBJ_P(countable), NULL, NULL, "count", &retval);
800+
if (Z_TYPE(retval) != IS_UNDEF) {
801+
RETVAL_LONG(zval_get_long(&retval));
802+
}
790803
}
791804
zval_ptr_dtor(&retval);
792805
return;
793-
} else {
794-
zend_type_error("Parameter must be an array or an object that implements Countable");
795-
return;
796806
}
807+
zend_type_error("Parameter must be an array or an object that implements Countable");
808+
return;
797809
}
798810
/* }}} */
799811

0 commit comments

Comments
 (0)