3d1a07e0ad
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
76 lines
2.7 KiB
PHP
76 lines
2.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace KTXM\ChronoManager\Import;
|
|
|
|
use Generator;
|
|
use InvalidArgumentException;
|
|
use KTXF\Resource\Identifier\CollectionIdentifier;
|
|
use KTXM\ChronoManager\Manager;
|
|
use KTXM\ChronoManager\Conversion\IcalDecoder;
|
|
use Sabre\VObject\Component\VCalendar;
|
|
use Sabre\VObject\Component\VEvent;
|
|
use Sabre\VObject\Component\VJournal;
|
|
use Sabre\VObject\Component\VTodo;
|
|
use Sabre\VObject\Parser\MimeDir;
|
|
use Sabre\VObject\Reader;
|
|
use Throwable;
|
|
|
|
/** Imports the three RFC 5545 calendar object types into Chrono entities. */
|
|
class ImportService {
|
|
|
|
public function __construct(
|
|
private readonly Manager $manager,
|
|
private readonly IcalDecoder $decoder,
|
|
) {}
|
|
|
|
/**
|
|
* @param resource $source readable, seekable iCalendar resource
|
|
* @return Generator<int, ImportEvent>
|
|
*/
|
|
public function import($source, CollectionIdentifier $target, ImportOptions $options, string $tenantId, string $userId): Generator {
|
|
if (!is_resource($source)) {
|
|
throw new InvalidArgumentException('Invalid import source: must be a file resource');
|
|
}
|
|
|
|
try {
|
|
rewind($source);
|
|
$calendar = Reader::read($source, MimeDir::OPTION_FORGIVING | MimeDir::OPTION_IGNORE_INVALID_LINES);
|
|
if (!$calendar instanceof VCalendar) {
|
|
throw new InvalidArgumentException('Supplied input is not an iCalendar document');
|
|
}
|
|
} catch (Throwable $e) {
|
|
if ($options->getCounts()) {
|
|
yield new ImportCountEvent(0);
|
|
}
|
|
yield new ImportObjectEvent(null, ImportDisposition::Error, ['Malformed iCalendar: ' . $e->getMessage()]);
|
|
return;
|
|
}
|
|
|
|
$components = array_values(array_filter(
|
|
$calendar->children(),
|
|
static fn($component): bool => $component instanceof VEvent
|
|
|| $component instanceof VTodo
|
|
|| $component instanceof VJournal,
|
|
));
|
|
|
|
if ($options->getCounts()) {
|
|
yield new ImportCountEvent(count($components));
|
|
}
|
|
|
|
foreach ($components as $component) {
|
|
$uid = isset($component->UID) ? (trim((string)$component->UID) ?: null) : null;
|
|
try {
|
|
$this->manager->entityCreate($tenantId, $userId, $target, $this->decoder->fromComponent($component));
|
|
yield new ImportObjectEvent($uid, ImportDisposition::Created);
|
|
} catch (Throwable $e) {
|
|
yield new ImportObjectEvent($uid, ImportDisposition::Error, [$e->getMessage()]);
|
|
if ($options->getErrors() === ImportOptions::ERROR_FAIL) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|