comfortable_mexican_sofa 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (171) hide show
  1. data/.gitignore +10 -0
  2. data/CHANGELOG.rdoc +2 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +55 -0
  5. data/Rakefile +88 -0
  6. data/VERSION +1 -0
  7. data/app/controllers/cms_admin/attachments_controller.rb +55 -0
  8. data/app/controllers/cms_admin/base_controller.rb +25 -0
  9. data/app/controllers/cms_admin/categories_controller.rb +69 -0
  10. data/app/controllers/cms_admin/layouts_controller.rb +71 -0
  11. data/app/controllers/cms_admin/pages_controller.rb +79 -0
  12. data/app/controllers/cms_admin/sections_controller.rb +17 -0
  13. data/app/controllers/cms_admin/snippets_controller.rb +58 -0
  14. data/app/controllers/cms_common/render_page.rb +47 -0
  15. data/app/controllers/cms_content_controller.rb +30 -0
  16. data/app/helpers/cms_helper.rb +12 -0
  17. data/app/models/cms_attachment.rb +17 -0
  18. data/app/models/cms_attachment_categorization.rb +5 -0
  19. data/app/models/cms_block.rb +15 -0
  20. data/app/models/cms_category.rb +36 -0
  21. data/app/models/cms_layout.rb +102 -0
  22. data/app/models/cms_page.rb +125 -0
  23. data/app/models/cms_page_categorization.rb +6 -0
  24. data/app/models/cms_snippet.rb +15 -0
  25. data/app/views/cms_admin/attachments/_details.html.haml +27 -0
  26. data/app/views/cms_admin/attachments/_form.html.haml +24 -0
  27. data/app/views/cms_admin/attachments/edit.html.haml +10 -0
  28. data/app/views/cms_admin/attachments/index.html.haml +36 -0
  29. data/app/views/cms_admin/attachments/new.html.haml +8 -0
  30. data/app/views/cms_admin/categories/_category.html.haml +21 -0
  31. data/app/views/cms_admin/categories/_category_subform.html.haml +12 -0
  32. data/app/views/cms_admin/categories/_form.html.haml +18 -0
  33. data/app/views/cms_admin/categories/_new.html.haml +7 -0
  34. data/app/views/cms_admin/categories/_toggle_link.html.haml +9 -0
  35. data/app/views/cms_admin/categories/_tree_branch.html.haml +36 -0
  36. data/app/views/cms_admin/categories/children.js.rjs +10 -0
  37. data/app/views/cms_admin/categories/create.js.rjs +9 -0
  38. data/app/views/cms_admin/categories/edit.html.haml +10 -0
  39. data/app/views/cms_admin/categories/index.html.haml +7 -0
  40. data/app/views/cms_admin/categories/new.html.haml +8 -0
  41. data/app/views/cms_admin/categories/show.html.haml +17 -0
  42. data/app/views/cms_admin/layouts/_details.html.haml +6 -0
  43. data/app/views/cms_admin/layouts/_form.html.haml +19 -0
  44. data/app/views/cms_admin/layouts/_toggle_link.html.haml +9 -0
  45. data/app/views/cms_admin/layouts/_tree_branch.html.haml +39 -0
  46. data/app/views/cms_admin/layouts/children.js.rjs +10 -0
  47. data/app/views/cms_admin/layouts/edit.html.haml +10 -0
  48. data/app/views/cms_admin/layouts/index.html.haml +7 -0
  49. data/app/views/cms_admin/layouts/new.html.haml +8 -0
  50. data/app/views/cms_admin/pages/_details.html.haml +25 -0
  51. data/app/views/cms_admin/pages/_form.html.haml +45 -0
  52. data/app/views/cms_admin/pages/_form_blocks.html.haml +48 -0
  53. data/app/views/cms_admin/pages/_toggle_link.html.haml +10 -0
  54. data/app/views/cms_admin/pages/_tree_branch.html.haml +41 -0
  55. data/app/views/cms_admin/pages/children.js.rjs +10 -0
  56. data/app/views/cms_admin/pages/edit.html.haml +11 -0
  57. data/app/views/cms_admin/pages/form_blocks.js.rjs +1 -0
  58. data/app/views/cms_admin/pages/index.html.haml +6 -0
  59. data/app/views/cms_admin/pages/new.html.haml +9 -0
  60. data/app/views/cms_admin/sections/show.html.haml +23 -0
  61. data/app/views/cms_admin/snippets/_form.html.haml +10 -0
  62. data/app/views/cms_admin/snippets/edit.html.haml +10 -0
  63. data/app/views/cms_admin/snippets/index.html.haml +26 -0
  64. data/app/views/cms_admin/snippets/new.html.haml +8 -0
  65. data/app/views/cms_content/show.xml.rxml +27 -0
  66. data/app/views/cms_content/sitemap.xml.rxml +16 -0
  67. data/app/views/layouts/cms_admin.html.haml +44 -0
  68. data/comfortable_mexican_sofa.gemspec +254 -0
  69. data/config/cms_routes.rb +25 -0
  70. data/generators/cms/cms_generator.rb +55 -0
  71. data/generators/cms/templates/README +32 -0
  72. data/generators/cms/templates/images/arrow_bottom.gif +0 -0
  73. data/generators/cms/templates/images/arrow_right.gif +0 -0
  74. data/generators/cms/templates/images/icon_attachment.gif +0 -0
  75. data/generators/cms/templates/images/icon_category.gif +0 -0
  76. data/generators/cms/templates/images/icon_draft.gif +0 -0
  77. data/generators/cms/templates/images/icon_layout.gif +0 -0
  78. data/generators/cms/templates/images/icon_move.gif +0 -0
  79. data/generators/cms/templates/images/icon_regular.gif +0 -0
  80. data/generators/cms/templates/images/icon_snippet.gif +0 -0
  81. data/generators/cms/templates/images/logo.png +0 -0
  82. data/generators/cms/templates/initializers/cms.rb +14 -0
  83. data/generators/cms/templates/initializers/paperclip.rb +14 -0
  84. data/generators/cms/templates/javascripts/codemirror_init.js +16 -0
  85. data/generators/cms/templates/javascripts/mce_init.js +17 -0
  86. data/generators/cms/templates/javascripts/utilities.js +27 -0
  87. data/generators/cms/templates/migrations/create_cms.rb +113 -0
  88. data/generators/cms/templates/stylesheets/cms_master.sass +414 -0
  89. data/init.rb +1 -0
  90. data/lib/comfortable_mexican_sofa.rb +46 -0
  91. data/lib/comfortable_mexican_sofa/acts_as_categorized.rb +87 -0
  92. data/lib/comfortable_mexican_sofa/acts_as_published.rb +60 -0
  93. data/lib/comfortable_mexican_sofa/cms_acts_as_tree.rb +108 -0
  94. data/lib/comfortable_mexican_sofa/cms_rails_extensions.rb +12 -0
  95. data/lib/comfortable_mexican_sofa/cms_tag.rb +109 -0
  96. data/lib/comfortable_mexican_sofa/cms_tags/attachment.rb +3 -0
  97. data/lib/comfortable_mexican_sofa/cms_tags/block.rb +117 -0
  98. data/lib/comfortable_mexican_sofa/cms_tags/helper.rb +3 -0
  99. data/lib/comfortable_mexican_sofa/cms_tags/page_block.rb +119 -0
  100. data/lib/comfortable_mexican_sofa/cms_tags/partial.rb +19 -0
  101. data/lib/comfortable_mexican_sofa/cms_tags/snippet.rb +19 -0
  102. data/rails/init.rb +1 -0
  103. data/test/fixtures/cms_attachment_categorizations.yml +7 -0
  104. data/test/fixtures/cms_attachments.yml +6 -0
  105. data/test/fixtures/cms_blocks.yml +38 -0
  106. data/test/fixtures/cms_categories.yml +19 -0
  107. data/test/fixtures/cms_layouts.yml +41 -0
  108. data/test/fixtures/cms_page_categorizations.yml +15 -0
  109. data/test/fixtures/cms_pages.yml +38 -0
  110. data/test/fixtures/cms_snippets.yml +7 -0
  111. data/test/fixtures/files/upload_file.txt +1 -0
  112. data/test/functional/cms_admin/attachments_controller_test.rb +63 -0
  113. data/test/functional/cms_admin/categories_controller_test.rb +86 -0
  114. data/test/functional/cms_admin/layouts_controller_test.rb +77 -0
  115. data/test/functional/cms_admin/pages_controller_test.rb +153 -0
  116. data/test/functional/cms_admin/sections_controller_test.rb +9 -0
  117. data/test/functional/cms_admin/snippets_controller_test.rb +63 -0
  118. data/test/functional/cms_content_controller_test.rb +52 -0
  119. data/test/models/cms_attachment_test.rb +16 -0
  120. data/test/models/cms_block_test.rb +11 -0
  121. data/test/models/cms_categorization_test.rb +39 -0
  122. data/test/models/cms_category_test.rb +71 -0
  123. data/test/models/cms_layout_test.rb +44 -0
  124. data/test/models/cms_page_test.rb +55 -0
  125. data/test/models/cms_snippet_test.rb +16 -0
  126. data/test/models/cms_tag_test.rb +70 -0
  127. data/test/rails_root/README +243 -0
  128. data/test/rails_root/Rakefile +10 -0
  129. data/test/rails_root/app/controllers/application_controller.rb +10 -0
  130. data/test/rails_root/app/helpers/application_helper.rb +3 -0
  131. data/test/rails_root/app/views/cms/under-development.html.haml +1 -0
  132. data/test/rails_root/app/views/complex_page/_example.html.erb +1 -0
  133. data/test/rails_root/config/boot.rb +110 -0
  134. data/test/rails_root/config/database.yml +22 -0
  135. data/test/rails_root/config/environment.rb +48 -0
  136. data/test/rails_root/config/environments/development.rb +17 -0
  137. data/test/rails_root/config/environments/production.rb +28 -0
  138. data/test/rails_root/config/environments/test.rb +28 -0
  139. data/test/rails_root/config/initializers/backtrace_silencers.rb +7 -0
  140. data/test/rails_root/config/initializers/inflections.rb +10 -0
  141. data/test/rails_root/config/initializers/mime_types.rb +5 -0
  142. data/test/rails_root/config/initializers/new_rails_defaults.rb +19 -0
  143. data/test/rails_root/config/initializers/session_store.rb +15 -0
  144. data/test/rails_root/config/locales/en.yml +5 -0
  145. data/test/rails_root/config/routes.rb +43 -0
  146. data/test/rails_root/doc/README_FOR_APP +2 -0
  147. data/test/rails_root/public/404.html +30 -0
  148. data/test/rails_root/public/422.html +30 -0
  149. data/test/rails_root/public/500.html +30 -0
  150. data/test/rails_root/public/favicon.ico +0 -0
  151. data/test/rails_root/public/images/rails.png +0 -0
  152. data/test/rails_root/public/index.html +275 -0
  153. data/test/rails_root/public/javascripts/application.js +2 -0
  154. data/test/rails_root/public/javascripts/controls.js +963 -0
  155. data/test/rails_root/public/javascripts/dragdrop.js +973 -0
  156. data/test/rails_root/public/javascripts/effects.js +1128 -0
  157. data/test/rails_root/public/javascripts/prototype.js +4320 -0
  158. data/test/rails_root/public/robots.txt +5 -0
  159. data/test/rails_root/public/stylesheets/sass/cms_master.sass +414 -0
  160. data/test/rails_root/script/about +4 -0
  161. data/test/rails_root/script/console +3 -0
  162. data/test/rails_root/script/dbconsole +3 -0
  163. data/test/rails_root/script/destroy +3 -0
  164. data/test/rails_root/script/generate +3 -0
  165. data/test/rails_root/script/performance/benchmarker +3 -0
  166. data/test/rails_root/script/performance/profiler +3 -0
  167. data/test/rails_root/script/plugin +3 -0
  168. data/test/rails_root/script/runner +3 -0
  169. data/test/rails_root/script/server +3 -0
  170. data/test/test_helper.rb +17 -0
  171. metadata +303 -0
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'comfortable_mexican_sofa'
@@ -0,0 +1,46 @@
1
+ require 'comfortable_mexican_sofa/cms_rails_extensions'
2
+ require 'comfortable_mexican_sofa/cms_acts_as_tree'
3
+ require 'comfortable_mexican_sofa/acts_as_published'
4
+ require 'comfortable_mexican_sofa/acts_as_categorized'
5
+
6
+ require 'comfortable_mexican_sofa/cms_tag'
7
+ require 'comfortable_mexican_sofa/cms_tags/block'
8
+ require 'comfortable_mexican_sofa/cms_tags/page_block'
9
+ require 'comfortable_mexican_sofa/cms_tags/snippet'
10
+ require 'comfortable_mexican_sofa/cms_tags/partial'
11
+ # require 'comfortable_mexican_sofa/cms_tags/helper'
12
+ # require 'comfortable_mexican_sofa/cms_tags/attachment'
13
+
14
+ # Helper inclusion
15
+ ActionView::Base.send(:include, CmsHelper)
16
+
17
+ module ComfortableMexicanSofa
18
+ class Config
19
+ def self.cattr_accessor_with_default(name, value = nil)
20
+ cattr_accessor name
21
+ self.send("#{name}=", value) if value
22
+ end
23
+
24
+ cattr_accessor_with_default :http_auth_enabled, true
25
+ cattr_accessor_with_default :http_auth_username, 'username'
26
+ cattr_accessor_with_default :http_auth_password, 'password'
27
+ cattr_accessor_with_default :cms_title
28
+ cattr_accessor_with_default :additional_cms_tabs, {}
29
+ cattr_accessor_with_default :paperclip_options, {}
30
+ end
31
+
32
+ def self.config(&block)
33
+ yield ComfortableMexicanSofa::Config
34
+ end
35
+ end
36
+
37
+ # loading engine routes
38
+ class ActionController::Routing::RouteSet
39
+ def load_routes_with_cms!
40
+ cms_routes = File.join(File.dirname(__FILE__), *%w[.. config cms_routes.rb])
41
+ add_configuration_file(cms_routes) unless configuration_files.include? cms_routes
42
+ load_routes_without_cms!
43
+ end
44
+
45
+ alias_method_chain :load_routes!, :cms
46
+ end
@@ -0,0 +1,87 @@
1
+ module ActsAsCategorized
2
+ module StubMethods
3
+
4
+ def acts_as_categorized
5
+
6
+ __categorized = self.to_s.underscore.to_sym
7
+ __categorizations = "#{__categorized}_categorizations".to_sym
8
+
9
+ # -- Attributes -------------------------------------------------------
10
+ attr_accessor :attr_category_ids # hash that comes from the form
11
+
12
+ # -- Relationships ----------------------------------------------------
13
+ has_many __categorizations,
14
+ :dependent => :destroy
15
+ has_many :cms_categories,
16
+ :through => __categorizations
17
+
18
+ # -- Callbacks --------------------------------------------------------
19
+ after_save :save_categorizations
20
+
21
+ # -- Named Scopes -----------------------------------------------------
22
+
23
+ named_scope :in_category, lambda { |category| {
24
+ :joins => __categorizations,
25
+ :conditions => { __categorizations => {:cms_category_id => (category.is_a?(CmsCategory) ? category.id : category) } }
26
+ }}
27
+
28
+ # -- Instance Methods -------------------------------------------------
29
+ define_method :save_categorizations do
30
+ return if attr_category_ids.blank?
31
+
32
+ category_ids_to_remove = attr_category_ids.select{ |k, v| v.to_i == 0}.collect{|k, v| k }
33
+ category_ids_to_create = attr_category_ids.select{ |k, v| v.to_i == 1}.collect{|k, v| k }
34
+
35
+ # removing unchecked categories
36
+ send(__categorizations).all(:conditions => { :cms_category_id => category_ids_to_remove}).collect(&:destroy)
37
+
38
+ # creating categorizations
39
+ category_ids_to_create.each do |category_id|
40
+ send(__categorizations).create(:cms_category_id => category_id)
41
+ end
42
+ end
43
+ end
44
+
45
+ def acts_as_categorization
46
+
47
+ __categorized = self.to_s.underscore.gsub('_categorization', '').to_sym
48
+ __categorized_id = "#{__categorized}_id".to_sym
49
+ __categorizations = "#{__categorized}_categorizations".to_sym
50
+
51
+ # -- Relationships --------------------------------------------------------
52
+ belongs_to __categorized.to_sym
53
+ belongs_to :cms_category
54
+
55
+ # -- Validations ----------------------------------------------------------
56
+ validates_presence_of __categorized_id,
57
+ :cms_category_id
58
+
59
+ validates_uniqueness_of __categorized_id, :scope => :cms_category_id
60
+
61
+ # -- AR Callbacks ---------------------------------------------------------
62
+ after_save :create_parent_categorization
63
+ after_destroy :destroy_children_categorizations
64
+
65
+ # -- Instance Methods -----------------------------------------------------
66
+ define_method :create_parent_categorization do
67
+ return unless cms_category.parent
68
+
69
+ params = {
70
+ :cms_category_id => cms_category.parent_id,
71
+ __categorized_id => send(__categorized).id
72
+ }
73
+ self.class.create!(params) unless self.class.exists?(params)
74
+ end
75
+
76
+ define_method :destroy_children_categorizations do
77
+ return if cms_category.children.blank?
78
+
79
+ cms_category.children.each do |c|
80
+ send(__categorized).send(__categorizations).first(:conditions => {"cms_category_id" => c.id }).try(:destroy)
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ ActiveRecord::Base.extend(ActsAsCategorized::StubMethods)
@@ -0,0 +1,60 @@
1
+ module ActsAsPublished
2
+ module StubMethods
3
+ def acts_as_published
4
+
5
+ extend ClassMethods
6
+ include InstanceMethods
7
+
8
+ named_scope :published, lambda { |*at_time| {
9
+ :conditions => published_find_conditions(*at_time)
10
+ }}
11
+ named_scope :unpublished, lambda { |*at_time| {
12
+ :conditions => unpublished_find_conditions(*at_time)
13
+ }}
14
+ end
15
+ end
16
+
17
+ module ClassMethods
18
+ def published_find_conditions(at_time = Time.now.utc)
19
+ [ "(#{self.table_name}.published_at IS NOT NULL AND #{self.table_name}.published_at <= ?)
20
+ AND
21
+ (#{self.table_name}.unpublished_at IS NULL OR #{self.table_name}.unpublished_at > ?)",
22
+ at_time, at_time
23
+ ]
24
+ end
25
+
26
+ def unpublished_find_conditions(at_time = Time.now.utc)
27
+ [ "(#{self.table_name}.published_at IS NULL OR #{self.table_name}.published_at > ?)
28
+ AND
29
+ (#{self.table_name}.unpublished_at IS NULL OR #{self.table_name}.unpublished_at <= ?)",
30
+ at_time, at_time
31
+ ]
32
+ end
33
+ end
34
+
35
+ module InstanceMethods
36
+
37
+ def is_published?(at_time = Time.now.utc)
38
+ published_at && published_at <= at_time && !(unpublished_at && unpublished_at <= at_time)
39
+ end
40
+
41
+ def published_status
42
+ is_published? ? "published" : "unpublished"
43
+ end
44
+
45
+ def publish!(at_time = Time.now.utc)
46
+ update_attributes(
47
+ :published_at => at_time,
48
+ :unpublished_at => nil
49
+ )
50
+ end
51
+
52
+ def unpublish!(at_time = Time.now.utc)
53
+ update_attributes(
54
+ :unpublished_at => at_time
55
+ )
56
+ end
57
+ end
58
+ end
59
+
60
+ ActiveRecord::Base.extend(ActsAsPublished::StubMethods)
@@ -0,0 +1,108 @@
1
+ module ActiveRecord
2
+ module Acts
3
+ module Tree
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ # Specify this +acts_as+ extension if you want to model a tree structure by providing a parent association and a children
9
+ # association. This requires that you have a foreign key column, which by default is called +parent_id+.
10
+ #
11
+ # class Category < ActiveRecord::Base
12
+ # acts_as_tree :order => "name"
13
+ # end
14
+ #
15
+ # Example:
16
+ # root
17
+ # \_ child1
18
+ # \_ subchild1
19
+ # \_ subchild2
20
+ #
21
+ # root = Category.create("name" => "root")
22
+ # child1 = root.children.create("name" => "child1")
23
+ # subchild1 = child1.children.create("name" => "subchild1")
24
+ #
25
+ # root.parent # => nil
26
+ # child1.parent # => root
27
+ # root.children # => [child1]
28
+ # root.children.first.children.first # => subchild1
29
+ #
30
+ # In addition to the parent and children associations, the following instance methods are added to the class
31
+ # after calling <tt>acts_as_tree</tt>:
32
+ # * <tt>siblings</tt> - Returns all the children of the parent, excluding the current node (<tt>[subchild2]</tt> when called on <tt>subchild1</tt>)
33
+ # * <tt>self_and_siblings</tt> - Returns all the children of the parent, including the current node (<tt>[subchild1, subchild2]</tt> when called on <tt>subchild1</tt>)
34
+ # * <tt>ancestors</tt> - Returns all the ancestors of the current node (<tt>[child1, root]</tt> when called on <tt>subchild2</tt>)
35
+ # * <tt>root</tt> - Returns the root of the current node (<tt>root</tt> when called on <tt>subchild2</tt>)
36
+ module ClassMethods
37
+ # Configuration options are:
38
+ #
39
+ # * <tt>foreign_key</tt> - specifies the column name to use for tracking of the tree (default: +parent_id+)
40
+ # * <tt>order</tt> - makes it possible to sort the children according to this SQL snippet.
41
+ # * <tt>counter_cache</tt> - keeps a count in a +children_count+ column if set to +true+ (default: +false+).
42
+ def acts_as_tree(options = {})
43
+ configuration = { :foreign_key => "parent_id", :order => nil, :counter_cache => nil }
44
+ configuration.update(options) if options.is_a?(Hash)
45
+
46
+ belongs_to :parent, :class_name => name, :foreign_key => configuration[:foreign_key], :counter_cache => configuration[:counter_cache]
47
+ has_many :children, :class_name => name, :foreign_key => configuration[:foreign_key], :order => configuration[:order], :dependent => :destroy
48
+
49
+ class_eval <<-EOV
50
+ include ActiveRecord::Acts::Tree::InstanceMethods
51
+
52
+ def self.roots
53
+ find(:all, :conditions => "#{configuration[:foreign_key]} IS NULL", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}})
54
+ end
55
+
56
+ def self.root
57
+ find(:first, :conditions => "#{configuration[:foreign_key]} IS NULL", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}})
58
+ end
59
+ EOV
60
+ end
61
+ end
62
+
63
+ module InstanceMethods
64
+ # Returns list of ancestors, starting from parent until root.
65
+ #
66
+ # subchild1.ancestors # => [child1, root]
67
+ def ancestors
68
+ node, nodes = self, []
69
+ nodes << node = node.parent while node.parent
70
+ nodes
71
+ end
72
+
73
+ # Returns all children and children of children
74
+ def descendants
75
+ nodes = []
76
+ self.children.each do |c|
77
+ nodes << c
78
+ nodes << c.descendants
79
+ end
80
+ nodes.flatten
81
+ end
82
+
83
+ # Returns the root node of the tree.
84
+ def root
85
+ node = self
86
+ node = node.parent while node.parent
87
+ node
88
+ end
89
+
90
+ # Returns all siblings of the current node.
91
+ #
92
+ # subchild1.siblings # => [subchild2]
93
+ def siblings
94
+ self_and_siblings - [self]
95
+ end
96
+
97
+ # Returns all siblings and a reference to the current node.
98
+ #
99
+ # subchild1.self_and_siblings # => [subchild1, subchild2]
100
+ def self_and_siblings
101
+ parent ? parent.children : self.class.roots
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+
108
+ ActiveRecord::Base.send :include, ActiveRecord::Acts::Tree
@@ -0,0 +1,12 @@
1
+ class String
2
+
3
+ # Converts string to something suitable to be used as an element id
4
+ def idify
5
+ self.strip.gsub(/\W/, '_').gsub(/\s|^_*|_*$/, '').squeeze('_')
6
+ end
7
+
8
+ # Converts a string to something usable as a url slug
9
+ def slugify
10
+ self.downcase.gsub(/\W|_/, ' ').strip.squeeze(' ').gsub(/\s/, '-')
11
+ end
12
+ end
@@ -0,0 +1,109 @@
1
+ module CmsTag
2
+
3
+ class TagError < StandardError; end
4
+
5
+ # Initializes all tags found in the provided content
6
+ # Will ignore duplicate tags. Will use format definition of the first one.
7
+ def self.parse_tags(*args)
8
+ options = args.extract_options!
9
+ content = args.first
10
+
11
+ # bailing out if nothing was sent for parsing
12
+ return [] if content.blank?
13
+
14
+ tags = []
15
+ CmsTag::Tag.subclasses.each do |tag|
16
+ tag = tag.constantize
17
+ tags << tag.parse_tags(content).group_by{|s| s.split(':')[0...2].join(':')}.collect{|g, tag_signature| tag.new(tag_signature.first, options)}
18
+ end
19
+ tags.flatten
20
+ end
21
+
22
+ class Tag
23
+ attr_accessor :tag_signature, :label, :view, :page
24
+
25
+ # Returns tag type based on it's classname
26
+ # CmsTag::MyAwesomeTag.tag_type => 'cms_my_awesome_tag'
27
+ def self.tag_type
28
+ 'cms_' + to_s.split('::').last.underscore
29
+ end
30
+
31
+ def tag_type
32
+ self.class.tag_type
33
+ end
34
+
35
+ # regular expression that finds tag signature
36
+ def self.regex
37
+ 'tag regex not defined'
38
+ end
39
+
40
+ # regex needed for content substitution
41
+ def regex
42
+ 'tag regex not defined'
43
+ end
44
+
45
+ # Returns tag identifiers from passed content based on regex defined
46
+ # for the particular tag
47
+ def self.parse_tags(content)
48
+ content.scan(regex).flatten
49
+ end
50
+
51
+ # order at which tags get replaced with their content during page rendering
52
+ def self.render_priority
53
+ 0
54
+ end
55
+
56
+ def self.has_form?
57
+ false
58
+ end
59
+
60
+ def initialize(*args)
61
+ options = args.extract_options!
62
+ self.tag_signature = args.first
63
+
64
+ # provides access to action view methods for rendering form elements
65
+ if options[:view]
66
+ unless options[:view].is_a?(ActionView::Base)
67
+ raise TagError, "Expected ActionView::Base but got #{options[:view].class}"
68
+ end
69
+ self.view = options[:view]
70
+ end
71
+
72
+ # owner of the the tag
73
+ if options[:page]
74
+ unless options[:page].is_a?(CmsPage)
75
+ raise TagError, "Expected CmsPage but got #{options[:page].class}"
76
+ end
77
+ self.page = options[:page]
78
+ end
79
+
80
+ tokens = self.tag_signature.split(':')
81
+ self.label = tokens[1]
82
+
83
+ assign_accessors
84
+ end
85
+
86
+ def assign_accessors
87
+ # ... FIX: looks retarded
88
+ end
89
+
90
+ def form_label
91
+ "Label Undefined!"
92
+ end
93
+
94
+ def form_input
95
+ "Form Field Undefined!"
96
+ end
97
+
98
+ def content
99
+ 'Undefined Tag'
100
+ end
101
+
102
+ # when cms_page renders its content this is what tag outputs on the page
103
+ def render
104
+ content
105
+ end
106
+
107
+ end
108
+
109
+ end
@@ -0,0 +1,3 @@
1
+ class CmsTag::Attachment < CmsTag::Tag
2
+
3
+ end
@@ -0,0 +1,117 @@
1
+ class CmsTag::Block < CmsTag::Tag
2
+
3
+ FORMAT = {
4
+ :text => {
5
+ :db_column => :content_text,
6
+ :description => '',
7
+ :form_output => lambda { |tag|
8
+ tag.view.text_area_tag "cms_page[blocks][#{tag.label}][content_text]", tag.content,
9
+ :rows => 20
10
+ }
11
+ },
12
+ :string => {
13
+ :db_column => :content_string,
14
+ :description => '',
15
+ :form_output => lambda { |tag|
16
+ tag.view.text_field_tag "cms_page[blocks][#{tag.label}][content_string]", tag.content
17
+ }
18
+ },
19
+ :rich_text => {
20
+ :db_column => :content_text,
21
+ :description => '',
22
+ :form_output => lambda { |tag|
23
+ tag.view.text_area_tag "cms_page[blocks][#{tag.label}][content_text]", tag.content,
24
+ :rows => 20,
25
+ :class => 'mceEditor'
26
+ }
27
+ },
28
+ :code => {
29
+ :db_column => :content_text,
30
+ :description => '',
31
+ :form_output => lambda { |tag|
32
+ tag.view.content_tag :div, :class => 'codemirror' do
33
+ tag.view.text_area_tag "cms_page[blocks][#{tag.label}][content_text]", tag.content,
34
+ :rows => 20,
35
+ :class => 'codeTextArea'
36
+ end
37
+ }
38
+ },
39
+ :integer => {
40
+ :db_column => :content_integer,
41
+ :description => '',
42
+ :form_output => lambda { |tag|
43
+ tag.view.text_field_tag "cms_page[blocks][#{tag.label}][content_integer]", tag.content
44
+ }
45
+ },
46
+ :boolean => {
47
+ :db_column => :content_boolean,
48
+ :description => '',
49
+ :form_output => lambda { |tag|
50
+ tag.view.check_box_tag "cms_page[blocks][#{tag.label}][content_boolean]", tag.content
51
+ }
52
+ },
53
+ :date => {
54
+ :db_column => :content_datetime,
55
+ :description => '',
56
+ :form_output => lambda { |tag|
57
+ tag.view.fields_for "cms_page[blocks][#{tag.label}]" do |field|
58
+ field.date_select :content_datetime, :default => tag.content
59
+ end
60
+ }
61
+ },
62
+ :time => {
63
+ :db_column => :content_datetime,
64
+ :description => '',
65
+ :form_output => lambda { |tag|
66
+ tag.view.fields_for "cms_page[blocks][#{tag.label}]" do |field|
67
+ field.datetime_select :content_datetime, :default => tag.content
68
+ end
69
+ }
70
+ }
71
+ }
72
+
73
+ attr_accessor :format
74
+
75
+ def self.regex
76
+ /\{\{\s*?(cms_block:.*?)\s*?\}\}/
77
+ end
78
+
79
+ def regex
80
+ /\{\{\s*?cms_block:#{Regexp.escape(label)}.*?\s*?\}\}/
81
+ end
82
+
83
+ def self.render_priority
84
+ 1
85
+ end
86
+
87
+ def self.has_form?
88
+ true
89
+ end
90
+
91
+ def assign_accessors
92
+ tokens = self.tag_signature.split(':')
93
+ self.label = tokens[1]
94
+ self.format = tokens[2]
95
+ end
96
+
97
+ def form_label
98
+ view.label_tag label.titleize
99
+ end
100
+
101
+ def form_input
102
+ if FORMAT.has_key? self.format.to_sym
103
+ FORMAT[self.format.to_sym][:form_output].call(self)
104
+ else
105
+ 'Unknown tag format'
106
+ end
107
+ end
108
+
109
+ def content
110
+ page && page.cms_block_content(self.label, FORMAT[self.format.to_sym][:db_column])
111
+ end
112
+
113
+ def render
114
+ ''
115
+ end
116
+
117
+ end