From 94b4604e47afecd85fafe46ba490cdf8013f97aa Mon Sep 17 00:00:00 2001
From: Adam G-H <32250-phenaproxima@users.noreply.drupalcode.org>
Date: Wed, 2 Oct 2024 15:08:36 +0000
Subject: [PATCH] Issue #3477232 by phenaproxima, fjgarlin, chrisfromredfin,
 omkar-pd, lostcarpark: Project detail page: "link to drupal.org" should be
 provided by the backend plugin

---
 .../DrupalDotOrgJsonApi.php                   |   2 ++
 src/Plugin/ProjectBrowserSource/Recipes.php   |   6 ++++++
 src/ProjectBrowser/Project.php                |   8 ++++----
 sveltejs/public/build/bundle.js               | Bin 316360 -> 314697 bytes
 sveltejs/public/build/bundle.js.map           | Bin 286889 -> 286090 bytes
 sveltejs/src/ModulePage.svelte                |  13 +------------
 .../ProjectBrowserTestMock.php                |   3 ++-
 7 files changed, 15 insertions(+), 17 deletions(-)

diff --git a/src/Plugin/ProjectBrowserSource/DrupalDotOrgJsonApi.php b/src/Plugin/ProjectBrowserSource/DrupalDotOrgJsonApi.php
index 2865b4bb8..3df3025df 100644
--- a/src/Plugin/ProjectBrowserSource/DrupalDotOrgJsonApi.php
+++ b/src/Plugin/ProjectBrowserSource/DrupalDotOrgJsonApi.php
@@ -6,6 +6,7 @@ use Drupal\Component\Serialization\Json;
 use Drupal\Component\Utility\Html;
 use Drupal\Core\Extension\ExtensionVersion;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\Core\Url;
 use Drupal\project_browser\DevelopmentStatus;
 use Drupal\project_browser\MaintenanceStatus;
 use Drupal\project_browser\Plugin\ProjectBrowserSourceBase;
@@ -396,6 +397,7 @@ class DrupalDotOrgJsonApi extends ProjectBrowserSourceBase {
           packageName: $project['attributes']['field_composer_namespace'] ?? 'drupal/' . $machine_name,
           categories: $module_categories,
           images: $project_images,
+          url: Url::fromUri('https://www.drupal.org/project/' . $machine_name),
         );
         $returned_list[] = $project_object;
       }
diff --git a/src/Plugin/ProjectBrowserSource/Recipes.php b/src/Plugin/ProjectBrowserSource/Recipes.php
index d31c93d0f..079e4a33b 100644
--- a/src/Plugin/ProjectBrowserSource/Recipes.php
+++ b/src/Plugin/ProjectBrowserSource/Recipes.php
@@ -13,6 +13,7 @@ use Drupal\Core\Extension\ModuleExtensionList;
 use Drupal\Core\File\FileSystemInterface;
 use Drupal\Core\File\FileUrlGeneratorInterface;
 use Drupal\Core\Recipe\Recipe;
+use Drupal\Core\Url;
 use Drupal\project_browser\Plugin\ProjectBrowserSourceBase;
 use Drupal\project_browser\ProjectBrowser\Project;
 use Drupal\project_browser\ProjectBrowser\ProjectsResultsPage;
@@ -81,6 +82,10 @@ class Recipes extends ProjectBrowserSourceBase {
           $package = file_get_contents($path . '/composer.json');
           $package = Json::decode($package);
           $package_name = $package['name'];
+
+          if (array_key_exists('homepage', $package)) {
+            $url = Url::fromUri($package['homepage']);
+          }
         }
 
         $recipe = Yaml::decode($file->getContents());
@@ -110,6 +115,7 @@ class Recipes extends ProjectBrowserSourceBase {
           author: [],
           packageName: $package_name,
           type: ProjectType::Recipe,
+          url: $url ?? NULL,
         );
       }
       $this->cacheBin->set($this->getPluginId(), $projects);
