bluetree-service/filesystem

View on GitHub
src/StaticObjects/Structure.php

Summary

Maintainability
A
1 hr
Test Coverage
<?php

namespace BlueFilesystem\StaticObjects;

class Structure implements FsInterface
{
    /**
     * @var array
     */
    protected $dirTree = [];

    /**
     * @var array
     */
    protected $paths = [
        'dir' => [],
        'file' => [],
    ];

    /**
     * @var string
     */
    protected $path;

    /**
     * @var bool
     */
    protected $recursive;

    /**
     * @param string $path
     * @param bool $recursive
     * @example new Structure('dir/some_dir')
     * @example new Structure('dir/some_dir', true)
     */
    public function __construct(string $path, bool $recursive = false)
    {
        $this->path = $path;
        $this->recursive = $recursive;

        $this->readDirectory($path, $recursive);
    }

    /**
     * re read directory content, (optionally all sub folders)
     *
     * @param string $path
     * @param boolean $recursive
     * @return array
     * @example readDirectory('dir/some_dir')
     * @example readDirectory('dir/some_dir', true)
     */
    public function readDirectory(string $path, bool $recursive = false): array
    {
        $this->dirTree = $this->readDirectoryRecursive($path, $recursive);

        return $this->dirTree;
    }

    /**
     * @param string $path
     * @param boolean $recursive
     * @return array
     */
    protected function readDirectoryRecursive(string $path, bool $recursive): array
    {
        $list = [];

        if (!self::exist($path)) {
            return [];
        }

        $iterator = new \DirectoryIterator($path);

        /** @var \DirectoryIterator $element */
        foreach ($iterator as $element) {
            if ($element->isDot()) {
                continue;
            }

            //@todo save dir asSplFileInfo
            if ($recursive && $element->isDir()) {
                $list[$element->getRealPath()] = $this->readDirectoryRecursive($element->getRealPath(), true);
            } else {
                $list[$element->getRealPath()] = $element->getFileInfo();
            }
        }

        return $list;
    }

    /**
     * @return array
     */
    public function getReadDirectory(): array
    {
        return $this->dirTree;
    }

    /**
     * @return array
     */
    public function getPaths(): array
    {
        return $this->paths;
    }

    /**
     * transform array wit directory/files tree to list of paths grouped on files and directories
     *
     * @param boolean $reverse if TRUE revert array (required for deleting)
     * @internal param string $path base path for elements, if empty use paths from transformed structure
     * @return array array with path list for files and directories
     * @example returnPaths(true)
     * @example returnPaths()
     */
    public function returnPaths(bool $reverse = false): array
    {
        $array = $this->dirTree;

        if ($reverse) {
            $array = \array_reverse($array);
        }

        $this->paths = $this->returnPathsRecursive($array);

        return $this->paths;
    }

    /**
     * @param callable $callback
     * @param bool $reload
     */
    public function processSplObjects(callable $callback, bool $reload = true): void
    {
        $this->processSplObjectsStructure($callback, $this->dirTree);

        if ($reload) {
            $this->dirTree = $this->readDirectory($this->path, $this->recursive);
        }
    }

    /**
     * @param callable $callback
     * @param array $array
     */
    protected function processSplObjectsStructure(callable $callback, array $array): void
    {
        foreach ($array as $path => $fileInfo) {
            $isDir = \is_dir($path);
            if (\is_array($fileInfo) && $isDir) {
                $this->processSplObjectsStructure($callback, $fileInfo);
                $callback(new \SplFileInfo($path), $path);
            } else {
                $callback($fileInfo, $path);
            }
        }
    }

    /**
     * transform array wit directory/files tree to list of paths grouped on files and directories
     *
     * @param array $array array to transform
     * @internal param string $path base path for elements, if empty use paths from transformed structure
     * @return array array with path list for files and directories
     * @example returnPaths(true)
     * @example returnPaths()
     */
    protected function returnPathsRecursive(array $array): array
    {
        $pathList = [
            'dir' => [],
            'file' => [],
        ];

        foreach ($array as $path => $fileInfo) {
            $isDir = \is_dir($path);

            if (\is_array($fileInfo) && $isDir) {
                $list = $this->returnPathsRecursive($fileInfo);

                /** @var string $element */
                foreach ($list as $element => $value) {
                    $pathList = $this->setPath($pathList, $element, $value, 'file');
                    $pathList = $this->setPath($pathList, $element, $value, 'dir');
                }

                $pathList['dir'][] = $path;
            } else {
                /** @var \DirectoryIterator $fileInfo */
                $pathList['file'][] = $fileInfo->getRealPath();
            }
        }

        return $pathList;
    }

    /**
     * check that file exists
     *
     * @param string $path
     * @return boolean true if exists, false if not
     */
    public static function exist(string $path): bool
    {
        return \file_exists($path);
    }

    /**
     * @param array $pathList
     * @param string $key
     * @param array $value
     * @param string $type
     * @return array
     */
    protected function setPath(array $pathList, string $key, array $value, string $type): array
    {
        if ($key === $type) {
            foreach ($value as $path) {
                $pathList[$type][] = $path;
            }
        }

        return $pathList;
    }
}