php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Doc Bug #80724 FilesystemIterator::FOLLOW_SYMLINKS remove KEY_AS_FILE from bitmask
Submitted: 2021-02-09 14:05 UTC Modified: 2021-02-15 09:07 UTC
From: antonfedonyuk at gmail dot com Assigned:
Status: Closed Package: SPL related
PHP Version: 7.3.27 OS: Any
Private report: No CVE-ID: None
 [2021-02-09 14:05 UTC] antonfedonyuk at gmail dot com
Description:
------------
---
From manual page: https://php.net/class.filesystemiterator
---
Flag FilesystemIterator::FOLLOW_SYMLINKS remove FilesystemIterator::KEY_AS_FILENAME from bitmask like this:
FilesystemIterator::KEY_AS_FILENAME | FilesystemIterator::FOLLOW_SYMLINKS

Test script:
---------------
<?php
// __DIR__ contains only self - 'test.php'
$iterator = new FilesystemIterator(__DIR__, FilesystemIterator::KEY_AS_FILENAME);
foreach ($iterator as $key => $value) {
    echo $key;
}

$iterator2 = new FilesystemIterator(__DIR__, FilesystemIterator::FOLLOW_SYMLINKS | FilesystemIterator::KEY_AS_FILENAME);
foreach ($iterator2 as $key => $value) {
    echo $key;
}


Expected result:
----------------
iterator: 'test.php'
iterator2: 'test.php'

Actual result:
--------------
iterator: 'test.php'
iterator2: 'path/test.php'

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-02-12 10:15 UTC] cmb@php.net
-Type: Bug +Type: Documentation Problem
 [2021-02-12 10:15 UTC] cmb@php.net
This behavior seems to be a deliberate design decision[1]; it
actually makes some sense, since you don't want to get the
basename only for symlinks, and mixing basenames and paths could
be confusing an error prone.

This needs to be documented, though.

[1] <https://github.com/php/php-src/blob/php-7.4.15/ext/spl/spl_directory.h#L139-L143>
 [2021-02-15 05:10 UTC] camporter1 at gmail dot com
I noticed this testing something where I needed both FOLLOW_SYMLINKS and KEY_AS_FILENAME as well.

I've submitted https://github.com/php/php-src/pull/6695 to change the behavior and test even though there might be disagreement about whether this is intentional behavior...
 [2021-02-15 09:07 UTC] antonfedonyuk at gmail dot com
cmb@php.net FilesystemIterator::getFilename() work in any case, symlink not pathname - FilesystemIterator::key() mix links and paths - it's too wrong. FilesystemIterator::FOLLOW_SYMLINKS change keys of FilesystemIterator, but manual says:
> makes RecursiveDirectoryIterator::hasChildren() follow symlinks. 

camporter1@dot.com your test for php8, I display results for php7

$iterator = new FilesystemIterator(__DIR__, FilesystemIterator::KEY_AS_FILENAME);
foreach ($iterator as $key => $value) {
    var_export(strpos($key, __DIR__ . DIRECTORY_SEPARATOR) !== false);
    break;
}
$iterator->rewind();
var_export(strpos($iterator->key(), __DIR__ . DIRECTORY_SEPARATOR) !== false);

$iterator2 = new FilesystemIterator(__DIR__, FilesystemIterator::FOLLOW_SYMLINKS | FilesystemIterator::KEY_AS_FILENAME);
foreach ($iterator2 as $key => $value) {
    var_export(strpos($key, __DIR__ . DIRECTORY_SEPARATOR) !== false);
    break;
}
$iterator2->rewind();
var_export(strpos($iterator2->key(), __DIR__ . DIRECTORY_SEPARATOR) !== false);

// result: false false true true
// tested on PHP 7.3.26, Windows 10, MSVC15(Visual C++ 2017)
 [2021-02-23 08:50 UTC] nikic@php.net
Automatic comment on behalf of camporter1@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=24e7299c9d7b9d41a50da591b9230c87deafcf4e
Log: Fixed bug #80724
 [2021-02-23 08:50 UTC] nikic@php.net
-Status: Open +Status: Closed
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Thu Dec 02 11:03:35 2021 UTC