diff --git a/lib/plugin/instance.rb b/lib/plugin/instance.rb index 916248efcf7..725fe7caee1 100644 --- a/lib/plugin/instance.rb +++ b/lib/plugin/instance.rb @@ -576,6 +576,22 @@ class Plugin::Instance DiscourseEvent.on(event_name) { |*args, **kwargs| block.call(*args, **kwargs) if enabled? } end + # A proxy to `DiscourseEvent.on(:site_setting_changed)` triggered when the plugin enabled setting specified by + # `enabled_site_setting` value is changed, including when the plugin is turned off. + # + # It is useful when the plugin needs to perform tasks like properly clearing caches when enabled/disabled + # note it will not be triggered when a plugin is installed/uninstalled by adding/removing its code + def on_enabled_change(&block) + event_proc = + Proc.new do |setting_name, old_value, new_value| + block.call(old_value, new_value) if setting_name == @enabled_site_setting + end + DiscourseEvent.on(:site_setting_changed, &event_proc) + + # returns the block to be used for DiscourseEvent.off(:site_setting_changed, &block) for testing purposes + event_proc + end + def notify_after_initialize color_schemes.each do |c| unless ColorScheme.where(name: c[:name]).exists? diff --git a/spec/lib/plugin/instance_spec.rb b/spec/lib/plugin/instance_spec.rb index 2610e269076..7377446a19a 100644 --- a/spec/lib/plugin/instance_spec.rb +++ b/spec/lib/plugin/instance_spec.rb @@ -183,6 +183,7 @@ TEXT class TroutPlugin < Plugin::Instance attr_accessor :enabled + def enabled? @enabled end @@ -278,6 +279,42 @@ TEXT @plugin.enabled = true expect(DiscoursePluginRegistry.build_html("test:html", ctx)).to eq("
hello
") end + + it "can act when the plugin is enabled/disabled" do + plugin = Plugin::Instance.new + plugin.enabled_site_setting(:discourse_sample_plugin_enabled) + + SiteSetting.discourse_sample_plugin_enabled = false + expect(plugin.enabled?).to eq(false) + + begin + expected_old_value = expected_new_value = nil + + event_handler = + plugin.on_enabled_change do |old_value, new_value| + expected_old_value = old_value + expected_new_value = new_value + end + + SiteSetting.discourse_sample_plugin_enabled = true + expect(expected_old_value).to eq(false) + expect(expected_new_value).to eq(true) + + SiteSetting.discourse_sample_plugin_enabled = false + expect(expected_old_value).to eq(true) + expect(expected_new_value).to eq(false) + + # ensures only the setting specified in `enabled_site_setting` is tracked + expected_old_value = expected_new_value = nil + plugin.enabled_site_setting(:discourse_sample_plugin_enabled_alternative) + SiteSetting.discourse_sample_plugin_enabled = true + expect(expected_old_value).to be_nil + expect(expected_new_value).to be_nil + ensure + # clear the underlying DiscourseEvent + DiscourseEvent.off(:site_setting_changed, &event_handler) + end + end end end