Kotchasan Framework Documentation

Kotchasan Framework Documentation

File Class - File and Directory Management

EN 05 Feb 2026 07:40

File Class - File and Directory Management

The File class provides utilities for managing files and directories, including copying, listing, creating, and removing directories.

Namespace

Kotchasan\File

Overview

File class provides:

  • Copy entire directories recursively
  • Get file extensions
  • List files in directories and subdirectories
  • Create directories with permissions
  • Remove directories and all contents

API Reference

copyDirectory()

Copy directory and all contents recursively

public static function copyDirectory(string $sourceDir, string $destDir): void

Parameters:

  • $sourceDir - Source directory path (must have trailing /)
  • $destDir - Destination directory path (must have trailing /)

Returns: void

Example:

use Kotchasan\File;

// Copy entire directory
File::copyDirectory('/path/to/source/', '/path/to/destination/');

// Copy theme
File::copyDirectory(
    ROOT_PATH . 'themes/default/',
    ROOT_PATH . 'themes/custom/'
);

// Backup system
class BackupSystem
{
    public function backupTemplate($templateName)
    {
        $source = ROOT_PATH . "templates/{$templateName}/";
        $backup = ROOT_PATH . "backups/" . date('Y-m-d_His') . "_{$templateName}/";

        if (is_dir($source)) {
            File::makeDirectory($backup);
            File::copyDirectory($source, $backup);
            return "Backup created: {$backup}";
        }

        return "Source not found";
    }

    public function duplicateProject($projectName)
    {
        $source = ROOT_PATH . "projects/{$projectName}/";
        $newName = $projectName . '_copy';
        $dest = ROOT_PATH . "projects/{$newName}/";

        File::copyDirectory($source, $dest);

        return "Project duplicated: {$newName}";
    }
}

// Theme installer system
class ThemeInstaller
{
    public function install($themeName)
    {
        $source = ROOT_PATH . "downloads/{$themeName}/";
        $dest = ROOT_PATH . "themes/{$themeName}/";

        if (!is_dir($source)) {
            return ['error' => 'Theme package not found'];
        }

        // Copy theme
        File::copyDirectory($source, $dest);

        // Remove package
        File::removeDirectory($source);

        return ['success' => "Theme {$themeName} installed"];
    }
}

ext()

Get file extension

public static function ext(string $path): string

Parameters:

  • $path - File path or filename

Returns: File extension (lowercase)

Example:

use Kotchasan\File;

// Basic usage
echo File::ext('config.php');              // "php"
echo File::ext('image.JPG');               // "jpg"
echo File::ext('document.pdf');            // "pdf"
echo File::ext('/path/to/file.txt');       // "txt"
echo File::ext('archive.tar.gz');          // "gz"

// Check file type
function isImageFile($filename)
{
    $imageExts = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
    return in_array(File::ext($filename), $imageExts);
}

echo isImageFile('photo.jpg') ? 'Yes' : 'No';  // "Yes"
echo isImageFile('document.pdf') ? 'Yes' : 'No';  // "No"

// File upload validation
class FileUpload
{
    private $allowedExts = ['jpg', 'png', 'pdf', 'doc', 'docx'];

    public function validate($filename)
    {
        $ext = File::ext($filename);

        if (!in_array($ext, $this->allowedExts)) {
            return [
                'valid' => false,
                'error' => "File type .{$ext} not allowed"
            ];
        }

        return ['valid' => true];
    }

    public function getFileType($filename)
    {
        $ext = File::ext($filename);

        $types = [
            'jpg' => 'image', 'png' => 'image', 'gif' => 'image',
            'pdf' => 'document', 'doc' => 'document', 'docx' => 'document',
            'mp4' => 'video', 'avi' => 'video',
            'mp3' => 'audio', 'wav' => 'audio'
        ];

        return $types[$ext] ?? 'unknown';
    }
}

$upload = new FileUpload();
echo $upload->getFileType('photo.jpg');  // "image"
echo $upload->getFileType('report.pdf'); // "document"

// File icon mapping
class FileIcon
{
    public static function getIcon($filename)
    {
        $ext = File::ext($filename);

        $icons = [
            'php' => '📄', 'js' => '📜', 'css' => '🎨',
            'jpg' => '🖼️', 'png' => '🖼️', 'gif' => '🖼️',
            'pdf' => '📕', 'doc' => '📘', 'xls' => '📊',
            'zip' => '📦', 'rar' => '📦',
            'mp4' => '🎬', 'mp3' => '🎵'
        ];

        return $icons[$ext] ?? '📄';
    }
}

