Project

General

Profile

Patch #44016 » 0001-Enable-instantiation-of-PluginLoader.patch

Takashi Kato, 2026-05-02 09:05

View differences:

lib/redmine/plugin.rb
49 49
  #
50 50
  # See: http://www.redmine.org/projects/redmine/wiki/Plugin_Tutorial
51 51
  class Plugin
52
    cattr_accessor :loader
53

  
52 54
    # Absolute path to the directory where plugins are located
53
    cattr_accessor :directory
54
    self.directory = PluginLoader.directory
55
    def self.directory
56
      loader.directory
57
    end
55 58

  
56 59
    # Absolute path to the public directory where plugins assets are copied
57
    cattr_accessor :public_directory
58
    self.public_directory = PluginLoader.public_directory
60
    def self.public_directory
61
      loader.public_directory
62
    end
59 63

  
60 64
    @registered_plugins = {}
61 65
    @used_partials = {}
......
103 107
        raise PluginNotFound, "Plugin not found. The directory for plugin #{p.id} should be #{p.directory}."
104 108
      end
105 109

  
106
      p.path = PluginLoader.directories.find {|d| d.to_s == p.directory}
110
      p.path = loader.directories.find {|d| d.to_s == p.directory}
107 111

  
108 112
      # Adds plugin locales if any
109 113
      # YAML translation files should be found under <plugin>/config/locales/
......
192 196
    def asset_paths
193 197
      return unless path.has_assets_dir?
194 198

  
195
      base_dir = Pathname.new(path.assets_dir)
196
      paths = base_dir.children.select(&:directory?)
197
      Redmine::AssetPath.new(base_dir, paths, asset_prefix)
199
      Redmine::AssetPath.new(path.base_dir, path.asset_paths, asset_prefix)
198 200
    end
199 201

  
200 202
    def <=>(plugin)
lib/redmine/plugin_loader.rb
19 19

  
20 20
module Redmine
21 21
  class PluginPath
22
    attr_reader :assets_dir, :initializer
22
    attr_reader :assets_dir, :initializer, :prefix
23 23

  
24
    def initialize(dir)
24
    def initialize(dir, prefix)
25 25
      @dir = dir
26
      @assets_dir = File.join dir, 'assets'
27
      @initializer = File.join dir, 'init.rb'
26
      @prefix = prefix
27
      @assets_dir = File.join @dir, 'assets'
28
      @initializer = File.join @dir, 'init.rb'
28 29
    end
29 30

  
30 31
    def run_initializer
......
42 43
    def has_initializer?
43 44
      File.file?(@initializer)
44 45
    end
46

  
47
    def base_dir
48
      @base_dir ||= Pathname.new(assets_dir)
49
    end
50

  
51
    def asset_paths
52
      paths = base_dir.children.select(&:directory?)
53
      paths
54
    end
45 55
  end
46 56

  
47 57
  class PluginLoader
48 58
    # Absolute path to the directory where plugins are located
49
    cattr_accessor :directory
50
    self.directory = Rails.root.join Rails.application.config.redmine_plugins_directory
59
    attr_accessor :directory
60

  
61
    attr_accessor :prefix
51 62

  
52 63
    # Absolute path to the public directory where plugins assets are copied
53
    cattr_accessor :public_directory
54
    self.public_directory = Rails.public_path.join('plugin_assets')
64
    attr_accessor :public_directory
55 65

  
56
    def self.load
57
      setup
58
      add_autoload_paths
66
    def initialize(directory:, prefix:)
67
      @directory = directory
68
      @prefix = prefix
69
      @plugin_directories = []
59 70

  
60
      Rails.application.config.to_prepare do
61
        PluginLoader.directories.each(&:run_initializer)
71
      Dir.glob(File.join(directory, '*')).each do |directory|
72
        next unless File.directory?(directory)
62 73

  
63
        Redmine::Hook.call_hook :after_plugins_loaded
74
        @plugin_directories << PluginPath.new(directory, prefix)
64 75
      end
65 76
    end
66 77

  
67
    def self.setup
68
      @plugin_directories = []
78
    def self.load
79
      directory = Rails.root.join(Rails.application.config.redmine_plugins_directory)
80
      prefix    = 'plugin_assets'
81
      loader = new(directory: directory, prefix: prefix)
69 82

  
70
      Dir.glob(File.join(directory, '*')).each do |directory|
71
        next unless File.directory?(directory)
83
      loader.public_directory = Rails.public_path.join(prefix)
84
      loader.add_autoload_paths
85

  
86
      Rails.application.config.to_prepare do
87
        Redmine::Plugin.loader = loader
88
        loader.directories.each(&:run_initializer)
72 89

  
73
        @plugin_directories << PluginPath.new(directory)
90
        Redmine::Hook.call_hook :after_plugins_loaded
74 91
      end
75 92
    end
76 93

  
77
    def self.add_autoload_paths
94
    def add_autoload_paths
78 95
      directories.each do |directory|
