Skip to content

Commit 67a4b12

Browse files
committed
Reintroduce Count handler
1 parent 26d2e35 commit 67a4b12

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
@@ -8379,6 +8379,14 @@ ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMPVAR|CV, UNUSED)
83798379
zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval);
83808380
count = zval_get_long(&retval);
83818381
zval_ptr_dtor(&retval);
8382+
/* Else if the object has a count handler defined */
8383+
} else if (zobj->handlers->count_elements) {
8384+
if (FAILURE == zobj->handlers->count_elements(zobj, &count)) {
8385+
zend_type_error("Parameter must be an array or an object that implements Countable");
8386+
}
8387+
if (UNEXPECTED(EG(exception))) {
8388+
count = 0;
8389+
}
83828390
} else {
83838391
zend_type_error("Parameter must be an array or an object that implements Countable");
83848392
}

Zend/zend_vm_execute.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9221,6 +9221,14 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CONST_
92219221
zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval);
92229222
count = zval_get_long(&retval);
92239223
zval_ptr_dtor(&retval);
9224+
/* Else if the object has a count handler defined */
9225+
} else if (zobj->handlers->count_elements) {
9226+
if (FAILURE == zobj->handlers->count_elements(zobj, &count)) {
9227+
zend_type_error("Parameter must be an array or an object that implements Countable");
9228+
}
9229+
if (UNEXPECTED(EG(exception))) {
9230+
count = 0;
9231+
}
92249232
} else {
92259233
zend_type_error("Parameter must be an array or an object that implements Countable");
92269234
}
@@ -16228,6 +16236,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMPVAR_UNUSED_HANDL
1622816236
zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval);
1622916237
count = zval_get_long(&retval);
1623016238
zval_ptr_dtor(&retval);
16239+
/* Else if the object has a count handler defined */
16240+
} else if (zobj->handlers->count_elements) {
16241+
if (FAILURE == zobj->handlers->count_elements(zobj, &count)) {
16242+
zend_type_error("Parameter must be an array or an object that implements Countable");
16243+
}
16244+
if (UNEXPECTED(EG(exception))) {
16245+
count = 0;
16246+
}
1623116247
} else {
1623216248
zend_type_error("Parameter must be an array or an object that implements Countable");
1623316249
}
@@ -44733,6 +44749,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CV_UNUSED_HANDLER(Z
4473344749
zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval);
4473444750
count = zval_get_long(&retval);
4473544751
zval_ptr_dtor(&retval);
44752+
/* Else if the object has a count handler defined */
44753+
} else if (zobj->handlers->count_elements) {
44754+
if (FAILURE == zobj->handlers->count_elements(zobj, &count)) {
44755+
zend_type_error("Parameter must be an array or an object that implements Countable");
44756+
}
44757+
if (UNEXPECTED(EG(exception))) {
44758+
count = 0;
44759+
}
4473644760
} else {
4473744761
zend_type_error("Parameter must be an array or an object that implements Countable");
4473844762
}

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)