Skip to content

Commit af53eaf

Browse files
committed
feat: adds pure base64 support to InlineFile
1 parent a1867dc commit af53eaf

File tree

1 file changed

+66
-17
lines changed

1 file changed

+66
-17
lines changed

src/Files/DTO/InlineFile.php

Lines changed: 66 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class InlineFile implements FileInterface, WithJsonSchemaInterface
2222
use HasMimeType;
2323

2424
/**
25-
* @var string The base64-encoded file data.
25+
* @var string The plain base64-encoded file data (without data URI prefix).
2626
*/
2727
private string $base64Data;
2828

@@ -32,43 +32,63 @@ class InlineFile implements FileInterface, WithJsonSchemaInterface
3232
* @since n.e.x.t
3333
*
3434
* @param string $base64Data The base64-encoded file data.
35-
* @param MimeType|string $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 $base64Data, $mimeType)
37+
public function __construct(string $base64Data, $mimeType = null)
3838
{
3939
// RFC 2397: dataurl := "data:" [ mediatype ] ";base64," data
40-
// mediatype is optional; if omitted, defaults to text/plain;charset=US-ASCII
41-
// We'll be more permissive and accept data URLs with or without MIME type
42-
$pattern = '/^data:(?:([a-zA-Z0-9][a-zA-Z0-9!#$&\-\^_+.]*\/[a-zA-Z0-9][a-zA-Z0-9!#$&\-\^_+.]*'
40+
$dataUriPattern = '/^data:(?:([a-zA-Z0-9][a-zA-Z0-9!#$&\-\^_+.]*\/[a-zA-Z0-9][a-zA-Z0-9!#$&\-\^_+.]*'
4341
. '(?:;[a-zA-Z0-9\-]+=[a-zA-Z0-9\-]+)*)?;)?base64,([A-Za-z0-9+\/]*={0,2})$/';
4442

45-
if (!preg_match($pattern, $base64Data, $matches)) {
46-
throw new \InvalidArgumentException(
47-
'Invalid base64 data provided. Expected format: data:[mimeType];base64,[data]'
48-
);
43+
// Check if this is a data URI
44+
if (preg_match($dataUriPattern, $base64Data, $matches)) {
45+
$this->base64Data = $matches[2];
46+
$this->mimeType = $this->parseMimeType($mimeType, empty($matches[1]) ? null : $matches[1]);
47+
return;
4948
}
5049

51-
$this->base64Data = $base64Data;
52-
53-
if ($mimeType instanceof MimeType) {
54-
$this->mimeType = $mimeType;
55-
} else {
56-
$this->mimeType = new MimeType($mimeType);
50+
// Check if this is plain base64 data
51+
if (preg_match('/^[A-Za-z0-9+\/]*={0,2}$/', $base64Data)) {
52+
if ($mimeType === null) {
53+
throw new \InvalidArgumentException(
54+
'MIME type is required when providing plain base64 data without data URI format.'
55+
);
56+
}
57+
$this->base64Data = $base64Data;
58+
$this->mimeType = $this->parseMimeType($mimeType);
59+
return;
5760
}
61+
62+
throw new \InvalidArgumentException(
63+
'Invalid base64 data provided. Expected either data URI format '
64+
. '(data:[mimeType];base64,[data]) or plain base64 string.'
65+
);
5866
}
5967

6068
/**
6169
* Gets the base64-encoded data.
6270
*
6371
* @since n.e.x.t
6472
*
65-
* @return string The base64-encoded data.
73+
* @return string The plain base64-encoded data (without data URI prefix).
6674
*/
6775
public function getBase64Data(): string
6876
{
6977
return $this->base64Data;
7078
}
7179

80+
/**
81+
* Gets the data as a data URL.
82+
*
83+
* @since n.e.x.t
84+
*
85+
* @return string The data URL in format: data:[mimeType];base64,[data].
86+
*/
87+
public function getDataUrl(): string
88+
{
89+
return sprintf('data:%s;base64,%s', (string) $this->mimeType, $this->base64Data);
90+
}
91+
7292
/**
7393
* {@inheritDoc}
7494
*
@@ -88,4 +108,33 @@ public static function getJsonSchema(): array
88108
'required' => ['mimeType', 'base64Data'],
89109
];
90110
}
111+
112+
/**
113+
* Parses and validates the MIME type.
114+
*
115+
* @since n.e.x.t
116+
*
117+
* @param MimeType|string|null $providedMimeType The explicitly provided MIME type.
118+
* @param string|null $extractedMimeType The MIME type extracted from data URI.
119+
* @return MimeType The parsed MIME type.
120+
*/
121+
private function parseMimeType($providedMimeType, ?string $extractedMimeType = null): MimeType
122+
{
123+
// Prefer explicitly provided MIME type
124+
if ($providedMimeType instanceof MimeType) {
125+
return $providedMimeType;
126+
}
127+
128+
if ($providedMimeType !== null) {
129+
return new MimeType($providedMimeType);
130+
}
131+
132+
// Use extracted MIME type from data URI
133+
if ($extractedMimeType !== null) {
134+
return new MimeType($extractedMimeType);
135+
}
136+
137+
// RFC 2397: if mediatype is omitted in data URI, defaults to text/plain
138+
return new MimeType('text/plain');
139+
}
91140
}

0 commit comments

Comments
 (0)