Files
myep/src/Service/BpnXmlSyncManager.php
T

124 lines
3.5 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Service;
use App\BusProNet\Model\XmlExportInfo;
use App\Model\BpnXmlSyncTarget;
use League\Flysystem\FilesystemException;
use League\Flysystem\FilesystemOperator;
use League\Flysystem\StorageAttributes;
use Psr\Log\LoggerInterface;
use Symfony\Contracts\Cache\TagAwareCacheInterface;
final class BpnXmlSyncManager
{
private const CACHE_TAGS_TO_INVALIDATE = [
'xml-sync',
];
public function __construct(
private readonly FilesystemOperator $xmlSource,
private readonly FilesystemOperator $xmlExport,
private readonly TagAwareCacheInterface $bpnCache,
private readonly LoggerInterface $logger,
) {
}
/**
* @return list<BpnXmlSyncTarget>
*/
public function getSyncTargets(): array
{
return [
new BpnXmlSyncTarget('travel', $this->xmlSource, $this->xmlExport),
];
}
public function readRemoteInfo(FilesystemOperator $source, string $datasetName): ?XmlExportInfo
{
try {
$content = $source->read(XmlExportInfo::getFilename());
return XmlExportInfo::fromString($content);
} catch (FilesystemException|\InvalidArgumentException $e) {
$this->logger->warning('Could not read remote info file, likely being updated', [
'dataset' => $datasetName,
'exception' => $e->getMessage(),
]);
return null;
}
}
public function readLocalInfo(FilesystemOperator $destination): ?XmlExportInfo
{
try {
if (false === $destination->fileExists(XmlExportInfo::getFilename())) {
return null;
}
$content = $destination->read(XmlExportInfo::getFilename());
return XmlExportInfo::fromString($content);
} catch (FilesystemException|\InvalidArgumentException) {
return null;
}
}
/**
* @return array{updated:int,deleted:int}
*
* @throws FilesystemException
*/
public function syncFiles(
FilesystemOperator $source,
FilesystemOperator $destination,
?callable $onStart = null,
?callable $onProgress = null,
): array {
$remoteFiles = $source
->listContents('.')
->filter(fn (StorageAttributes $attributes) => $attributes->isFile())
->map(fn (StorageAttributes $attributes) => $attributes->path())
->toArray();
$localFiles = $destination
->listContents('.')
->filter(fn (StorageAttributes $attributes) => $attributes->isFile())
->map(fn (StorageAttributes $attributes) => $attributes->path())
->toArray();
$filesToDelete = array_diff($localFiles, $remoteFiles);
if (null !== $onStart) {
$onStart(count($remoteFiles));
}
foreach ($remoteFiles as $path) {
$content = $source->read($path);
$destination->write($path, $content);
if (null !== $onProgress) {
$onProgress();
}
}
foreach ($filesToDelete as $path) {
$destination->delete($path);
}
return [
'updated' => count($remoteFiles),
'deleted' => count($filesToDelete),
];
}
public function invalidateCaches(): int
{
$this->bpnCache->invalidateTags(self::CACHE_TAGS_TO_INVALIDATE);
return count(self::CACHE_TAGS_TO_INVALIDATE);
}
}