echo FileIcon::getIcon('photo.jpg');   // "🖼️"
echo FileIcon::getIcon('music.mp3');   // "🎵"

listFiles()

List all files in directory and subdirectories

public static function listFiles(
    string $dir,
    array &$result,
    array $filter = []
): void

Parameters:

  • $dir - Directory path (must have trailing /)
  • $result - Array to store results (passed by reference)
  • $filter - Array of file extensions to filter (optional, lowercase)

Returns: void (results stored in $result)

Example:

use Kotchasan\File;

// List all files
$files = [];
File::listFiles('/path/to/directory/', $files);
print_r($files);

// Filter PHP files only
$phpFiles = [];
File::listFiles(ROOT_PATH . 'app/', $phpFiles, ['php']);
foreach ($phpFiles as $file) {
    echo $file . "\n";
}

// Find all images
$images = [];
File::listFiles(ROOT_PATH . 'uploads/', $images, ['jpg', 'png', 'gif']);
echo "Found " . count($images) . " images\n";

// File search system
class FileSearch
{
    public function findByExtension($dir, $extensions)
    {
        $files = [];
        File::listFiles($dir, $files, $extensions);
        return $files;
    }

    public function findByPattern($dir, $pattern)
    {
        $allFiles = [];
        File::listFiles($dir, $allFiles);

        return array_filter($allFiles, function($file) use ($pattern) {
            return strpos(basename($file), $pattern) !== false;
        });
    }

    public function getFileStats($dir)
    {
        $files = [];
        File::listFiles($dir, $files);

        $stats = [
            'total' => count($files),
            'size' => 0,
            'types' => []
        ];

        foreach ($files as $file) {
            $stats['size'] += filesize($file);
            $ext = File::ext($file);
            $stats['types'][$ext] = ($stats['types'][$ext] ?? 0) + 1;
        }

        return $stats;
    }
}

// Code analyzer
class CodeAnalyzer
{
    public function countLines($dir)
    {
        $phpFiles = [];
        File::listFiles($dir, $phpFiles, ['php']);

        $totalLines = 0;
        foreach ($phpFiles as $file) {
            $lines = count(file($file));
            $totalLines += $lines;
        }

        return [
            'files' => count($phpFiles),
            'lines' => $totalLines,
            'average' => round($totalLines / max(count($phpFiles), 1))
        ];
    }
}

// Media library
class MediaLibrary
{
    public function getImages($uploadDir)
    {
        $images = [];
        File::listFiles($uploadDir, $images, ['jpg', 'jpeg', 'png', 'gif', 'webp']);

        $result = [];
        foreach ($images as $path) {
            $result[] = [
                'path' => $path,
                'name' => basename($path),
                'size' => filesize($path),
                'modified' => filemtime($path)
            ];
        }

        return $result;
    }
}

makeDirectory()

Create directory with permissions validation

public static function makeDirectory(string $dir, int $mode = 0755): bool

Parameters:

  • $dir - Directory path to create
  • $mode - Permission mode (default: 0755)

Returns: true = created/writable, false = failed

Example:

use Kotchasan\File;

// Create basic directory
$success = File::makeDirectory('/path/to/newdir/');
if ($success) {
    echo "Directory created";
} else {
    echo "Failed to create directory";
}

// With custom permissions
File::makeDirectory('/path/to/dir/', 0777);  // Full permission
File::makeDirectory('/path/to/dir/', 0755);  // Owner rwx, others rx

// Upload system
class UploadManager
{
    public function prepareUploadDirectory($userId)
    {
        $userDir = ROOT_PATH . "uploads/user_{$userId}/";

        if (!File::makeDirectory($userDir)) {
            return ['error' => 'Cannot create upload directory'];
        }

        // Create directory structure
        File::makeDirectory($userDir . 'images/');
        File::makeDirectory($userDir . 'documents/');
        File::makeDirectory($userDir . 'videos/');

        return ['success' => 'Upload directory ready'];
    }
}

// Cache system
class CacheManager
{
    private $cacheDir;

    public function __construct()
    {
        $this->cacheDir = ROOT_PATH . 'storage/cache/';
        File::makeDirectory($this->cacheDir);
    }

    public function write($key, $data, $ttl = 3600)
    {
        $file = $this->cacheDir . md5($key) . '.cache';

        $cacheData = [
            'expires' => time() + $ttl,
            'data' => $data
        ];

        file_put_contents($file, serialize($cacheData));
    }

