diff --git a/src/Console/AddRecordCommand.php b/src/Console/AddRecordCommand.php index 95137fa..807ce70 100644 --- a/src/Console/AddRecordCommand.php +++ b/src/Console/AddRecordCommand.php @@ -23,8 +23,11 @@ namespace OCC\OaiPmh2\Console; use OCC\OaiPmh2\Database; +use OCC\OaiPmh2\Database\Format; +use OCC\OaiPmh2\Database\Record; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -40,6 +43,36 @@ )] class AddRecordCommand extends Command { + /** + * Configures the current command. + * + * @return void + */ + protected function configure(): void + { + $this->addArgument( + 'identifier', + InputArgument::REQUIRED, + 'The record identifier.' + ); + $this->addArgument( + 'format', + InputArgument::REQUIRED, + 'The metadata prefix.' + ); + $this->addArgument( + 'file', + InputArgument::REQUIRED, + 'The file containing the record content.' + ); + $this->addArgument( + 'sets', + InputArgument::IS_ARRAY | InputArgument::OPTIONAL, + 'The list of sets to associate the record with.' + ); + parent::configure(); + } + /** * Executes the current command. * @@ -50,7 +83,42 @@ class AddRecordCommand extends Command */ protected function execute(InputInterface $input, OutputInterface $output): int { + /** @var array */ + $arguments = $input->getArguments(); + /** @var Format */ + $format = Database::getInstance()->getEntityManager()->getReference(Format::class, $arguments['format']); + + $content = file_get_contents($arguments['file']); + if ($content === false) { + $output->writeln([ + '', + sprintf( + ' [ERROR] File "%s" not found or not readable. ', + $arguments['file'] + ), + '' + ]); + return Command::INVALID; + } + + $record = new Record($arguments['identifier'], $format); + if (trim($content) !== '') { + $record->setContent($content); + } + // TODO: Add full set support. + + Database::getInstance()->addOrUpdateRecord($record); Database::getInstance()->pruneOrphanSets(); + + $output->writeln([ + '', + sprintf( + ' [OK] Record "%s" with metadata prefix "%s" added or updated successfully! ', + $arguments['identifier'], + $arguments['format'] + ), + '' + ]); return Command::SUCCESS; } } diff --git a/src/Console/DeleteRecordCommand.php b/src/Console/DeleteRecordCommand.php index 5ce84f8..c0b5e76 100644 --- a/src/Console/DeleteRecordCommand.php +++ b/src/Console/DeleteRecordCommand.php @@ -24,8 +24,11 @@ use OCC\OaiPmh2\Configuration; use OCC\OaiPmh2\Database; +use OCC\OaiPmh2\Database\Format; +use OCC\OaiPmh2\Database\Record; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -41,6 +44,26 @@ )] class DeleteRecordCommand extends Command { + /** + * Configures the current command. + * + * @return void + */ + protected function configure(): void + { + $this->addArgument( + 'identifier', + InputArgument::REQUIRED, + 'The record identifier.' + ); + $this->addArgument( + 'format', + InputArgument::REQUIRED, + 'The metadata prefix.' + ); + parent::configure(); + } + /** * Executes the current command. * @@ -51,8 +74,42 @@ class DeleteRecordCommand extends Command */ protected function execute(InputInterface $input, OutputInterface $output): int { - $policy = Configuration::getInstance()->deletedRecords; - Database::getInstance()->pruneOrphanSets(); - return Command::SUCCESS; + /** @var array */ + $arguments = $input->getArguments(); + $entityManager = Database::getInstance()->getEntityManager(); + + $format = $entityManager->getReference(Format::class, $arguments['format']); + $record = $entityManager->find( + Record::class, + [ + 'identifier' => $arguments['identifier'], + 'format' => $format + ] + ); + + if (isset($record)) { + Database::getInstance()->deleteRecord($record); + $output->writeln([ + '', + sprintf( + ' [OK] Record "%s" with metadata prefix "%s" successfully deleted. ', + $arguments['identifier'], + $arguments['format'] + ), + '' + ]); + return Command::SUCCESS; + } else { + $output->writeln([ + '', + sprintf( + ' [ERROR] Record "%s" with metadata prefix "%s" not found. ', + $arguments['identifier'], + $arguments['format'] + ), + '' + ]); + return Command::FAILURE; + } } } diff --git a/src/Console/UpdateFormatsCommand.php b/src/Console/UpdateFormatsCommand.php index 3111df0..ac35337 100644 --- a/src/Console/UpdateFormatsCommand.php +++ b/src/Console/UpdateFormatsCommand.php @@ -93,7 +93,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } foreach (array_keys($inDatabase) as $prefix) { if (!in_array($prefix, array_keys($formats), true)) { - Database::getInstance()->removeMetadataFormat($inDatabase[$prefix]); + Database::getInstance()->deleteMetadataFormat($inDatabase[$prefix]); ++$deleted; $output->writeln([ sprintf( diff --git a/src/Database.php b/src/Database.php index c76c459..eb74445 100644 --- a/src/Database.php +++ b/src/Database.php @@ -420,13 +420,13 @@ public function pruneResumptionTokens(): int } /** - * Remove metadata format and all associated records. + * Delete metadata format and all associated records. * * @param Format $format The metadata format * * @return void */ - public function removeMetadataFormat(Format $format): void + public function deleteMetadataFormat(Format $format): void { $repository = $this->entityManager->getRepository(Record::class); $criteria = Criteria::create()->where(Criteria::expr()->eq('format', $format)); @@ -439,6 +439,25 @@ public function removeMetadataFormat(Format $format): void $this->pruneOrphanSets(); } + /** + * Delete a record. + * + * @param Record $record The record + * + * @return void + */ + public function deleteRecord(Record $record): void + { + if (Configuration::getInstance()->deletedRecords === 'no') { + $this->entityManager->remove($record); + } else { + $record->setContent(null); + $record->setLastChanged(new DateTime()); + } + $this->entityManager->flush(); + $this->pruneOrphanSets(); + } + /** * This is a singleton class, thus the constructor is private. * diff --git a/src/Middleware/Dispatcher.php b/src/Middleware/Dispatcher.php index 8f0db37..b8f2fb8 100644 --- a/src/Middleware/Dispatcher.php +++ b/src/Middleware/Dispatcher.php @@ -103,6 +103,7 @@ protected function processResponse(ResponseInterface $response): ResponseInterfa { // TODO: Add support for content compression // https://openarchives.org/OAI/openarchivesprotocol.html#ResponseCompression + // https://github.com/middlewares/encoder return $response->withHeader('Content-Type', 'text/xml'); } diff --git a/src/Middleware/Identify.php b/src/Middleware/Identify.php index ffab658..6cd8e75 100644 --- a/src/Middleware/Identify.php +++ b/src/Middleware/Identify.php @@ -81,9 +81,12 @@ protected function prepareResponse(ServerRequestInterface $request): void $granularity = $document->createElement('granularity', 'YYYY-MM-DDThh:mm:ssZ'); $identify->appendChild($granularity); - // TODO: Add support for content compression - // $compression = $document->createElement('compression', '...'); - // $identify->appendChild($compression); + // TODO: Implement explicit content compression support. + // $compressionDeflate = $document->createElement('compression', 'deflate'); + // $identify->appendChild($compressionDeflate); + + // $compressionGzip = $document->createElement('compression', 'gzip'); + // $identify->appendChild($compressionGzip); $this->preparedResponse = $document; }