longer referenced.
. The deprecated parameter `$version` of curl_version() has been removed.
+- Date:
+ . DatePeriod now implements IteratorAggregate (instead of Traversable).
+
+- DOM:
+ . DOMNamedNodeMap now implements IteratorAggregate (instead of Traversable).
+ . DOMNodeList now implements IteratorAggregate (instead of Traversable).
+
+- Intl:
+ . IntlBreakIterator now implements IteratorAggregate (instead of Traversable).
+ . ResourceBundle now implements IteratorAggregate (instead of Traversable).
+
- Enchant:
. The enchant extension now uses libenchant-2 by default when available.
libenchant version 1 is still supported but is deprecated and could
- MBString:
. The Unicode data tables have been updated to version 13.0.0.
+- PDO:
+ . PDOStatement now implements IteratorAggregate (instead of Traversable).
+
- MySQLi / PDO MySQL:
. When mysqlnd is not used (which is the default and recommended option),
the minimum supported libmysqlclient version is now 5.1.
+ . mysqli_result now implements IteratorAggregate (instead of Traversable).
- PGSQL / PDO PGSQL:
. The PGSQL and PDO PGSQL extensions now require at least libpq 9.1.
o. cast_object() object handler is now required
p. ARG_COUNT() macro removed
q. GC_COLLECTABLE flag
+ r. Cannot implement Traversable only
2. Build system changes
a. Abstract
Assignments to GC_TYPE_INFO() might need to be changed to properly
set the value of the GC_NOT_COLLECTABLE flag.
+ r. Just for for userland classes, it is no longer allowed to implement only
+ the Traversable interface. Instead, it is necessary to implement either
+ Iterator or IteratorAggregate. You can do the latter by implementing
+ zend_ce_aggregate and providing the following method implementation:
+
+ ZEND_METHOD(MyClass, getIterator) {
+ ZEND_PARSE_PARAMETERS_NONE();
+ zend_create_internal_iterator_zval(return_value, ZEND_THIS);
+ }
+
========================
2. Build system changes
========================
ZEND_API zend_class_entry *zend_ce_serializable;
ZEND_API zend_class_entry *zend_ce_countable;
ZEND_API zend_class_entry *zend_ce_stringable;
+ZEND_API zend_class_entry *zend_ce_internal_iterator;
+
+static zend_object_handlers zend_internal_iterator_handlers;
/* {{{ zend_call_method
Only returns the returned zval if retval_ptr != NULL */
/* {{{ zend_implement_traversable */
static int zend_implement_traversable(zend_class_entry *interface, zend_class_entry *class_type)
{
- /* check that class_type is traversable at c-level or implements at least one of 'aggregate' and 'Iterator' */
- uint32_t i;
-
- if (class_type->get_iterator || (class_type->parent && class_type->parent->get_iterator)) {
- return SUCCESS;
- }
/* Abstract class can implement Traversable only, in which case the extending class must
* implement Iterator or IteratorAggregate. */
if (class_type->ce_flags & ZEND_ACC_EXPLICIT_ABSTRACT_CLASS) {
return SUCCESS;
}
+
+ /* Check that class_type implements at least one of 'IteratorAggregate' or 'Iterator' */
if (class_type->num_interfaces) {
ZEND_ASSERT(class_type->ce_flags & ZEND_ACC_RESOLVED_INTERFACES);
- for (i = 0; i < class_type->num_interfaces; i++) {
+ for (uint32_t i = 0; i < class_type->num_interfaces; i++) {
if (class_type->interfaces[i] == zend_ce_aggregate || class_type->interfaces[i] == zend_ce_iterator) {
return SUCCESS;
}
}
/* }}}*/
+typedef struct {
+ zend_object std;
+ zend_object_iterator *iter;
+ zend_bool rewind_called;
+} zend_internal_iterator;
+
+static zend_object *zend_internal_iterator_create(zend_class_entry *ce) {
+ zend_internal_iterator *intern = emalloc(sizeof(zend_internal_iterator));
+ zend_object_std_init(&intern->std, ce);
+ intern->std.handlers = &zend_internal_iterator_handlers;
+ intern->iter = NULL;
+ intern->rewind_called = 0;
+ return &intern->std;
+}
+
+ZEND_API int zend_create_internal_iterator_zval(zval *return_value, zval *obj) {
+ zend_class_entry *scope = EG(current_execute_data)->func->common.scope;
+ ZEND_ASSERT(scope->get_iterator != zend_user_it_get_new_iterator);
+ zend_object_iterator *iter = scope->get_iterator(Z_OBJCE_P(obj), obj, /* by_ref */ 0);
+ if (!iter) {
+ return FAILURE;
+ }
+
+ zend_internal_iterator *intern =
+ (zend_internal_iterator *) zend_internal_iterator_create(zend_ce_internal_iterator);
+ intern->iter = iter;
+ ZVAL_OBJ(return_value, &intern->std);
+ return SUCCESS;
+}
+
+static void zend_internal_iterator_free(zend_object *obj) {
+ zend_internal_iterator *intern = (zend_internal_iterator *) obj;
+ if (intern->iter) {
+ zend_iterator_dtor(intern->iter);
+ }
+ zend_object_std_dtor(&intern->std);
+}
+
+static zend_internal_iterator *zend_internal_iterator_fetch(zval *This) {
+ zend_internal_iterator *intern = (zend_internal_iterator *) Z_OBJ_P(This);
+ if (!intern->iter) {
+ zend_throw_error(NULL, "The InternalIterator object has not been properly initialized");
+ return NULL;
+ }
+ return intern;
+}
+
+/* Many iterators will not behave correctly if rewind() is not called, make sure it happens. */
+static int zend_internal_iterator_ensure_rewound(zend_internal_iterator *intern) {
+ if (!intern->rewind_called) {
+ zend_object_iterator *iter = intern->iter;
+ intern->rewind_called = 1;
+ if (iter->funcs->rewind) {
+ iter->funcs->rewind(iter);
+ if (UNEXPECTED(EG(exception))) {
+ return FAILURE;
+ }
+ }
+ }
+ return SUCCESS;
+}
+
+
+ZEND_METHOD(InternalIterator, __construct) {
+ zend_throw_error(NULL, "Cannot manually construct InternalIterator");
+}
+
+ZEND_METHOD(InternalIterator, current) {
+ ZEND_PARSE_PARAMETERS_NONE();
+
+ zend_internal_iterator *intern = zend_internal_iterator_fetch(ZEND_THIS);
+ if (!intern) {
+ RETURN_THROWS();
+ }
+
+ if (zend_internal_iterator_ensure_rewound(intern) == FAILURE) {
+ RETURN_THROWS();
+ }
+
+ zval *data = intern->iter->funcs->get_current_data(intern->iter);
+ if (data) {
+ ZVAL_COPY_DEREF(return_value, data);
+ }
+}
+
+ZEND_METHOD(InternalIterator, key) {
+ ZEND_PARSE_PARAMETERS_NONE();
+
+ zend_internal_iterator *intern = zend_internal_iterator_fetch(ZEND_THIS);
+ if (!intern) {
+ RETURN_THROWS();
+ }
+
+ if (zend_internal_iterator_ensure_rewound(intern) == FAILURE) {
+ RETURN_THROWS();
+ }
+
+ if (intern->iter->funcs->get_current_key) {
+ intern->iter->funcs->get_current_key(intern->iter, return_value);
+ } else {
+ RETURN_LONG(intern->iter->index);
+ }
+}
+
+ZEND_METHOD(InternalIterator, next) {
+ ZEND_PARSE_PARAMETERS_NONE();
+
+ zend_internal_iterator *intern = zend_internal_iterator_fetch(ZEND_THIS);
+ if (!intern) {
+ RETURN_THROWS();
+ }
+
+ if (zend_internal_iterator_ensure_rewound(intern) == FAILURE) {
+ RETURN_THROWS();
+ }
+
+ intern->iter->funcs->move_forward(intern->iter);
+ intern->iter->index++;
+}
+
+ZEND_METHOD(InternalIterator, valid) {
+ ZEND_PARSE_PARAMETERS_NONE();
+
+ zend_internal_iterator *intern = zend_internal_iterator_fetch(ZEND_THIS);
+ if (!intern) {
+ RETURN_THROWS();
+ }
+
+ if (zend_internal_iterator_ensure_rewound(intern) == FAILURE) {
+ RETURN_THROWS();
+ }
+
+ RETURN_BOOL(intern->iter->funcs->valid(intern->iter) == SUCCESS);
+}
+
+ZEND_METHOD(InternalIterator, rewind) {
+ ZEND_PARSE_PARAMETERS_NONE();
+
+ zend_internal_iterator *intern = zend_internal_iterator_fetch(ZEND_THIS);
+ if (!intern) {
+ RETURN_THROWS();
+ }
+
+ if (!intern->iter->funcs->rewind) {
+ /* Allow calling rewind() if no iteration has happened yet,
+ * even if the iterator does not support rewinding. */
+ if (intern->iter->index != 0) {
+ zend_throw_error(NULL, "Iterator does not support rewinding");
+ RETURN_THROWS();
+ }
+ intern->iter->index = 0;
+ return;
+ }
+
+ intern->iter->funcs->rewind(intern->iter);
+ intern->iter->index = 0;
+}
+
/* {{{ zend_register_interfaces */
ZEND_API void zend_register_interfaces(void)
{
+ zend_class_entry ce;
+
REGISTER_MAGIC_INTERFACE(traversable, Traversable);
REGISTER_MAGIC_INTERFACE(aggregate, IteratorAggregate);
REGISTER_MAGIC_INTERFACE(serializable, Serializable);
- zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "ArrayAccess", class_ArrayAccess_methods);
zend_ce_arrayaccess = zend_register_internal_interface(&ce);
INIT_CLASS_ENTRY(ce, "Stringable", class_Stringable_methods);
zend_ce_stringable = zend_register_internal_interface(&ce);
+
+ INIT_CLASS_ENTRY(ce, "InternalIterator", class_InternalIterator_methods);
+ zend_ce_internal_iterator = zend_register_internal_class(&ce);
+ zend_class_implements(zend_ce_internal_iterator, 1, zend_ce_iterator);
+ zend_ce_internal_iterator->ce_flags |= ZEND_ACC_FINAL;
+ zend_ce_internal_iterator->create_object = zend_internal_iterator_create;
+ zend_ce_internal_iterator->serialize = zend_class_serialize_deny;
+ zend_ce_internal_iterator->unserialize = zend_class_unserialize_deny;
+
+ memcpy(&zend_internal_iterator_handlers, zend_get_std_object_handlers(),
+ sizeof(zend_object_handlers));
+ zend_internal_iterator_handlers.free_obj = zend_internal_iterator_free;
}
/* }}} */
ZEND_API int zend_class_serialize_deny(zval *object, unsigned char **buffer, size_t *buf_len, zend_serialize_data *data);
ZEND_API int zend_class_unserialize_deny(zval *object, zend_class_entry *ce, const unsigned char *buf, size_t buf_len, zend_unserialize_data *data);
+ZEND_API int zend_create_internal_iterator_zval(zval *return_value, zval *obj);
+
END_EXTERN_C()
#endif /* ZEND_INTERFACES_H */
{
public function __toString(): string;
}
+
+final class InternalIterator implements Iterator
+{
+ private function __construct();
+
+ /** @return mixed */
+ public function current();
+
+ /** @return mixed */
+ public function key();
+
+ public function next(): void;
+
+ public function valid(): bool;
+
+ public function rewind(): void;
+}
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Stringable___toString, 0, 0, IS_STRING, 0)
ZEND_END_ARG_INFO()
+#define arginfo_class_InternalIterator___construct arginfo_class_IteratorAggregate_getIterator
+#define arginfo_class_InternalIterator_current arginfo_class_IteratorAggregate_getIterator
+
+#define arginfo_class_InternalIterator_key arginfo_class_IteratorAggregate_getIterator
+
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_InternalIterator_next, 0, 0, IS_VOID, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_InternalIterator_valid, 0, 0, _IS_BOOL, 0)
+ZEND_END_ARG_INFO()
+
+#define arginfo_class_InternalIterator_rewind arginfo_class_InternalIterator_next
+
+
+ZEND_METHOD(InternalIterator, __construct);
+ZEND_METHOD(InternalIterator, current);
+ZEND_METHOD(InternalIterator, key);
+ZEND_METHOD(InternalIterator, next);
+ZEND_METHOD(InternalIterator, valid);
+ZEND_METHOD(InternalIterator, rewind);
static const zend_function_entry class_Traversable_methods[] = {
ZEND_ABSTRACT_ME_WITH_FLAGS(Stringable, __toString, arginfo_class_Stringable___toString, ZEND_ACC_PUBLIC|ZEND_ACC_ABSTRACT)
ZEND_FE_END
};
+
+
+static const zend_function_entry class_InternalIterator_methods[] = {
+ ZEND_ME(InternalIterator, __construct, arginfo_class_InternalIterator___construct, ZEND_ACC_PRIVATE)
+ ZEND_ME(InternalIterator, current, arginfo_class_InternalIterator_current, ZEND_ACC_PUBLIC)
+ ZEND_ME(InternalIterator, key, arginfo_class_InternalIterator_key, ZEND_ACC_PUBLIC)
+ ZEND_ME(InternalIterator, next, arginfo_class_InternalIterator_next, ZEND_ACC_PUBLIC)
+ ZEND_ME(InternalIterator, valid, arginfo_class_InternalIterator_valid, ZEND_ACC_PUBLIC)
+ ZEND_ME(InternalIterator, rewind, arginfo_class_InternalIterator_rewind, ZEND_ACC_PUBLIC)
+ ZEND_FE_END
+};
RETURN_LONG(count);
}
+ZEND_METHOD(WeakMap, getIterator)
+{
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ zend_create_internal_iterator_zval(return_value, ZEND_THIS);
+}
+
void zend_register_weakref_ce(void) /* {{{ */
{
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "WeakMap", class_WeakMap_methods);
zend_ce_weakmap = zend_register_internal_class(&ce);
zend_ce_weakmap->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NO_DYNAMIC_PROPERTIES;
+ zend_class_implements(
+ zend_ce_weakmap, 3, zend_ce_arrayaccess, zend_ce_countable, zend_ce_aggregate);
zend_ce_weakmap->create_object = zend_weakmap_create_object;
zend_ce_weakmap->get_iterator = zend_weakmap_get_iterator;
zend_ce_weakmap->serialize = zend_class_serialize_deny;
zend_ce_weakmap->unserialize = zend_class_unserialize_deny;
- /* Must happen after get_iterator is assigned. */
- zend_class_implements(
- zend_ce_weakmap, 3, zend_ce_arrayaccess, zend_ce_countable, zend_ce_traversable);
-
memcpy(&zend_weakmap_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
zend_weakmap_handlers.offset = XtOffsetOf(zend_weakmap, std);
zend_weakmap_handlers.free_obj = zend_weakmap_free_obj;
public function get(): ?object {}
}
-final class WeakMap implements ArrayAccess, Countable, Traversable
+final class WeakMap implements ArrayAccess, Countable, IteratorAggregate
{
/**
* @param object $object
public function offsetUnset($object): void {}
public function count(): int {}
+
+ public function getIterator(): Iterator {}
}
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_WeakMap_count, 0, 0, IS_LONG, 0)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_WeakMap_getIterator, 0, 0, Iterator, 0)
+ZEND_END_ARG_INFO()
+
ZEND_METHOD(WeakReference, __construct);
ZEND_METHOD(WeakReference, create);
ZEND_METHOD(WeakMap, offsetExists);
ZEND_METHOD(WeakMap, offsetUnset);
ZEND_METHOD(WeakMap, count);
+ZEND_METHOD(WeakMap, getIterator);
static const zend_function_entry class_WeakReference_methods[] = {
ZEND_ME(WeakMap, offsetExists, arginfo_class_WeakMap_offsetExists, ZEND_ACC_PUBLIC)
ZEND_ME(WeakMap, offsetUnset, arginfo_class_WeakMap_offsetUnset, ZEND_ACC_PUBLIC)
ZEND_ME(WeakMap, count, arginfo_class_WeakMap_count, ZEND_ACC_PUBLIC)
+ ZEND_ME(WeakMap, getIterator, arginfo_class_WeakMap_getIterator, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
ce_period.create_object = date_object_new_period;
date_ce_period = zend_register_internal_class_ex(&ce_period, NULL);
date_ce_period->get_iterator = date_object_period_get_iterator;
- zend_class_implements(date_ce_period, 1, zend_ce_traversable);
+ zend_class_implements(date_ce_period, 1, zend_ce_aggregate);
memcpy(&date_object_handlers_period, &std_object_handlers, sizeof(zend_object_handlers));
date_object_handlers_period.offset = XtOffsetOf(php_period_obj, std);
date_object_handlers_period.free_obj = date_object_free_storage_period;
}
/* }}} */
+PHP_METHOD(DatePeriod, getIterator)
+{
+ ZEND_PARSE_PARAMETERS_NONE();
+
+ zend_create_internal_iterator_zval(return_value, ZEND_THIS);
+}
+
static int check_id_allowed(char *id, zend_long what) /* {{{ */
{
if ((what & PHP_DATE_TIMEZONE_GROUP_AFRICA) && strncasecmp(id, "Africa/", 7) == 0) return 1;
public static function __set_state(array $array) {}
}
-class DatePeriod implements Traversable
+class DatePeriod implements IteratorAggregate
{
/* Has an overloaded signature */
public function __construct($start, $interval = UNKNOWN, $end = UNKNOWN) {}
/** @return DatePeriod */
public static function __set_state(array $array) {}
+
+ public function getIterator(): Iterator {}
}
#define arginfo_class_DatePeriod___set_state arginfo_class_DateTime___set_state
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_DatePeriod_getIterator, 0, 0, Iterator, 0)
+ZEND_END_ARG_INFO()
+
ZEND_FUNCTION(strtotime);
ZEND_FUNCTION(date);
ZEND_METHOD(DatePeriod, getRecurrences);
ZEND_METHOD(DatePeriod, __wakeup);
ZEND_METHOD(DatePeriod, __set_state);
+ZEND_METHOD(DatePeriod, getIterator);
static const zend_function_entry ext_functions[] = {
ZEND_ME(DatePeriod, getRecurrences, arginfo_class_DatePeriod_getRecurrences, ZEND_ACC_PUBLIC)
ZEND_ME(DatePeriod, __wakeup, arginfo_class_DatePeriod___wakeup, ZEND_ACC_PUBLIC)
ZEND_ME(DatePeriod, __set_state, arginfo_class_DatePeriod___set_state, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+ ZEND_ME(DatePeriod, getIterator, arginfo_class_DatePeriod_getIterator, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
--- /dev/null
+--TEST--
+DatePeriod can be used as an IteratorAggregate
+--FILE--
+<?php
+
+$period = new DatePeriod('R2/2012-07-01T00:00:00Z/P7D');
+foreach ($period as $i => $date) {
+ echo "$i: ", $date->format('Y-m-d'), "\n";
+}
+
+echo "\n";
+foreach ($period->getIterator() as $i => $date) {
+ echo "$i: ", $date->format('Y-m-d'), "\n";
+}
+
+echo "\n";
+$iter = $period->getIterator();
+for (; $iter->valid(); $iter->next()) {
+ $i = $iter->key();
+ $date = $iter->current();
+ echo "$i: ", $date->format('Y-m-d'), "\n";
+}
+
+echo "\n";
+$iter->rewind();
+for (; $iter->valid(); $iter->next()) {
+ $i = $iter->key();
+ $date = $iter->current();
+ echo "$i: ", $date->format('Y-m-d'), "\n";
+}
+
+echo "\n";
+foreach (new IteratorIterator($period) as $i => $date) {
+ echo "$i: ", $date->format('Y-m-d'), "\n";
+}
+
+// Extension that does not overwrite getIterator().
+class MyDatePeriod1 extends DatePeriod {
+}
+
+echo "\n";
+$period = new MyDatePeriod1('R2/2012-07-01T00:00:00Z/P7D');
+foreach ($period as $i => $date) {
+ echo "$i: ", $date->format('Y-m-d'), "\n";
+}
+
+// Extension that does overwrite getIterator().
+class MyDatePeriod2 extends DatePeriod {
+ public function getIterator(): Iterator {
+ return new ArrayIterator([1, 2, 3]);
+ }
+}
+
+echo "\n";
+$period = new MyDatePeriod2('R2/2012-07-01T00:00:00Z/P7D');
+foreach ($period as $i => $notDate) {
+ echo "$i: $notDate\n";
+}
+
+?>
+--EXPECT--
+0: 2012-07-01
+1: 2012-07-08
+2: 2012-07-15
+
+0: 2012-07-01
+1: 2012-07-08
+2: 2012-07-15
+
+0: 2012-07-01
+1: 2012-07-08
+2: 2012-07-15
+
+0: 2012-07-01
+1: 2012-07-08
+2: 2012-07-15
+
+0: 2012-07-01
+1: 2012-07-08
+2: 2012-07-15
+
+0: 2012-07-01
+1: 2012-07-08
+2: 2012-07-15
+
+0: 1
+1: 2
+2: 3
#include "php.h"
#if defined(HAVE_LIBXML) && defined(HAVE_DOM)
#include "php_dom.h"
+#include "zend_interfaces.h"
/*
* class DOMNamedNodeMap
}
/* }}} end dom_namednodemap_count */
+PHP_METHOD(DOMNamedNodeMap, getIterator)
+{
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ zend_create_internal_iterator_zval(return_value, ZEND_THIS);
+}
+
#endif
#include "php.h"
#if defined(HAVE_LIBXML) && defined(HAVE_DOM)
#include "php_dom.h"
+#include "zend_interfaces.h"
/*
* class DOMNodeList
}
/* }}} end dom_nodelist_item */
+ZEND_METHOD(DOMNodeList, getIterator)
+{
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ zend_create_internal_iterator_zval(return_value, ZEND_THIS);
+}
#endif
ce.create_object = dom_nnodemap_objects_new;
dom_nodelist_class_entry = zend_register_internal_class_ex(&ce, NULL);
dom_nodelist_class_entry->get_iterator = php_dom_get_iterator;
- zend_class_implements(dom_nodelist_class_entry, 2, zend_ce_traversable, zend_ce_countable);
+ zend_class_implements(dom_nodelist_class_entry, 2, zend_ce_aggregate, zend_ce_countable);
zend_hash_init(&dom_nodelist_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
dom_register_prop_handler(&dom_nodelist_prop_handlers, "length", sizeof("length")-1, dom_nodelist_length_read, NULL);
ce.create_object = dom_nnodemap_objects_new;
dom_namednodemap_class_entry = zend_register_internal_class_ex(&ce, NULL);
dom_namednodemap_class_entry->get_iterator = php_dom_get_iterator;
- zend_class_implements(dom_namednodemap_class_entry, 2, zend_ce_traversable, zend_ce_countable);
+ zend_class_implements(dom_namednodemap_class_entry, 2, zend_ce_aggregate, zend_ce_countable);
zend_hash_init(&dom_namednodemap_prop_handlers, 0, NULL, dom_dtor_prop_handler, 1);
dom_register_prop_handler(&dom_namednodemap_prop_handlers, "length", sizeof("length")-1, dom_namednodemap_length_read, NULL);
public function prepend(...$nodes): void {}
}
-class DOMNodeList
+class DOMNodeList implements IteratorAggregate, Countable
{
/** @return int|false */
public function count() {}
- /** @return DOMNode|null */
+ public function getIterator(): Iterator {}
+
+ /** @return ?DOMNode */
public function item(int $index) {}
}
public function splitText(int $offset) {}
}
-class DOMNamedNodeMap
+class DOMNamedNodeMap implements IteratorAggregate, Countable
{
/** @return DOMNode|null */
public function getNamedItem(string $name) {}
/** @return int|false */
public function count() {}
+
+ public function getIterator(): Iterator {}
}
class DOMEntity extends DOMNode
#define arginfo_class_DOMNodeList_count arginfo_class_DOMNode_getLineNo
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_DOMNodeList_getIterator, 0, 0, Iterator, 0)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DOMNodeList_item, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, index, IS_LONG, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_DOMNamedNodeMap_count arginfo_class_DOMNode_getLineNo
+#define arginfo_class_DOMNamedNodeMap_getIterator arginfo_class_DOMNodeList_getIterator
+
#define arginfo_class_DOMEntityReference___construct arginfo_class_DOMElement_getAttribute
#define arginfo_class_DOMProcessingInstruction___construct arginfo_class_DOMAttr___construct
ZEND_METHOD(DOMDocumentFragment, append);
ZEND_METHOD(DOMDocumentFragment, prepend);
ZEND_METHOD(DOMNodeList, count);
+ZEND_METHOD(DOMNodeList, getIterator);
ZEND_METHOD(DOMNodeList, item);
ZEND_METHOD(DOMCharacterData, appendData);
ZEND_METHOD(DOMCharacterData, substringData);
ZEND_METHOD(DOMNamedNodeMap, getNamedItemNS);
ZEND_METHOD(DOMNamedNodeMap, item);
ZEND_METHOD(DOMNamedNodeMap, count);
+ZEND_METHOD(DOMNamedNodeMap, getIterator);
ZEND_METHOD(DOMEntityReference, __construct);
ZEND_METHOD(DOMProcessingInstruction, __construct);
#if defined(LIBXML_XPATH_ENABLED)
static const zend_function_entry class_DOMNodeList_methods[] = {
ZEND_ME(DOMNodeList, count, arginfo_class_DOMNodeList_count, ZEND_ACC_PUBLIC)
+ ZEND_ME(DOMNodeList, getIterator, arginfo_class_DOMNodeList_getIterator, ZEND_ACC_PUBLIC)
ZEND_ME(DOMNodeList, item, arginfo_class_DOMNodeList_item, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
ZEND_ME(DOMNamedNodeMap, getNamedItemNS, arginfo_class_DOMNamedNodeMap_getNamedItemNS, ZEND_ACC_PUBLIC)
ZEND_ME(DOMNamedNodeMap, item, arginfo_class_DOMNamedNodeMap_item, ZEND_ACC_PUBLIC)
ZEND_ME(DOMNamedNodeMap, count, arginfo_class_DOMNamedNodeMap_count, ZEND_ACC_PUBLIC)
+ ZEND_ME(DOMNamedNodeMap, getIterator, arginfo_class_DOMNamedNodeMap_getIterator, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
/** @generate-function-entries */
-class IntlBreakIterator implements Traversable
+class IntlBreakIterator implements IteratorAggregate
{
/** @return IntlBreakIterator|null */
public static function createCharacterInstance(?string $locale = null) {}
/** @return bool|null */
public function setText(string $text) {}
+
+ public function getIterator(): Iterator {}
}
class IntlRuleBasedBreakIterator extends IntlBreakIterator
ZEND_ARG_TYPE_INFO(0, text, IS_STRING, 0)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_IntlBreakIterator_getIterator, 0, 0, Iterator, 0)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_IntlRuleBasedBreakIterator___construct, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, rules, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, areCompiled, _IS_BOOL, 0, "false")
ZEND_METHOD(IntlBreakIterator, preceding);
ZEND_METHOD(IntlBreakIterator, previous);
ZEND_METHOD(IntlBreakIterator, setText);
+ZEND_METHOD(IntlBreakIterator, getIterator);
ZEND_METHOD(IntlRuleBasedBreakIterator, __construct);
ZEND_METHOD(IntlRuleBasedBreakIterator, getBinaryRules);
ZEND_METHOD(IntlRuleBasedBreakIterator, getRules);
ZEND_ME(IntlBreakIterator, preceding, arginfo_class_IntlBreakIterator_preceding, ZEND_ACC_PUBLIC)
ZEND_ME(IntlBreakIterator, previous, arginfo_class_IntlBreakIterator_previous, ZEND_ACC_PUBLIC)
ZEND_ME(IntlBreakIterator, setText, arginfo_class_IntlBreakIterator_setText, ZEND_ACC_PUBLIC)
+ ZEND_ME(IntlBreakIterator, getIterator, arginfo_class_IntlBreakIterator_getIterator, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
BreakIterator_handlers.get_debug_info = BreakIterator_get_debug_info;
BreakIterator_handlers.free_obj = BreakIterator_objects_free;
- zend_class_implements(BreakIterator_ce_ptr, 1,
- zend_ce_traversable);
+ zend_class_implements(BreakIterator_ce_ptr, 1, zend_ce_aggregate);
zend_declare_class_constant_long(BreakIterator_ce_ptr,
"DONE", sizeof("DONE") - 1, BreakIterator::DONE );
#include "breakiterator_class.h"
#include "../locale/locale.h"
#include <zend_exceptions.h>
+#include <zend_interfaces.h>
}
using PHP::CodePointBreakIterator;
message = intl_error_get_message(BREAKITER_ERROR_P(bio));
RETURN_STR(message);
}
+
+U_CFUNC PHP_METHOD(IntlBreakIterator, getIterator)
+{
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ zend_create_internal_iterator_zval(return_value, ZEND_THIS);
+}
/** @generate-function-entries */
-class ResourceBundle implements Traversable
+class ResourceBundle implements IteratorAggregate, Countable
{
public function __construct(?string $locale, ?string $bundlename, bool $fallback = true) {}
* @alias resourcebundle_get_error_message
*/
public function getErrorMessage() {}
+
+ public function getIterator(): Iterator {}
}
#define arginfo_class_ResourceBundle_getErrorMessage arginfo_class_ResourceBundle_count
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_ResourceBundle_getIterator, 0, 0, Iterator, 0)
+ZEND_END_ARG_INFO()
+
ZEND_METHOD(ResourceBundle, __construct);
ZEND_FUNCTION(resourcebundle_create);
ZEND_FUNCTION(resourcebundle_locales);
ZEND_FUNCTION(resourcebundle_get_error_code);
ZEND_FUNCTION(resourcebundle_get_error_message);
+ZEND_METHOD(ResourceBundle, getIterator);
static const zend_function_entry class_ResourceBundle_methods[] = {
ZEND_ME_MAPPING(getLocales, resourcebundle_locales, arginfo_class_ResourceBundle_getLocales, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
ZEND_ME_MAPPING(getErrorCode, resourcebundle_get_error_code, arginfo_class_ResourceBundle_getErrorCode, ZEND_ACC_PUBLIC)
ZEND_ME_MAPPING(getErrorMessage, resourcebundle_get_error_message, arginfo_class_ResourceBundle_getErrorMessage, ZEND_ACC_PUBLIC)
+ ZEND_ME(ResourceBundle, getIterator, arginfo_class_ResourceBundle_getIterator, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
}
/* }}} */
+PHP_METHOD(ResourceBundle, getIterator) {
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ zend_create_internal_iterator_zval(return_value, ZEND_THIS);
+}
+
/* {{{ resourcebundle_register_class
* Initialize 'ResourceBundle' class
*/
ResourceBundle_object_handlers.read_dimension = resourcebundle_array_get;
ResourceBundle_object_handlers.count_elements = resourcebundle_array_count;
- zend_class_implements(ResourceBundle_ce_ptr, 2, zend_ce_traversable, zend_ce_countable);
+ zend_class_implements(ResourceBundle_ce_ptr, 2, zend_ce_aggregate, zend_ce_countable);
}
/* }}} */
zend_declare_property_null(ce, "num_rows", sizeof("num_rows") - 1, ZEND_ACC_PUBLIC);
zend_declare_property_null(ce, "type", sizeof("type") - 1, ZEND_ACC_PUBLIC);
mysqli_result_class_entry->get_iterator = php_mysqli_result_get_iterator;
- zend_class_implements(mysqli_result_class_entry, 1, zend_ce_traversable);
+ zend_class_implements(mysqli_result_class_entry, 1, zend_ce_aggregate);
zend_hash_add_ptr(&classes, ce->name, &mysqli_result_properties);
REGISTER_MYSQLI_CLASS_ENTRY("mysqli_stmt", mysqli_stmt_class_entry, class_mysqli_stmt_methods);
}
/* }}} */
+PHP_METHOD(mysqli_result, getIterator)
+{
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ zend_create_internal_iterator_zval(return_value, ZEND_THIS);
+}
+
/* {{{ php_mysqli_fetch_into_hash_aux
*/
void php_mysqli_fetch_into_hash_aux(zval *return_value, MYSQL_RES * result, zend_long fetchtype)
public function refresh(int $options) {}
}
-class mysqli_result
+class mysqli_result implements IteratorAggregate
{
/** @alias mysqli_result_construct */
public function __construct(object $mysqli_link, int $resmode = MYSQLI_STORE_RESULT) {}
* @alias mysqli_free_result
*/
public function free_result() {}
+
+ public function getIterator(): Iterator;
}
class mysqli_stmt
#define arginfo_class_mysqli_result_free_result arginfo_class_mysqli_character_set_name
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_mysqli_result_getIterator, 0, 0, Iterator, 0)
+ZEND_END_ARG_INFO()
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_mysqli_stmt___construct, 0, 0, 1)
ZEND_ARG_OBJ_INFO(0, mysqli_link, mysqli, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, statement, IS_STRING, 1, "null")
#if defined(MYSQLI_USE_MYSQLND)
ZEND_FUNCTION(mysqli_fetch_all);
#endif
+ZEND_METHOD(mysqli_result, getIterator);
ZEND_FUNCTION(mysqli_stmt_construct);
#if defined(MYSQLI_USE_MYSQLND)
ZEND_FUNCTION(mysqli_stmt_more_results);
ZEND_ME_MAPPING(fetch_row, mysqli_fetch_row, arginfo_class_mysqli_result_fetch_row, ZEND_ACC_PUBLIC)
ZEND_ME_MAPPING(field_seek, mysqli_field_seek, arginfo_class_mysqli_result_field_seek, ZEND_ACC_PUBLIC)
ZEND_ME_MAPPING(free_result, mysqli_free_result, arginfo_class_mysqli_result_free_result, ZEND_ACC_PUBLIC)
+ ZEND_ME(mysqli_result, getIterator, arginfo_class_mysqli_result_getIterator, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
'field_seek' => true,
'free' => true,
'free_result' => true,
+ 'getIterator' => true,
);
if ($IS_MYSQLND)
$expected_methods['fetch_all'] = true;
}
/* }}} */
+PHP_METHOD(PDOStatement, getIterator)
+{
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ zend_create_internal_iterator_zval(return_value, ZEND_THIS);
+}
+
/* {{{ overloaded handlers for PDOStatement class */
static zval *dbstmt_prop_write(zend_object *object, zend_string *name, zval *value, void **cache_slot)
{
pdo_dbstmt_ce->create_object = pdo_dbstmt_new;
pdo_dbstmt_ce->serialize = zend_class_serialize_deny;
pdo_dbstmt_ce->unserialize = zend_class_unserialize_deny;
- zend_class_implements(pdo_dbstmt_ce, 1, zend_ce_traversable);
+ zend_class_implements(pdo_dbstmt_ce, 1, zend_ce_aggregate);
zend_declare_property_null(pdo_dbstmt_ce, "queryString", sizeof("queryString")-1, ZEND_ACC_PUBLIC);
memcpy(&pdo_dbstmt_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
/** @generate-function-entries */
-class PDOStatement implements Traversable
+class PDOStatement implements IteratorAggregate
{
/**
* @param mixed $driverdata
/** @return bool */
public function setFetchMode(int $mode, $param1 = UNKNOWN, $param2 = UNKNOWN) {}
+
+ public function getIterator(): Iterator {}
}
final class PDORow
ZEND_ARG_INFO(0, param2)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_PDOStatement_getIterator, 0, 0, Iterator, 0)
+ZEND_END_ARG_INFO()
+
ZEND_METHOD(PDOStatement, bindColumn);
ZEND_METHOD(PDOStatement, bindParam);
ZEND_METHOD(PDOStatement, rowCount);
ZEND_METHOD(PDOStatement, setAttribute);
ZEND_METHOD(PDOStatement, setFetchMode);
+ZEND_METHOD(PDOStatement, getIterator);
static const zend_function_entry class_PDOStatement_methods[] = {
ZEND_ME(PDOStatement, rowCount, arginfo_class_PDOStatement_rowCount, ZEND_ACC_PUBLIC)
ZEND_ME(PDOStatement, setAttribute, arginfo_class_PDOStatement_setAttribute, ZEND_ACC_PUBLIC)
ZEND_ME(PDOStatement, setFetchMode, arginfo_class_PDOStatement_setFetchMode, ZEND_ACC_PUBLIC)
+ ZEND_ME(PDOStatement, getIterator, arginfo_class_PDOStatement_getIterator, ZEND_ACC_PUBLIC)
ZEND_FE_END
};
/* default fetch mode is BOTH, so we see if the ctor can overwrite that */
}
- function getIterator()
+ function getIterator(): Iterator
{
echo __METHOD__ . "\n";
$this->execute();