zval_ptr_dtor(&retval);
}
if (intern->u.caching.flags & CIT_CALL_TOSTRING) {
+#if MBO_0
+ /* This version requires zend_make_printable_zval() being able to
+ * call __toString().
+ */
int use_copy;
zval expr_copy;
ALLOC_ZVAL(intern->u.caching.zstr);
} else {
zval_copy_ctor(intern->u.caching.zstr);
}
+#else
+ zval expr_copy;
+ if (intern->current.data->value.obj.handlers->cast_object &&
+ intern->current.data->value.obj.handlers->cast_object(intern->current.data, &expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS)
+ {
+ ALLOC_ZVAL(intern->u.caching.zstr);
+ *intern->u.caching.zstr = expr_copy;
+ INIT_PZVAL(intern->u.caching.zstr);
+ zval_copy_ctor(intern->u.caching.zstr);
+ zval_dtor(&expr_copy);
+ } else {
+ zend_class_entry *ce_data = spl_get_class_entry(intern->current.data TSRMLS_CC);
+ if (ce_data && zend_hash_exists(&ce_data->function_table, "__tostring", sizeof("__tostring"))) {
+ zend_call_method_with_0_params(&intern->current.data, ce_data, NULL, "__tostring", &intern->u.caching.zstr);
+ } else {
+ ALLOC_ZVAL(intern->u.caching.zstr);
+ *intern->u.caching.zstr = *intern->current.data;
+ zval_copy_ctor(intern->u.caching.zstr);
+ INIT_PZVAL(intern->u.caching.zstr);
+ convert_to_string(intern->u.caching.zstr);
+ }
+ }
+#endif
}
spl_dual_it_next(intern, 0 TSRMLS_CC);
} else {
--- /dev/null
+--TEST--
+SPL: CachingIterator and __toString()
+--SKIPIF--
+<?php if (!extension_loaded("spl")) print "skip"; ?>
+--FILE--
+<?php
+
+class Student
+{
+ private $id;
+ private $name;
+
+ public function __construct($id, $name)
+ {
+ $this->id = $id;
+ $this->name = $name;
+ }
+
+ public function __toString()
+ {
+ return $this->id . ', ' . $this->name;
+ }
+
+ public function getId()
+ {
+ return $this->id;
+ }
+}
+
+class StudentIdFilter extends FilterIterator
+{
+ private $id;
+
+ public function __construct(ArrayObject $students, Student $other)
+ {
+ FilterIterator::__construct($students->getIterator());
+ $this->id = $other->getId();
+ }
+
+ public function accept()
+ {
+ echo "ACCEPT ".$this->current()->getId()." == ".$this->id."\n";
+ return $this->current()->getId() == $this->id;
+ }
+}
+
+class StudentList implements IteratorAggregate
+{
+ private $students;
+
+ public function __construct()
+ {
+ $this->students = new ArrayObject(array());
+ }
+
+ public function add(Student $student)
+ {
+ if (!$this->contains($student)) {
+ $this->students[] = $student;
+ }
+ }
+
+ public function contains(Student $student)
+ {
+ foreach ($this->students as $s)
+ {
+ if ($s->getId() == $student->getId()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public function getIterator() {
+ return new CachingIterator($this->students->getIterator(), true);
+ }
+}
+
+$students = new StudentList();
+$students->add(new Student('01234123', 'Joe'));
+$students->add(new Student('00000014', 'Bob'));
+$students->add(new Student('00000014', 'Foo'));
+
+// The goal is to verify we can access the cached string value even if it was
+// generated by a call to __toString(). To check this we need to access the
+// iterator's __toString() method.
+$it = $students->getIterator();
+foreach ($it as $student) {
+ echo $it->__toString(), "\n";
+}
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECT--
+01234123, Joe
+00000014, Bob
+===DONE===