Skip to content

Commit ffc40da

Browse files
committed
Reintroduce Count handler
1 parent a6923cd commit ffc40da

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
@@ -8438,6 +8438,14 @@ ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMPVAR|CV, UNUSED)
84388438
zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval);
84398439
count = zval_get_long(&retval);
84408440
zval_ptr_dtor(&retval);
8441+
/* Else if the object has a count handler defined */
8442+
} else if (zobj->handlers->count_elements) {
8443+
if (FAILURE == zobj->handlers->count_elements(zobj, &count)) {
8444+
zend_type_error("Parameter must be an array or an object that implements Countable");
8445+
}
8446+
if (UNEXPECTED(EG(exception))) {
8447+
count = 0;
8448+
}
84418449
} else {
84428450
zend_type_error("Parameter must be an array or an object that implements Countable");
84438451
}

Zend/zend_vm_execute.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9270,6 +9270,14 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CONST_
92709270
zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval);
92719271
count = zval_get_long(&retval);
92729272
zval_ptr_dtor(&retval);
9273+
/* Else if the object has a count handler defined */
9274+
} else if (zobj->handlers->count_elements) {
9275+
if (FAILURE == zobj->handlers->count_elements(zobj, &count)) {
9276+
zend_type_error("Parameter must be an array or an object that implements Countable");
9277+
}
9278+
if (UNEXPECTED(EG(exception))) {
9279+
count = 0;
9280+
}
92739281
} else {
92749282
zend_type_error("Parameter must be an array or an object that implements Countable");
92759283
}
@@ -16277,6 +16285,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_TMPVAR_UNUSED_HANDL
1627716285
zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval);
1627816286
count = zval_get_long(&retval);
1627916287
zval_ptr_dtor(&retval);
16288+
/* Else if the object has a count handler defined */
16289+
} else if (zobj->handlers->count_elements) {
16290+
if (FAILURE == zobj->handlers->count_elements(zobj, &count)) {
16291+
zend_type_error("Parameter must be an array or an object that implements Countable");
16292+
}
16293+
if (UNEXPECTED(EG(exception))) {
16294+
count = 0;
16295+
}
1628016296
} else {
1628116297
zend_type_error("Parameter must be an array or an object that implements Countable");
1628216298
}
@@ -45059,6 +45075,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_COUNT_SPEC_CV_UNUSED_HANDLER(Z
4505945075
zend_call_method_with_0_params(zobj, NULL, NULL, "count", &retval);
4506045076
count = zval_get_long(&retval);
4506145077
zval_ptr_dtor(&retval);
45078+
/* Else if the object has a count handler defined */
45079+
} else if (zobj->handlers->count_elements) {
45080+
if (FAILURE == zobj->handlers->count_elements(zobj, &count)) {
45081+
zend_type_error("Parameter must be an array or an object that implements Countable");
45082+
}
45083+
if (UNEXPECTED(EG(exception))) {
45084+
count = 0;
45085+
}
4506245086
} else {
4506345087
zend_type_error("Parameter must be an array or an object that implements Countable");
4506445088
}

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)