generated from Nodarx/template
218 lines
5.7 KiB
PHP
218 lines
5.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace KTXM\ProviderImap\Client;
|
|
|
|
final class MessagePart
|
|
{
|
|
/**
|
|
* @param array<string, string> $parameters
|
|
* @param array<string, string> $dispositionParameters
|
|
* @param list<string> $language
|
|
* @param list<MessagePart> $parts
|
|
*/
|
|
public function __construct(
|
|
private readonly string $partId,
|
|
private readonly string $mimeType,
|
|
private readonly array $parameters = [],
|
|
private readonly ?string $contentId = null,
|
|
private readonly ?string $description = null,
|
|
private readonly ?string $encoding = null,
|
|
private readonly ?int $size = null,
|
|
private readonly ?string $disposition = null,
|
|
private readonly array $dispositionParameters = [],
|
|
private readonly array $language = [],
|
|
private readonly ?string $location = null,
|
|
private readonly ?string $content = null,
|
|
private readonly array $parts = [],
|
|
) {}
|
|
|
|
public function partId(): string
|
|
{
|
|
return $this->partId;
|
|
}
|
|
|
|
public function mimeType(): string
|
|
{
|
|
return $this->mimeType;
|
|
}
|
|
|
|
/**
|
|
* @return array<string, string>
|
|
*/
|
|
public function parameters(): array
|
|
{
|
|
return $this->parameters;
|
|
}
|
|
|
|
public function contentId(): ?string
|
|
{
|
|
return $this->contentId;
|
|
}
|
|
|
|
public function description(): ?string
|
|
{
|
|
return $this->description;
|
|
}
|
|
|
|
public function encoding(): ?string
|
|
{
|
|
return $this->encoding;
|
|
}
|
|
|
|
public function size(): ?int
|
|
{
|
|
return $this->size;
|
|
}
|
|
|
|
public function disposition(): ?string
|
|
{
|
|
return $this->disposition;
|
|
}
|
|
|
|
/**
|
|
* @return array<string, string>
|
|
*/
|
|
public function dispositionParameters(): array
|
|
{
|
|
return $this->dispositionParameters;
|
|
}
|
|
|
|
/**
|
|
* @return list<string>
|
|
*/
|
|
public function language(): array
|
|
{
|
|
return $this->language;
|
|
}
|
|
|
|
public function location(): ?string
|
|
{
|
|
return $this->location;
|
|
}
|
|
|
|
public function content(): ?string
|
|
{
|
|
return $this->content;
|
|
}
|
|
|
|
/**
|
|
* @return list<MessagePart>
|
|
*/
|
|
public function parts(): array
|
|
{
|
|
return $this->parts;
|
|
}
|
|
|
|
public function isMultipart(): bool
|
|
{
|
|
return str_starts_with($this->mimeType, 'multipart/');
|
|
}
|
|
|
|
/**
|
|
* @param array<string, string> $sections
|
|
*/
|
|
public function withInjectedSections(array $sections): self
|
|
{
|
|
if ($this->parts !== []) {
|
|
$parts = [];
|
|
foreach ($this->parts as $part) {
|
|
$parts[] = $part->withInjectedSections($sections);
|
|
}
|
|
|
|
return new self(
|
|
$this->partId,
|
|
$this->mimeType,
|
|
$this->parameters,
|
|
$this->contentId,
|
|
$this->description,
|
|
$this->encoding,
|
|
$this->size,
|
|
$this->disposition,
|
|
$this->dispositionParameters,
|
|
$this->language,
|
|
$this->location,
|
|
$this->content,
|
|
$parts,
|
|
);
|
|
}
|
|
|
|
if (!str_starts_with($this->mimeType, 'text/')) {
|
|
return $this;
|
|
}
|
|
|
|
if (!array_key_exists($this->partId, $sections)) {
|
|
return $this;
|
|
}
|
|
|
|
return new self(
|
|
$this->partId,
|
|
$this->mimeType,
|
|
$this->parameters,
|
|
$this->contentId,
|
|
$this->description,
|
|
$this->encoding,
|
|
$this->size,
|
|
$this->disposition,
|
|
$this->dispositionParameters,
|
|
$this->language,
|
|
$this->location,
|
|
self::decodeContent($sections[$this->partId], $this->encoding, $this->parameters['charset'] ?? 'us-ascii'),
|
|
[],
|
|
);
|
|
}
|
|
|
|
public function toArray(): array
|
|
{
|
|
$data = [
|
|
'partId' => $this->partId,
|
|
'blobId' => $this->partId,
|
|
'cId' => $this->contentId,
|
|
'type' => $this->mimeType,
|
|
'charset' => $this->parameters['charset'] ?? null,
|
|
'name' => $this->parameters['name'] ?? $this->dispositionParameters['filename'] ?? null,
|
|
'encoding' => $this->encoding,
|
|
'size' => $this->size,
|
|
'disposition' => $this->disposition,
|
|
'language' => $this->language === [] ? null : implode(',', $this->language),
|
|
'location' => $this->location,
|
|
'content' => $this->content,
|
|
];
|
|
|
|
$children = [];
|
|
foreach ($this->parts as $part) {
|
|
$children[] = $part->toArray();
|
|
}
|
|
|
|
$data['subParts'] = $children === [] ? null : $children;
|
|
|
|
return array_filter($data, static fn (mixed $value): bool => $value !== null);
|
|
}
|
|
|
|
private static function decodeContent(string $content, ?string $encoding, string $charset): string
|
|
{
|
|
$decoded = match (strtolower($encoding ?? '7bit')) {
|
|
'quoted-printable' => quoted_printable_decode($content),
|
|
'base64' => base64_decode($content, true) ?: '',
|
|
default => $content,
|
|
};
|
|
|
|
if ($charset === '' || in_array(strtolower($charset), ['utf-8', 'utf8'], true)) {
|
|
return mb_convert_encoding($decoded, 'UTF-8', 'UTF-8');
|
|
}
|
|
|
|
try {
|
|
$converted = mb_convert_encoding($decoded, 'UTF-8', $charset);
|
|
if ($converted !== false) {
|
|
return $converted;
|
|
}
|
|
} catch (\ValueError) {
|
|
}
|
|
|
|
$converted = @iconv($charset, 'UTF-8//TRANSLIT//IGNORE', $decoded);
|
|
$decoded = $converted !== false ? $converted : $decoded;
|
|
|
|
return mb_convert_encoding($decoded, 'UTF-8', 'UTF-8');
|
|
}
|
|
} |