# encoding: utf-8 require 'fedux_org_stdlib/require_files' require 'fedux_org_stdlib/gem_plugins/no_plugin' require 'fedux_org_stdlib/gem_plugins/plugin' require 'fedux_org_stdlib/gem_plugins/exceptions' require 'fedux_org_stdlib/list' require_library %w( active_support/core_ext/string/inflections active_support/core_ext/object/blank hirb/console ) module FeduxOrgStdlib module GemPlugins # Plugin Manager # # To use the plugin manager you should build the plugins for your # application as rubygems. How you name the plugins is up to you, but it is # recommended to use something like `your-application-`, where # `your-application-` is the prefix (please mind the dash at the end). # # @example PluginManager-class # # module YourApplication # class PluginManager < FeduxOrgStdlib::GemPlugins::PluginManager # end # end # # @example Default prefix # # Please make sure you create a class for your plugin manager to make it # work. Otherwise give the prefix via parameter - see below. # # # -- main.rb -- # # main module # module YourApplication # # The manager uses "#{self.name.underscore.gsub(/\//, '-')}-" as prefix # @plugin_manager = PluginManager.new # # class << self # attr_reader :plugin_manager # # def load_plugins # self.plugin_manager.load_plugins # end # end # end # # # @example Use different prefix # # -- main.rb -- # # main module # module YourApplication # # The manager uses 'asdf-' as prefix # @plugin_manager = PluginManager.new(prefix: 'asdf-') # # [...] # end # # At some place you need to load your plugins. # # @example Load plugins in your application # # # -- runner.rb -- # # YourApplication.load_plugins # class PluginManager private attr_reader :plugins, :prefix, :whitelist, :blacklist public def initialize(prefix: __plugin_prefix, whitelist: [], blacklist: []) @prefix = Regexp.new(prefix) @whitelist = Array(whitelist) @blacklist = Array(blacklist) # needs variables above @plugins = locate_plugins end # Disable a plugin def disable_plugin(name) plugin = plugins.find(NoPlugin.new(name)) { |p| p.name == name } return if plugin.blank? plugin.disable end # Enable a plugin def enable_plugin(name) plugin = plugins.find(NoPlugin.new(name)) { |p| p.name == name } return if plugin.blank? plugin.enable end # Require all enabled plugins, disabled plugins are skipped. def load_plugins each_enabled_plugin { |p| p.activate } end # String representation def to_s data = plugins.sort.inject([]) { |a, e| a << {name: e.name, enabled: e.enabled?, gem_name: e.gem_name, required_file: e.required_file} } List.new(data).to_s( fields: [:name, :gem_name, :enabled, :required_file] ) end private def each_enabled_plugin(&block) plugins.find_all { |p| p.enabled? }.each(&block) end # Find all installed plugins and store them in an internal array. def locate_plugins plgs = [] Gem.refresh (Gem::Specification.respond_to?(:each) ? Gem::Specification : Gem.source_index.find_name('')).each do |gem| name = gem.name.sub(prefix, '') next if gem.name !~ prefix next if plgs.any? { |plugin| plugin.name == name } enabled = if !whitelist.blank? && !whitelist.include?(name) false elsif !blacklist.blank? && blacklist.include?(name) false else true end plgs << Plugin.new( name, gem_name: gem.name, enabled: enabled, prefix: prefix, ) end plgs end def __plugin_prefix name = if self.class.name.deconstantize.blank? self.class.name else self.class.name.deconstantize end "#{name.underscore.gsub(/\//, '-')}-" end end end end