79 96
        # Add the plugin directories to rails autoload paths
80 97
        engine_cfg = Rails::Engine::Configuration.new(directory.to_s)
......
86 103
      end
87 104
    end
88 105

  
89
    def self.directories
106
    def directories
90 107
      @plugin_directories
91 108
    end
92 109
  end
test/fixtures/plugins/foo_plugin/app/javascript/foo.js
1
export sample() {
2
}
test/fixtures/plugins/foo_plugin/init.rb
1
Redmine::Plugin.register :foo_plugin do
2
  name 'Test plugin redmine_test_plugin_foo'
3
  author 'Author name'
4
  description 'This is a plugin for Redmine test'
5
  version '0.0.1'
6
end
7

  
8

  
test/generators/controller_generator_test.rb
29 29

  
30 30
  setup do
31 31
    @plugin_directory = Redmine::Plugin.directory
32
    Redmine::Plugin.directory = TMP_DIR
32
    Redmine::Plugin.loader.directory = TMP_DIR
33 33
  end
34 34

  
35 35
  teardown do
36
    Redmine::Plugin.directory = @plugin_directory
36
    Redmine::Plugin.loader.directory = @plugin_directory
37 37
  end
38 38

  
39 39
  def test_generates_files_from_templates
test/generators/migration_generator_test.rb
29 29

  
30 30
  setup do
31 31
    @plugin_directory = Redmine::Plugin.directory
32
    Redmine::Plugin.directory = TMP_DIR
32
    Redmine::Plugin.loader.directory = TMP_DIR
33 33
  end
34 34

  
35 35
  teardown do
36
    Redmine::Plugin.directory = @plugin_directory
36
    Redmine::Plugin.loader.directory = @plugin_directory
37 37
  end
38 38

  
39 39
  def test_migration_file_name_is_snake_case
test/generators/model_generator_test.rb
29 29

  
30 30
  setup do
31 31
    @plugin_directory = Redmine::Plugin.directory
32
    Redmine::Plugin.directory = TMP_DIR
32
    Redmine::Plugin.loader.directory = TMP_DIR
33 33
  end
34 34

  
35 35
  teardown do
36
    Redmine::Plugin.directory = @plugin_directory
36
    Redmine::Plugin.loader.directory = @plugin_directory
37 37
  end
38 38

  
39 39
  def test_generates_files_from_templates
test/integration/routing/plugins_test.rb
21 21

  
22 22
class RoutingPluginsTest < Redmine::RoutingTest
23 23
  def setup
24
    @original_plugin_dir = Redmine::PluginLoader.directory
24
    @original_loader = Redmine::Plugin.loader
25 25

  
26 26
    Redmine::Plugin.clear
27
    Redmine::PluginLoader.directory = Rails.root.join('test/fixtures/plugins')
28
    Redmine::Plugin.directory = Rails.root.join('test/fixtures/plugins')
29
    Redmine::PluginLoader.load
30
    Redmine::PluginLoader.directories.each(&:run_initializer) # to define relative controllers
27
    loader = Redmine::PluginLoader.new(directory: Rails.root.join('test/fixtures/plugins'), prefix: @original_loader.prefix)
28
    loader.public_directory = Rails.public_path.join(@original_loader.prefix)
29
    loader.add_autoload_paths
30
    Redmine::Plugin.loader = loader
31

  
32
    loader.directories.each(&:run_initializer) # to define relative controllers
31 33
    RedmineApp::Application.instance.routes_reloader.reload!
32 34
  end
33 35

  
34 36
  def teardown
35 37
    Redmine::Plugin.clear
36
    Redmine::PluginLoader.directory = @original_plugin_dir
37
    Redmine::Plugin.directory = @original_plugin_dir
38
    Redmine::Plugin.loader = @original_loader
38 39
    Redmine::PluginLoader.load
39 40
    RedmineApp::Application.instance.routes_reloader.reload!
40 41
  end
test/unit/lib/redmine/plugin_test.rb
22 22
class Redmine::PluginTest < ActiveSupport::TestCase
23 23
  def setup
24 24
    @klass = Redmine::Plugin
25
    @original_loader = Redmine::Plugin.loader
26

  
25 27
    # Change plugin directory for testing to default
26 28
    # plugins/foo => test/fixtures/plugins/foo
27
    @klass.directory = Rails.root.join('test/fixtures/plugins')
29
    loader = Redmine::PluginLoader.new(directory: Rails.root.join('test/fixtures/plugins'), prefix: @original_loader.prefix)
30
    @klass.loader = loader
28 31
    # In case some real plugins are installed
29 32
    @klass.clear
30

  
31
    # Change plugin loader's directory for testing
32
    Redmine::PluginLoader.directory = @klass.directory
33
    Redmine::PluginLoader.setup
34 33
  end
35 34

  
36 35
  def teardown
37 36
    @klass.clear
37
    Redmine::Plugin.loader = @original_loader
38 38
  end
39 39

  
40 40
  def test_register
(1-1/2)