public
Fork of halorgium/mephisto
Description: A mirror of the mephisto code-base
Homepage: http://mephistoblog.com/
Clone URL: git://github.com/technoweenie/mephisto.git
Click here to lend your support to: mephisto and make a donation at www.pledgie.com !
mephisto / lib / mephisto / routing.rb
100644 101 lines (83 sloc) 3.643 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
module Mephisto
  class Routing
    # Adds Mephisto routes. Yield a given block to allow custom routes.
    #
    # Mephisto::Routing.connect_with map do
    # map.foo ...
    # end
    def self.connect_with(map)
      map.feed 'feed/*sections', :controller => 'feed', :action => 'feed'
      
      map.with_options :controller => 'assets', :action => 'show' do |m|
        m.connect ':dir/:path.:ext', :dir => /stylesheets|javascripts|images/
        m.css 'stylesheets/:path.:ext', :dir => 'stylesheets'
        m.js 'javascripts/:path.:ext', :dir => 'javascripts'
        m.images 'images/:path.:ext', :dir => 'images'
      end
 
      map.moderate 'admin/articles/comments', :controller => 'admin/comments', :action => 'index'
      map.purge 'admin/articles/comments/purge', :controller => 'admin/comments', :action => 'destroy'
 
      map.resources :articles, :path_prefix => 'admin', :controller => 'admin/articles' do |r|
        r.resources :comments, :controller => 'admin/comments', :member => { :unapprove => :post, :approve => :post, :edit => :get, :preview => :post }
      end
 
      map.overview 'admin/overview.xml', :controller => 'admin/overview', :action => 'feed'
      map.admin 'admin', :controller => 'admin/overview', :action => 'index'
      map.resources :assets, :path_prefix => '/admin', :controller => 'admin/assets', :member => { :add_bucket => :post },
        :collection => { :latest => :post, :search => :post, :upload => :post, :clear_bucket => :post }
      
      # Where oh where is my xmlrpc code?
      # map.connect 'xmlrpc', :controller => 'backend', :action => 'xmlrpc'
      
      map_from_plugins(map)
      
      map.connect ':controller/:action/:id/:version', :version => nil, :controller => /routing_navigator|account|(admin\/\w+)/, :id => /[^\/]*/
 
      yield if block_given?
      
      map.dispatch '*path', :controller => 'mephisto', :action => 'dispatch'
      map.home '', :controller => 'mephisto', :action => 'dispatch'
    end
    
    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
      end
    end
    
    def self.redirect(options)
      options.each do |key, value|
        redirections[convert_redirection_to_regex(key)] = sanitize_path(value)
      end
    end
 
    def self.handle_redirection(path)
      redirections.each do |pattern, action|
        if match = pattern.match(path)
          if action == :deny
            return [:not_found]
          else
            return [:moved_permanently, {:location => build_destination(action.dup, match)}]
          end
        end
      end
      nil
    end
    
    protected
      @@sanitize_path_regex = /^(\/)|(https?:\/\/)/
      def self.sanitize_path(path)
        path =~ @@sanitize_path_regex ? path : "/#{path.split("://").last}"
      end
      
      def self.convert_redirection_to_regex(path)
        path = path.split("://").last
        path = path[1..-1] if path[0..0] == '/'
        path = Regexp.escape(path)
        path.gsub! /\//, "\\/"
        path.gsub! /(\\\*)|(\\\?$)/, "(.*)"
        path.gsub! /\\\?/, "([^\\/]+)"
        Regexp.new("^#{path}$")
      end
      
      def self.build_destination(path, matches)
        i = -1
        path.gsub!(/\$\d+/) { |s| matches[s[1..-1].to_i] }
        path.gsub!(/[^:]\/\//, &:first)
        path.chomp!('/')
        path
      end
  end
end