enjoys/upload

4.1.0 2025-06-28 09:06 UTC

README

Mutation testing badge tests static Build Status Scrutinizer Code Quality Code Coverage

File uploads library with validation uses PSR-7 UploadedFileInterface and League\Flysystem as a file storage library

Installation

Requires PHP 8.2 or later.

Install via Composer:

composer require enjoys/upload:^4.0

Basic Usage

use Psr\Http\Message\ServerRequestInterface;

/** @var Psr\Http\Message\UploadedFileInterface $uploadedFile */
/** @var League\Flysystem\Filesystem $filesystem */

$file = new Enjoys\Upload\UploadProcessing($uploadedFile, $filesystem);

try {
    $file->upload();       
} catch (\Exception $e) {
    // Handle exception
}

Validation Rules

The library includes 3 built-in validation rules. You can also create custom rules by implementing Enjoys\Upload\RuleInterface.

Available rules:

  • Extension (Enjoys\Upload\Rule\Extension) — Validates file extensions
  • Size (Enjoys\Upload\Rule\Size) — Validates file size
  • MediaType (Enjoys\Upload\Rule\MediaType) — Validates MIME types

Adding Validation Rules

/** @var Enjoys\Upload\UploadProcessing $file */
/** @var Enjoys\Upload\RuleInterface $rule */

$file->addRule($rule); // Add before calling upload()
$file->upload();
Extension Rule

Case-insensitive extension validation:

$rule = new Enjoys\Upload\Rule\Extension();
$rule->allow('png'); // Single extension
$rule->allow('png, jpg'); // Comma-separated
$rule->allow(['png', 'jpg']); // Array of extensions
Size Rule
$rule = new Enjoys\Upload\Rule\Size();
$rule->setMaxSize(10 * 1024 * 1024) // 10MB
     ->setMinSize(1 * 1024 * 1024); // 1MB (values in bytes)
MediaType Rule
$rule = new Enjoys\Upload\Rule\MediaType();
$rule->allow('image/*') // All image types
     ->allow('application/pdf') // PDF files
     ->allow('*/vnd.openxmlformats-officedocument.*'); // Office documents

Event System

The library provides PSR-14 compatible events:

Available Events:

  • BeforeValidationEvent - Dispatched before validation starts
  • BeforeUploadEvent - Dispatched after validation, before file upload
  • AfterUploadEvent - Dispatched after successful file upload
  • UploadErrorEvent - Dispatched when any error occurs

Usage Example:

use Enjoys\Upload\Event\AfterUploadEvent;
use Psr\EventDispatcher\EventDispatcherInterface;

/** @var EventDispatcherInterface $dispatcher */

// Initialize with event dispatcher
$upload = new UploadProcessing($uploadedFile, $filesystem, $dispatcher);

// Add event listener
$dispatcher->addListener(
    AfterUploadEvent::class,
    function (AfterUploadEvent $event) {
        logger()->info("File uploaded to: " . $event->uploadProcessing->getTargetPath());
    }
);

$upload->upload();

Event Propagation:

All events implement StoppableEventInterface. To stop further processing:

$dispatcher->addListener(
    BeforeUploadEvent::class,
    function (BeforeUploadEvent $event) {
        if ($shouldStop) {
            $event->stopPropagation(); // Stops other listeners
        }
    }
);

API Reference

Enjoys\Upload\UploadProcessing::class

setFilename(filename: string)

Sets a new filename for the uploaded file (call before upload).

addRule(rule: Enjoys\Upload\RuleInterface)

Adds a single validation rule (call before upload).

addRules(rules: Enjoys\Upload\RuleInterface[])

Adds multiple validation rules (call before upload).

upload(targetPath: string)

Processes the file upload. Optionally specify a subdirectory.

getTargetPath(): ?string

Returns the file storage path after upload, or null if not uploaded.

getFilesystem()

Returns the League\Flysystem\Filesystem::class instance.

getUploadedFile(): UploadedFileInterface

Returns the PSR-7 UploadedFileInterface instance.

getFileInfo()

Returns the FileInfo object with file metadata.

Enjoys\Upload\FileInfo::class

getFilename(): string

Returns the full filename (e.g., new_file_name.jpg).

getOriginalFilename(): string

Returns the original uploaded filename.

getFilenameWithoutExtension(): string

Returns the filename without extension.

getExtension(): string

Returns the file extension (without dot).

getExtensionWithDot(): string

Returns the file extension with leading dot.

getSize(): int

Returns the file size in bytes.

getMediaType(): string

Returns the client-reported MIME type.