    public function read($key)
    {
        $file = $this->cacheDir . md5($key) . '.cache';

        if (!file_exists($file)) {
            return null;
        }

        $cacheData = unserialize(file_get_contents($file));

        if ($cacheData['expires'] < time()) {
            unlink($file);
            return null;
        }

        return $cacheData['data'];
    }
}

// Log system
class Logger
{
    private $logDir;

    public function __construct()
    {
        $this->logDir = ROOT_PATH . 'storage/logs/';

        if (!File::makeDirectory($this->logDir)) {
            throw new \Exception('Cannot create log directory');
        }
    }

    public function log($level, $message)
    {
        $date = date('Y-m-d');
        $logFile = $this->logDir . "{$level}_{$date}.log";

        $entry = sprintf(
            "[%s] [%s] %s\n",
            date('Y-m-d H:i:s'),
            strtoupper($level),
            $message
        );

        file_put_contents($logFile, $entry, FILE_APPEND);
    }
}

removeDirectory()

Remove directory and all contents recursively

public static function removeDirectory(string $dir, bool $removeSelf = true): void

Parameters:

  • $dir - Directory path to remove (must have trailing /)
  • $removeSelf - true = remove directory itself, false = remove only contents

Returns: void

Example:

use Kotchasan\File;

// Remove entire directory
File::removeDirectory('/path/to/directory/');

// Remove only contents (keep directory)
File::removeDirectory('/path/to/cache/', false);

// Cleanup system
class CleanupManager
{
    public function clearCache()
    {
        $cacheDir = ROOT_PATH . 'storage/cache/';

        // Clear all cache files but keep directory
        File::removeDirectory($cacheDir, false);

        return "Cache cleared";
    }

    public function clearOldLogs($daysOld = 30)
    {
        $logDir = ROOT_PATH . 'storage/logs/';
        $files = [];
        File::listFiles($logDir, $files, ['log']);

        $cutoff = time() - ($daysOld * 86400);
        $removed = 0;

        foreach ($files as $file) {
            if (filemtime($file) < $cutoff) {
                unlink($file);
                $removed++;
            }
        }

        return "Removed {$removed} old log files";
    }

    public function clearTempFiles()
    {
        $tempDir = ROOT_PATH . 'storage/temp/';
        File::removeDirectory($tempDir, false);

        return "Temp files cleared";
    }
}

// Uninstaller
class ModuleUninstaller
{
    public function uninstall($moduleName)
    {
        $moduleDir = ROOT_PATH . "modules/{$moduleName}/";

        if (!is_dir($moduleDir)) {
            return ['error' => 'Module not found'];
        }

        // Remove entire module directory
        File::removeDirectory($moduleDir);

        return ['success' => "Module {$moduleName} uninstalled"];
    }

    public function reset($moduleName)
    {
        $dataDir = ROOT_PATH . "modules/{$moduleName}/data/";

        // Remove data but keep structure
        File::removeDirectory($dataDir, false);

        return ['success' => "Module {$moduleName} reset"];
    }
}

// Backup rotation
class BackupRotation
{
    private $backupDir;
    private $maxBackups = 5;

    public function __construct($backupDir)
    {
        $this->backupDir = $backupDir;
        File::makeDirectory($backupDir);
    }

    public function rotate()
    {
        $backups = [];
        File::listFiles($this->backupDir, $backups);

        // Sort by time (oldest first)
        usort($backups, function($a, $b) {
            return filemtime($a) - filemtime($b);
        });

        // Remove old backups exceeding limit
        $toRemove = count($backups) - $this->maxBackups;
        if ($toRemove > 0) {
            for ($i = 0; $i < $toRemove; $i++) {
                if (is_dir($backups[$i])) {
                    File::removeDirectory($backups[$i]);
                } else {
                    unlink($backups[$i]);
                }
            }
        }

        return "Kept latest {$this->maxBackups} backups";
    }
}

Real-World Examples

1. Asset Compiler System

use Kotchasan\File;

class AssetCompiler
{
    public function compileAssets()
    {
        $sourceDir = ROOT_PATH . 'resources/';
        $buildDir = ROOT_PATH . 'public/assets/';

        // Create build directory
        File::makeDirectory($buildDir);

        // Clear previous build
        File::removeDirectory($buildDir, false);

        // Find CSS files
        $cssFiles = [];
        File::listFiles($sourceDir . 'css/', $cssFiles, ['css']);

        // Find JS files
        $jsFiles = [];
        File::listFiles($sourceDir . 'js/', $jsFiles, ['js']);

        // Compile CSS
        $this->compileCss($cssFiles, $buildDir . 'app.css');

        // Compile JS
        $this->compileJs($jsFiles, $buildDir . 'app.js');

        // Copy images
        File::copyDirectory(
            $sourceDir . 'images/',
            $buildDir . 'images/'
        );

        return "Assets compiled successfully";
    }