diff --git a/src/ProjectBrowser/Project.php b/src/ProjectBrowser/Project.php
index 301dd60ac..db1808be8 100644
--- a/src/ProjectBrowser/Project.php
+++ b/src/ProjectBrowser/Project.php
@@ -94,8 +94,8 @@ class Project implements \JsonSerializable {
    *   Author of the project in array format.
    * @param string $packageName
    *   The Composer package name of this project, e.g. `drupal/project_browser`.
-   * @param string $url
-   *   URL of the project.
+   * @param \Drupal\Core\Url|null $url
+   *   URL of the project, if any. Defaults to NULL.
    * @param array $categories
    *   Value of module_categories of the project.
    * @param array $images
@@ -127,7 +127,7 @@ class Project implements \JsonSerializable {
     public int $created,
     public array $author,
     public string $packageName,
-    public string $url = '',
+    public ?Url $url = NULL,
     public array $categories = [],
     public array $images = [],
     public array $warnings = [],
@@ -212,7 +212,7 @@ class Project implements \JsonSerializable {
       'is_maintained' => $this->isMaintained,
       'is_active' => $this->isActive,
       'flag_project_star_user_count' => $this->starUserCount,
-      'url' => $this->url,
+      'url' => $this->url?->setAbsolute()->toString(),
       'status' => match ($this->status) {
         ActivationStatus::Absent => 'absent',
         ActivationStatus::Present => 'present',
diff --git a/sveltejs/public/build/bundle.js b/sveltejs/public/build/bundle.js
index 9dfa1203c6e12615d72bcf461050b11fc8986a19..230921d72d367d2edf7b650eabf5b13db7f1b4a0 100644
GIT binary patch
delta 630
zcmX|;OGuPq7=`)%?>Kj3hTpW*Y?wuAd5g*@BwK_KDM;j^vaHk)p&Un(%*eR}2^NTk
zN0jkW46`t^Me;#61s7%%(y9wCtVIZ+qCtxS?f(^8zMPkHp7XwM<N9pB9(*qHbuI*?
zg&hZ_iyIe&hx0XJ5A$|QYrI_-r%g4H?Gd<CU#<A%H0Nx3SA~tsS;Bd5rctPwMs4;5
zofYu#%}dSFlQC%LlX|3ZqZLkmD3Nx$-ywnHuV7_o4R$DzD^)&yA!Mk}mC~BbcsH^*
zl_d_TV@>k?H{J=sqTCh8ad560UR7CzCUCIMFukM+yIQHnIC$R(Q4@9eBpCIhTz##_
zbOQYm*ciQmR5j_xV{o(;XL^3dQaz=$mjl<m*BSz~nc3cbUZ0O2C$tngZXv|=xaOui
zrdjB}BJ2zfNC!JxaFye?;ZrBu@CBTY8A^Mfu~Qtxcat%ZW9h=hqamCyIW4>!LX`e6
zl6g3cBjNxX!#HQc*?2PoopTpuN^ckmy%Fp*LBT*6N!%YXiad&-1uV*wE>+b5n@v6I
z!f&w^vlNi&|F3Rk!vlEKO1CL*#{LLMU9CSvku<{{{L^fhl=op&7znG)ayuv2gnQFK
zW%r|P^IkTpLaE1J4?x>OS!<R_Tr4yejZY-2zfov{rNc<$(vVTLEXSx{JcJTX4<nT$
rL-6rz7q-y=*=4RA=Tw0_#q&W~z~ElvOUom8Dp{5$Gu2`Y3%UOQg&X9=

delta 1091
zcma)*UrgIo6vuOZ_s}wEp{1qRz@U~zyICnMT0~RboFvN<by3-afpxTWgAQp|TDAw;
zu30j-=^Pp3_Z=8FH5wl@5u)ZMLnARJ8)gZZ7^iV6+rysxLl+a1B`)5UjOg25e&^ob
zJ?EZtKj(ZGXKa^0upRl7d^TJUv0v`BQOgSyKyjR#<@p%>UadCELAnpK9<snyq)PnZ
zq3TyJ9VB__ptg7sZ8oy$x~P@2USViQE=Df-U9T`YO3NBt3zDf6+$|p)6<4m~v{%%@
zJ56THYgCIrpA=S@PO(+K)WbJ6V0D}gsOn+U<knAW<nAz!GJ;`tVLr)EsnnuM1_pQ^
zV=>AN^5a3iN;o&j4OoeCCte%j?b3OGk5u4ToOfY9p;_haBo8p|?BPoIjtMi)yh|H#
zF3GKUJHvJO`7^B=e`UB}bMGFC9dac`T+gI3$^PNCL~1|wM#zafcG`fq#(018U^<-~
zecb08SoiQHQ;B#in)bO}524s6n(#wJSfu+9$LXHk#e+|{LGOu1Tp8nL+&s*Ku=EiN
zf1nG`W;k}QRZ3N5q(Y?qL45l@*|F<uVL;6|-zaf6U?nAt_-9;^QJl?qIm<ddiei?Z
z!)lft=*e+6b>N*QYQoYUVZ&0EEAT7S=ldMnMPQS^<XsOfuaGZCL_N;@LiL#I6He+x
zp;tJhGtXmOuAtB_T53BtyN33KBg2X4fzGz52Q;kN5dK_q;r3;!liwWWAC1VL<XQ@%
z;39|VzX6y#sq*-I;sH!7Xmv<-YX*$%;LZ98&5Yx5@uG~s&OTayUF-UY8u8(Awjxv%
z8};ARw1v)Ul?d(Nj>*|2#>9x&A~SDrl-5XGORL5$c*uc?(`?bFxl+#vqYO^)-<l$H
zf4h3ArKl88_POY#vX3lG@+<0wELUMmyD;I)TX#j0IIO~3r#MZDXIVf$J#shvd3`N~
zT-Et2(gK@M{6fJG<;2r4P4mqXSUdVtN_FNL?&YvwVK3itbcWqp+7Ew`JXoILt(chN
z7TlWVMumTym+F<7TNMFitU1-c_Pm<<t3k4seiW&pbX-DO!lKsxvzlF*#M((>C+DXw
jC^al}Q8i9<kyC#3ChG#HGGzXLU$!-h4moszS04Tsw*+&{

diff --git a/sveltejs/public/build/bundle.js.map b/sveltejs/public/build/bundle.js.map
index 33da41c1c1fd4a09783e304e57d2941e11bded0f..a34b7d491f514d2bc8c77cd2e97957fbaa335234 100644
GIT binary patch
delta 245
zcmV<R01E%9!4ZnP5rBjNv;yaUmu7(i@t1&H0SgUGWnpq|AZ>4QWhW_phiQTWw`qa{
zz-*V%AOjnhMehS%0Y;Y*69gN#zwZOeTLei#RY8~Ty#q6sApZjjmj_4$7z9Z{L`9da
zO9U^LP6R2JU`+(w0y9RpKTZT90k>jL1gZg-lad1*mnTsKEdfrKu!RE_mupc3B$wJz
z1WyGpLP2&$moQQUmIF9OO_#8=11SnmK{rN9EKNaeLzi*%10c5?Qv?SA0(V50ar6Tq
v1y4bAL`s)!^aCiDfF}bBw|`UwQUjL+SOh->S3xmHP?zCA1RA$vSOi80CCyO9

delta 524
zcmeC$Ex7WaU_%Sz7N+O*(>K&GaZGQJX5yXxx}NF0bVf-@L9vy-eo9ekL1K<xeo?x9
zK~a8IYI2GG^n7V1Ic0V07^Rpz1vsz^%S<g-$j?)7f$Nz5p@GR@dYn8H`*c1<py|)+
znLY|(Dr*NS+y0?}`9RKe!S~EE(@(!;j$`zieo&fOdb{g8=2OwrH^?)y%ceUyhPvqF
zJ2^ULJLxz(Iy!<0YimzOmvZOnYdx8zrnh;qh%)86Oc(sZEIfVh7iOO6WmU|4)7L67
zvojgHO~2^H62oNTGF{)B#S~SUX)v=g$b!fcH|#bff-Tq%v_P7XrNlkQWxApOi}7^1
zXUy!=?|ZX6+kV7{Wi{jUQ;&gm>iMz=PVe<&(PsA6$(^p~$09QQydR4S$U*GWANevX
zuy{I#n@)dd%c3xSgBJ_y^dEjKUL4le22PGS?vc~w!dRrH>-({=O<ynt==d^!mUQMy
zci-s;W0<v>D%`j82C(QdGUd8XH}q##V#;!zo*2NQI!%X}WBP>2%$(b&1hND%gY6P^
h1qPBeG636qK7=KV)jHg<$Yc8XCBPtd31xBP006vvsh<D<

diff --git a/sveltejs/src/ModulePage.svelte b/sveltejs/src/ModulePage.svelte
index 6b095844f..56ed92951 100644
--- a/sveltejs/src/ModulePage.svelte
+++ b/sveltejs/src/ModulePage.svelte
@@ -115,17 +115,6 @@
       </div>
     {/if}
 
-    {#if project.project_machine_name}
-      <div
-        class="pb-module-page__view-commands pb-module-page__sidebar_element"
-      >
-        <button
-          class="project__action_button"
-          onclick="window.location.href='https://drupal.org/project/{project.project_machine_name}';"
-          >View on Drupal.org</button
-        >
-      </div>
-    {/if}
     {#if project.url}
       <div
         class="pb-module-page__view-commands pb-module-page__sidebar_element"
@@ -133,7 +122,7 @@
         <button
           class="project__action_button"
           onclick="window.location.href='{project.url}';"
-          >View on Drupal.org</button
+          >{Drupal.t('Learn more')}</button
         >
       </div>
     {/if}
diff --git a/tests/modules/project_browser_test/src/Plugin/ProjectBrowserSource/ProjectBrowserTestMock.php b/tests/modules/project_browser_test/src/Plugin/ProjectBrowserSource/ProjectBrowserTestMock.php
index 712022a82..c048b4d1a 100644
--- a/tests/modules/project_browser_test/src/Plugin/ProjectBrowserSource/ProjectBrowserTestMock.php
+++ b/tests/modules/project_browser_test/src/Plugin/ProjectBrowserSource/ProjectBrowserTestMock.php
@@ -8,6 +8,7 @@ use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Database\Connection;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\State\StateInterface;
+use Drupal\Core\Url;
 use Drupal\project_browser\DevelopmentStatus;
 use Drupal\project_browser\MaintenanceStatus;
 use Drupal\project_browser\Plugin\ProjectBrowserSourceBase;
@@ -421,7 +422,7 @@ class ProjectBrowserTestMock extends ProjectBrowserSourceBase {
           created: $project_data['created'],
           author: ['name' => $project_data['author']],
           packageName: 'drupal/' . $project_data['field_project_machine_name'],
-          url: 'https://www.drupal.org/project/' . $project_data['field_project_machine_name'],
+          url: Url::fromUri('https://www.drupal.org/project/' . $project_data['field_project_machine_name']),
           // Add name property to each category, so it can be rendered.
           categories: array_map(fn($category) => $categories[$category['id']] ?? '', $project_data['project_data']['taxonomy_vocabulary_3'] ?? []),
           images: $project_data['project_data']['field_project_images'] ?? [],
-- 
GitLab