Skip to content

Commit 05b57c6

Browse files
committed
refactor: switches to mime type VO pattern
1 parent d51a35f commit 05b57c6

File tree

7 files changed

+211
-100
lines changed

7 files changed

+211
-100
lines changed

src/Files/Contracts/FileInterface.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace WordPress\AiClient\Files\Contracts;
66

7+
use WordPress\AiClient\Files\ValueObjects\MimeType;
8+
79
/**
810
* Interface for file representations in the AI client.
911
*
@@ -18,7 +20,7 @@ interface FileInterface
1820
* Gets the MIME type of the file.
1921
*
2022
* @since n.e.x.t
21-
* @return string The MIME type (e.g., 'image/png', 'audio/mp3').
23+
* @return MimeType The MIME type (e.g., 'image/png', 'audio/mp3').
2224
*/
23-
public function getMimeType(): string;
25+
public function getMimeType(): MimeType;
2426
}

src/Files/DTO/InlineFile.php

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use WordPress\AiClient\Common\Contracts\WithJsonSchemaInterface;
88
use WordPress\AiClient\Files\Contracts\FileInterface;
99
use WordPress\AiClient\Files\Traits\HasMimeType;
10+
use WordPress\AiClient\Files\ValueObjects\MimeType;
1011

1112
/**
1213
* Represents a file with inline base64-encoded data.
@@ -31,9 +32,9 @@ class InlineFile implements FileInterface, WithJsonSchemaInterface
3132
* @since n.e.x.t
3233
*
3334
* @param string $base64Data The base64-encoded file data.
34-
* @param string|null $mimeType The MIME type of the file.
35+
* @param MimeType|string $mimeType The MIME type of the file.
3536
*/
36-
public function __construct(string $base64Data, string $mimeType = null)
37+
public function __construct(string $base64Data, $mimeType)
3738
{
3839
// RFC 2397: dataurl := "data:" [ mediatype ] ";base64," data
3940
// mediatype is optional; if omitted, defaults to text/plain;charset=US-ASCII
@@ -49,17 +50,10 @@ public function __construct(string $base64Data, string $mimeType = null)
4950

5051
$this->base64Data = $base64Data;
5152

52-
if ($mimeType === null) {
53-
// Extract MIME type from data URL if present
54-
if (!empty($matches[1])) {
55-
// MIME type was provided in the data URL
56-
$this->mimeType = $matches[1];
57-
} else {
58-
// No MIME type provided; default to text/plain per RFC 2397
59-
$this->mimeType = 'text/plain';
60-
}
61-
} else {
53+
if ($mimeType instanceof MimeType) {
6254
$this->mimeType = $mimeType;
55+
} else {
56+
$this->mimeType = new MimeType($mimeType);
6357
}
6458
}
6559

@@ -88,6 +82,7 @@ public static function getJsonSchema(): array
8882
'mimeType' => [
8983
'type' => 'string',
9084
'description' => 'The MIME type of the file.',
85+
'pattern' => '^[a-zA-Z0-9][a-zA-Z0-9!#$&\-\^_+.]*\/[a-zA-Z0-9][a-zA-Z0-9!#$&\-\^_+.]*$',
9186
],
9287
'base64Data' => [
9388
'type' => 'string',

src/Files/DTO/LocalFile.php

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use WordPress\AiClient\Common\Contracts\WithJsonSchemaInterface;
88
use WordPress\AiClient\Files\Contracts\FileInterface;
99
use WordPress\AiClient\Files\Traits\HasMimeType;
10-
use WordPress\AiClient\Files\Utilities\MimeTypeUtil;
10+
use WordPress\AiClient\Files\ValueObjects\MimeType;
1111

1212
/**
1313
* Represents a file stored locally on the filesystem.
@@ -32,24 +32,18 @@ class LocalFile implements FileInterface, WithJsonSchemaInterface
3232
* @since n.e.x.t
3333
*
3434
* @param string $path The local filesystem path to the file.
35-
* @param string|null $mimeType The MIME type of the file.
35+
* @param MimeType|string|null $mimeType The MIME type of the file.
3636
*/
37-
public function __construct(string $path, string $mimeType = null)
37+
public function __construct(string $path, $mimeType = null)
3838
{
3939
$this->path = $path;
4040

41-
if ($mimeType !== null) {
41+
if ($mimeType instanceof MimeType) {
4242
$this->mimeType = $mimeType;
43+
} elseif (is_string($mimeType)) {
44+
$this->mimeType = new MimeType($mimeType);
4345
} else {
44-
// Extract extension from path
45-
$extension = pathinfo($path, PATHINFO_EXTENSION);
46-
47-
if (!empty($extension)) {
48-
$this->mimeType = MimeTypeUtil::getMimeTypeForExtension($extension);
49-
} else {
50-
// No extension found, default to text/plain
51-
$this->mimeType = 'text/plain';
52-
}
46+
$this->mimeType = $this->getMimeTypeFromExtension($path);
5347
}
5448
}
5549

@@ -65,6 +59,31 @@ public function getPath(): string
6559
return $this->path;
6660
}
6761

62+
/**
63+
* Extracts MIME type from file extension.
64+
*
65+
* @since n.e.x.t
66+
*
67+
* @param string $path The file path.
68+
* @return MimeType The MIME type.
69+
*/
70+
private function getMimeTypeFromExtension(string $path): MimeType
71+
{
72+
$extension = pathinfo($path, PATHINFO_EXTENSION);
73+
74+
if (!empty($extension)) {
75+
try {
76+
return MimeType::fromExtension($extension);
77+
} catch (\InvalidArgumentException $e) {
78+
// Unknown extension, default to text/plain
79+
return new MimeType('text/plain');
80+
}
81+
}
82+
83+
// No extension found, default to text/plain
84+
return new MimeType('text/plain');
85+
}
86+
6887
/**
6988
* {@inheritDoc}
7089
*
@@ -78,6 +97,7 @@ public static function getJsonSchema(): array
7897
'mimeType' => [
7998
'type' => 'string',
8099
'description' => 'The MIME type of the file.',
100+
'pattern' => '^[a-zA-Z0-9][a-zA-Z0-9!#$&\-\^_+.]*\/[a-zA-Z0-9][a-zA-Z0-9!#$&\-\^_+.]*$',
81101
],
82102
'path' => [
83103
'type' => 'string',

src/Files/DTO/RemoteFile.php

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use WordPress\AiClient\Common\Contracts\WithJsonSchemaInterface;
88
use WordPress\AiClient\Files\Contracts\FileInterface;
99
use WordPress\AiClient\Files\Traits\HasMimeType;
10-
use WordPress\AiClient\Files\Utilities\MimeTypeUtil;
10+
use WordPress\AiClient\Files\ValueObjects\MimeType;
1111

1212
/**
1313
* Represents a file accessible via a remote URL.
@@ -32,35 +32,18 @@ class RemoteFile implements FileInterface, WithJsonSchemaInterface
3232
* @since n.e.x.t
3333
*
3434
* @param string $url The URL to the remote file.
35-
* @param string|null $mimeType The MIME type of the file.
35+
* @param MimeType|string|null $mimeType The MIME type of the file.
3636
*/
37-
public function __construct(string $url, string $mimeType = null)
37+
public function __construct(string $url, $mimeType = null)
3838
{
3939
$this->url = $url;
4040

41-
if ($mimeType !== null) {
41+
if ($mimeType instanceof MimeType) {
4242
$this->mimeType = $mimeType;
43+
} elseif (is_string($mimeType)) {
44+
$this->mimeType = new MimeType($mimeType);
4345
} else {
44-
// Parse URL to extract filename and extension
45-
$parsedUrl = parse_url($url);
46-
$path = $parsedUrl['path'] ?? '';
47-
48-
// Remove query string and fragment if present in the path
49-
$cleanPath = strtok($path, '?#');
50-
51-
if ($cleanPath === false) {
52-
$cleanPath = $path;
53-
}
54-
55-
// Extract extension from the path
56-
$extension = pathinfo($cleanPath, PATHINFO_EXTENSION);
57-
58-
if (!empty($extension)) {
59-
$this->mimeType = MimeTypeUtil::getMimeTypeForExtension($extension);
60-
} else {
61-
// No extension found, default to text/plain
62-
$this->mimeType = 'text/plain';
63-
}
46+
$this->mimeType = $this->getMimeTypeFromExtension($url);
6447
}
6548
}
6649

@@ -76,6 +59,43 @@ public function getUrl(): string
7659
return $this->url;
7760
}
7861

62+
/**
63+
* Extracts MIME type from URL extension.
64+
*
65+
* @since n.e.x.t
66+
*
67+
* @param string $url The file URL.
68+
* @return MimeType The MIME type.
69+
*/
70+
private function getMimeTypeFromExtension(string $url): MimeType
71+
{
72+
// Parse URL to extract filename and extension
73+
$parsedUrl = parse_url($url);
74+
$path = $parsedUrl['path'] ?? '';
75+
76+
// Remove query string and fragment if present in the path
77+
$cleanPath = strtok($path, '?#');
78+
79+
if ($cleanPath === false) {
80+
$cleanPath = $path;
81+
}
82+
83+
// Extract extension from the path
84+
$extension = pathinfo($cleanPath, PATHINFO_EXTENSION);
85+
86+
if (!empty($extension)) {
87+
try {
88+
return MimeType::fromExtension($extension);
89+
} catch (\InvalidArgumentException $e) {
90+
// Unknown extension, default to text/plain
91+
return new MimeType('text/plain');
92+
}
93+
}
94+
95+
// No extension found, default to text/plain
96+
return new MimeType('text/plain');
97+
}
98+
7999
/**
80100
* {@inheritDoc}
81101
*
@@ -89,6 +109,7 @@ public static function getJsonSchema(): array
89109
'mimeType' => [
90110
'type' => 'string',
91111
'description' => 'The MIME type of the file.',
112+
'pattern' => '^[a-zA-Z0-9][a-zA-Z0-9!#$&\-\^_+.]*\/[a-zA-Z0-9][a-zA-Z0-9!#$&\-\^_+.]*$',
92113
],
93114
'url' => [
94115
'type' => 'string',

src/Files/Traits/HasMimeType.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace WordPress\AiClient\Files\Traits;
66

7+
use WordPress\AiClient\Files\ValueObjects\MimeType;
8+
79
/**
810
* Provides MIME type functionality for file objects.
911
*
@@ -17,18 +19,18 @@ trait HasMimeType
1719
/**
1820
* The MIME type of the file.
1921
*
20-
* @var string
22+
* @var MimeType
2123
*/
22-
protected string $mimeType;
24+
protected MimeType $mimeType;
2325

2426
/**
2527
* Gets the MIME type of the file.
2628
*
27-
* @return string The MIME type.
29+
* @return MimeType The MIME type.
2830
*
2931
* @since 1.0.0
3032
*/
31-
public function getMimeType(): string
33+
public function getMimeType(): MimeType
3234
{
3335
return $this->mimeType;
3436
}

0 commit comments

Comments
 (0)