    private function compileCss($files, $output)
    {
        $combined = '';
        foreach ($files as $file) {
            $combined .= file_get_contents($file) . "\n";
        }
        file_put_contents($output, $combined);
    }

    private function compileJs($files, $output)
    {
        $combined = '';
        foreach ($files as $file) {
            $combined .= file_get_contents($file) . ";\n";
        }
        file_put_contents($output, $combined);
    }
}

2. File Manager System

class FileManager
{
    private $baseDir;

    public function __construct($baseDir)
    {
        $this->baseDir = rtrim($baseDir, '/') . '/';
        File::makeDirectory($this->baseDir);
    }

    public function listDirectory($path = '')
    {
        $fullPath = $this->baseDir . $path;

        if (!is_dir($fullPath)) {
            return ['error' => 'Directory not found'];
        }

        $items = [];
        $handle = opendir($fullPath);

        while (false !== ($item = readdir($handle))) {
            if ($item === '.' || $item === '..') {
                continue;
            }

            $itemPath = $fullPath . $item;
            $isDir = is_dir($itemPath);

            $items[] = [
                'name' => $item,
                'type' => $isDir ? 'directory' : 'file',
                'size' => $isDir ? null : filesize($itemPath),
                'extension' => $isDir ? null : File::ext($item),
                'modified' => filemtime($itemPath)
            ];
        }

        closedir($handle);
        return $items;
    }

    public function createDirectory($path)
    {
        $fullPath = $this->baseDir . $path . '/';

        if (File::makeDirectory($fullPath)) {
            return ['success' => 'Directory created'];
        }

        return ['error' => 'Cannot create directory'];
    }

    public function deleteDirectory($path)
    {
        $fullPath = $this->baseDir . $path . '/';

        File::removeDirectory($fullPath);
        return ['success' => 'Directory deleted'];
    }

    public function copyDirectory($source, $dest)
    {
        $sourcePath = $this->baseDir . $source . '/';
        $destPath = $this->baseDir . $dest . '/';

        File::makeDirectory($destPath);
        File::copyDirectory($sourcePath, $destPath);

        return ['success' => 'Directory copied'];
    }
}

Best Practices

1. Use Trailing Slash

// ✅ Good - has trailing slash
File::copyDirectory('/path/to/source/', '/path/to/dest/');
File::listFiles('/path/to/dir/', $files);

// ❌ Bad - no trailing slash (may cause errors)
File::copyDirectory('/path/to/source', '/path/to/dest');

2. Check Permissions Before Use

// ✅ Good
if (File::makeDirectory($dir)) {
    // Proceed
} else {
    // Handle error
}

// ❌ Bad
File::makeDirectory($dir); // No return value check

3. Be Careful When Deleting Directories

// ✅ Good - with confirmation
function deleteUserData($userId)
{
    $confirm = readline("Delete all data for user {$userId}? (yes/no): ");
    if ($confirm === 'yes') {
        File::removeDirectory("/data/users/{$userId}/");
    }
}

// ❌ Bad - deletes immediately without confirmation
File::removeDirectory($dir); // Dangerous!

4. Filter File Extensions

// ✅ Good - filter only what you need
$images = [];
File::listFiles($dir, $images, ['jpg', 'png']);

// ❌ Bad - gets all files
$all = [];
File::listFiles($dir, $all);  // May include unwanted files

Important Considerations

[!WARNING]
removeDirectory(): Permanently deletes files, cannot be recovered. Use with caution!

[!IMPORTANT]
Permissions: Ensure proper read/write/delete permissions in operating system

[!NOTE]
Trailing Slash: Methods accepting directory paths require trailing /

[!TIP]
Error Handling: Methods use @ to suppress warnings, check return values

  • [Files] - File upload and validation
  • Image - Image processing

Summary

File class has 5 main methods:

  1. copyDirectory() - Copy entire directory
  2. ext() - Get file extension
  3. listFiles() - List files with filtering
  4. makeDirectory() - Create directory with permissions
  5. removeDirectory() - Remove directory and contents

Perfect for:

  • File management systems
  • Backup/Restore systems
  • Asset compilation
  • Cache management
  • Module/Plugin systems