diff --git a/src/EnabledSourceHandler.php b/src/EnabledSourceHandler.php index 7018bc138a1bf5d341e4607237330c0f77df8189..65250812dec58a43b3cb4e3c9cd6617adbf394e5 100644 --- a/src/EnabledSourceHandler.php +++ b/src/EnabledSourceHandler.php @@ -105,7 +105,6 @@ class EnabledSourceHandler implements LoggerAwareInterface, EventSubscriberInter // we expect to be in the data store. foreach ($stored as $source_id => $arguments) { $arguments[1] = array_map($this->getStoredProject(...), $arguments[1]); - $arguments[] = $source_id; $projects[$source_id] = new ProjectsResultsPage(...$arguments); } } @@ -130,6 +129,8 @@ class EnabledSourceHandler implements LoggerAwareInterface, EventSubscriberInter $results->totalResults, array_column($results->list, 'id'), $results->pluginLabel, + $source_id, + $results->error, ]; } $this->keyValue->set($cache_key, $stored); diff --git a/src/Plugin/ProjectBrowserSource/DrupalDotOrgJsonApi.php b/src/Plugin/ProjectBrowserSource/DrupalDotOrgJsonApi.php index 45fccfb8ad01b8fd5817ee24b5033b567d258f42..90ba986b642075a9ccd9a7402b4d689c981b0b1b 100644 --- a/src/Plugin/ProjectBrowserSource/DrupalDotOrgJsonApi.php +++ b/src/Plugin/ProjectBrowserSource/DrupalDotOrgJsonApi.php @@ -283,15 +283,18 @@ class DrupalDotOrgJsonApi extends ProjectBrowserSourceBase { * {@inheritdoc} */ public function getProjects(array $query = []): ProjectsResultsPage { - $api_response = $this->fetchProjects($query); - $filter_values = $this->filterValues(); - $maintained_values = $filter_values['maintained'] ?? []; + if (!empty($filter_values['drupal_version']) && $filter_values['drupal_version']['supported'] === FALSE) { + $error_message = $filter_values['drupal_version']['message'] ?? $this->t('The current version of Drupal is not supported in the Drupal.org endpoint.'); + return $this->createResultsPage([], 0, $error_message); + } + $api_response = $this->fetchProjects($query); $returned_list = []; if (is_array($api_response) && !empty($api_response['list'])) { $related = !empty($api_response['related']) ? $api_response['related'] : NULL; $current_drupal_version = $this->getNumericSemverVersion(\Drupal::VERSION); + $maintained_values = $filter_values['maintained'] ?? []; foreach ($api_response['list'] as $project) { // Map any properties from jsonapi format to the simplified record // format used by Project Browser. @@ -624,6 +627,7 @@ class DrupalDotOrgJsonApi extends ProjectBrowserSourceBase { protected function filterValues(): array { $values = []; $url = self::DRUPAL_ORG_ENDPOINT . '/drupalorg-api/project-browser-filters'; + $url .= '?drupal_version=' . \Drupal::VERSION; $filter_values = $this->cacheBin->get('DrupalDotOrgJsonApi:filter_values'); if ($filter_values) { $values = $filter_values->data; diff --git a/src/Plugin/ProjectBrowserSourceBase.php b/src/Plugin/ProjectBrowserSourceBase.php index 17accd58ed36c2d083d71c366d8e0738253af5a5..afe348c5e664ddab2f0ae7b3387783c0a4ba3789 100644 --- a/src/Plugin/ProjectBrowserSourceBase.php +++ b/src/Plugin/ProjectBrowserSourceBase.php @@ -86,16 +86,19 @@ abstract class ProjectBrowserSourceBase extends PluginBase implements ProjectBro * The projects to list on the page. * @param int|null $total_results * (optional) The total number of results. Defaults to the size of $results. + * @param string|null $error + * (optional) Error message to be passed along, if any. * * @return \Drupal\project_browser\ProjectBrowser\ProjectsResultsPage * A list of projects to send to the client. */ - protected function createResultsPage(array $results, ?int $total_results = NULL): ProjectsResultsPage { + protected function createResultsPage(array $results, ?int $total_results = NULL, ?string $error = NULL): ProjectsResultsPage { return new ProjectsResultsPage( $total_results ?? count($results), array_values($results), (string) $this->getPluginDefinition()['label'], $this->getPluginId(), + $error ); } diff --git a/src/ProjectBrowser/ProjectsResultsPage.php b/src/ProjectBrowser/ProjectsResultsPage.php index 3da3effb539f5411da58884378eaffb37ccda291..3ce74890f682865b6e8b6c18cc0f90b6391fed23 100644 --- a/src/ProjectBrowser/ProjectsResultsPage.php +++ b/src/ProjectBrowser/ProjectsResultsPage.php @@ -20,12 +20,15 @@ class ProjectsResultsPage { * The source plugin's label. * @param string $pluginId * The source plugin's ID. + * @param string $error + * (optional) Error to pass along, if any. */ public function __construct( public readonly int $totalResults, public readonly array $list, public readonly string $pluginLabel, public readonly string $pluginId, + public readonly ?string $error = NULL, ) { assert(array_is_list($list)); assert(Inspector::assertAllObjects($list, Project::class)); diff --git a/sveltejs/public/build/bundle.js b/sveltejs/public/build/bundle.js index f4246798143d5771bc7d505889793ebd39941fa2..b4c37a7b5121e3c975553c3cf5247006319da9fb 100644 Binary files a/sveltejs/public/build/bundle.js and b/sveltejs/public/build/bundle.js differ diff --git a/sveltejs/public/build/bundle.js.map b/sveltejs/public/build/bundle.js.map index 9a896a181adea79b9c48dee5bb7a72c976354b9e..de752a45cda964ab5e128cc221b7d0e115e29198 100644 Binary files a/sveltejs/public/build/bundle.js.map and b/sveltejs/public/build/bundle.js.map differ diff --git a/sveltejs/src/ProjectBrowser.svelte b/sveltejs/src/ProjectBrowser.svelte index 224135af90995b598b92782fb3858f5e6a493210..e79aa10ecc563f01e3db1c6b31c016752e96dabc 100644 --- a/sveltejs/src/ProjectBrowser.svelte +++ b/sveltejs/src/ProjectBrowser.svelte @@ -126,6 +126,7 @@ const res = await fetch(url); if (res.ok) { + const messenger = new Drupal.Message(); data = await res.json(); // A list of the available sources to get project data. sources = Object.keys(data); @@ -133,12 +134,14 @@ rows = data[$activeTab].list; $rowsCount = data[$activeTab].totalResults; + if (data[$activeTab].error && data[$activeTab].error.length) { + messenger.add(data[$activeTab].error, { type: 'error' }); + } + if ( PACKAGE_MANAGER.available && (PACKAGE_MANAGER.errors.length || PACKAGE_MANAGER.warnings.length) ) { - const messenger = new Drupal.Message(); - if (PACKAGE_MANAGER.errors.length) { PACKAGE_MANAGER.errors.forEach((e) => { messenger.add(`Unable to download modules via the UI: ${e}`, { diff --git a/tests/fixtures/drupalorg_jsonapi/project-browser-filters-error.json b/tests/fixtures/drupalorg_jsonapi/project-browser-filters-error.json new file mode 100644 index 0000000000000000000000000000000000000000..82df2d48412b8180894fedb001d308bc67e1f40d --- /dev/null +++ b/tests/fixtures/drupalorg_jsonapi/project-browser-filters-error.json @@ -0,0 +1 @@ +{"active":["e767288c-9800-4fb4-aeb8-8c311533838a","219c1cf2-dd7f-474b-9dd5-a26643fbc699"],"maintained":["089406ad-304d-4737-80d1-2f08527ae49e","cee844e2-68b5-489d-bafa-6a0ade2b6dfd","09a378d2-fd35-41f3-bff0-10d9801741a4"],"drupal_version":{"supported":false,"message":"Unsupported version."}} \ No newline at end of file diff --git a/tests/fixtures/drupalorg_jsonapi/project-browser-filters.json b/tests/fixtures/drupalorg_jsonapi/project-browser-filters.json index 5a9b240fd1bafe78f554d37401166a1b18f9b94b..eb41909c17503cf60a248c9359862d2c4eb7dc18 100644 --- a/tests/fixtures/drupalorg_jsonapi/project-browser-filters.json +++ b/tests/fixtures/drupalorg_jsonapi/project-browser-filters.json @@ -1 +1 @@ -{"active":["e767288c-9800-4fb4-aeb8-8c311533838a","219c1cf2-dd7f-474b-9dd5-a26643fbc699"],"maintained":["089406ad-304d-4737-80d1-2f08527ae49e","cee844e2-68b5-489d-bafa-6a0ade2b6dfd","09a378d2-fd35-41f3-bff0-10d9801741a4"]} \ No newline at end of file +{"active":["e767288c-9800-4fb4-aeb8-8c311533838a","219c1cf2-dd7f-474b-9dd5-a26643fbc699"],"maintained":["089406ad-304d-4737-80d1-2f08527ae49e","cee844e2-68b5-489d-bafa-6a0ade2b6dfd","09a378d2-fd35-41f3-bff0-10d9801741a4"],"drupal_version":{"supported":true,"message":"Supported version."}} \ No newline at end of file diff --git a/tests/modules/project_browser_test/project_browser_test.services.yml b/tests/modules/project_browser_test/project_browser_test.services.yml index b01467dcf2912ebd7a7f00850adc962f207fe296..a3c7d4b2b4ca4dae56dc3c93f8f226c22d5efc83 100644 --- a/tests/modules/project_browser_test/project_browser_test.services.yml +++ b/tests/modules/project_browser_test/project_browser_test.services.yml @@ -7,7 +7,7 @@ services: class: Drupal\project_browser_test\DrupalOrgClientMiddleware tags: - { name: http_client_middleware } - arguments: ['@module_handler'] + arguments: ['@module_handler', '@state'] Drupal\project_browser_test\TestActivator: autowire: true public: false diff --git a/tests/modules/project_browser_test/src/DrupalOrgClientMiddleware.php b/tests/modules/project_browser_test/src/DrupalOrgClientMiddleware.php index e84bd64d123ac92749afc1cc3e9182cb911714a7..b6beb005a43e1e21fbcaccc504ae81f093d029f6 100644 --- a/tests/modules/project_browser_test/src/DrupalOrgClientMiddleware.php +++ b/tests/modules/project_browser_test/src/DrupalOrgClientMiddleware.php @@ -3,6 +3,7 @@ namespace Drupal\project_browser_test; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\State\StateInterface; use Drupal\project_browser\Plugin\ProjectBrowserSource\DrupalDotOrgJsonApi; use GuzzleHttp\Promise\FulfilledPromise; use GuzzleHttp\Psr7\Response; @@ -75,7 +76,8 @@ class DrupalOrgClientMiddleware { * @const array */ const DRUPALORG_ENDPOINT_TO_FIXTURE_MAP = [ - '/drupalorg-api/project-browser-filters' => 'project-browser-filters.json', + '/drupalorg-api/project-browser-filters?drupal_version=' . \Drupal::VERSION => 'project-browser-filters.json', + '/drupalorg-api/project-browser-filters?drupal_version=9.0.5' => 'project-browser-filters-error.json', ]; /** @@ -83,9 +85,12 @@ class DrupalOrgClientMiddleware { * * @param \Drupal\Core\Extension\ModuleHandlerInterface $moduleHandler * The module handler. + * @param \Drupal\Core\State\StateInterface $state + * The state key value store. */ public function __construct( private readonly ModuleHandlerInterface $moduleHandler, + private readonly StateInterface $state, ) { } @@ -133,6 +138,15 @@ class DrupalOrgClientMiddleware { $relevant_path = str_replace(DrupalDotOrgJsonApi::DRUPAL_ORG_ENDPOINT, '', $request->getUri()); $path_to_fixture = self::DRUPALORG_ENDPOINT_TO_FIXTURE_MAP; + $is_outdated = $this->state->get('project_browser:test_deprecated_api'); + if ( + strpos($relevant_path, '/drupalorg-api/project-browser-filters?drupal_version=') !== FALSE && + $is_outdated + ) { + // Force the wrong Drupal version. + $relevant_path = '/drupalorg-api/project-browser-filters?drupal_version=9.0.5'; + } + if (isset($path_to_fixture[$relevant_path])) { $module_path = $this->moduleHandler->getModule('project_browser')->getPath(); $data = file_get_contents($module_path . '/tests/fixtures/drupalorg_jsonapi/' . $path_to_fixture[$relevant_path]); diff --git a/tests/src/FunctionalJavascript/ProjectBrowserUiTestJsonApi.php b/tests/src/FunctionalJavascript/ProjectBrowserUiTestJsonApi.php index 85a692f6bd83c94cd5fbe253ec1f801458cf1bca..7e829566a26f90240df8fd7f58b6e41e92bceb4a 100644 --- a/tests/src/FunctionalJavascript/ProjectBrowserUiTestJsonApi.php +++ b/tests/src/FunctionalJavascript/ProjectBrowserUiTestJsonApi.php @@ -51,6 +51,19 @@ class ProjectBrowserUiTestJsonApi extends WebDriverTestBase { ])); } + /** + * Tests the display of the error message sent from Drupal.org. + */ + public function testErrorMessageWhenWrongDrupalVersion(): void { + // Fake the Drupal version. + $this->container->get('state')->set('project_browser:test_deprecated_api', TRUE); + + $assert_session = $this->assertSession(); + + $this->drupalGet('admin/modules/browse/drupalorg_jsonapi'); + $this->svelteInitHelper('text', 'Unsupported version'); + } + /** * Tests the grid view. */