protected function _list($path, $prefix = '', $mode = 'file', $recursive = false, $filter = null)
    {
        $files  = [];
        $ignore = ['.', '..', '.DS_Store', '.svn', '.git', '.gitignore', '.gitmodules', 'cgi-bin'];

        if ($scan = @scandir($path)) {
            foreach ($scan as $file) {
                // continue if ignore match
                if (Arr::in($file, $ignore)) {
                    continue;
                }

                if (is_dir($path . '/' . $file)) {
                    // add dir
                    if ($mode === 'dir') {
                        // continue if no regex filter match
                        if ($filter && !preg_match($filter, $file)) {
                            continue;
                        }

                        $files[] = $prefix . $file;
                    }

                    // continue if not recursive
                    if (!$recursive) {
                        continue;
                    }

                    // read subdirectory
                    $files = array_merge(
                        $files,
                        $this->_list($path . '/' . $file, $prefix . $file . '/', $mode, $recursive, $filter)
                    );

                } else {
                    // add file
                    if ($mode === 'file') {
                        // continue if no regex filter match
                        if ($filter && !preg_match($filter, $file)) {
                            continue;
                        }

                        $files[] = $prefix.$file;
                    }
                }
            }
        }

        return $files;
    }