From c6ae255c10bf324538e603912ff33cb3275d50e3 Mon Sep 17 00:00:00 2001 From: Richard Steinmetz Date: Sun, 8 Feb 2026 11:35:21 +0100 Subject: [PATCH] chore(refactor): improve output interface to psr logger adapter Signed-off-by: Richard Steinmetz --- lib/Command/PreGenerate.php | 13 ++- lib/Service/PreGenerateService.php | 32 ++---- .../LoggerInterfaceToOutputAdapter.php | 101 ++++++++++++++++++ lib/Support/OutputInterfaceLoggerAdapter.php | 99 ----------------- 4 files changed, 123 insertions(+), 122 deletions(-) create mode 100644 lib/Support/LoggerInterfaceToOutputAdapter.php delete mode 100644 lib/Support/OutputInterfaceLoggerAdapter.php diff --git a/lib/Command/PreGenerate.php b/lib/Command/PreGenerate.php index c724355..13ef7aa 100644 --- a/lib/Command/PreGenerate.php +++ b/lib/Command/PreGenerate.php @@ -11,6 +11,8 @@ use OCA\PreviewGenerator\Exceptions\EncryptionEnabledException; use OCA\PreviewGenerator\Service\PreGenerateService; +use OCA\PreviewGenerator\Support\LoggerInterfaceToOutputAdapter; +use OCP\IConfig; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -18,6 +20,7 @@ class PreGenerate extends Command { public function __construct( private readonly PreGenerateService $preGenerateService, + private readonly IConfig $config, ) { parent::__construct(); } @@ -25,12 +28,18 @@ public function __construct( protected function configure(): void { $this ->setName('preview:pre-generate') - ->setDescription('Pre generate only images that have been added or changed since the last regular run'); + ->setDescription('Pre-generate only images that have been added or changed since the last regular run'); } protected function execute(InputInterface $input, OutputInterface $output): int { + // Set timestamp output + $formatter = new TimestampFormatter($this->config, $output->getFormatter()); + $output->setFormatter($formatter); + + $this->preGenerateService->setLogger(new LoggerInterfaceToOutputAdapter($output)); + try { - $this->preGenerateService->preGenerate($output); + $this->preGenerateService->preGenerate(); } catch (EncryptionEnabledException $e) { $output->writeln('Encryption is enabled. Aborted.'); return 1; diff --git a/lib/Service/PreGenerateService.php b/lib/Service/PreGenerateService.php index 9d26799..505445f 100644 --- a/lib/Service/PreGenerateService.php +++ b/lib/Service/PreGenerateService.php @@ -10,10 +10,8 @@ namespace OCA\PreviewGenerator\Service; use OC\DB\Exceptions\DbalException; -use OCA\PreviewGenerator\Command\TimestampFormatter; use OCA\PreviewGenerator\Exceptions\EncryptionEnabledException; use OCA\PreviewGenerator\SizeHelper; -use OCA\PreviewGenerator\Support\OutputInterfaceLoggerAdapter; use OCA\PreviewGenerator\Support\PreviewLimiter\PreviewLimiter; use OCP\AppFramework\Db\TTransactional; use OCP\AppFramework\Utility\ITimeFactory; @@ -27,7 +25,7 @@ use OCP\IDBConnection; use OCP\IPreview; use OCP\IUserManager; -use Symfony\Component\Console\Output\OutputInterface; +use Psr\Log\LoggerInterface; class PreGenerateService { use TTransactional; @@ -35,7 +33,7 @@ class PreGenerateService { /* @return array{width: int, height: int, crop: bool} */ private array $specifications; - private ?OutputInterface $output = null; + private ?LoggerInterface $logger = null; private ?PreviewLimiter $limiter = null; public function __construct( @@ -51,6 +49,10 @@ public function __construct( ) { } + public function setLogger(LoggerInterface $logger): void { + $this->logger = $logger; + } + public function setLimiter(PreviewLimiter $limiter): void { $this->limiter = $limiter; } @@ -58,27 +60,17 @@ public function setLimiter(PreviewLimiter $limiter): void { /** * @throws EncryptionEnabledException If encryption is enabled. */ - public function preGenerate(OutputInterface $output): void { + public function preGenerate(): void { if ($this->encryptionManager->isEnabled()) { throw new EncryptionEnabledException(); } - // Set timestamp output - if (!($output instanceof OutputInterfaceLoggerAdapter)) { - $formatter = new TimestampFormatter($this->config, $output->getFormatter()); - $output->setFormatter($formatter); - } - - $this->output = $output; - if ($this->limiter) { - $output->writeln('Using limiter: ' . get_class($this->limiter)); + $this->logger?->debug('Using limiter: ' . get_class($this->limiter)); } $this->specifications = $this->sizeHelper->generateSpecifications(); - if ($this->output->getVerbosity() > OutputInterface::VERBOSITY_VERY_VERBOSE) { - $output->writeln('Specifications: ' . json_encode($this->specifications)); - } + $this->logger?->debug('Specifications: ' . json_encode($this->specifications)); $this->startProcessing(); } @@ -163,9 +155,7 @@ private function processFile(File $file): void { } if ($this->previewGenerator->isMimeSupported($file->getMimeType())) { - if ($this->output->getVerbosity() > OutputInterface::VERBOSITY_VERBOSE) { - $this->output->writeln('Generating previews for ' . $file->getPath()); - } + $this->logger?->debug('Generating previews for ' . $file->getPath()); try { $this->previewGenerator->generatePreviews($file, $this->specifications); @@ -174,7 +164,7 @@ private function processFile(File $file): void { } catch (\InvalidArgumentException|GenericFileException $e) { $class = $e::class; $error = $e->getMessage(); - $this->output->writeln("{$class}: {$error}"); + $this->logger?->error("{$class}: {$error}"); } catch (DbalException $e) { // Since the introduction of the oc_previews table, preview duplication caused by // duplicated specifications will cause a UniqueConstraintViolationException. We can diff --git a/lib/Support/LoggerInterfaceToOutputAdapter.php b/lib/Support/LoggerInterfaceToOutputAdapter.php new file mode 100644 index 0000000..e88d629 --- /dev/null +++ b/lib/Support/LoggerInterfaceToOutputAdapter.php @@ -0,0 +1,101 @@ +getVerbosity()); + } + + public function emergency(string|Stringable $message, array $context = []): void { + $this->writeToOutput('error', $message, $context); + } + + public function alert(string|Stringable $message, array $context = []): void { + $this->writeToOutput('error', $message, $context); + } + + public function critical(string|Stringable $message, array $context = []): void { + $this->writeToOutput('error', $message, $context); + } + + public function error(string|Stringable $message, array $context = []): void { + $this->writeToOutput('error', $message, $context); + } + + public function warning(string|Stringable $message, array $context = []): void { + if ($this->output->getVerbosity() < OutputInterface::VERBOSITY_NORMAL) { + return; + } + + $this->writeToOutput(null, $message, $context); + } + + public function notice(string|Stringable $message, array $context = []): void { + if ($this->output->getVerbosity() < OutputInterface::VERBOSITY_VERBOSE) { + return; + } + + $this->writeToOutput(null, $message, $context); + } + + public function info(string|Stringable $message, array $context = []): void { + if ($this->output->getVerbosity() < OutputInterface::VERBOSITY_VERY_VERBOSE) { + return; + } + + $this->writeToOutput(null, $message, $context); + } + + public function debug(string|Stringable $message, array $context = []): void { + if ($this->output->getVerbosity() < OutputInterface::VERBOSITY_DEBUG) { + return; + } + + $this->writeToOutput(null, $message, $context); + } + + public function log($level, $message, array $context = []): void { + match ($level) { + LogLevel::EMERGENCY => $this->emergency($message, $context), + LogLevel::ALERT => $this->alert($message, $context), + LogLevel::CRITICAL => $this->critical($message, $context), + LogLevel::ERROR => $this->error($message, $context), + LogLevel::WARNING => $this->warning($message, $context), + LogLevel::NOTICE => $this->notice($message, $context), + LogLevel::INFO => $this->info($message, $context), + LogLevel::DEBUG => $this->debug($message, $context), + }; + } + + private function writeToOutput( + ?string $decorator, + string|Stringable $message, + array $context = [], + ): void { + $message = (string)$message; + if (!empty($context)) { + $message .= ' ' . json_encode($context); + } + + if ($decorator) { + $this->output->writeln("<$decorator>$message"); + } else { + $this->output->writeln($message); + } + } +} diff --git a/lib/Support/OutputInterfaceLoggerAdapter.php b/lib/Support/OutputInterfaceLoggerAdapter.php deleted file mode 100644 index 6ed4bd0..0000000 --- a/lib/Support/OutputInterfaceLoggerAdapter.php +++ /dev/null @@ -1,99 +0,0 @@ -logLevel = $logLevel; - } - - public function writeln(string|iterable $messages, int $options = 0) { - if (is_iterable($messages)) { - $message = implode(' ', [...$messages]); - } else { - $message = $messages; - } - - $this->logger->log($this->logLevel, $message, [ - 'source' => self::class, - ]); - } - - public function write( - iterable|string $messages, - bool $newline = false, - int $options = 0, - ) { - $this->writeln($messages, $options); - } - - public function setVerbosity(int $level) { - $this->logLevel = match ($level) { - self::VERBOSITY_DEBUG => LogLevel::DEBUG, - self::VERBOSITY_VERY_VERBOSE => LogLevel::INFO, - self::VERBOSITY_VERBOSE => LogLevel::NOTICE, - self::VERBOSITY_NORMAL => LogLevel::WARNING, - _ => LogLevel::ERROR, - }; - } - - public function getVerbosity(): int { - return match ($this->logLevel) { - LogLevel::DEBUG => self::VERBOSITY_DEBUG, - LogLevel::INFO => self::VERBOSITY_VERY_VERBOSE, - LogLevel::NOTICE => self::VERBOSITY_VERBOSE, - LogLevel::WARNING => self::VERBOSITY_NORMAL, - _ => self::VERBOSITY_QUIET, - }; - } - - public function isQuiet(): bool { - return $this->getVerbosity() === self::VERBOSITY_QUIET; - } - - public function isVerbose(): bool { - return $this->getVerbosity() === self::VERBOSITY_VERBOSE; - } - - public function isVeryVerbose(): bool { - return $this->getVerbosity() === self::VERBOSITY_VERY_VERBOSE; - } - - public function isDebug(): bool { - return $this->getVerbosity() === self::VERBOSITY_DEBUG; - } - - public function setDecorated(bool $decorated) { - } - - public function isDecorated(): bool { - throw new RuntimeException('Not implemented'); - } - - public function setFormatter(OutputFormatterInterface $formatter) { - } - - public function getFormatter(): OutputFormatterInterface { - throw new RuntimeException('Not implemented'); - } -}