From ae769f3f53928a5d96a5152ba51a954c667d1a6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Randy=20=C4=8Cupi=C4=87?= Date: Sun, 15 Oct 2023 12:06:48 +0200 Subject: [PATCH] Add command for refreshing stored resources --- .../Command/RefreshStoredResourcesCommand.php | 149 ++++++++++++++++++ .../Resources/config/services/commands.yaml | 8 + 2 files changed, 157 insertions(+) create mode 100644 bundle/Command/RefreshStoredResourcesCommand.php diff --git a/bundle/Command/RefreshStoredResourcesCommand.php b/bundle/Command/RefreshStoredResourcesCommand.php new file mode 100644 index 00000000..4819d6a9 --- /dev/null +++ b/bundle/Command/RefreshStoredResourcesCommand.php @@ -0,0 +1,149 @@ +resourceRepository = $entityManager->getRepository(RemoteResource::class); + + parent::__construct(); + } + + protected function configure(): void + { + $this + ->setName('netgen:remote_media:refresh') + ->setDescription('This command will refresh all stored resources in the database with newest data. WARNING: this might consume API rate limits.') + ->addOption('batch-size', 'bs', InputOption::VALUE_OPTIONAL, 'Size of batch', 500) + ->addOption('delete', 'd', InputOption::VALUE_NONE, 'Force deleting resources that are not found on remote.'); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $limit = $input->getOption('batch-size'); + $delete = $input->getOption('delete'); + $offset = 0; + + $this->progressBar = new ProgressBar($output, $this->resourceRepository->count([])); + $this->progressBar->start(); + + $this->resourcesToDelete = []; + + do { + $resources = $this->getBatch($limit, $offset); + + $this->refreshResources($resources); + + $offset += $limit; + } while (count($resources) > 0); + + $this->progressBar->finish(); + + if (count($this->resourcesToDelete) > 0 && $delete === false) { + $output->writeln(PHP_EOL . 'There are ' . count($this->resourcesToDelete) . ' resources no longer existing on remote. Use --delete to delete them.'); + + return Command::SUCCESS; + } + + if (count($this->resourcesToDelete) > 0 && $delete === true) { + $output->writeln(PHP_EOL . 'Deleting resources that are no longer on remote:'); + + $progressBar = new ProgressBar($output, count($this->resourcesToDelete)); + $progressBar->start(); + + foreach ($this->resourcesToDelete as $resource) { + $this->provider->remove($resource); + $progressBar->advance(); + } + + $progressBar->finish(); + } + + return Command::SUCCESS; + } + + /** + * @return \Netgen\RemoteMedia\API\Values\RemoteResource[] + */ + private function getBatch(int $limit, int $offset): array + { + return $this->resourceRepository->findBy([], null, $limit, $offset); + } + + /** + * @param \Netgen\RemoteMedia\API\Values\RemoteResource[] $resources + */ + private function refreshResources(array $resources): void + { + $remoteIds = array_map( + static fn (RemoteResource $resource): string => $resource->getRemoteId(), + $resources, + ); + + $remoteResources = $this->getRemoteBatch($remoteIds); + + foreach ($resources as $resource) { + if (!array_key_exists($resource->getRemoteId(), $remoteResources)) { + $this->resourcesToDelete[] = $resource; + + $this->progressBar->advance(); + + continue; + } + + $remoteResource = $remoteResources[$resource->getRemoteId()]; + + $this->provider->store($resource->refresh($remoteResource)); + $this->progressBar->advance(); + } + } + + /** + * @param string[] $remoteIds + * + * @return array + */ + private function getRemoteBatch(array $remoteIds): array + { + $query = Query::fromRemoteIds($remoteIds); + + $searchResult = $this->provider->search($query); + + $resources = []; + foreach ($searchResult->getResources() as $resource) { + $resources[$resource->getRemoteId()] = $resource; + } + + return $resources; + } +} diff --git a/bundle/Resources/config/services/commands.yaml b/bundle/Resources/config/services/commands.yaml index 1dd05895..465ac9ec 100644 --- a/bundle/Resources/config/services/commands.yaml +++ b/bundle/Resources/config/services/commands.yaml @@ -1,4 +1,12 @@ services: + netgen_remote_media.command.refresh_stored_resources: + class: Netgen\Bundle\RemoteMediaBundle\Command\RefreshStoredResourcesCommand + arguments: + - "@doctrine.orm.entity_manager" + - "@netgen_remote_media.provider" + tags: + - { name: console.command } + netgen_remote_media.command.api_usage: class: Netgen\Bundle\RemoteMediaBundle\Command\ShowApiUsageCommand arguments: