- Add comprehensive health check system with multiple endpoints - Add Prometheus metrics endpoint - Add production logging configurations (5 strategies) - Add complete deployment documentation suite: * QUICKSTART.md - 30-minute deployment guide * DEPLOYMENT_CHECKLIST.md - Printable verification checklist * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference * production-logging.md - Logging configuration guide * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation * README.md - Navigation hub * DEPLOYMENT_SUMMARY.md - Executive summary - Add deployment scripts and automation - Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment - Update README with production-ready features All production infrastructure is now complete and ready for deployment.
185 lines
4.5 KiB
PHP
185 lines
4.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Domain\Media;
|
|
|
|
use App\Framework\Core\ValueObjects\Dimensions;
|
|
use App\Framework\Core\ValueObjects\FileSize;
|
|
use App\Framework\Core\ValueObjects\Hash;
|
|
use App\Framework\Database\Attributes\Column;
|
|
use App\Framework\Database\Attributes\Entity;
|
|
use App\Framework\Database\Attributes\Type;
|
|
use App\Framework\Filesystem\ValueObjects\FilePath;
|
|
use App\Framework\Http\MimeType;
|
|
use App\Framework\Ulid\Ulid;
|
|
|
|
#[Entity(tableName: 'images', idColumn: 'ulid')]
|
|
final readonly class Image
|
|
{
|
|
/** @var ImageVariant[] $variants */
|
|
#[Type(ImageVariant::class, foreignKey: 'image_id', localKey: 'ulid')]
|
|
public array $variants;
|
|
|
|
public function __construct(
|
|
#[Column(name: 'ulid', primary: true)]
|
|
public Ulid $ulid,
|
|
#[Column(name: 'filename')]
|
|
public string $filename,
|
|
#[Column(name: 'original_filename')]
|
|
public string $originalFilename,
|
|
#[Column(name: 'mime_type')]
|
|
public MimeType $mimeType,
|
|
#[Column(name: 'file_size')]
|
|
public FileSize $fileSize,
|
|
#[Column(name: 'width')]
|
|
public int $width,
|
|
#[Column(name: 'height')]
|
|
public int $height,
|
|
#[Column(name: 'hash'/*, unique: true*/)]
|
|
public Hash $hash,
|
|
#[Column(name: 'path')]
|
|
public FilePath $path,
|
|
#[Column(name: 'alt_text')]
|
|
public string $altText,
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* Get dimensions as Value Object
|
|
*/
|
|
public function getDimensions(): Dimensions
|
|
{
|
|
return new Dimensions($this->width, $this->height);
|
|
}
|
|
|
|
/**
|
|
* Get aspect ratio
|
|
*/
|
|
public function getAspectRatio(): float
|
|
{
|
|
return $this->getDimensions()->getAspectRatio();
|
|
}
|
|
|
|
/**
|
|
* Check if image is portrait orientation
|
|
*/
|
|
public function isPortrait(): bool
|
|
{
|
|
return $this->getDimensions()->isPortrait();
|
|
}
|
|
|
|
/**
|
|
* Check if image is landscape orientation
|
|
*/
|
|
public function isLandscape(): bool
|
|
{
|
|
return $this->getDimensions()->isLandscape();
|
|
}
|
|
|
|
/**
|
|
* Check if image is square
|
|
*/
|
|
public function isSquare(): bool
|
|
{
|
|
return $this->getDimensions()->isSquare();
|
|
}
|
|
|
|
/**
|
|
* Get human readable file size
|
|
*/
|
|
public function getHumanReadableFileSize(): string
|
|
{
|
|
return $this->fileSize->toHumanReadable();
|
|
}
|
|
|
|
/**
|
|
* Get file extension
|
|
*/
|
|
public function getFileExtension(): string
|
|
{
|
|
return $this->path->getExtension();
|
|
}
|
|
|
|
/**
|
|
* Check if hash matches
|
|
*/
|
|
public function verifyHash(Hash $hash): bool
|
|
{
|
|
return $this->hash->equals($hash);
|
|
}
|
|
|
|
/**
|
|
* Check if file is an image based on MIME type
|
|
*/
|
|
public function isImageFile(): bool
|
|
{
|
|
return $this->mimeType->isImage();
|
|
}
|
|
|
|
/**
|
|
* Get ULID as string
|
|
*/
|
|
public function getUlidString(): string
|
|
{
|
|
return $this->ulid->__toString();
|
|
}
|
|
|
|
/**
|
|
* Create new instance with updated filename
|
|
*/
|
|
public function withFilename(string $filename): self
|
|
{
|
|
return new self(
|
|
ulid: $this->ulid,
|
|
filename: $filename,
|
|
originalFilename: $this->originalFilename,
|
|
mimeType: $this->mimeType,
|
|
fileSize: $this->fileSize,
|
|
width: $this->width,
|
|
height: $this->height,
|
|
hash: $this->hash,
|
|
path: $this->path,
|
|
altText: $this->altText
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Create new instance with updated alt text
|
|
*/
|
|
public function withAltText(string $altText): self
|
|
{
|
|
return new self(
|
|
ulid: $this->ulid,
|
|
filename: $this->filename,
|
|
originalFilename: $this->originalFilename,
|
|
mimeType: $this->mimeType,
|
|
fileSize: $this->fileSize,
|
|
width: $this->width,
|
|
height: $this->height,
|
|
hash: $this->hash,
|
|
path: $this->path,
|
|
altText: $altText
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Create new instance with updated path
|
|
*/
|
|
public function withPath(FilePath $path): self
|
|
{
|
|
return new self(
|
|
ulid: $this->ulid,
|
|
filename: $this->filename,
|
|
originalFilename: $this->originalFilename,
|
|
mimeType: $this->mimeType,
|
|
fileSize: $this->fileSize,
|
|
width: $this->width,
|
|
height: $this->height,
|
|
hash: $this->hash,
|
|
path: $path,
|
|
altText: $this->altText
|
|
);
|
|
}
|
|
}
|