1 require 'annotatable'
2 require 'simpleton'
3 require 'radiant/admin_ui'
4
5 module Radiant
6 class Extension
7 include Simpleton
8 include Annotatable
9
10 annotate :version, :description, :url, :extension_name, :path
11
12 attr_writer :active
13
14 def active?
15 @active
16 end
17
18 def root
19 path.to_s
20 end
21
22 def migrated?
23 migrator.new(:up, migrations_path).pending_migrations.empty?
24 end
25
26 def enabled?
27 active? and migrated?
28 end
29
30 # Conventional plugin-like routing
31 def routed?
32 File.exist?(routing_file)
33 end
34
35 def migrations_path
36 File.join(self.root, 'db', 'migrate')
37 end
38
39 def migrates_from
40 @migrates_from ||= {}
41 end
42
43 def routing_file
44 File.join(self.root, 'config', 'routes.rb')
45 end
46
47 def load_initializers
48 Dir["#{self.root}/config/initializers/**/*.rb"].sort.each do |initializer|
49 load(initializer)
50 end
51 end
52
53 def migrator
54 unless @migrator
55 extension = self
56 @migrator = Class.new(ExtensionMigrator){ self.extension = extension }
57 end
58 @migrator
59 end
60
61 def admin
62 AdminUI.instance
63 end
64
65 def tab(name, options={}, &block)
66 @the_tab = admin.nav[name]
67 unless @the_tab
68 @the_tab = Radiant::AdminUI::NavTab.new(name)
69 before = options.delete(:before)
70 after = options.delete(:after)
71 tab_name = before || after
72 tab_object = admin.nav[tab_name]
73 if tab_object
74 index = admin.nav.index(tab_object)
75 index += 1 unless before
76 admin.nav.insert(index, @the_tab)
77 else
78 admin.nav << @the_tab
79 end
80 end
81 if block_given?
82 block.call(@the_tab)
83 end
84 return @the_tab
85 end
86 alias :add_tab :tab
87
88 def add_item(*args)
89 @the_tab.add_item(*args)
90 end
91
92 # Determine if another extension is installed and up to date.
93 #
94 # if MyExtension.extension_enabled?(:third_party)
95 # ThirdPartyExtension.extend(MyExtension::IntegrationPoints)
96 # end
97 def extension_enabled?(extension)
98 begin
99 extension = (extension.to_s.camelcase + 'Extension').constantize
100 extension.enabled?
101 rescue NameError
102 false
103 end
104 end
105
106 class << self
107
108 def activate_extension
109 return if instance.active?
110 instance.activate if instance.respond_to? :activate
111 ActionController::Routing::Routes.add_configuration_file(instance.routing_file) if instance.routed?
112 ActionController::Routing::Routes.reload
113 instance.active = true
114 end
115 alias :activate :activate_extension
116
117 def deactivate_extension
118 return unless instance.active?
119 instance.active = false
120 instance.deactivate if instance.respond_to? :deactivate
121 end
122 alias :deactivate :deactivate_extension
123
124 def define_routes(&block)
125 ActiveSupport::Deprecation.warn("define_routes has been deprecated in favor of your extension's config/routes.rb",caller)
126 route_definitions << block
127 end
128
129 def inherited(subclass)
130 subclass.extension_name = subclass.name.to_name('Extension')
131 end
132
133 def route_definitions
134 @route_definitions ||= []
135 end
136
137 def migrate_from(extension_name, until_migration=nil)
138 instance.migrates_from[extension_name] = until_migration
139 end
140
141 # Expose the configuration object for init hooks
142 # class MyExtension < ActiveRecord::Base
143 # extension_config do |config|
144 # config.after_initialize do
145 # run_something
146 # end
147 # end
148 # end
149 def extension_config(&block)
150 yield Rails.configuration
151 end
152
153 end
154 end
155 end