From a7f1a33840064f57cc014e22d367707b98580000 Mon Sep 17 00:00:00 2001
From: Fran Garcia-Linares <14157-fjgarlin@users.noreply.drupalcode.org>
Date: Wed, 18 Dec 2024 22:02:52 +0000
Subject: [PATCH] Issue #3470518: Align project browsing with project_browser

---
 drupalorg/drupalorg.module    | 32 +++++++++++----------
 drupalorg/drupalorg.pages.inc | 52 ++++++++++++++++++++++++++++++++++-
 2 files changed, 69 insertions(+), 15 deletions(-)

diff --git a/drupalorg/drupalorg.module b/drupalorg/drupalorg.module
index 679f41454..6747fc8bf 100644
--- a/drupalorg/drupalorg.module
+++ b/drupalorg/drupalorg.module
@@ -5090,15 +5090,8 @@ function drupalorg_node_view($node, $view_mode = 'full') {
         'namespace' => $repository->namespace,
         'name' => $repository->name,
       ]], 'setting');
-      $repository_logo = _drupalorg_get_repository_logo($repository);
-      if ($repository_logo) {
-        $repository_logo_markup = '<img
-          class="repository-logo"
-          src="' . $repository_logo . '"
-          alt="' . t('Logo for the @name project', ['@name' => $node->title]) . '"
-        /> ';
-
-        $title = drupal_set_title($repository_logo_markup . drupal_get_title(), PASS_THROUGH);
+      if ($repository_logo_markup = _drupalorg_get_repository_logo($node)) {
+        drupal_set_title($repository_logo_markup . drupal_get_title(), PASS_THROUGH);
       }
     }
   }
@@ -5160,16 +5153,20 @@ function _drupalorg_organization_credit_summary(stdClass $node) {
 }
 
 /**
- * Returns the URL of the repository avatar or NULL if it's not set.
+ * Returns an image tag for the project’s repoistory avatar.
  */
-function _drupalorg_get_repository_logo($repository) {
-  $link = $repository->getUrlHandler()->getRepositoryViewUrl() . '/-/avatar';
+function _drupalorg_get_repository_logo(stdClass $node) {
+  $repository = versioncontrol_project_repository_load($node->nid);
+  if (!$repository) {
+    return;
+  }
 
   $cache_id = 'drupalorg_repository_logo_' . $repository->gitlab_project_id;
   if ($cache = cache_get($cache_id)) {
     $link = $cache->data;
   }
   else {
+    $link = $repository->getUrlHandler()->getRepositoryViewUrl() . '/-/avatar';
     try {
       $client = new GuzzleHttp\Client(['timeout' => 5.0]);
       $response = $client->request('HEAD', $link);
@@ -5191,7 +5188,13 @@ function _drupalorg_get_repository_logo($repository) {
     cache_set($cache_id, $link);
   }
 
-  return $link;
+  if ($link) {
+    return theme('image', [
+      'path' => $link,
+      'alt' => t('Logo for the @name project', ['@name' => $node->title]),
+      'attributes' => ['class' => 'repository-logo'],
+    ]) . ' ';
+  }
 }
 
 /**
@@ -10396,7 +10399,8 @@ function drupalorg_browse_projects_form($form, &$form_state, $project_type) {
       $options['im_vid_' . $vocab->vid . ':' . $term->tid] = $term->name;
     }
 
-    $form['f'][] = [
+    // Make the name of these inputs predictable.
+    $form['f'][$vocab->vid] = [
       '#type' => 'select',
       '#title' => check_plain($vocab->name),
       '#options' => $options,
diff --git a/drupalorg/drupalorg.pages.inc b/drupalorg/drupalorg.pages.inc
index 12d4b4112..b91433092 100644
--- a/drupalorg/drupalorg.pages.inc
+++ b/drupalorg/drupalorg.pages.inc
@@ -148,7 +148,22 @@ function drupalorg_project_browse_page($project_type) {
     }
     $results = [];
     foreach (node_load_multiple($nids) as $node) {
-      $results[] = node_view($node, 'teaser');
+      $body_no_tags = !empty($node->body[LANGUAGE_NONE]) ? strip_tags($node->body[LANGUAGE_NONE][0]['value']) : '';
+      $body_no_breaks = trim(preg_replace('/[\t\n\r\s]+/', ' ', $body_no_tags));
+      $body_truncated = truncate_utf8($body_no_breaks, 200, TRUE, TRUE, 1);
+      $body = check_plain($body_truncated);
+      $terms = _drupalorg_get_node_categories_as_links($node);
+      if (!empty($terms)) {
+        $body .= '<br><span class="terms description">' . t('Categories: ') . implode(', ', $terms) . '</span>';
+      }
+      $results[] = [
+        'title' => [
+          '#markup' => '<h2>' . _drupalorg_get_repository_logo($node) . l($node->title, 'node/' . $node->nid) . '</h2>',
+        ],
+        'body' => [
+          '#markup' => '<p>' . $body . '</p>',
+        ],
+      ];
     }
   }
   catch (\Exception $e) {
@@ -174,6 +189,41 @@ function drupalorg_project_browse_page($project_type) {
   ];
 }
 
+/**
+ * Extract categories from a node and return them as links.
+ */
+function _drupalorg_get_node_categories_as_links($node) {
+  $categories = [];
+
+  if (!empty($node->taxonomy_vocabulary_3)) {
+    foreach ($node->taxonomy_vocabulary_3[LANGUAGE_NONE] as $key => $value) {
+      $categories[] = $value['tid'];
+    }
+  }
+
+  if (!empty($categories)) {
+    $current_uri = urldecode(request_uri());
+    // If the parameter is not there add a fake one, which will be replaced.
+    if (strpos($current_uri, 'f[3]=im_vid_3') === FALSE) {
+      $current_uri .= (strpos($current_uri, '?') === FALSE) ? '?' : '&';
+      $current_uri .= 'f[3]=im_vid_3:123';
+    }
+    $terms = taxonomy_term_load_multiple($categories);
+    $links = [];
+    $pattern = '/f\[3\]=im_vid_3:[0-9]+/';
+    foreach ($terms as $term) {
+      $replacement = 'f[3]=im_vid_3:' . $term->tid;
+      $link = preg_replace($pattern, $replacement, $current_uri);
+      // Not using l() or url() since query string is inline instead of in an
+      // array structure.
+      $links[] = '<a href="' . $link . '">' . check_plain($term->name) . '</a>';
+    }
+    return $links;
+  }
+
+  return [];
+}
+
 /**
  * Page callback, shortcut to get to issue pages.
  */
-- 
GitLab