<?php

namespace goodboyalex\php_components_pack\classes;

/**
 * Класс, реализующий функционал работы с файлами и выполнение операций над файлами одной командой.
 *
 * @author Александр Бабаев
 * @package php_components_pack
 * @version 1.0
 * @since 1.0.21
 */
final class File
{
    /**
     * Получает список файлов в директории и поддиректориях, соответствующей шаблону $pattern.
     *
     * @param string $dir Родительская директория
     * @param string $pattern Шаблон имени файла
     *
     * @return false|array Список файлов или false в случае ошибки
     */
    public static function FindFiles (string $dir, string $pattern = '*.php'): false|array
    {
        // Получаем список файлов и каталогов в текущей директории
        $files = glob("$dir/$pattern");

        // Если произошла ошибка
        if ($files === false)
            // - то возвращаем false
            return false;

        // Перебираем поддиректории
        foreach (glob("$dir/*", GLOB_ONLYDIR | GLOB_NOSORT) as $subDir) {
            // - если ошибка
            if ($subDir === false)
                // - то пропускаем
                continue;

            // - рекурсивный вызов для каждой поддиректории
            $files = array_merge($files, self::FindFiles($subDir, $pattern));
        }

        // Возвращаем список файлов
        return $files;
    }

    /**
     * Получает имя файла без пути к нему и расширения.
     *
     * @param string $fileName Полное имя файла с путем к нему.
     *
     * @return string Имя файла без пути к нему и расширения.
     */
    public static function ExtractFileNameWithoutExtension (string $fileName): string
    {
        // Имя файла без пути к нему
        $fileNameOnly = self::ExtractFileName($fileName);

        // Расширение файла
        $fileExtension = self::ExtractFileExtension($fileName);

        // Возвращаем имя файла без пути к нему и расширения.
        return substr($fileNameOnly, 0, -strlen($fileExtension) - 1);
    }

    /**
     * Получает имя файла без пути к нему, но с расширением.
     *
     * @param string $fileName Полное имя файла с путем к нему.
     *
     * @return string Имя файла без пути к нему, но с расширением.
     */
    public static function ExtractFileName (string $fileName): string
    {
        return basename($fileName);
    }

    /**
     * Получает расширение файла.
     *
     * @param string $fileName Имя файла с путем к нему.
     *
     * @return string Расширение файла.
     */
    public static function ExtractFileExtension (string $fileName): string
    {

        return pathinfo($fileName, PATHINFO_EXTENSION);
    }

    /**
     * Получает относительный путь к файлу, относительно заданной папки
     *
     * @param string $fullPath Полный путь к файлу
     * @param string $basePath Вырезаемый путь (с начала)
     *
     * @return false|string Относительный путь к файлу
     */
    public static function GetRelativePath (string $fullPath, string $basePath): false|string
    {
        return stripos($fullPath, $basePath) !== false ? str_replace($basePath, "", $fullPath) : false;
    }

    /**
     * Удаляет директорию вместе со всеми файлами и поддиректориями.
     *
     * @param string $directory Полный путь к директории.
     *
     * @return bool Результат удаления.
     */
    public static function RemoveDir (string $directory): bool
    {
        // Если директории не существует
        if (!file_exists($directory))
            // - то удаление не требуется
            return true;

        // Если это не директория
        if (!is_dir($directory))
            // - то удаляем файл
            return unlink($directory);

        // Перебираем все файлы и поддиректории
        foreach (scandir($directory) as $item) {
            // - если это '.' или '..'
            if ($item == '.' || $item == '..')
                // -- то пропускаем
                continue;

            // - задаём переменную - целевую директорию
            $target = $directory . DIRECTORY_SEPARATOR . $item;

            // - если это директория
            if (is_dir($target))
                // -- то рекурсивно удаляем её
                if (!self::RemoveDir($target))
                    // --- и прерываем удаление директории, если ошибка
                    return false;
                else
                    // -- иначе удаляем файл
                    unlink($target);
        }

        // Удаляем директорию
        return rmdir($directory);
    }
}