ReleaseMetadata.php 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace OC\Updater;
  8. use Exception;
  9. use JsonException;
  10. use OC\Updater\Exceptions\ReleaseMetadataException;
  11. use OCP\Http\Client\IClientService;
  12. /** retrieve releases metadata from official servers
  13. *
  14. * @since 30.0.0
  15. */
  16. class ReleaseMetadata {
  17. public function __construct(
  18. private IClientService $clientService,
  19. ) {
  20. }
  21. /**
  22. * returns metadata based on release version
  23. *
  24. * - version is a stable release, metadata is downloaded from official releases folder
  25. * - version is not a table release, metadata is downloaded from official prereleases folder
  26. * - version is a major version (30, 31, 32, ...), latest metadata are downloaded
  27. *
  28. * @param string $version
  29. *
  30. * @return array
  31. * @throws ReleaseMetadataException
  32. * @since 30.0.0
  33. */
  34. public function getMetadata(string $version): array {
  35. if (!str_contains($version, '.')) {
  36. $url = 'https://download.nextcloud.com/server/releases/latest-' . $version . '.metadata';
  37. } else {
  38. [,,$minor] = explode('.', $version);
  39. if (ctype_digit($minor)) {
  40. $url = 'https://download.nextcloud.com/server/releases/nextcloud-' . $version . '.metadata';
  41. } else {
  42. $url = 'https://download.nextcloud.com/server/prereleases/nextcloud-' . $version . '.metadata';
  43. }
  44. }
  45. return $this->downloadMetadata($url);
  46. }
  47. /**
  48. * download Metadata from a link
  49. *
  50. * @param string $url
  51. *
  52. * @return array
  53. * @throws ReleaseMetadataException
  54. * @since 30.0.0
  55. */
  56. public function downloadMetadata(string $url): array {
  57. $client = $this->clientService->newClient();
  58. try {
  59. $response = $client->get($url, [
  60. 'timeout' => 10,
  61. 'connect_timeout' => 10
  62. ]);
  63. } catch (Exception $e) {
  64. throw new ReleaseMetadataException('could not reach metadata at ' . $url, previous: $e);
  65. }
  66. try {
  67. return json_decode($response->getBody(), true, flags: JSON_THROW_ON_ERROR);
  68. } catch (JsonException) {
  69. throw new ReleaseMetadataException('remote document is not valid');
  70. }
  71. }
  72. }