Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
initial commit to engines branch
  • Loading branch information
Sven Fuchs committed Feb 20, 2008
1 parent 2772ec1 commit 1ad1b56
Show file tree
Hide file tree
Showing 47 changed files with 2,170 additions and 194 deletions.
4 changes: 2 additions & 2 deletions app/controllers/admin/plugins_controller.rb
Expand Up @@ -2,7 +2,7 @@ class Admin::PluginsController < Admin::BaseController
before_filter :find_plugin, :except => :index

def index
@plugins = Mephisto::DirectoryPlugin.scan
@plugins = Mephisto.plugins
end

def update
Expand All @@ -19,6 +19,6 @@ def destroy

protected
def find_plugin
@plugin = Mephisto::Plugin[params[:id]]
@plugin = Mephisto.plugins[params[:id]]
end
end
6 changes: 3 additions & 3 deletions app/views/admin/plugins/_plugin.rhtml
@@ -1,10 +1,10 @@
<tr class="published" >
<td class="published">
<% if plugin.configurable? -%>
<%= link_to plugin.path, :action => 'show', :id => plugin.path %>
<%= link_to plugin.mephisto_name, :action => 'show', :id => plugin.name %>
<% else -%>
<%=h plugin.path %>
<%=h plugin.mephisto_name %>
<% end -%>
</td>
<td class="published"><%= plugin.configurable? ? link_to(image_tag('/images/mephisto/icons/8-em-check.png', :style => 'vertical-align: middle'), :action => "show", :id => plugin.path) : '&nbsp;' %></span> </td>
<td class="published"><%= plugin.configurable? ? link_to(image_tag('/images/mephisto/icons/8-em-check.png', :style => 'vertical-align: middle'), :action => "show", :id => plugin.name) : '&nbsp;' %></span> </td>
</tr>
4 changes: 2 additions & 2 deletions app/views/admin/plugins/show.rhtml
Expand Up @@ -23,7 +23,7 @@
<div id="page-nav">
<ul id="act-nav" class="clear">
<li>
<%= link_to 'Restore Defaults', :action => 'destroy', :id => @plugin.plugin_name %>
<%= link_to 'Restore Defaults', :action => 'destroy', :id => @plugin.name %>
</li>
<li>
<%= link_to 'Index', :action => 'index' %>
Expand All @@ -33,7 +33,7 @@
<% end %>
<% content_for :form do -%>
<%= form_tag({:action => 'update', :id => @plugin.plugin_name}, {:id => 'plugin-config-form'}) %>
<%= form_tag({:action => 'update', :id => @plugin.name}, {:id => 'plugin-config-form'}) %>
<% end -%>
<% if @plugin.default_options.any? -%>
Expand Down
2 changes: 2 additions & 0 deletions config/environment.rb
Expand Up @@ -10,6 +10,8 @@

# Bootstrap the Rails environment, frameworks, and default configuration
require File.join(File.dirname(__FILE__), 'boot')
require File.join(File.dirname(__FILE__), '../vendor/plugins/engines/boot')
require File.join(File.dirname(__FILE__), '../lib/mephisto/plugin')

# requires vendor-loaded redcloth
require 'RedCloth-3.0.4/lib/redcloth' unless Object.const_defined?(:RedCloth)
Expand Down
4 changes: 4 additions & 0 deletions config/initializers/mephisto_init.rb
Expand Up @@ -12,6 +12,8 @@
# it's loaded before all other plugins
# Object::RAILS_PATH = Pathname.new(File.expand_path(RAILS_ROOT))

require 'mephisto'

class ActionController::Dispatcher
def self.register_liquid_tags
Mephisto.liquid_filters.each { |mod| Liquid::Template.register_filter mod }
Expand All @@ -36,5 +38,7 @@ def cleanup_application_with_plugins(force = false)
inflect.uncountable %w( audio )
end

Engines::Plugin::Config.set_table_name 'mephisto_plugins'

Dependencies.autoloaded_constants.delete "Mephisto"
Dependencies.autoloaded_constants.delete "Mephisto::Plugin"
228 changes: 45 additions & 183 deletions lib/mephisto/plugin.rb
@@ -1,187 +1,49 @@
module Mephisto
# This module assists with general Mephisto plugins.
class Plugin < ActiveRecord::Base
set_table_name 'mephisto_plugins'
serialize :options, Hash

@@custom_routes = []
@@view_paths = {}
@@tabs = []
@@admin_tabs = []
cattr_reader :custom_routes, :view_paths, :tabs, :admin_tabs

