-------------------------------------------------------------------------------
DirectoryIterator implements SeekableIterator, which "should throw an
OutOfBoundsException if the position is not seekable". As is, seek just returns
and one must call valid(). This approach is different than most (all?) other
SeekableIterator implementations and leads to developer confusion. See the
bug report for a specific example.
Currently when you use RecursiveDirectoryIterator with the
CURRENT_AS_PATHNAME flag PHP will throw an UnexpectedValueException with
message 'Objects returned by RecursiveIterator::getChildren() must implement
RecursiveIterator'.This happend because getChildren() will return the
current directory name instead of an Iterator (or subclass of) as required
by the RecursiveIterator interface.
This commit changes getChildren() to return annother
RecursiveDirectoryIterator but current() still returns the path name when
CURRENT_AS_PATHNAME is used. A PHPT test case (bug66405.phpt) that
reproduces the bug is included.
This fix was originally against the PHP-5.4 branch, but it was not merged
before 5.4 reached EOL. I am hoping to get it applied to 5.5, 5.6, and
master.
Defining a __toString() method was having no effect when concatenating
the object. This was because the cast_object() handler would ignore
__toString().
Using echo() directly would actually use __toString(), but this was a
bug: the ECHO handler would try zend_std_cast_object_tostring() before
cast_object(), but cast_object() should have priority as
zend_std_cast_object_tostring() assumes an object with a
zend_class_entry.
The solution was already introduced in 5.4 by Etienne Kneuss and
Pierre but wasn't merged back into 5.3 . SplFileObject should
not be used with directories. So just putting together all the
necessary pieces from 5.4
Turns out I'd forgotten to also update the destructor for the iterator
returned by DirectoryIterator.
The iterator for DirectoryIterator maintains the same ->current pointer
throughout its existence (the DirectoryIterator itself) and returns it
(the same object) everytime a value is requested from the iterator.
Moving forward the iterator only changes the object. Previous code
added two references to the object in get_iterator on the account of
1) the iterator memory living in its DirectoryIterator object and
2) the object being stored in iterator->current. This seems to be
unnecessary. Iterators are not responsible for incrementing the refcount
of the values they yield, that's up to the caller (the engine). What
matters for the iterator is that the object exists as long as the
iterator exists and this can be guaranteed by incremented the refcount
only once. Consequently, I only add one reference in get_iterator
(and reclaim it in the iterator destructor).