]> source.dussan.org Git - redmine.git/commitdiff
Extract Redmine::PluginLoader from Redmine::Plugin (#32938).
authorMarius Balteanu <marius.balteanu@zitec.com>
Wed, 17 Nov 2021 20:36:53 +0000 (20:36 +0000)
committerMarius Balteanu <marius.balteanu@zitec.com>
Wed, 17 Nov 2021 20:36:53 +0000 (20:36 +0000)
Patch by Takashi Kato.

git-svn-id: http://svn.redmine.org/redmine/trunk@21283 e93f8b46-1217-0410-a6f0-8f06a7374b81

config/initializers/30-redmine.rb
lib/redmine/plugin.rb
lib/redmine/plugin_loader.rb [new file with mode: 0644]

index 73cd08052de3cea557a4ab8ce921642740b4baad..d6240f25dfbcf52dde99d9892810f085055996e0 100644 (file)
@@ -5,6 +5,7 @@ I18n.backend = Redmine::I18n::Backend.new
 I18n.config.available_locales = nil
 
 require 'redmine'
+require 'redmine/plugin_loader'
 
 # Load the secret token from the Redmine configuration file
 secret = Redmine::Configuration['secret_token']
@@ -17,15 +18,9 @@ if Object.const_defined?(:OpenIdAuthentication)
   OpenIdAuthentication.store = openid_authentication_store.presence || :memory
 end
 
-Redmine::Plugin.load
+Redmine::PluginLoader.load
+plugin_assets_reloader = Redmine::PluginLoader.create_assets_reloader
 
-plugin_assets_dirs = {}
-Redmine::Plugin.all.each do |plugin|
-  plugin_assets_dirs[plugin.assets_directory] = ["*"]
-end
-plugin_assets_reloader = ActiveSupport::FileUpdateChecker.new([], plugin_assets_dirs) do
-  Redmine::Plugin.mirror_assets
-end
 Rails.application.reloaders << plugin_assets_reloader
 unless Redmine::Configuration['mirror_plugins_assets_on_startup'] == false
   plugin_assets_reloader.execute
index 48d04dcac1a43fbba5936f079b15ec11c6c9f18f..50b6a2f4c24f52400c9ade67789110ca93b7b9cd 100644 (file)
@@ -52,15 +52,17 @@ module Redmine
   class Plugin
     # Absolute path to the directory where plugins are located
     cattr_accessor :directory
-    self.directory = File.join(Rails.root, 'plugins')
+    self.directory = PluginLoader.directory
 
     # Absolute path to the plublic directory where plugins assets are copied
     cattr_accessor :public_directory
-    self.public_directory = File.join(Rails.root, 'public', 'plugin_assets')
+    self.public_directory = PluginLoader.public_directory
 
     @registered_plugins = {}
     @used_partials = {}
 
+    attr_accessor :path
+
     class << self
       attr_reader :registered_plugins
       private :new
@@ -102,6 +104,8 @@ module Redmine
         raise PluginNotFound, "Plugin not found. The directory for plugin #{p.id} should be #{p.directory}."
       end
 
+      p.path = PluginLoader.directories{ |d| d.dir == p.directory }
+
       # Adds plugin locales if any
       # YAML translation files should be found under <plugin>/config/locales/
       Rails.application.config.i18n.load_path += Dir.glob(File.join(p.directory, 'config', 'locales', '*.yml'))
@@ -113,15 +117,6 @@ module Redmine
         ActionMailer::Base.prepend_view_path(view_path)
       end
 
-      # Add the plugin directories to rails autoload paths
-      engine_cfg = Rails::Engine::Configuration.new(p.directory)
-      engine_cfg.paths.add 'lib', eager_load: true
-      Rails.application.config.eager_load_paths += engine_cfg.eager_load_paths
-      Rails.application.config.autoload_once_paths += engine_cfg.autoload_once_paths
-      Rails.application.config.autoload_paths += engine_cfg.autoload_paths
-      ActiveSupport::Dependencies.autoload_paths +=
-        engine_cfg.eager_load_paths + engine_cfg.autoload_once_paths + engine_cfg.autoload_paths
-
       # Defines plugin setting if present
       if p.settings
         Setting.define_plugin_setting p
@@ -174,23 +169,6 @@ module Redmine
       registered_plugins[id.to_sym].present?
     end
 
-    def self.load
-      Dir.glob(File.join(self.directory, '*')).sort.each do |directory|
-        if File.directory?(directory)
-          lib = File.join(directory, "lib")
-          if File.directory?(lib)
-            $:.unshift lib
-            ActiveSupport::Dependencies.autoload_paths += [lib]
-          end
-          initializer = File.join(directory, "init.rb")
-          if File.file?(initializer)
-            require initializer
-          end
-        end
-      end
-      Redmine::Hook.call_hook :after_plugins_loaded
-    end
-
     def initialize(id)
       @id = id.to_sym
     end
@@ -205,7 +183,7 @@ module Redmine
 
     # Returns the absolute path to the plugin assets directory
     def assets_directory
-      File.join(directory, 'assets')
+      path.assedts_dir
     end
 
     def <=>(plugin)
@@ -441,58 +419,6 @@ module Redmine
       settings && settings.is_a?(Hash) && !settings[:partial].blank?
     end
 
-    def mirror_assets
-      source = assets_directory
-      destination = public_directory
-      return unless File.directory?(source)
-
-      source_files = Dir[source + "/**/*"]
-      source_dirs = source_files.select {|d| File.directory?(d)}
-      source_files -= source_dirs
-
-      unless source_files.empty?
-        base_target_dir = File.join(destination, File.dirname(source_files.first).gsub(source, ''))
-        begin
-          FileUtils.mkdir_p(base_target_dir)
-        rescue => e
-          raise "Could not create directory #{base_target_dir}: " + e.message
-        end
-      end
-
-      source_dirs.each do |dir|
-        # strip down these paths so we have simple, relative paths we can
-        # add to the destination
-        target_dir = File.join(destination, dir.gsub(source, ''))
-        begin
-          FileUtils.mkdir_p(target_dir)
-        rescue => e
-          raise "Could not create directory #{target_dir}: " + e.message
-        end
-      end
-
-      source_files.each do |file|
-        begin
-          target = File.join(destination, file.gsub(source, ''))
-          unless File.exist?(target) && FileUtils.identical?(file, target)
-            FileUtils.cp(file, target)
-          end
-        rescue => e
-          raise "Could not copy #{file} to #{target}: " + e.message
-        end
-      end
-    end
-
-    # Mirrors assets from one or all plugins to public/plugin_assets
-    def self.mirror_assets(name=nil)
-      if name.present?
-        find(name).mirror_assets
-      else
-        all.each do |plugin|
-          plugin.mirror_assets
-        end
-      end
-    end
-
     # The directory containing this plugin's migrations (<tt>plugin/db/migrate</tt>)
     def migration_directory
       File.join(directory, 'db', 'migrate')
diff --git a/lib/redmine/plugin_loader.rb b/lib/redmine/plugin_loader.rb
new file mode 100644 (file)
index 0000000..3009560
--- /dev/null
@@ -0,0 +1,140 @@
+# frozen_string_literal: true
+
+# Redmine - project management software
+# Copyright (C) 2006-2021  Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+module Redmine
+  class PluginPath
+    attr_reader :assets_dir, :initializer
+
+    def initialize(dir)
+      @dir = dir
+      @assets_dir = File.join dir, 'assets'
+      @initializer = File.join dir, 'init.rb'
+    end
+
+    def run_initializer
+      load initializer if has_initializer?
+    end
+
+    def to_s
+      @dir
+    end
+
+    def mirror_assets
+      return unless has_assets_dir?
+
+      source_files = Dir["#{assets_dir}/**/*"]
+      source_dirs = source_files.select { |d| File.directory?(d)}
+      source_files -= source_dirs
+      unless source_files.empty?
+        base_target_dir = File.join(PluginLoader.public_directory, File.dirname(source_files.first).gsub(assets_dir, ''))
+        begin
+          FileUtils.mkdir_p(base_target_dir)
+        rescue => e
+          raise "Could not create directory #{base_target_dir}: " + e.message
+        end
+      end
+      source_dirs.each do |dir|
+        # strip down these paths so we have simple, relative paths we can
+        # add to the destination
+        target_dir = File.join(PluginLoader.public_directory, dir.gsub(assets_dir, ''))
+        begin
+          FileUtils.mkdir_p(target_dir)
+        rescue => e
+          raise "Could not create directory #{target_dir}: " + e.message
+        end
+      end
+      source_files.each do |file|
+        target = File.join(PluginLoader.public_directory, file.gsub(assets_dir, ''))
+        unless File.exist?(target) && FileUtils.identical?(file, target)
+          FileUtils.cp(file, target)
+        end
+      rescue => e
+        raise "Could not copy #{file} to #{target}: " + e.message
+      end
+    end
+
+    def has_assets_dir?
+      File.directory?(@assets_dir)
+    end
+
+    def has_initializer?
+      File.file?(@initializer)
+    end
+  end
+
+  class PluginLoader
+    # Absolute path to the directory where plugins are located
+    cattr_accessor :directory
+    self.directory = Rails.root.join('plugins')
+
+    # Absolute path to the plublic directory where plugins assets are copied
+    cattr_accessor :public_directory
+    self.public_directory = Rails.root.join('public/plugin_assets')
+
+    def self.create_assets_reloader
+      plugin_assets_dirs = {}
+      @plugin_directories.each do |dir|
+        plugin_assets_dirs[dir.assets_dir] = ['*']
+      end
+      ActiveSupport::FileUpdateChecker.new([], plugin_assets_dirs) do
+        mirror_assets
+      end
+    end
+
+    def self.load
+      setup
+      add_autoload_paths
+
+      Rails.application.config.to_prepare do
+        PluginLoader.directories.each(&:run_initializer)
+
+        Redmine::Hook.call_hook :after_plugins_loaded
+      end
+    end
+
+    def self.setup
+      @plugin_directories = []
+
+      Dir.glob(File.join(directory, '*')).sort.each do |directory|
+        next unless File.directory?(directory)
+
+        @plugin_directories << PluginPath.new(directory)
+      end
+    end
+
+    def self.add_autoload_paths
+      directories.each do |directory|
+        # Add the plugin directories to rails autoload paths
+        engine_cfg = Rails::Engine::Configuration.new(directory.to_s)
+        engine_cfg.paths.add 'lib', eager_load: true
+        Rails.application.config.eager_load_paths += engine_cfg.eager_load_paths
+        Rails.application.config.autoload_once_paths += engine_cfg.autoload_once_paths
+        Rails.application.config.autoload_paths += engine_cfg.autoload_paths
+      end
+    end
+
+    def self.directories
+      @plugin_directories
+    end
+
+    def self.mirror_assets
+      directories.each(&:mirror_assets)
+    end
+  end
+end