class << self
expiring_attr_reader :plugin_name, 'name.demodulize.underscore'
expiring_attr_reader :plugin_path, "RAILS_PATH + 'vendor/plugins' + ('mephisto_' + plugin_name)"

plugin_property_source = %w(author version homepage notes).collect! do |property|
<<-END
def #{property}(value = nil)
@#{property} = value if value
@#{property}
end
END
end
eval plugin_property_source * "\n"

# Finds or initializes a new plugin record from the database by the plugin name
def find_or_initialize
find_or_initialize_by_name(plugin_name)
end

#
# Matches key to sub classes of Mephisto::Plugin in the namespace Mephisto::Plugins.
# In other words, your plugin needs to subclass the former and be within the latter.
#
def find_class(key)
klass_name = key.to_s.camelize
klass = Mephisto::Plugins.const_get klass_name
if klass < Mephisto::Plugin
klass
else
raise NameError, "Plugin class must subclass Mephisto::Plugin"
end
end

def [](key)
find_class(key).find_or_initialize
end

def load(plugin_list)
returning find_all_by_name(plugin_list).index_by(&:name) do |plugins|
plugin_list.each do |name|
if plugin_class = plugins[name].nil? && self[name]
plugins[name] ||= plugin_class.new(:name => name)
end
end
end
end

def default_options
@default_options ||= {}
end

