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
@@ -0,0 +1,17 @@
1
+ class CmsAdmin::SectionsController < CmsAdmin::BaseController
2
+
3
+ def show
4
+ @page = CmsPage.sections.find_by_id(params[:id])
5
+ @pages = @page.children.paginate :page => params[:page]
6
+
7
+ # attempt to singularize section name
8
+ @section_label = @page.label.singularize
9
+ end
10
+
11
+ def test_get_show
12
+ get :show, :id => cms_pages(:complex_page)
13
+ assert_response :success
14
+ assert assigns(:pages)
15
+ end
16
+
17
+ end
@@ -0,0 +1,58 @@
1
+ class CmsAdmin::SnippetsController < CmsAdmin::BaseController
2
+
3
+ before_filter :load_snippet, :only => [:edit, :update, :destroy]
4
+
5
+ def index
6
+ @snippets = CmsSnippet.paginate :page => params[:page]
7
+ end
8
+
9
+ def new
10
+ # ...
11
+ end
12
+
13
+ def edit
14
+ # ...
15
+ end
16
+
17
+ def create
18
+ @snippet = CmsSnippet.new(params[:snippet])
19
+ @snippet.save!
20
+
21
+ flash[:notice] = 'Snippet created'
22
+ redirect_to :action => :edit, :id => @snippet
23
+
24
+ rescue ActiveRecord::RecordInvalid
25
+ render :action => :new
26
+ end
27
+
28
+ def update
29
+ @snippet.update_attributes!(params[:snippet])
30
+
31
+ flash[:notice] = 'Snippet updated'
32
+ redirect_to :action => :edit, :id => @snippet
33
+
34
+ rescue ActiveRecord::RecordInvalid
35
+ render :action => :edit
36
+ end
37
+
38
+ def destroy
39
+ @snippet.destroy
40
+
41
+ flash[:notice] = 'Snippet removed'
42
+ redirect_to :action => :index
43
+ end
44
+
45
+ def reorder
46
+ params[:snippet_list].each_with_index do |id, position|
47
+ CmsSnippet.find(id).update_attribute(:position, position)
48
+ end
49
+ render :nothing => true
50
+ end
51
+
52
+ protected
53
+
54
+ def load_snippet
55
+ @snippet = CmsSnippet.find_by_id(params[:id])
56
+ end
57
+
58
+ end
@@ -0,0 +1,47 @@
1
+ module CmsCommon::RenderPage
2
+
3
+ def render_page(options = {})
4
+
5
+ @cms_page_preview_mode = options[:preview]
6
+
7
+ # Rendering 404 page
8
+ if !@cms_page
9
+ @cms_page = CmsPage.published.find_by_full_path('404')
10
+ if !@cms_page
11
+ render :text => '404 Page Not Found', :status => 404
12
+ else
13
+ render :inline => @cms_page.content, :layout => (@cms_page.cms_layout.app_layout || false), :status => 404
14
+ end
15
+ return
16
+ end
17
+
18
+ respond_to do |format|
19
+ format.html do
20
+ if @cms_page.redirect_to_page
21
+ redirect_to @cms_page.redirect_to_page.full_path
22
+ else
23
+
24
+ layout = (@cms_page.cms_layout.app_layout || false)
25
+
26
+ if Rails.env.development? || Rails.env.test?
27
+ # attempt to load content from the filesystem first
28
+ begin
29
+ @cms_page_slug = @cms_page_slug.blank? ? 'index' : @cms_page_slug
30
+ render :template => "/cms/#{@cms_page_slug}", :layout => layout
31
+ return
32
+ rescue ActionView::MissingTemplate ; end
33
+ end
34
+
35
+ render :inline => @cms_page.content, :layout => layout
36
+ end
37
+ end
38
+ format.xml do
39
+ @cms_page_children = @cms_page.children[0...25].collect do |p|
40
+ p.rendered_content = render_to_string(:inline => p.content, :layout => false)
41
+ p
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ end
@@ -0,0 +1,30 @@
1
+ class CmsContentController < ApplicationController
2
+
3
+ include CmsCommon::RenderPage
4
+
5
+ unloadable
6
+
7
+ before_filter :parse_path, :only => :show
8
+
9
+ def show
10
+ @cms_page_slug = params[:path].join('/')
11
+ @cms_page = CmsPage.published.find_by_full_path(@cms_page_slug)
12
+ render_page
13
+ end
14
+
15
+ def sitemap
16
+ respond_to do |format|
17
+ format.xml do
18
+ @cms_pages = CmsPage.all
19
+ end
20
+ end
21
+ end
22
+
23
+ protected
24
+
25
+ def parse_path
26
+ params[:format] = (params[:path].last && (match = params[:path].last.match(/\.(.*?)$/)) && match[1]) || 'html'
27
+ params[:path].last && params[:path].last.gsub!(/\.(.*?)$/, '')
28
+ end
29
+
30
+ end
@@ -0,0 +1,12 @@
1
+ module CmsHelper
2
+
3
+ CMS_C = %w( crazy cool colorful cremated creamed crusty clapping campy crude corky comfortable crappy cromulent childish crafty cruddy creaky cranky catatonic comatose circular curvaceous crabby cyan canned clobbered controlling candid cagey callous capable capricious ceaseless changeable cheerful chilly chivalrous chubby chunky clammy classy cloistered cloudy clumsy coherent cold colossal combative comfortable cooing cooperative courageous cowardly craven credible creepy crooked cuddly cultured curly curved cynical casual).freeze
4
+ CMS_M = %w( massive monster mini mighty morbid mexican moses machine mucus murder macabre macho maddening madly magenta magical magnificent majestic makeshift malicious mammoth maniacal many marked massive materialistic mature measly meek melodic merciful mere mighty mindless miniature minor miscreant moaning modern moldy momentous muddled mundane murky mushy mysterious).freeze
5
+ CMS_S = %w( scott sean sack sail salt sand scale scarecrow scarf scene scent school science scissors screw sea seashore seat secretary seed selection self sense servant shade shake shame shape sheep sheet shelf ship shirt shock shoe shoes shop show side sidewalk sign silk silver sink sister sisters size skate skin skirt sky slave sleep sleet slip slope smash smell smile smoke snail snails snake snakes sneeze snow soap society sock soda sofa son song songs sort sound soup space spade spark spiders sponge spoon spot spring spy square squirrel stage stamp star start statement station steam steel stem step stew stick sticks stitch stocking stomach stone stop store story stove stranger straw stream street stretch string structure substance sugar suggestion suit summer sun support surprise sweater swim swing system sangria).freeze
6
+
7
+ def application_name
8
+ ComfortableMexicanSofa::Config.cms_title ||
9
+ [CMS_C, CMS_M, CMS_S].collect{|a| a.sort_by{rand}.first.capitalize}.join
10
+ end
11
+
12
+ end
@@ -0,0 +1,17 @@
1
+ class CmsAttachment < ActiveRecord::Base
2
+
3
+ # -- Relationships --------------------------------------------------------
4
+
5
+ has_attached_file :file, ComfortableMexicanSofa::Config.paperclip_options
6
+ acts_as_categorized
7
+
8
+ # -- Validations ----------------------------------------------------------
9
+
10
+ validates_attachment_presence :file
11
+ validates_presence_of :label
12
+
13
+ # -- Named Scopes ----------------------------------------------------------
14
+
15
+ default_scope :order => 'created_at DESC'
16
+
17
+ end
@@ -0,0 +1,5 @@
1
+ class CmsAttachmentCategorization < ActiveRecord::Base
2
+
3
+ acts_as_categorization
4
+
5
+ end
@@ -0,0 +1,15 @@
1
+ class CmsBlock < ActiveRecord::Base
2
+
3
+ # -- Relationships --------------------------------------------------------
4
+ belongs_to :cms_page
5
+
6
+ # -- Validations ----------------------------------------------------------
7
+ validates_presence_of :label
8
+ validates_uniqueness_of :label, :scope => :cms_page_id
9
+
10
+ # -- Scopes ---------------------------------------------------------------
11
+ named_scope :with_label, lambda{ |name|{
12
+ :conditions => {:label => name}
13
+ }}
14
+
15
+ end
@@ -0,0 +1,36 @@
1
+ class CmsCategory < ActiveRecord::Base
2
+
3
+ # -- Relationships --------------------------------------------------------
4
+ acts_as_tree
5
+
6
+ has_many :cms_page_categorizations, :dependent => :destroy
7
+ has_many :cms_attachment_categorizations, :dependent => :destroy
8
+
9
+ has_many :cms_pages, :through => :cms_page_categorizations
10
+ has_many :cms_attachments, :through => :cms_attachment_categorizations
11
+
12
+ # -- Validations ----------------------------------------------------------
13
+ validates_presence_of :slug, :label
14
+ validates_uniqueness_of :slug, :scope => :parent_id
15
+
16
+ # -- Named Scopes ---------------------------------------------------------
17
+ default_scope :order => 'label'
18
+
19
+ # -- Callbacks ------------------------------------------------------------
20
+ before_validation :set_slug_if_blank
21
+
22
+ # -- Class Methods --------------------------------------------------------
23
+ def set_slug_if_blank
24
+ self.slug = self.label.slugify if self.slug.blank?
25
+ end
26
+
27
+ def self.categories_for_select(collection = CmsCategory.roots, level = 0)
28
+ out = []
29
+ collection.each do |category|
30
+ out += [["#{". . " * level} #{category.label}", category.id]]
31
+ out += self.categories_for_select(category.children, level+1) if category.children.count > 0
32
+ end
33
+ out
34
+ end
35
+
36
+ end
@@ -0,0 +1,102 @@
1
+ class CmsLayout < ActiveRecord::Base
2
+
3
+ # -- Relationships --------------------------------------------------------
4
+ acts_as_tree :counter_cache => :children_count
5
+ has_many :cms_pages, :dependent => :nullify
6
+
7
+ # -- Validations ----------------------------------------------------------
8
+ validates_presence_of :label
9
+ validates_uniqueness_of :label
10
+ validate :validate_block_presence,
11
+ :validate_proper_relationship
12
+
13
+ # -- AR Callbacks ---------------------------------------------------------
14
+ before_save :flag_as_extendable,
15
+ :update_page_blocks
16
+
17
+ # -- Scopes ---------------------------------------------------------------
18
+ default_scope :order => 'position ASC'
19
+ named_scope :extendable, :conditions => { :is_extendable => true }
20
+
21
+ # -- Class Methods --------------------------------------------------------
22
+ def self.options_for_select
23
+ [['---', nil]] + CmsLayout.all.collect{ |l| [l.label, l.id]}
24
+ end
25
+
26
+ def self.app_layouts_for_select
27
+ path = "#{RAILS_ROOT}/app/views/layouts"
28
+ regex = /^([a-z0-9]\w+)\.html/i
29
+
30
+ app_layouts = begin
31
+ Dir.entries(path).collect{|l| l.match(regex).try(:captures)}.compact.flatten
32
+ rescue
33
+ # no app layouts
34
+ end
35
+
36
+ !app_layouts.blank? ? [['---', nil]] + app_layouts : [['---', nil]]
37
+ end
38
+
39
+ # -- Instance Methods -----------------------------------------------------
40
+ def content
41
+ if parent
42
+ parent.content.gsub(/\{\{\s*cms_page_block:default:.*?\}\}/, self.read_attribute(:content))
43
+ else
44
+ read_attribute(:content)
45
+ end
46
+ end
47
+
48
+ def app_layout
49
+ this_layout = read_attribute(:app_layout)
50
+ if this_layout.blank?
51
+ parent && parent.app_layout
52
+ else
53
+ this_layout
54
+ end
55
+ end
56
+
57
+ def extendable_for_select
58
+ [['---', nil]] + CmsLayout.extendable.all.reject{|l| ([self]+self.descendants).member?(l)}.collect{ |l| [l.label, l.id] }
59
+ end
60
+
61
+ def tags(options = {})
62
+ CmsTag::parse_tags(self.content, options)
63
+ end
64
+
65
+ protected
66
+
67
+ def validate_block_presence
68
+ self.errors.add(:content, 'does not have any cms_blocks defined') if self.tags.empty?
69
+ end
70
+
71
+ def validate_proper_relationship
72
+ if self.descendants.member?(parent) || self.parent == self
73
+ self.errors.add(:parent_id, 'layout is invalid')
74
+ end
75
+ end
76
+
77
+ def validate_children_against_extendable
78
+ # todo
79
+ end
80
+
81
+ def flag_as_extendable
82
+ self.is_extendable = !self.tags.select{|t| t.tag_type == 'cms_page_block' && t.label == 'default'}.blank?
83
+ true
84
+ end
85
+
86
+ def update_page_blocks
87
+ return if new_record? || !content_changed?
88
+
89
+ old_tags = CmsTag::parse_tags(content_was).select{|t| ['cms_block', 'cms_page_block'].member?(t.tag_type)}.collect{|t| t.label}
90
+ new_tags = CmsTag::parse_tags(content).select{|t| ['cms_block', 'cms_page_block'].member?(t.tag_type)}.collect{|t| t.label}
91
+
92
+ # creating new cms_blocks for all pages using this layout
93
+ labels_for_blocks = new_tags - old_tags
94
+ if !labels_for_blocks.blank?
95
+ cms_pages.each do |cms_page|
96
+ labels_for_blocks.each do |label|
97
+ cms_page.cms_blocks.create(:label => label)
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,125 @@
1
+ class CmsPage < ActiveRecord::Base
2
+
3
+ attr_accessor :rendered_content
4
+
5
+ # -- Relationships --------------------------------------------------------
6
+ acts_as_tree :counter_cache => :children_count
7
+ acts_as_published
8
+ acts_as_categorized
9
+
10
+ belongs_to :cms_layout
11
+ has_many :cms_blocks,
12
+ :dependent => :destroy
13
+ belongs_to :redirect_to_page,
14
+ :class_name => 'CmsPage',
15
+ :foreign_key => :redirect_to_page_id
16
+ has_one :redirected_from_page,
17
+ :class_name => 'CmsPage',
18
+ :foreign_key => :redirect_to_page_id
19
+
20
+ #-- Validations -----------------------------------------------------------
21
+ validates_presence_of :cms_layout_id,
22
+ :unless => lambda{|p| p.redirect_to_page}
23
+ validates_presence_of :label
24
+ validates_presence_of :slug,
25
+ :unless => lambda{|p| CmsPage.count == 0 || p == CmsPage.root}
26
+ validates_format_of :slug,
27
+ :with => /^\w[a-z0-9_-]*$/i,
28
+ :unless => lambda{|p| CmsPage.count == 0 || p == CmsPage.root}
29
+ validates_uniqueness_of :full_path
30
+
31
+ validate :validate_redirect_to
32
+
33
+ # -- AR Callbacks ---------------------------------------------------------
34
+ before_validation :assign_full_path
35
+ after_save :save_blocks,
36
+ :sync_child_slugs
37
+
38
+ # -- Scopes ---------------------------------------------------------------
39
+ default_scope :order => 'position ASC'
40
+ named_scope :sections,
41
+ :conditions => {:is_section => true}
42
+
43
+ # -- Class Methods --------------------------------------------------------
44
+ def self.[](slug)
45
+ CmsPage.find_by_slug!(slug)
46
+ end
47
+
48
+ # -- Instance Methods -----------------------------------------------------
49
+ def content
50
+ # TODO: Add column to cache the render output. pointless to run it all the time
51
+ render_content
52
+ end
53
+
54
+ # FIX: Recursive Tag/Content Replacement
55
+ # Works, but potentionally dangerous and not particularly efficient
56
+ def render_content(content = nil)
57
+ content = cms_layout.content.dup if !content
58
+ while (!(tags = CmsTag::parse_tags(content, :page => self).sort_by{|t| t.class.render_priority}).blank?)
59
+ tags.each do |tag|
60
+ content.gsub!(tag.regex) { tag.render }
61
+ end
62
+ end
63
+ content
64
+ end
65
+
66
+ def blocks=(blocks)
67
+ blocks.each do |label, params|
68
+ if !self.new_record? && !(block = self.cms_blocks.select{|b| b.label == label}.first).blank?
69
+ block.attributes = params
70
+ else
71
+ self.cms_blocks.build({:label => label}.merge(params))
72
+ end
73
+ end
74
+ end
75
+
76
+ def pages_for_select(page = CmsPage.root, level = 0, exclude_self = false)
77
+ page ||= CmsPage.root
78
+ return [] if !page || (page == self && exclude_self)
79
+ out = [["#{". . " * level} #{page.label}", page.id]]
80
+ page.children.each do |child|
81
+ if child.children.count > 0
82
+ out += pages_for_select(child, level + 1, exclude_self)
83
+ else
84
+ unless (child == self && exclude_self)
85
+ out += [["#{". . " * (level + 1)} #{child.label}", child.id]]
86
+ end
87
+ end
88
+ end
89
+ out
90
+ end
91
+
92
+ def full_path
93
+ "/#{read_attribute(:full_path)}"
94
+ end
95
+
96
+ def cms_block_content(label, content)
97
+ self.cms_blocks.select{|b| b.label.to_s == label.to_s}.first.try(content)
98
+ end
99
+
100
+ protected
101
+
102
+ def assign_full_path
103
+ self.full_path = (self.ancestors.reverse.collect{|p| p.slug}.compact + [self.slug]).join('/')
104
+ end
105
+
106
+ def validate_redirect_to
107
+ if self.redirect_to_page && (self == self.redirect_to_page || self.redirect_to_page.redirect_to_page)
108
+ self.errors.add(:redirect_to_page_id)
109
+ end
110
+ end
111
+
112
+ def save_blocks
113
+ self.cms_blocks.each do |b|
114
+ b.save! if b.changed?
115
+ end
116
+ end
117
+
118
+ def sync_child_slugs
119
+ if slug_changed?
120
+ children.each do |child|
121
+ child.save!
122
+ end
123
+ end
124
+ end
125
+ end