public function nlist($directory = '.', $recursive = false, $filter = 'sort')
{
if (!$this->isDir($directory)) {
throw new FtpException('"' . $directory . '" is not a directory');
}
$files = $this->ftp->nlist($directory);
if ($files === false) {
throw new FtpException('Unable to list directory');
}
$result = array();
$dir_len = strlen($directory);
// if it's the current
if (false !== ($kdot = array_search('.', $files))) {
unset($files[$kdot]);
}
// if it's the parent
if (false !== ($kdot = array_search('..', $files))) {
unset($files[$kdot]);
}
if (!$recursive) {
foreach ($files as $file) {
$result[] = $directory . '/' . $file;
}
// working with the reference (behavior of several PHP sorting functions)
$filter($result);
return $result;
}
// utils for recursion
$flatten = function (array $arr) use(&$flatten) {
$flat = [];
foreach ($arr as $k => $v) {
if (is_array($v)) {
$flat = array_merge($flat, $flatten($v));
} else {
$flat[] = $v;
}
}
return $flat;
};
foreach ($files as $file) {
$file = $directory . '/' . $file;
// if contains the root path (behavior of the recursivity)
if (0 === strpos($file, $directory, $dir_len)) {
$file = substr($file, $dir_len);
}
if ($this->isDir($file)) {
$result[] = $file;
$items = $flatten($this->nlist($file, true, $filter));
foreach ($items as $item) {
$result[] = $item;
}
} else {
$result[] = $file;
}
}
$result = array_unique($result);
$filter($result);
return $result;
}