def option(property, default, field_type = :text_field)
class_eval <<-END, __FILE__, __LINE__
def #{property}
write_attribute(:options, {}) if read_attribute(:options).nil?
options[#{property.inspect}].blank? ? #{default.inspect} : options[#{property.inspect}]
end
def #{property}=(value)
write_attribute(:options, {}) if read_attribute(:options).nil?
options[#{property.inspect}] = value
end
END
default_options[property] = field_type
end

# Installs the plugin's tables using the schema file in lib/#{plugin_name}/schema.rb
#
# script/runner -e production 'Mephisto::Plugins::Foo.install'
# => installs the mephisto_foo plugin.
#
def install
self::Schema.install
end

# Uninstalls the plugin's tables using the schema file in lib/#{plugin_name}/schema.rb
def uninstall
self::Schema.uninstall
end

# Adds a custom route to Mephisto from a plugin. These routes are created in the order they are added.
# They will be the last routes before the Mephisto Dispatcher catch-all route.
def add_route(*args)
custom_routes << args
end

# Keeps track of custom adminstration tabs. Each item is an array of arguments to be passed to link_to.
#
# module Mephisto
# module Plugins
# class Foo < Mephisto::Plugin
# add_tab 'Foo', :controller => 'foo'
# end
# end
# end
def add_tab(*args)
tabs << args
end

# Keeps track of custom adminstration tabs for ADMIN users only. Each item is an array of arguments to be passed to link_to.
#
# module Mephisto
# module Plugins
# class Foo < Mephisto::Plugin
# add_admin_tab 'Foo', :controller => 'foo'
# end
# end
# end
def add_admin_tab(*args)
admin_tabs << args
end

# Sets up a custom public controller for this plugin. It adds the plugin's lib directory to the controller paths directory and
# saves the view path. Call this from your plugin's init.rb file.
#
# # #underscore will be called on the title parameter, so the 4th parameter 'foo' is unnecessary here.
# module Mephisto
# module Plugins
# class Foo < Mephisto::Plugin
# public_controller 'Foo', 'foo'
# end
# end
# end
#
# Once set, create your controller in #{YOUR_PLUGIN}/lib/foo_controller.rb.
#
# class FooController < ApplicationController
# self.template_root = Mephisto::Plugin.view_paths[:foo]
# ...
# end
#
# Your views will then be stored in #{YOUR_PLUGIN}/views/foo/*.rhtml.
def public_controller(title, name = nil)
returning((name || title.underscore).to_sym) do |controller_name|
view_paths[controller_name] = (plugin_path + 'views').to_s
end
end
require File.join(File.dirname(__FILE__), 'plugin_about_patch')

# needs to be loaded before or at beginning of plugin init stage because it
# allows to use add_tab and add_admin_tab from plugin init.rb

module Mephisto
def self.plugins
@@plugins ||= Engines::Plugin::List.new Engines.plugins.select{ |plugin| plugin.mephisto_plugin? }
end

# Sets up a custom admin controller. Mephisto::Plugin.public_controller is used for the basic setup. This also automatically
# adds a tab for you, and symlinks Mephisto's core app/views/layouts path. Like Mephisto::Plugin.public_controller, this should be
# called from your plugin's init.rb file.
#
# module Mephisto
# module Plugins
# class Foo < Mephisto::Plugin
# admin_controller 'Foo', 'foo'
# end
# end
# end
#
# module Admin
# class FooController < Admin::BaseController
# self.template_root = Mephisto::Plugin.view_paths[:foo]
# ...
# end
# end
#
# Your views will then be stored in #{YOUR_PLUGIN}/views/admin/foo/*.rhtml.
def admin_controller(title, name = nil, options = {})
returning public_controller(title, name) do |controller_name|
add_tab title, {:controller => "admin/#{controller_name}"}.update(options)
unless File.exists?(File.join(view_paths[controller_name], 'layouts'))
FileUtils.mkdir_p view_paths[controller_name]
FileUtils.symlink(RAILS_PATH + 'app/views/layouts', File.join(view_paths[controller_name], 'layouts'))
end
end
end
module Plugin
@@tabs = []
@@admin_tabs = []
mattr_reader :tabs, :admin_tabs

# delegate read access to about info
%w(author homepage version notes).each do |property|
module_eval "def #{property}; about['#{property}'] end", __FILE__, __LINE__
end

plugin_property_source = %w(author version homepage notes plugin_name plugin_path default_options).collect! do |property|
"def #{property}() self.class.#{property} end"

# Keeps track of custom adminstration tabs. Each item is an array of arguments to be passed to link_to.
def add_tab(*args)
args.push(:controller => args.first.to_s.downcase) if (args.size == 1)
Mephisto::Plugin.tabs << args
end

# Keeps track of custom adminstration tabs for ADMIN users only. Each item is an array of arguments to be passed to link_to.
def add_admin_tab(*args)
args.push(:controller => args.first.to_s.downcase) if (args.size == 1)
Mephisto::Plugin.admin_tabs << args
end

def mephisto_plugin?
name =~ /^mephisto_(\w+)$/
end

def configurable?
not default_options.empty?
end

def mephisto_name
name.sub /^mephisto_/, ''
end
eval plugin_property_source * "\n"
alias :conf_name :mephisto_name
end
end
end

Engines::Plugin.send :include, Mephisto::Plugin

26 changes: 26 additions & 0 deletions lib/mephisto/plugin_about_patch.rb
@@ -0,0 +1,26 @@
# separately patching Rails::Plugin assuming that this patch will be accepted:
# http://dev.rubyonrails.org/ticket/10979

unless Rails::Plugin.respond_to?(:directory)
Rails::Plugin.class_eval do
attr_reader :directory, :name, :about

alias :initialize_without_about_info :initialize
def initialize(directory)
initialize_without_about_info(directory)
load_about_information
end

private

def load_about_information
begin
about_yml_path = File.join(@directory, "about.yml")
parsed_yml = File.exist?(about_yml_path) ? YAML.load(File.read(about_yml_path)) : {}
@about = parsed_yml || {}
rescue Exception
@about = {}
end
end
end
end
9 changes: 6 additions & 3 deletions lib/mephisto/routing.rb
Expand Up @@ -33,9 +33,8 @@ def self.connect_with(map)
map.connect ':controller/:action/:id/:version', :version => nil, :controller => /routing_navigator|account|(admin\/\w+)/, :id => /[^\/]*/

yield if block_given?
Mephisto::Plugin.custom_routes.each do |path, options|
map.connect path, options
end

map_from_plugins(map)

map.dispatch '*path', :controller => 'mephisto', :action => 'dispatch'
map.home '', :controller => 'mephisto', :action => 'dispatch'
Expand All @@ -45,6 +44,10 @@ class << self
expiring_attr_reader :redirections, '{}'
end

def self.map_from_plugins(map)
Engines.plugins.each { |plugin| map.from_plugin(plugin.name) }
end

def self.deny(*paths)
paths.each do |path|
redirections[convert_redirection_to_regex(path)] = :deny
Expand Down
18 changes: 18 additions & 0 deletions spec/controllers/plugin_routing_spec.rb
@@ -0,0 +1,18 @@
# cant get this working with autotest for some reason
# invoking the spec manually will work though

# require File.join(File.dirname(__FILE__), '/../../config/boot')
#
# Rails::Configuration.send(:define_method, :plugin_paths) do
# ["#{RAILS_ROOT}/vendor/plugins", "#{RAILS_ROOT}/vendor/plugins/engines_config/test/plugins"]
# end
#
# require File.dirname(__FILE__) + '/../spec_helper'
#
# describe "Mephisto::Plugin routing" do
# controller_name 'mephisto'
#
# it "should work" do
# route_for(:controller => "somethings", :action => "index").should == "/something"
# end
# end

0 comments on commit 1ad1b56

Please sign in to comment.