From ae277e28a64840433141f8085ab9a080ebce5ef2 Mon Sep 17 00:00:00 2001
From: Robin Ward <robin.ward@gmail.com>
Date: Tue, 9 Jun 2015 16:24:04 -0400
Subject: [PATCH] FEATURE: Allow embedding topics without creating them, by id

---
 app/controllers/embed_controller.rb       | 15 ++++--
 public/javascripts/embed.js               | 57 +++++++++++++++--------
 spec/controllers/embed_controller_spec.rb | 14 ++++++
 3 files changed, 61 insertions(+), 25 deletions(-)

diff --git a/app/controllers/embed_controller.rb b/app/controllers/embed_controller.rb
index 198288297..f296998ef 100644
--- a/app/controllers/embed_controller.rb
+++ b/app/controllers/embed_controller.rb
@@ -1,13 +1,18 @@
 class EmbedController < ApplicationController
   skip_before_filter :check_xhr, :preload_json, :verify_authenticity_token
-
   before_filter :ensure_embeddable
 
   layout 'embed'
 
   def comments
-    embed_url = params.require(:embed_url)
-    topic_id = TopicEmbed.topic_id_for_embed(embed_url)
+    embed_url = params[:embed_url]
+
+    topic_id = nil
+    if embed_url.present?
+      topic_id = TopicEmbed.topic_id_for_embed(embed_url)
+    else
+      topic_id = params[:topic_id].to_i
+    end
 
     if topic_id
       @topic_view = TopicView.new(topic_id,
@@ -21,7 +26,8 @@ class EmbedController < ApplicationController
       if @topic_view && @topic_view.posts.size == SiteSetting.embed_post_limit
         @posts_left = @topic_view.topic.posts_count - SiteSetting.embed_post_limit - 1
       end
-    else
+
+    elsif embed_url.present?
       Jobs.enqueue(:retrieve_topic, user_id: current_user.try(:id), embed_url: embed_url)
       render 'loading'
     end
@@ -30,7 +36,6 @@ class EmbedController < ApplicationController
   end
 
   def count
-
     embed_urls = params[:embed_url]
     by_url = {}
 
diff --git a/public/javascripts/embed.js b/public/javascripts/embed.js
index e299ae547..33c11d337 100644
--- a/public/javascripts/embed.js
+++ b/public/javascripts/embed.js
@@ -1,24 +1,41 @@
-/* global discourseUrl */
-/* global discourseUserName */
-/* global discourseEmbedUrl */
 (function() {
-  var comments = document.getElementById('discourse-comments'),
-  iframe = document.createElement('iframe');
-  if (typeof discourseUserName === 'undefined') {
-    iframe.src =
-      [ discourseUrl,
-        'embed/comments?embed_url=',
-        encodeURIComponent(discourseEmbedUrl)
-      ].join('');
-  } else {
-    iframe.src =
-      [ discourseUrl,
-        'embed/comments?embed_url=',
-        encodeURIComponent(discourseEmbedUrl),
-        '&discourse_username=',
-        discourseUserName
-      ].join('');
+
+  var DE = window.DiscourseEmbed || {};
+  var comments = document.getElementById('discourse-comments');
+  var iframe = document.createElement('iframe');
+
+  ['discourseUrl', 'discourseEmbedUrl', 'discourseUserName'].forEach(function(i) {
+    if (window[i]) { DE[i] = DE[i] || window[i]; }
+  });
+
+  var queryParams = {};
+
+  if (DE.discourseEmbedUrl) {
+    queryParams.embed_url = encodeURIComponent(DE.discourseEmbedUrl);
   }
+
+  if (DE.discourseUserName) {
+    queryParams.discourse_username = DE.discourseUserName;
+  }
+
+  if (DE.topicId) {
+    queryParams.topic_id = DE.topicId;
+  }
+
+  var src = DE.discourseUrl + 'embed/comments';
+  var keys = Object.keys(queryParams);
+  if (keys.length > 0) {
+    src += "?";
+
+    for (var i=0; i<keys.length; i++) {
+      if (i > 0) { src += "&"; }
+
+      var k = keys[i];
+      src += k + "=" + queryParams[k];
+    }
+  }
+
+  iframe.src = src;
   iframe.id = 'discourse-embed-frame';
   iframe.width = "100%";
   iframe.frameBorder = "0";
@@ -48,7 +65,7 @@
 
   function postMessageReceived(e) {
     if (!e) { return; }
-    if (discourseUrl.indexOf(e.origin) === -1) { return; }
+    if (DE.discourseUrl.indexOf(e.origin) === -1) { return; }
 
     if (e.data) {
       if (e.data.type === 'discourse-resize' && e.data.height) {
diff --git a/spec/controllers/embed_controller_spec.rb b/spec/controllers/embed_controller_spec.rb
index 514d84f57..4fc2319d6 100644
--- a/spec/controllers/embed_controller_spec.rb
+++ b/spec/controllers/embed_controller_spec.rb
@@ -16,6 +16,20 @@ describe EmbedController do
     expect(response).not_to be_success
   end
 
+  context "by topic id" do
+
+    before do
+      SiteSetting.embeddable_hosts = host
+      controller.request.stubs(:referer).returns('http://eviltrout.com/some-page')
+    end
+
+    it "allows a topic to be embedded by id" do
+      topic = Fabricate(:topic)
+      get :comments, topic_id: topic.id
+      expect(response).to be_success
+    end
+  end
+
   context "with a host" do
     before do
       SiteSetting.embeddable_hosts = host