adachsoft / filesystem
A flexible and powerful PHP filesystem library for handling files and directories
Requires
- adachsoft/collection: dev-main
Requires (Dev)
- phpunit/phpunit: ^12.3
This package is not auto-updated.
Last update: 2025-09-15 09:02:09 UTC
README
A robust PHP filesystem abstraction library providing both physical and in-memory filesystem implementations with security features and comprehensive error handling.
๐ Features
- Dual filesystem implementations: Physical filesystem and in-memory filesystem
- Security-first design: Path traversal protection and input validation
- Immutable models: Path, FileInfo, and FileSearchCriteria classes
- Comprehensive error handling: Custom exception hierarchy
- Collection support: PathCollection integration with AdachSoft Collection
- File search capabilities: Advanced file filtering with criteria
- Cross-platform compatibility: Unix and Windows path normalization
- PSR-4 autoloading: Modern PHP standards
๐ฆ Installation
Method 1: Composer Configuration via CLI (Recommended)
Add the private repository and install:
# Add the filesystem repository
composer config repositories.adachsoft/filesystem vcs https://gitlab.com/a.adach/filesystem.git
# Add the collections dependency repository
composer config repositories.adachsoft/collection vcs https://gitlab.com/a.adach/collections.git
# Install the package
composer require adachsoft/filesystem
Method 2: Manual composer.json Configuration
Add the repositories to your composer.json
:
{
"repositories": [
{
"type": "vcs",
"url": "https://gitlab.com/a.adach/filesystem.git"
},
{
"type": "vcs",
"url": "https://gitlab.com/a.adach/collections.git"
}
],
"require": {
"adachsoft/filesystem": "^1.0"
}
}
Then run:
composer install
Method 3: One-liner Command
Execute all commands at once:
composer config repositories.adachsoft/filesystem vcs https://gitlab.com/a.adach/filesystem.git && composer config repositories.adachsoft/collection vcs https://gitlab.com/a.adach/collections.git && composer require adachsoft/filesystem
๐ฏ Quick Start
Physical FileSystem
<?php
use AdachSoft\FileSystem\PhysicalFileSystem;
use AdachSoft\FileSystem\Model\Path;
// Create filesystem instance with base directory
$fs = new PhysicalFileSystem('/var/www/project');
// Write a file
$fs->writeFile(new Path('config/app.yml'), 'database: mysql');
// Read a file
$content = $fs->readFile(new Path('config/app.yml'));
// Check if file exists
if ($fs->fileExists(new Path('config/app.yml'))) {
echo "File exists!";
}
// Create directory
$fs->createDirectory(new Path('uploads/images'));
// List directory contents
$contents = $fs->listContents(new Path('uploads'));
foreach ($contents as $path) {
echo $path->toString() . "\n";
}
In-Memory FileSystem
<?php
use AdachSoft\FileSystem\InMemoryFileSystem;
use AdachSoft\FileSystem\Model\Path;
// Create in-memory filesystem
$fs = new InMemoryFileSystem();
// All operations work the same as PhysicalFileSystem
$fs->writeFile(new Path('test.txt'), 'Hello World');
$fs->createDirectory(new Path('docs'));
// Reset filesystem (clear all data)
$fs->reset();
Working with Paths
<?php
use AdachSoft\FileSystem\Model\Path;
// Create path objects
$path = new Path('config/database.yml');
// Get path components
$basename = $path->getBasename(); // 'database.yml'
$parent = $path->getParent(); // Path('config')
// Join paths
$newPath = $path->getParent()->join('cache.yml'); // Path('config/cache.yml')
// String representation
echo $path->toString(); // 'config/database.yml'
File Search with Criteria
<?php
use AdachSoft\FileSystem\PhysicalFileSystem;
use AdachSoft\FileSystem\Model\Path;
use AdachSoft\FileSystem\Model\FileSearchCriteria;
$fs = new PhysicalFileSystem('/var/www/project');
// Create search criteria
$criteria = new FileSearchCriteria(
directory: new Path('src'),
filename: '*.php',
extension: 'php',
recursive: true
);
// Find all PHP files
$phpFiles = $fs->findFiles($criteria);
// Find files with specific pattern
$criteria = FileSearchCriteria::create(new Path('tests'))
->withFilename('Test.php')
->withExtension('php')
->withRecursive(false);
$testFiles = $fs->findFiles($criteria);
Working with File Information
<?php
use AdachSoft\FileSystem\PhysicalFileSystem;
use AdachSoft\FileSystem\Model\Path;
$fs = new PhysicalFileSystem('/var/www/project');
// Get file information
$fileInfo = $fs->getFileInfo(new Path('composer.json'));
echo "Path: " . $fileInfo->getPath()->toString() . "\n";
echo "Size: " . $fileInfo->getSize() . " bytes\n";
echo "Modified: " . $fileInfo->getLastModified()->format('Y-m-d H:i:s') . "\n";
echo "Is file: " . ($fileInfo->isFile() ? 'Yes' : 'No') . "\n";
echo "Is directory: " . ($fileInfo->isDirectory() ? 'Yes' : 'No') . "\n";
// Get timestamps and sizes directly
$timestamp = $fs->getLastModifiedTime(new Path('composer.json'));
$fileSize = $fs->getFileSize(new Path('composer.json'));
Path Collections
<?php
use AdachSoft\FileSystem\Model\PathCollection;
use AdachSoft\FileSystem\Model\Path;
// Create collection of paths
$paths = new PathCollection([
new Path('src/FileSystem.php'),
new Path('src/Model/Path.php'),
new Path('tests/FileSystemTest.php')
]);
// Iterate over collection
foreach ($paths as $path) {
echo $path->toString() . "\n";
}
๐ API Reference
FileSystemInterface Methods
Method | Description |
---|---|
writeFile(Path $path, string $content): void | Write content to file |
readFile(Path $path): string | Read file content |
deleteFile(Path $path): void | Delete file |
fileExists(Path $path): bool | Check if file exists |
createDirectory(Path $path): void | Create directory |
deleteDirectory(Path $path, bool $recursive = false): void | Delete directory |
directoryExists(Path $path): bool | Check if directory exists |
pathExists(Path $path): bool | Check if path exists |
isDir(Path $path): bool | Check if path is directory |
isFile(Path $path): bool | Check if path is file |
listContents(Path $path): PathCollection | List directory contents |
move(Path $source, Path $destination): void | Move/rename file or directory |
getFileInfo(Path $path): FileInfo | Get file information |
getLastModifiedTime(Path $path): int | Get last modified timestamp |
getFileSize(Path $path): int | Get file size in bytes |
findFiles(FileSearchCriteria $criteria): PathCollection | Find files by criteria |
Model Classes
Path
__construct(string $path)
- Create path objecttoString(): string
- Get string representationgetBasename(): string
- Get filename/directory namegetParent(): Path
- Get parent directoryjoin(string|Path $path): Path
- Join with another path
FileInfo
getPath(): Path
- Get file pathgetSize(): int
- Get file sizegetLastModified(): DateTimeImmutable
- Get modification dateisFile(): bool
- Check if is fileisDirectory(): bool
- Check if is directory
FileSearchCriteria
create(Path $directory): self
- Create search criteriawithFilename(string $filename): self
- Set filename patternwithExtension(string $extension): self
- Set file extensionwithExcludedDirectories(PathCollection $dirs): self
- Set excluded directorieswithRecursive(bool $recursive): self
- Set recursive search
PathCollection
- Extends
AbstractImmutableCollection<Path>
- Type-safe collection of Path objects
Exception Classes
FileSystemException
- Base exception classFileNotFoundException
- File not foundDirectoryNotFoundException
- Directory not foundFileSystemIOException
- I/O operation failedPathTraversalException
- Path traversal attempt detected
๐งช Testing
Run the test suite:
composer test
Run tests with coverage:
composer test-coverage
๐ Security Features
- Path traversal protection: All paths are validated against base directory
- Input sanitization: Windows and Unix path normalization
- Safe directory operations: Recursive deletion requires explicit flag
- Immutable models: Prevents accidental state changes
๐๏ธ Development Setup
Clone the repository:
git clone https://gitlab.com/a.adach/filesystem.git cd filesystem
Install dependencies:
composer install
Run tests:
composer test
๐ค Contributing
Contributions are welcome! Please feel free to submit a Merge Request.
- Fork the repository on GitLab
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Merge Request on GitLab
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Support
For support and questions:
- Create an issue on GitLab
- Contact: adachsoft@gmail.com
๐ Links
- GitLab Repository: https://gitlab.com/a.adach/filesystem
- GitLab Issues: https://gitlab.com/a.adach/filesystem/-/issues
- Related Collection Library: https://gitlab.com/a.adach/collections
Made with โค๏ธ by AdachSoft