From 860deeb07285f9fa1e37f18f6045f547d00da606 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9gis=20Hanol?= <regis@hanol.fr>
Date: Mon, 29 Jun 2020 12:31:20 +0200
Subject: [PATCH] FIX: identify slug-less topic urls everywhere

In 91c89df6, I fixed the onebox to support local topics with a slug-less URL.
This commit fixes all the other spots (search, topic links and user badges) where we look up for a local topic.

Follow-up-to: 91c89df6
---
 app/controllers/user_badges_controller.rb |  9 +++++----
 app/models/topic_link.rb                  | 21 +++++++++++++--------
 lib/search.rb                             |  8 ++++++--
 3 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/app/controllers/user_badges_controller.rb b/app/controllers/user_badges_controller.rb
index 0abbfecdd38..2771e443f1b 100644
--- a/app/controllers/user_badges_controller.rb
+++ b/app/controllers/user_badges_controller.rb
@@ -65,10 +65,11 @@ class UserBadgesController < ApplicationController
       end
 
       if route = Discourse.route_for(params[:reason])
-        topic_id = route[:topic_id].to_i
-        post_number = route[:post_number] || 1
-
-        post_id = Post.find_by(topic_id: topic_id, post_number: post_number).try(:id) if topic_id > 0
+        if route[:controller] == "topics" && route[:action] == "show"
+          topic_id = (route[:id] || route[:topic_id]).to_i
+          post_number = route[:post_number] || 1
+          post_id = Post.find_by(topic_id: topic_id, post_number: post_number)&.id if topic_id > 0
+        end
       end
     end
 
diff --git a/app/models/topic_link.rb b/app/models/topic_link.rb
index 3f992d9f8ff..134bde3b697 100644
--- a/app/models/topic_link.rb
+++ b/app/models/topic_link.rb
@@ -276,20 +276,25 @@ class TopicLink < ActiveRecord::Base
       internal = true
 
       # We aren't interested in tracking internal links to users
-      return nil if route[:controller] == 'users'
+      return nil if route[:controller] == "users"
 
-      topic_id = route[:topic_id].to_i
+      topic_id = route[:topic_id]
+      topic_slug = route[:slug]
       post_number = route[:post_number] || 1
-      topic_slug = route[:id]
 
-      # Store the canonical URL
-      topic = Topic.find_by(id: topic_id)
-      topic ||= Topic.find_by(slug: topic_slug) if topic_slug
-      topic_id = nil unless topic
+      if route[:controller] == "topics" && route[:action] == "show"
+        topic_id ||= route[:id]
+        topic_slug ||= route[:id]
+      end
+
+      topic = Topic.find_by(id: topic_id) if topic_id
+      topic ||= Topic.find_by(slug: topic_slug) if topic_slug.present?
 
       if topic.present?
         url = +"#{Discourse.base_url_no_prefix}#{topic.relative_url}"
         url << "/#{post_number}" if post_number.to_i > 1
+      else
+        topic_id = nil
       end
     end
 
@@ -314,7 +319,7 @@ class TopicLink < ActiveRecord::Base
       domain: parsed.host,
       internal: internal,
       link_topic_id: topic&.id,
-      link_post_id: reflected_post.try(:id),
+      link_post_id: reflected_post&.id,
       quote: link.is_quote,
       extension: file_extension,
     )
diff --git a/lib/search.rb b/lib/search.rb
index d95ec378c93..9b593d8d155 100644
--- a/lib/search.rb
+++ b/lib/search.rb
@@ -247,8 +247,12 @@ class Search
         single_topic(@term.to_i)
       else
         begin
-          route = Rails.application.routes.recognize_path(@term)
-          single_topic(route[:topic_id]) if route[:topic_id].present?
+          if route = Discourse.route_for(@term)
+            if route[:controller] == "topics" && route[:action] == "show"
+              topic_id = (route[:id] || route[:topic_id]).to_i
+              single_topic(topic_id) if topic_id > 0
+            end
+          end
         rescue ActionController::RoutingError
         end
       end