/** * Returns a list of files in the given directory. * * @param string $directory The directory, by default is "." the current directory * @param bool $recursive * @param callable $filter A callable to filter the result, by default is asort() PHP function. * The result is passed in array argument, * must take the argument by reference ! * The callable should proceed with the reference array * because is the behavior of several PHP sorting * functions (by reference ensure directly the compatibility * with all PHP sorting functions). * * @return array * @throws FtpException If unable to list the directory */ 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; }