aslakjo-aslakjo-comatose 2.0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/CHANGELOG +195 -0
  2. data/INSTALL +20 -0
  3. data/LICENSE +20 -0
  4. data/MANIFEST +91 -0
  5. data/README.markdown +159 -0
  6. data/Rakefile +176 -0
  7. data/SPECS +61 -0
  8. data/about.yml +7 -0
  9. data/bin/comatose +112 -0
  10. data/comatose.gemspec +113 -0
  11. data/generators/comatose_migration/USAGE +15 -0
  12. data/generators/comatose_migration/comatose_migration_generator.rb +74 -0
  13. data/generators/comatose_migration/templates/migration.rb +35 -0
  14. data/generators/comatose_migration/templates/v4_upgrade.rb +15 -0
  15. data/generators/comatose_migration/templates/v6_upgrade.rb +23 -0
  16. data/generators/comatose_migration/templates/v7_upgrade.rb +22 -0
  17. data/init.rb +2 -0
  18. data/install.rb +18 -0
  19. data/lib/acts_as_versioned.rb +543 -0
  20. data/lib/comatose.rb +33 -0
  21. data/lib/comatose/comatose_drop.rb +79 -0
  22. data/lib/comatose/configuration.rb +69 -0
  23. data/lib/comatose/page_wrapper.rb +119 -0
  24. data/lib/comatose/processing_context.rb +69 -0
  25. data/lib/comatose/tasks/admin.rb +60 -0
  26. data/lib/comatose/tasks/data.rb +82 -0
  27. data/lib/comatose/tasks/setup.rb +52 -0
  28. data/lib/comatose/version.rb +4 -0
  29. data/lib/comatose_admin_controller.rb +395 -0
  30. data/lib/comatose_admin_helper.rb +37 -0
  31. data/lib/comatose_controller.rb +138 -0
  32. data/lib/comatose_helper.rb +3 -0
  33. data/lib/comatose_page.rb +141 -0
  34. data/lib/liquid.rb +52 -0
  35. data/lib/liquid/block.rb +96 -0
  36. data/lib/liquid/context.rb +190 -0
  37. data/lib/liquid/document.rb +17 -0
  38. data/lib/liquid/drop.rb +48 -0
  39. data/lib/liquid/errors.rb +7 -0
  40. data/lib/liquid/extensions.rb +53 -0
  41. data/lib/liquid/file_system.rb +62 -0
  42. data/lib/liquid/htmltags.rb +64 -0
  43. data/lib/liquid/standardfilters.rb +111 -0
  44. data/lib/liquid/standardtags.rb +399 -0
  45. data/lib/liquid/strainer.rb +42 -0
  46. data/lib/liquid/tag.rb +25 -0
  47. data/lib/liquid/template.rb +88 -0
  48. data/lib/liquid/variable.rb +39 -0
  49. data/lib/redcloth.rb +1129 -0
  50. data/lib/support/class_options.rb +36 -0
  51. data/lib/support/inline_rendering.rb +48 -0
  52. data/lib/support/route_mapper.rb +50 -0
  53. data/lib/text_filters.rb +140 -0
  54. data/lib/text_filters/markdown.rb +14 -0
  55. data/lib/text_filters/markdown_smartypants.rb +15 -0
  56. data/lib/text_filters/none.rb +8 -0
  57. data/lib/text_filters/rdoc.rb +13 -0
  58. data/lib/text_filters/simple.rb +8 -0
  59. data/lib/text_filters/textile.rb +15 -0
  60. data/rails/init.rb +3 -0
  61. data/resources/layouts/comatose_admin_template.html.erb +28 -0
  62. data/resources/public/images/collapsed.gif +0 -0
  63. data/resources/public/images/expanded.gif +0 -0
  64. data/resources/public/images/no-children.gif +0 -0
  65. data/resources/public/images/page.gif +0 -0
  66. data/resources/public/images/spinner.gif +0 -0
  67. data/resources/public/images/title-hover-bg.gif +0 -0
  68. data/resources/public/javascripts/comatose_admin.js +401 -0
  69. data/resources/public/stylesheets/comatose_admin.css +404 -0
  70. data/tasks/comatose.rake +9 -0
  71. data/test/behaviors.rb +106 -0
  72. data/test/fixtures/comatose_pages.yml +96 -0
  73. data/test/functional/comatose_admin_controller_test.rb +114 -0
  74. data/test/functional/comatose_controller_test.rb +44 -0
  75. data/test/javascripts/test.html +26 -0
  76. data/test/javascripts/test_runner.js +307 -0
  77. data/test/test_helper.rb +55 -0
  78. data/test/unit/class_options_test.rb +52 -0
  79. data/test/unit/comatose_page_test.rb +136 -0
  80. data/test/unit/processing_context_test.rb +108 -0
  81. data/test/unit/text_filters_test.rb +52 -0
  82. data/views/comatose_admin/_form.html.erb +96 -0
  83. data/views/comatose_admin/_page_list_item.html.erb +60 -0
  84. data/views/comatose_admin/delete.html.erb +18 -0
  85. data/views/comatose_admin/edit.html.erb +5 -0
  86. data/views/comatose_admin/index.html.erb +29 -0
  87. data/views/comatose_admin/new.html.erb +5 -0
  88. data/views/comatose_admin/reorder.html.erb +30 -0
  89. data/views/comatose_admin/versions.html.erb +40 -0
  90. data/views/layouts/comatose_admin.html.erb +837 -0
  91. data/views/layouts/comatose_admin_customize.html.erb +28 -0
  92. data/views/layouts/comatose_content.html.erb +17 -0
  93. metadata +148 -0
