Guest User

Untitled

a guest
Feb 21st, 2018
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.53 KB | None | 0 0
  1. module Mephisto
  2. class Dispatcher
  3. PERMALINK_OPTIONS = { :year => '\d{4}', :month => '\d{1,2}', :day => '\d{1,2}', :permalink => '[\w\-]+', :id => '\d+' }
  4. PERMALINK_VAR = /^:([a-z]+)$/
  5.  
  6. cattr_accessor :permalink_map
  7. cattr_accessor :permalink_locations
  8.  
  9. def self.define_permalink_route(regex, &handler)
  10. return unless regex && handler # bail?
  11. print "adding [define_permalink_route]\n"
  12.  
  13. @@permalink_map ||= []
  14. @@permalink_map << { :regex => regex, :handler => handler }
  15. end
  16.  
  17. define_permalink_route(/comments((\/(\d+))|(\.xml))?/) do |options|
  18. print "running route check [options: %s]\n" % options.inspect
  19.  
  20. if options[1] == 'comments.xml'
  21. [:comments_feed, nil, options.first]
  22. elsif options[2]
  23. [:comment, nil, options.first, options.last]
  24. else
  25. [:comments, nil, options.first]
  26. end
  27. end
  28.  
  29. define_permalink_route(/changes\.xml/) do |options|
  30. [:changes_feed, nil, options.first]
  31. end
  32.  
  33. def self.run(site, path)
  34. # check for any bad urls like /foo//bar
  35. return [:error, nil, *path] if path.any? &:blank?
  36.  
  37. if args = Mephisto::Routing.handle_redirection(path * "/")
  38. return [:redirect, *args]
  39. end
  40.  
  41. print "permalink_map: %s\n" % @@permalink_map.inspect
  42. # check for permalink
  43. if options = recognize_permalink(site, path)
  44. print "detected permalink [path: %s]\n" % path
  45. permalink_map.each do |entry|
  46. if entry[:regex].match( options[1] )
  47. return entry[:handler].to_proc.call( options )
  48. end
  49. end
  50.  
  51. return [:single, nil, options.first]
  52. end
  53.  
  54. # check for tags
  55. return [:tags, nil] + path[1..-1] if path.first == site.tag_path
  56.  
  57. # check for search
  58. if path.first == site.search_path
  59. return (path.size == 1) ? [:search, nil] : [:error, nil]
  60. end
  61.  
  62. dispatch_type = :list
  63. section = nil
  64. returning [] do |result|
  65. # look for the section in the path
  66. while section.nil? && path.any?
  67. section = site.sections.detect { |s| s.path == path.join('/') }
  68. result << path.pop if section.nil?
  69. end
  70. section ||= site.sections.home
  71. result.reverse!
  72.  
  73. # check for archives
  74. if result[0] == section.archive_path
  75. # only allow /archives, /archives/yyyy and /archives/yyyy/mm
  76. if (result.size < 4 && year?(result[1]) && month?(result[2]))
  77. dispatch_type = :archives
  78. result.shift
  79. else
  80. dispatch_type = :error
  81. end
  82. end
  83.  
  84. # check for pages
  85. dispatch_type = :page if dispatch_type == :list && section.show_paged_articles?
  86.  
  87. # check for invalid section or paged attributes
  88. if (dispatch_type == :page && result.size > 1) || (dispatch_type == :list && result.any?)
  89. dispatch_type = :error
  90. end
  91.  
  92. #result.size > (result[0] == :page ? )
  93. result.unshift section
  94. result.unshift dispatch_type
  95. end
  96. end
  97.  
  98. # returns an array with 3 values: [article_params, suffix, comment_id]
  99. def self.recognize_permalink(site, path)
  100. full_path = path.join('/')
  101. regex, variables = build_permalink_regex_with(site.permalink_style)
  102. if match = regex.match(full_path)
  103. returning([{}]) do |result|
  104. variables.each_with_index do |var, i|
  105. result.first[var] = match[i+1]
  106. end
  107. result << match[variables.size + 2] # comments | comments.xml | changes.xml
  108. result.last.gsub!(/\/(.*)$/, '') if result.last
  109. result << match[variables.size + 4] # comment id
  110. end
  111. end
  112. end
  113.  
  114. def self.build_permalink_regex_with(permalink_style)
  115. variables = []
  116. regex = permalink_style.split('/').inject [] do |s, piece|
  117. if name = variable_format?(piece)
  118. variables << name.to_sym
  119. s << "(#{PERMALINK_OPTIONS[variables.last]})"
  120. else
  121. s << piece
  122. end
  123. end
  124.  
  125. loct = permalink_map.collect do |pm|
  126. pms = pm[:regex].inspect
  127. "(%s)" % pms[1..(pms.length-2)]
  128. end
  129. pregex = "^#{regex.join('\/')}(\\\/(#{loct.join('|')})?)?$"
  130. print "regex: %s\n" % pregex
  131. [Regexp.new(pregex), variables]
  132. end
  133.  
  134. def self.variable_format?(var)
  135. var =~ PERMALINK_VAR ? $1 : nil
  136. end
  137.  
  138. def self.variable?(var)
  139. (name = variable_format?(var)) && PERMALINK_OPTIONS.keys.include?(name.to_sym) rescue nil
  140. end
  141.  
  142. def self.build_permalink_with(permalink_style, article)
  143. old_published = article.published_at
  144. article.published_at ||= Time.now.utc
  145. article.article_id ||= article.id
  146. permalink_style.split('/').inject [''] do |s, piece|
  147. s << ((name = variable_format?(piece)) && PERMALINK_OPTIONS.keys.include?(name.to_sym) ? variable_value_for(article, name) : piece)
  148. end.join('/')
  149. ensure
  150. article.published_at = old_published
  151. end
  152.  
  153. private
  154. @@year_regex = %r{^#{PERMALINK_OPTIONS[:year]}$}
  155. @@month_regex = %r{^#{PERMALINK_OPTIONS[:month]}$}
  156.  
  157. def self.year?(n)
  158. n.nil? || n =~ @@year_regex
  159. end
  160.  
  161. def self.month?(n)
  162. n.nil? || n =~ @@month_regex
  163. end
  164.  
  165. def self.variable_value_for(article, variable)
  166. variable == 'id' ? article.article_id.to_s : article.send(variable).to_s
  167. end
  168. end
  169. end
Add Comment
Please, Sign In to add comment