Something went wrong. Try again.
Parse and validate AT Protocol Lexicons with DTO generation for Laravel
Something went wrong. Try again.
4.1 kB · 152 lines
PHP
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153<?php
namespace SocialDept\AtpSchema\Data\Types;
use SocialDept\AtpSchema\Data\TypeDefinition;use SocialDept\AtpSchema\Exceptions\RecordValidationException;
class BlobType extends TypeDefinition{ /** * Accepted MIME types. * * @var array<string>|null */ public readonly ?array $accept;
/** * Maximum blob size in bytes. */ public readonly ?int $maxSize;
/** * Create a new BlobType. * * @param array<string>|null $accept */ public function __construct( ?array $accept = null, ?int $maxSize = null, ?string $description = null ) { parent::__construct('blob', $description);
$this->accept = $accept; $this->maxSize = $maxSize; }
/** * Create from array data. */ public static function fromArray(array $data): self { return new self( accept: $data['accept'] ?? null, maxSize: $data['maxSize'] ?? null, description: $data['description'] ?? null ); }
/** * Convert to array. */ public function toArray(): array { $array = ['type' => $this->type];
if ($this->description !== null) { $array['description'] = $this->description; }
if ($this->accept !== null) { $array['accept'] = $this->accept; }
if ($this->maxSize !== null) { $array['maxSize'] = $this->maxSize; }
return $array; }
/** * Validate a value against this type definition. */ public function validate(mixed $value, string $path = ''): void { if (! is_array($value)) { throw RecordValidationException::invalidType($path, 'blob (object)', gettype($value)); }
// Blob must have $type property if (! isset($value['$type']) || $value['$type'] !== 'blob') { throw RecordValidationException::invalidValue($path, 'must have $type property set to "blob"'); }
// Blob must have ref (CID reference) if (! isset($value['ref'])) { throw RecordValidationException::invalidValue($path, 'must have ref property'); }
// Blob must have mimeType if (! isset($value['mimeType'])) { throw RecordValidationException::invalidValue($path, 'must have mimeType property'); }
// Blob must have size if (! isset($value['size'])) { throw RecordValidationException::invalidValue($path, 'must have size property'); }
// Validate MIME type if accept is specified if ($this->accept !== null) { $mimeType = $value['mimeType'];
if (! $this->isMimeTypeAccepted($mimeType)) { $accepted = implode(', ', $this->accept);
throw RecordValidationException::invalidValue($path, "MIME type must be one of: {$accepted}"); } }
// Validate size if maxSize is specified if ($this->maxSize !== null) { $size = $value['size'];
if (! is_int($size)) { throw RecordValidationException::invalidValue($path, 'size must be an integer'); }
if ($size > $this->maxSize) { throw RecordValidationException::invalidValue($path, "size must not exceed {$this->maxSize} bytes"); } } }
/** * Check if a MIME type is accepted. */ protected function isMimeTypeAccepted(string $mimeType): bool { if ($this->accept === null) { return true; }
foreach ($this->accept as $accepted) { // Exact match if ($accepted === $mimeType) { return true; }
// Wildcard match (e.g., image/*) if (str_ends_with($accepted, '/*')) { $prefix = substr($accepted, 0, -1); if (str_starts_with($mimeType, $prefix)) { return true; } } }
return false; }}