@@ -0,0 +1,52 @@
1
+ require 'rake'
2
+ require 'rake/tasklib'
3
+
4
+ namespace :comatose do
5
+ #
6
+ # Setup Task...
7
+ #
8
+ namespace :setup do
9
+
10
+ desc "If the installation didn't add the images correctly, use this task"
11
+ task :copy_images do
12
+ plugin_dir = File.join(File.dirname(__FILE__), '..')
13
+ unless FileTest.exist? File.join(RAILS_ROOT, 'public', 'images', 'comatose')
14
+ FileUtils.mkdir( File.join(RAILS_ROOT, 'public', 'images', 'comatose') )
15
+ end
16
+ FileUtils.cp(
17
+ Dir[File.join(plugin_dir, 'resources', 'public', 'images', '*.gif')],
18
+ File.join(RAILS_ROOT, 'public', 'images', 'comatose'),
19
+ :verbose => true
20
+ )
21
+ puts "Finished."
22
+ end
23
+
24
+ # For use when upgrading...
25
+
26
+ def move(args)
27
+ if ENV['USE_SVN'] == 'true'
28
+ `svn move #{args}`
29
+ else
30
+ `mv #{args}`
31
+ end
32
+ end
33
+
34
+ def delete(args)
35
+ if ENV['USE_SVN'] == 'true'
36
+ `svn delete #{args}`
37
+ else
38
+ `rm -rf #{args}`
39
+ end
40
+ end
41
+
42
+ # TODO: Test the setup:restructure_customization task...
43
+ desc "[EXPERIMENTAL] Restructures customized admin folder to version 0.6 from older version -- Only run this if you have customized the admin. USE_SVN=true if you want to update subversion"
44
+ task :restructure_customization do
45
+ ENV['USE_SVN'] ||= 'false'
46
+ move 'public/javscripts/comatose.js public/javscripts/comatose_admin.js'
47
+ move 'public/stylesheets/comatose.css public/stylesheets/comatose_admin.css'
48
+ move 'app/views/comatose app/views/comatose_admin'
49
+ delete 'app/views/layouts/comatose_content.html.erb'
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,4 @@
1
+ module Comatose
2
+ VERSION = "2.0.5"
3
+ VERSION_STRING = "#{VERSION} (beta)"
4
+ end
@@ -0,0 +1,395 @@
1
+ # The controller for serving cms content...
2
+ class ComatoseAdminController < ActionController::Base
3
+ unloadable
4
+
5
+ define_option :original_template_root, nil
6
+ define_option :plugin_layout_path, File.join( '..', '..', '..', 'vendor', 'plugins', 'comatose', 'views', 'layouts' )
7
+
8
+ before_filter :handle_authorization
9
+ before_filter :set_content_type
10
+ layout 'comatose_admin'
11
+
12
+ # Shows the page tree
13
+ def index
14
+ @root_pages = [fetch_root_page].flatten
15
+ end
16
+
17
+ # Edit a specfic page (posts back)
18
+ def edit
19
+ # Clear the page cache for this page... ?
20
+ @page = ComatosePage.find params[:id]
21
+ @root_pages = [fetch_root_page].flatten
22
+ if request.post?
23
+ @page.update_attributes(params[:page])
24
+ @page.updated_on = Time.now
25
+ @page.author = fetch_author_name
26
+ if @page.save
27
+ expire_cms_page @page
28
+ expire_cms_fragment @page
29
+ flash[:notice] = "Saved changes to '#{@page.title}'"
30
+ redirect_to :controller=>self.controller_name, :action=>'index'
31
+ end
32
+ end
33
+ end
34
+
35
+ # Create a new page (posts back)
36
+ def new
37
+ @root_pages = [fetch_root_page].flatten
38
+ if request.post?
39
+ @page = ComatosePage.new params[:page]
40
+ @page.author = fetch_author_name
41
+ if @page.save
42
+ flash[:notice] = "Created page '#{@page.title}'"
43
+ redirect_to :controller=>self.controller_name, :action=>'index'
44
+ end
45
+ else
46
+ @page = ComatosePage.new :title=>'New Page', :parent_id=>(params[:parent] || nil)
47
+ end
48
+ end
49
+
50
+ # Saves position of child pages
51
+ def reorder
52
+ # If it's AJAX, do our thing and move on...
53
+ if request.xhr?
54
+ params["page_list_#{params[:id]}"].each_with_index { |id,idx| ComatosePage.update(id, :position => idx) }
55
+ expire_cms_page ComatosePage.find(params[:id])
56
+ render :text=>'Updated sort order', :layout=>false
57
+ else
58
+ @page = ComatosePage.find params[:id]
59
+ if params.has_key? :cmd
60
+ @target = ComatosePage.find params[:page]
61
+ case params[:cmd]
62
+ when 'up' then @target.move_higher
63
+ when 'down' then @target.move_lower
64
+ end
65
+ redirect_to :action=>'reorder', :id=>@page
66
+ end
67
+ end
68
+ end
69
+
70
+ # Allows comparing between two versions of a page's content
71
+ def versions
72
+ @page = ComatosePage.find params[:id]
73
+ @version_num = (params[:version] || @page.versions.length).to_i
74
+ @version = @page.find_version(@version_num)
75
+ end
76
+
77
+ # Reverts a page to a specific version...
78
+ def set_version
79
+ if request.post?
80
+ @page = ComatosePage.find params[:id]
81
+ @version_num = params[:version]
82
+ @page.revert_to!(@version_num)
83
+ end
84
+ redirect_to :controller=>self.controller_name, :action=>'index'
85
+ end
86
+
87
+ # Deletes the specified page
88
+ def delete
89
+ @page = ComatosePage.find params[:id]
90
+ if request.post?
91
+ expire_cms_pages_from_bottom @page
92
+ expire_cms_fragments_from_bottom @page
93
+ @page.destroy
94
+ flash[:notice] = "Deleted page '#{@page.title}'"
95
+ redirect_to :controller=>self.controller_name, :action=>'index'
96
+ end
97
+ end
98
+
99
+ # Returns a preview of the page content...
100
+ def preview
101
+ begin
102
+ page = ComatosePage.new(params[:page])
103
+ page.author = fetch_author_name
104
+ if params.has_key? :version
105
+ content = page.to_html( {'params'=>params.stringify_keys, 'version'=>params[:version]} )
106
+ else
107
+ content = page.to_html( {'params'=>params.stringify_keys} )
108
+ end
109
+ rescue SyntaxError
110
+ content = "<p>There was an error generating the preview.</p><p><pre>#{$!.to_s.gsub(/\</, '&lt;')}</pre></p>"
111
+ rescue
112
+ content = "<p>There was an error generating the preview.</p><p><pre>#{$!.to_s.gsub(/\</, '&lt;')}</pre></p>"
113
+ end
114
+ render :text=>content, :layout => false
115
+ end
116
+
117
+ # Expires the entire page cache
118
+ def expire_page_cache
119
+ expire_cms_pages_from_bottom( fetch_root_page )
120
+ expire_cms_fragments_from_bottom( fetch_root_page )
121
+ flash[:notice] = "Page cache has been flushed"
122
+ redirect_to :controller=>self.controller_name, :action=>'index'
123
+ end
124
+
125
+ # Walks the page tree and generates HTML files in your /public
126
+ # folder... It will skip pages that have a 'nocache' keyword
127
+ # TODO: Make page cache generation work when in :plugin mode
128
+ def generate_page_cache
129
+ if runtime_mode == :plugin
130
+ @errors = ["Page cache cannot be generated in plugin mode"]
131
+ else
132
+ @errors = generate_all_pages_html(params)
133
+ end
134
+ if @errors.length == 0
135
+ flash[:notice] = "Pages Cached Successfully"
136
+ else
137
+ flash[:notice] = "Pages Cache Error(s): #{@errors.join(', ')}"
138
+ flash[:cache_errors] = @errors
139
+ end
140
+ redirect_to :controller=>self.controller_name, :action=>'index'
141
+ end
142
+
143
+ def export
144
+ if Comatose.config.allow_import_export
145
+ send_data(page_to_hash(ComatosePage.root).to_yaml, :disposition => 'attachment', :type => 'text/yaml', :filename => "comatose-pages.yml")
146
+ else
147
+ flash[:notice] = "Export is not allowed"
148
+ redirect_to :controller=>self.controller_name, :action=>'index'
149
+ end
150
+ end
151
+
152
+ def import
153
+ if Comatose.config.allow_import_export
154
+ data = YAML::load(params[:import_file])
155
+ hash_to_page_tree(data, ComatosePage.root)
156
+ flash[:notice] = "Pages Imported Successfully"
157
+ else
158
+ flash[:notice] = "Import isn't allowed"
159
+ end
160
+ redirect_to :controller=>self.controller_name, :action=>'index'
161
+ end
162
+
163
+ protected
164
+
165
+ def handle_authorization
166
+ if Comatose.config.admin_authorization.is_a? Proc
167
+ instance_eval &Comatose.config.admin_authorization
168
+ elsif Comatose.config.admin_authorization.is_a? Symbol
169
+ send(Comatose.config.admin_authorization)
170
+ elsif defined? authorize
171
+ authorize
172
+ else
173
+ true
174
+ end
175
+ end
176
+
177
+ def fetch_author_name
178
+ if Comatose.config.admin_get_author.is_a? Proc
179
+ instance_eval &Comatose.config.admin_get_author
180
+ elsif Comatose.config.admin_get_author.is_a? Symbol
181
+ send(Comatose.config.admin_get_author)
182
+ elsif defined? get_author
183
+ get_author
184
+ end
185
+ end
186
+
187
+ # Can be overridden -- return your root comtase page
188
+ def fetch_root_page
189
+ if Comatose.config.admin_get_root_page.is_a? Proc
190
+ instance_eval &Comatose.config.admin_get_root_page
191
+ elsif Comatose.config.admin_get_root_page.is_a? Symbol
192
+ send(Comatose.config.admin_get_root_page)
193
+ elsif defined? get_root_page
194
+ get_root_page
195
+ end
196
+ end
197
+
198
+ # Sets the HTTP content-type header based on what's configured
199
+ # in Comatose.config.content_type
200
+ def set_content_type
201
+ response.headers["Content-Type"] = "text/html; charset=#{Comatose.config.content_type}" unless Comatose.config.content_type.nil?
202
+ end
203
+
204
+ # Calls generate_page_html for each mount point..
205
+ def generate_all_pages_html(params={})
206
+ @errors = []
207
+ @been_cached = []
208
+ Comatose.mount_points.each do |root_info|
209
+ ComatosePage.active_mount_info = root_info
210
+ generate_page_html(ComatosePage.find_by_path( root_info[:index] ), root_info, params)
211
+ end
212
+ @errors
213
+ end
214
+
215
+ # Accepts a Comatose Page and a root_info object to generate
216
+ # the page as a static HTML page -- using the layout that was
217
+ # defined on the mount point
218
+ def generate_page_html(page, root_info, params={})
219
+ @been_cached ||= []
220
+ unless page.has_keyword? :nocache or @been_cached.include? page.id
221
+ uri = page.uri
222
+ uri = "#{uri}/index".split('/').flatten.join('/') if page.full_path == root_info[:index]
223
+ @page = Comatose::PageWrapper.new(page)
224
+ begin
225
+ page_layout = get_page_layout(root_info)
226
+ #puts "mode = #{runtime_mode}, layout = #{page_layout}, template_root = #{template_root}, original_template_root = #{original_template_root}"
227
+ html = render_to_string( :text=>page.to_html({'params'=>params.stringify_keys}), :layout=>page_layout )
228
+ cache_page( html, uri )
229
+ rescue
230
+ logger.error "Comatose CMS Page Cache Exception: #{$!}"
231
+ @errors << "(#{page}/#{page.slug}) - #{$!}"
232
+ end
233
+ @been_cached << page.id
234
+ # recurse...
235
+ page.children.each do |child|
236
+ generate_page_html(child, root_info)
237
+ end
238
+ end
239
+ end
240
+
241
+ # Calls the class methods of the same name...
242
+ def expire_cms_page(page)
243
+ self.class.expire_cms_page(page)
244
+ end
245
+ def expire_cms_pages_from_bottom(page)
246
+ self.class.expire_cms_pages_from_bottom(page)
247
+ end
248
+
249
+
250
+ # expire the page from the fragment cache
251
+ def expire_cms_fragment(page)
252
+ key = page.full_path.gsub(/\//, '+')
253
+ expire_fragment(key)
254
+ end
255
+
256
+ # expire pages starting at a specific node
257
+ def expire_cms_fragments_from_bottom(page)
258
+ pages = page.is_a?(Array) ? page : [page]
259
+ pages.each do |page|
260
+ page.children.each {|c| expire_cms_fragments_from_bottom( c ) } if !page.children.empty?
261
+ expire_cms_fragment( page )
262
+ end
263
+ end
264
+
265
+ # Class Methods...
266
+ class << self
267
+
268
+ # Walks all the way down, and back up the tree -- the allows the expire_cms_page
269
+ # to delete empty directories better
270
+ def expire_cms_pages_from_bottom(page)
271
+ pages = page.is_a?(Array) ? page : [page]
272
+ pages.each do |page|
273
+ page.children.each {|c| expire_cms_pages_from_bottom( c ) } if !page.children.empty?
274
+ expire_cms_page( page )
275
+ end
276
+ end
277
+
278
+ # Expire the page from all the mount points...
279
+ def expire_cms_page(page)
280
+ Comatose.mount_points.each do |path_info|
281
+ ComatosePage.active_mount_info = path_info
282
+ expire_page(page.uri)
283
+ # If the page is the index page for the root, expire it too
284
+ if path_info[:root] == page.uri
285
+ expire_page("#{path_info[:root]}/index")
286
+ end
287
+ begin # I'm not sure this matters too much -- but it keeps things clean
288
+ dir_path = File.join(RAILS_ROOT, 'public', page.uri[1..-1])
289
+ Dir.delete( dir_path ) if FileTest.directory?( dir_path ) and !page.parent.nil?
290
+ rescue
291
+ # It probably isn't empty -- just as well we leave it be
292
+ #STDERR.puts " - Couldn't delete dir #{dir_path} -> #{$!}"
293
+ end
294
+ end
295
+ end
296
+
297
+ # Returns a path to plugin layout, if it's unspecified, otherwise
298
+ # a path to an application layout...
299
+ def get_page_layout(params)
300
+ if params[:layout] == 'comatose_content'
301
+ File.join(plugin_layout_path, params[:layout])
302
+ else
303
+ params[:layout]
304
+ end
305
+ end
306
+
307
+ def configure_template_root
308
+ if self.runtime_mode == :unknown
309
+ if FileTest.exist? File.join(RAILS_ROOT, 'public', 'javascripts', 'comatose_admin.js')
310
+ self.runtime_mode = :application
311
+ else
312
+ self.runtime_mode = :plugin
313
+ end
314
+ end
315
+ end
316
+
317
+ def runtime_mode
318
+ @@runtime_mode ||= :unknown
319
+ end
320
+
321
+ def runtime_mode=(mode)
322
+ admin_view_path = File.expand_path(File.join( File.dirname(__FILE__), '..', 'views'))
323
+ if self.respond_to?(:template_root)
324
+ case mode
325
+ when :plugin
326
+ self.original_template_root = self.template_root
327
+ self.template_root = admin_view_path
328
+ when :application
329
+ self.template_root = self.original_template_root if self.original_template_root
330
+ end
331
+ else
332
+ ActionController::Base.append_view_path(admin_view_path) unless ActionController::Base.view_paths.include?(admin_view_path)
333
+ end
334
+ @@runtime_mode = mode
335
+ end
336
+
337
+ end
338
+
339
+ # Check to see if we are in 'embedded' mode, or are being 'customized'
340
+ # embedded = runtime_mode of :plugin
341
+ # customized = runtime_mode of :application
342
+ configure_template_root
343
+
344
+ #
345
+ # Include any modules...
346
+ Comatose.config.admin_includes.each do |mod|
347
+ if mod.is_a? String
348
+ include mod.constantize
349
+ elsif mod.is_a? Symbol
350
+ include mod.to_s.classify.constantize
351
+ else
352
+ include mod
353
+ end
354
+ end
355
+
356
+ # Include any helpers...
357
+ Comatose.config.admin_helpers.each do |mod|
358
+ if mod.is_a? String
359
+ helper mod.constantize
360
+ elsif mod.is_a? Symbol
361
+ helper mod.to_s.classify.constantize
362
+ else
363
+ helper mod
364
+ end
365
+ end
366
+
367
+ private
368
+
369
+ def page_to_hash(page)
370
+ data = page.attributes.clone
371
+ # Pull out the specific, or unnecessary fields
372
+ %w(id parent_id updated_on author position version created_on full_path).each {|key| data.delete(key)}
373
+ if !page.children.empty?
374
+ data['children'] = []
375
+ page.children.each do |child|
376
+ data['children'] << page_to_hash(child)
377
+ end
378
+ end
379
+ data
380
+ end
381
+
382
+ def hash_to_page_tree(hsh, page)
383
+ child_ary = hsh.delete 'children'
384
+ page.update_attributes(hsh)
385
+ page.save
386
+ child_ary.each do |child_hsh|
387
+ if child_pg = page.children.find_by_slug( child_hsh['slug'] )
388
+ hash_to_page_tree( child_hsh, child_pg )
389
+ else
390
+ hash_to_page_tree( child_hsh, page.children.create )
391
+ end
392
+ end if child_ary
393
+ end
394
+
395
+ end