comfypress 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (289) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.travis.yml +22 -0
  4. data/Gemfile +22 -0
  5. data/Gemfile.lock +175 -0
  6. data/LICENSE +20 -0
  7. data/README.md +79 -0
  8. data/Rakefile +5 -0
  9. data/app/assets/images/comfypress/arrow_bottom.gif +0 -0
  10. data/app/assets/images/comfypress/arrow_right.gif +0 -0
  11. data/app/assets/images/comfypress/bootstrap/glyphicons-halflings-white.png +0 -0
  12. data/app/assets/images/comfypress/bootstrap/glyphicons-halflings.png +0 -0
  13. data/app/assets/images/comfypress/checkerboard.gif +0 -0
  14. data/app/assets/images/comfypress/icon_draft.gif +0 -0
  15. data/app/assets/images/comfypress/icon_file.gif +0 -0
  16. data/app/assets/images/comfypress/icon_layout.gif +0 -0
  17. data/app/assets/images/comfypress/icon_move.gif +0 -0
  18. data/app/assets/images/comfypress/icon_page.gif +0 -0
  19. data/app/assets/images/comfypress/icon_site.gif +0 -0
  20. data/app/assets/images/comfypress/icon_snippet.gif +0 -0
  21. data/app/assets/images/comfypress/nav_arrow.png +0 -0
  22. data/app/assets/javascripts/comfypress/admin/application.js +1 -0
  23. data/app/assets/javascripts/comfypress/application.js.coffee +175 -0
  24. data/app/assets/javascripts/comfypress/lib/bootstrap-datetimepicker.js +21 -0
  25. data/app/assets/javascripts/comfypress/lib/bootstrap-wysihtml5.js +492 -0
  26. data/app/assets/javascripts/comfypress/lib/bootstrap.js +6 -0
  27. data/app/assets/javascripts/comfypress/lib/codemirror.js +10 -0
  28. data/app/assets/javascripts/comfypress/lib/wysihtml5.js +261 -0
  29. data/app/assets/stylesheets/comfypress/admin/application.css +1 -0
  30. data/app/assets/stylesheets/comfypress/application.css.sass +8 -0
  31. data/app/assets/stylesheets/comfypress/base.css.sass +333 -0
  32. data/app/assets/stylesheets/comfypress/bootstrap_overrides.css.sass +45 -0
  33. data/app/assets/stylesheets/comfypress/codemirror_overrides.css.sass +27 -0
  34. data/app/assets/stylesheets/comfypress/lib/bootstrap-datetimepicker.css +9 -0
  35. data/app/assets/stylesheets/comfypress/lib/bootstrap-wysihtml5.css +102 -0
  36. data/app/assets/stylesheets/comfypress/lib/bootstrap.css +9 -0
  37. data/app/assets/stylesheets/comfypress/lib/codemirror.css +240 -0
  38. data/app/assets/stylesheets/comfypress/wysihtml5_overrides.css.sass +5 -0
  39. data/app/controllers/application_controller.rb +5 -0
  40. data/app/controllers/cms_admin/base_controller.rb +51 -0
  41. data/app/controllers/cms_admin/categories_controller.rb +35 -0
  42. data/app/controllers/cms_admin/files_controller.rb +108 -0
  43. data/app/controllers/cms_admin/layouts_controller.rb +67 -0
  44. data/app/controllers/cms_admin/menu_items_controller.rb +65 -0
  45. data/app/controllers/cms_admin/menus_controller.rb +60 -0
  46. data/app/controllers/cms_admin/pages_controller.rb +112 -0
  47. data/app/controllers/cms_admin/revisions_controller.rb +57 -0
  48. data/app/controllers/cms_admin/sites_controller.rb +64 -0
  49. data/app/controllers/cms_admin/snippets_controller.rb +64 -0
  50. data/app/controllers/cms_content_controller.rb +79 -0
  51. data/app/helpers/application_helper.rb +16 -0
  52. data/app/models/cms/block.rb +48 -0
  53. data/app/models/cms/categorization.rb +21 -0
  54. data/app/models/cms/category.rb +30 -0
  55. data/app/models/cms/file.rb +75 -0
  56. data/app/models/cms/layout.rb +99 -0
  57. data/app/models/cms/menu.rb +26 -0
  58. data/app/models/cms/menu_item.rb +14 -0
  59. data/app/models/cms/page.rb +202 -0
  60. data/app/models/cms/revision.rb +17 -0
  61. data/app/models/cms/site.rb +113 -0
  62. data/app/models/cms/snippet.rb +58 -0
  63. data/app/models/cms.rb +5 -0
  64. data/app/views/cms_admin/categories/_categories.html.haml +3 -0
  65. data/app/views/cms_admin/categories/_edit.html.haml +6 -0
  66. data/app/views/cms_admin/categories/_form.html.haml +8 -0
  67. data/app/views/cms_admin/categories/_index.html.haml +24 -0
  68. data/app/views/cms_admin/categories/_show.html.haml +13 -0
  69. data/app/views/cms_admin/categories/create.js.erb +7 -0
  70. data/app/views/cms_admin/categories/destroy.js.erb +3 -0
  71. data/app/views/cms_admin/categories/edit.js.erb +3 -0
  72. data/app/views/cms_admin/categories/update.js.erb +6 -0
  73. data/app/views/cms_admin/files/_file.html.haml +13 -0
  74. data/app/views/cms_admin/files/_form.html.haml +14 -0
  75. data/app/views/cms_admin/files/_index.html.haml +14 -0
  76. data/app/views/cms_admin/files/_page_form.html.haml +9 -0
  77. data/app/views/cms_admin/files/destroy.js.coffee +2 -0
  78. data/app/views/cms_admin/files/edit.html.haml +5 -0
  79. data/app/views/cms_admin/files/index.html.haml +28 -0
  80. data/app/views/cms_admin/files/new.html.haml +5 -0
  81. data/app/views/cms_admin/layouts/_form.html.haml +17 -0
  82. data/app/views/cms_admin/layouts/_index_branch.html.haml +23 -0
  83. data/app/views/cms_admin/layouts/edit.html.haml +9 -0
  84. data/app/views/cms_admin/layouts/index.html.haml +9 -0
  85. data/app/views/cms_admin/layouts/new.html.haml +5 -0
  86. data/app/views/cms_admin/menu_items/_form.html.haml +22 -0
  87. data/app/views/cms_admin/menu_items/edit.html.haml +8 -0
  88. data/app/views/cms_admin/menu_items/index.html.haml +24 -0
  89. data/app/views/cms_admin/menu_items/new.html.haml +5 -0
  90. data/app/views/cms_admin/menus/_form.html.haml +8 -0
  91. data/app/views/cms_admin/menus/edit.html.haml +8 -0
  92. data/app/views/cms_admin/menus/index.html.haml +24 -0
  93. data/app/views/cms_admin/menus/new.html.haml +5 -0
  94. data/app/views/cms_admin/pages/_form.html.haml +38 -0
  95. data/app/views/cms_admin/pages/_form_blocks.html.haml +28 -0
  96. data/app/views/cms_admin/pages/_index_branch.html.haml +35 -0
  97. data/app/views/cms_admin/pages/edit.html.haml +9 -0
  98. data/app/views/cms_admin/pages/form_blocks.js.erb +2 -0
  99. data/app/views/cms_admin/pages/index.html.haml +11 -0
  100. data/app/views/cms_admin/pages/new.html.haml +5 -0
  101. data/app/views/cms_admin/pages/toggle_branch.js.erb +11 -0
  102. data/app/views/cms_admin/revisions/show.html.haml +28 -0
  103. data/app/views/cms_admin/sites/_form.html.haml +14 -0
  104. data/app/views/cms_admin/sites/_mirrors.html.haml +17 -0
  105. data/app/views/cms_admin/sites/edit.html.haml +5 -0
  106. data/app/views/cms_admin/sites/index.html.haml +24 -0
  107. data/app/views/cms_admin/sites/new.html.haml +5 -0
  108. data/app/views/cms_admin/snippets/_form.html.haml +11 -0
  109. data/app/views/cms_admin/snippets/edit.html.haml +9 -0
  110. data/app/views/cms_admin/snippets/index.html.haml +28 -0
  111. data/app/views/cms_admin/snippets/new.html.haml +5 -0
  112. data/app/views/cms_content/_menu.html.haml +5 -0
  113. data/app/views/cms_content/render_sitemap.xml.builder +15 -0
  114. data/app/views/layouts/cms_admin/_body.html.haml +16 -0
  115. data/app/views/layouts/cms_admin/_center.html.haml +7 -0
  116. data/app/views/layouts/cms_admin/_footer.html.haml +3 -0
  117. data/app/views/layouts/cms_admin/_footer_js.html.haml +7 -0
  118. data/app/views/layouts/cms_admin/_head.html.haml +12 -0
  119. data/app/views/layouts/cms_admin/_left.html.haml +11 -0
  120. data/app/views/layouts/cms_admin/_right.html.haml +1 -0
  121. data/app/views/layouts/cms_admin.html.haml +4 -0
  122. data/comfypress.gemspec +28 -0
  123. data/config/application.rb +69 -0
  124. data/config/boot.rb +6 -0
  125. data/config/database.sqlite.yml +47 -0
  126. data/config/database.yml +47 -0
  127. data/config/environment.rb +5 -0
  128. data/config/environments/development.rb +39 -0
  129. data/config/environments/production.rb +67 -0
  130. data/config/environments/test.rb +39 -0
  131. data/config/initializers/comfypress.rb +100 -0
  132. data/config/initializers/paperclip.rb +3 -0
  133. data/config/locales/de.yml +236 -0
  134. data/config/locales/en.yml +285 -0
  135. data/config/locales/es.yml +236 -0
  136. data/config/locales/fr.yml +236 -0
  137. data/config/locales/ja.yml +237 -0
  138. data/config/locales/pl.yml +236 -0
  139. data/config/locales/pt-BR.yml +236 -0
  140. data/config/locales/ru.yml +236 -0
  141. data/config/locales/sv.yml +236 -0
  142. data/config/locales/zh-CN.yml +236 -0
  143. data/config/routes.rb +10 -0
  144. data/config.ru +4 -0
  145. data/db/cms_fixtures/sample-site/layouts/default/_default.yml +1 -0
  146. data/db/cms_fixtures/sample-site/layouts/default/content.html +5 -0
  147. data/db/cms_fixtures/sample-site/layouts/default/css.css +1 -0
  148. data/db/cms_fixtures/sample-site/layouts/default/js.js +1 -0
  149. data/db/cms_fixtures/sample-site/layouts/default/nested/_nested.yml +2 -0
  150. data/db/cms_fixtures/sample-site/layouts/default/nested/content.html +2 -0
  151. data/db/cms_fixtures/sample-site/layouts/default/nested/css.css +1 -0
  152. data/db/cms_fixtures/sample-site/layouts/default/nested/js.js +1 -0
  153. data/db/cms_fixtures/sample-site/pages/index/_index.yml +2 -0
  154. data/db/cms_fixtures/sample-site/pages/index/child/_child.yml +3 -0
  155. data/db/cms_fixtures/sample-site/pages/index/child/left.html +1 -0
  156. data/db/cms_fixtures/sample-site/pages/index/child/right.html +1 -0
  157. data/db/cms_fixtures/sample-site/pages/index/content.html +2 -0
  158. data/db/cms_fixtures/sample-site/snippets/default/_default.yml +1 -0
  159. data/db/cms_fixtures/sample-site/snippets/default/content.html +1 -0
  160. data/db/migrate/01_create_cms.rb +163 -0
  161. data/db/seeds.rb +9 -0
  162. data/db/upgrade_migrations/02_upgrade_to_1_1_0.rb +19 -0
  163. data/db/upgrade_migrations/03_upgrade_to_1_2_0.rb +15 -0
  164. data/db/upgrade_migrations/04_upgrade_to_1_3_0.rb +23 -0
  165. data/db/upgrade_migrations/05_upgrade_to_1_4_0.rb +33 -0
  166. data/db/upgrade_migrations/06_upgrade_to_1_5_0.rb +21 -0
  167. data/db/upgrade_migrations/07_upgrade_to_1_6_0.rb +25 -0
  168. data/doc/preview.png +0 -0
  169. data/doc/sofa.png +0 -0
  170. data/lib/comfypress/authentication/dummy_auth.rb +8 -0
  171. data/lib/comfypress/authentication/http_auth.rb +18 -0
  172. data/lib/comfypress/configuration.rb +99 -0
  173. data/lib/comfypress/engine.rb +18 -0
  174. data/lib/comfypress/error.rb +24 -0
  175. data/lib/comfypress/extensions/acts_as_tree.rb +102 -0
  176. data/lib/comfypress/extensions/has_revisions.rb +64 -0
  177. data/lib/comfypress/extensions/is_categorized.rb +49 -0
  178. data/lib/comfypress/extensions/is_mirrored.rb +85 -0
  179. data/lib/comfypress/extensions/rails.rb +24 -0
  180. data/lib/comfypress/fixtures.rb +289 -0
  181. data/lib/comfypress/form_builder.rb +97 -0
  182. data/lib/comfypress/render_methods.rb +85 -0
  183. data/lib/comfypress/routing.rb +62 -0
  184. data/lib/comfypress/sitemap.rb +27 -0
  185. data/lib/comfypress/tag.rb +154 -0
  186. data/lib/comfypress/tags/asset.rb +25 -0
  187. data/lib/comfypress/tags/collection.rb +64 -0
  188. data/lib/comfypress/tags/field_datetime.rb +17 -0
  189. data/lib/comfypress/tags/field_integer.rb +17 -0
  190. data/lib/comfypress/tags/field_rich_text.rb +17 -0
  191. data/lib/comfypress/tags/field_string.rb +17 -0
  192. data/lib/comfypress/tags/field_text.rb +17 -0
  193. data/lib/comfypress/tags/file.rb +29 -0
  194. data/lib/comfypress/tags/helper.rb +24 -0
  195. data/lib/comfypress/tags/menu.rb +27 -0
  196. data/lib/comfypress/tags/page_datetime.rb +13 -0
  197. data/lib/comfypress/tags/page_file.rb +51 -0
  198. data/lib/comfypress/tags/page_files.rb +52 -0
  199. data/lib/comfypress/tags/page_integer.rb +13 -0
  200. data/lib/comfypress/tags/page_markdown.rb +22 -0
  201. data/lib/comfypress/tags/page_rich_text.rb +13 -0
  202. data/lib/comfypress/tags/page_string.rb +13 -0
  203. data/lib/comfypress/tags/page_text.rb +13 -0
  204. data/lib/comfypress/tags/partial.rb +23 -0
  205. data/lib/comfypress/tags/snippet.rb +19 -0
  206. data/lib/comfypress/version.rb +3 -0
  207. data/lib/comfypress/view_hooks.rb +32 -0
  208. data/lib/comfypress/view_methods.rb +52 -0
  209. data/lib/comfypress.rb +66 -0
  210. data/lib/generators/comfy/cms/README +10 -0
  211. data/lib/generators/comfy/cms/cms_generator.rb +57 -0
  212. data/lib/tasks/comfypress.rake +45 -0
  213. data/script/rails +6 -0
  214. data/test/fixtures/cms/blocks.yml +12 -0
  215. data/test/fixtures/cms/categories.yml +4 -0
  216. data/test/fixtures/cms/categorizations.yml +3 -0
  217. data/test/fixtures/cms/files.yml +9 -0
  218. data/test/fixtures/cms/layouts.yml +40 -0
  219. data/test/fixtures/cms/menu_items.yml +15 -0
  220. data/test/fixtures/cms/menus.yml +9 -0
  221. data/test/fixtures/cms/pages.yml +39 -0
  222. data/test/fixtures/cms/revisions.yml +21 -0
  223. data/test/fixtures/cms/sites.yml +6 -0
  224. data/test/fixtures/cms/snippets.yml +6 -0
  225. data/test/fixtures/files/data.zip +0 -0
  226. data/test/fixtures/files/document.pdf +0 -0
  227. data/test/fixtures/files/image.gif +0 -0
  228. data/test/fixtures/files/image.jpg +0 -0
  229. data/test/fixtures/views/_nav_hook.html.erb +1 -0
  230. data/test/fixtures/views/_nav_hook_2.html.erb +1 -0
  231. data/test/fixtures/views/render_test/_test.html.erb +1 -0
  232. data/test/fixtures/views/render_test/new.html.erb +1 -0
  233. data/test/fixtures/views/render_test/render_layout.html.erb +1 -0
  234. data/test/functional/cms_admin/base_controller_test.rb +18 -0
  235. data/test/functional/cms_admin/categories_controller_test.rb +70 -0
  236. data/test/functional/cms_admin/files_controller_test.rb +216 -0
  237. data/test/functional/cms_admin/layouts_controller_test.rb +123 -0
  238. data/test/functional/cms_admin/pages_controller_test.rb +450 -0
  239. data/test/functional/cms_admin/revisions_controller_test.rb +138 -0
  240. data/test/functional/cms_admin/sites_controller_test.rb +105 -0
  241. data/test/functional/cms_admin/snippets_controller_test.rb +140 -0
  242. data/test/functional/cms_content_controller_test.rb +205 -0
  243. data/test/gemfiles/Gemfile.rails.3.1 +16 -0
  244. data/test/gemfiles/Gemfile.rails.3.2 +16 -0
  245. data/test/gemfiles/Gemfile.rails.4.0 +16 -0
  246. data/test/integration/authentication_test.rb +48 -0
  247. data/test/integration/fixtures_test.rb +61 -0
  248. data/test/integration/mirrors_test.rb +72 -0
  249. data/test/integration/render_cms_test.rb +233 -0
  250. data/test/integration/sites_test.rb +120 -0
  251. data/test/integration/view_hooks_test.rb +43 -0
  252. data/test/test_helper.rb +124 -0
  253. data/test/unit/cms/menu_item_test.rb +7 -0
  254. data/test/unit/cms/menu_test.rb +7 -0
  255. data/test/unit/configuration_test.rb +42 -0
  256. data/test/unit/fixtures_test.rb +357 -0
  257. data/test/unit/mirrors_test.rb +242 -0
  258. data/test/unit/models/block_test.rb +199 -0
  259. data/test/unit/models/categorization_test.rb +76 -0
  260. data/test/unit/models/category_test.rb +39 -0
  261. data/test/unit/models/file_test.rb +89 -0
  262. data/test/unit/models/layout_test.rb +125 -0
  263. data/test/unit/models/page_test.rb +255 -0
  264. data/test/unit/models/site_test.rb +152 -0
  265. data/test/unit/models/snippet_test.rb +49 -0
  266. data/test/unit/revisions_test.rb +185 -0
  267. data/test/unit/sitemap_test.rb +20 -0
  268. data/test/unit/tag_test.rb +308 -0
  269. data/test/unit/tags/asset_test.rb +56 -0
  270. data/test/unit/tags/collection_test.rb +116 -0
  271. data/test/unit/tags/field_datetime_test.rb +50 -0
  272. data/test/unit/tags/field_integer_test.rb +49 -0
  273. data/test/unit/tags/field_rich_text_test.rb +49 -0
  274. data/test/unit/tags/field_string_test.rb +52 -0
  275. data/test/unit/tags/field_text_test.rb +48 -0
  276. data/test/unit/tags/file_test.rb +67 -0
  277. data/test/unit/tags/helper_test.rb +86 -0
  278. data/test/unit/tags/page_datetime_test.rb +50 -0
  279. data/test/unit/tags/page_file_test.rb +119 -0
  280. data/test/unit/tags/page_files_test.rb +113 -0
  281. data/test/unit/tags/page_integer_test.rb +49 -0
  282. data/test/unit/tags/page_markdown_test.rb +48 -0
  283. data/test/unit/tags/page_rich_text_test.rb +49 -0
  284. data/test/unit/tags/page_string_test.rb +49 -0
  285. data/test/unit/tags/page_text_test.rb +52 -0
  286. data/test/unit/tags/partial_test.rb +76 -0
  287. data/test/unit/tags/snippet_test.rb +45 -0
  288. data/test/unit/view_methods_test.rb +80 -0
  289. metadata +457 -0
@@ -0,0 +1,49 @@
1
+ module ComfyPress::IsCategorized
2
+
3
+ def self.included(base)
4
+ base.send :extend, ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def cms_is_categorized
9
+ include ComfyPress::IsCategorized::InstanceMethods
10
+
11
+ has_many :categorizations,
12
+ :as => :categorized,
13
+ :class_name => 'Cms::Categorization',
14
+ :dependent => :destroy
15
+ has_many :categories,
16
+ :through => :categorizations,
17
+ :class_name => 'Cms::Category'
18
+
19
+ attr_accessor :category_ids
20
+
21
+ after_save :sync_categories
22
+
23
+ scope :for_category, lambda { |*categories|
24
+ if (categories = [categories].flatten.compact).present?
25
+ select("DISTINCT #{table_name}.*").
26
+ joins(:categorizations => :category).
27
+ where('cms_categories.label' => categories)
28
+ end
29
+ }
30
+ end
31
+ end
32
+
33
+ module InstanceMethods
34
+ def sync_categories
35
+ (self.category_ids || {}).each do |category_id, flag|
36
+ case flag.to_i
37
+ when 1
38
+ if category = Cms::Category.find_by_id(category_id)
39
+ category.categorizations.create(:categorized => self)
40
+ end
41
+ when 0
42
+ self.categorizations.where(:category_id => category_id).destroy_all
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ ActiveRecord::Base.send :include, ComfyPress::IsCategorized
@@ -0,0 +1,85 @@
1
+ module ComfyPress::IsMirrored
2
+
3
+ def self.included(base)
4
+ base.send :extend, ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def cms_is_mirrored
9
+ include ComfyPress::IsMirrored::InstanceMethods
10
+
11
+ attr_accessor :is_mirrored
12
+
13
+ after_save :sync_mirror
14
+ after_destroy :destroy_mirror
15
+ end
16
+ end
17
+
18
+ module InstanceMethods
19
+
20
+ # Mirrors of the object found on other sites
21
+ def mirrors
22
+ return [] unless self.site.is_mirrored?
23
+ (Cms::Site.mirrored - [self.site]).collect do |site|
24
+ case self
25
+ when Cms::Layout then site.layouts.find_by_identifier(self.identifier)
26
+ when Cms::Page then site.pages.find_by_full_path(self.full_path)
27
+ when Cms::Snippet then site.snippets.find_by_identifier(self.identifier)
28
+ end
29
+ end.compact
30
+ end
31
+
32
+ # Creating or updating a mirror object. Relationships are mirrored
33
+ # but content is unique. When updating need to grab mirrors based on
34
+ # self.slug_was, new objects will use self.slug.
35
+ def sync_mirror
36
+ return if self.is_mirrored || !self.site.is_mirrored?
37
+
38
+ (Cms::Site.mirrored - [self.site]).each do |site|
39
+ mirror = case self
40
+ when Cms::Layout
41
+ m = site.layouts.find_by_identifier(self.identifier_was || self.identifier) || site.layouts.new
42
+ m.attributes = {
43
+ :identifier => self.identifier,
44
+ :parent_id => site.layouts.find_by_identifier(self.parent.try(:identifier)).try(:id)
45
+ }
46
+ m
47
+ when Cms::Page
48
+ m = site.pages.find_by_full_path(self.full_path_was || self.full_path) || site.pages.new
49
+ m.attributes = {
50
+ :slug => self.slug,
51
+ :label => self.slug.blank?? self.label : m.label,
52
+ :parent_id => site.pages.find_by_full_path(self.parent.try(:full_path)).try(:id),
53
+ :layout => site.layouts.find_by_identifier(self.layout.try(:identifier))
54
+ }
55
+ m
56
+ when Cms::Snippet
57
+ m = site.snippets.find_by_identifier(self.identifier_was || self.identifier) || site.snippets.new
58
+ m.attributes = {
59
+ :identifier => self.identifier
60
+ }
61
+ m
62
+ end
63
+
64
+ mirror.is_mirrored = true
65
+ begin
66
+ mirror.save!
67
+ rescue ActiveRecord::RecordInvalid
68
+ logger.detailed_error($!)
69
+ end
70
+ end
71
+ end
72
+
73
+ # Mirrors should be destroyed
74
+ def destroy_mirror
75
+ return if self.is_mirrored || !self.site.is_mirrored?
76
+ mirrors.each do |mirror|
77
+ mirror.is_mirrored = true
78
+ mirror.destroy
79
+ end
80
+ end
81
+ end
82
+
83
+ end
84
+
85
+ ActiveRecord::Base.send :include, ComfyPress::IsMirrored
@@ -0,0 +1,24 @@
1
+ class String
2
+ # Converts string to something suitable to be used as an element id
3
+ def slugify
4
+ self.strip.gsub(/\W|_/, '-').gsub(/\s|^_*|_*$/, '').squeeze('-')
5
+ end
6
+ end
7
+
8
+ module Enumerable
9
+ # Like a normal collect, only with index
10
+ def collect_with_index
11
+ result = []
12
+ self.each_with_index do |elt, idx|
13
+ result << yield(elt, idx)
14
+ end
15
+ result
16
+ end
17
+ end
18
+
19
+ class ActiveSupport::BufferedLogger
20
+ def detailed_error(e)
21
+ error(e.message)
22
+ e.backtrace.each{|line| error line }
23
+ end
24
+ end
@@ -0,0 +1,289 @@
1
+ module ComfyPress::Fixtures
2
+
3
+ def self.import_all(to_site, from_folder = nil, force_import = false)
4
+ import_layouts to_site, from_folder, nil, true, nil, [], force_import
5
+ import_pages to_site, from_folder, nil, true, nil, [], force_import
6
+ import_snippets to_site, from_folder, force_import
7
+ end
8
+
9
+ def self.export_all(from_site, to_folder = nil)
10
+ export_layouts from_site, to_folder
11
+ export_pages from_site, to_folder
12
+ export_snippets from_site, to_folder
13
+ end
14
+
15
+ def self.import_layouts(to_site, from_folder = nil, path = nil, root = true, parent = nil, layout_ids = [], force_import = false)
16
+ site = Cms::Site.find_or_create_by_identifier(to_site)
17
+ unless path ||= find_fixtures_path((from_folder || to_site), 'layouts')
18
+ ComfyPress.logger.warn('Cannot find Layout fixtures')
19
+ return []
20
+ end
21
+
22
+ Dir.glob("#{path}/*").select{|f| File.directory?(f)}.each do |path|
23
+ identifier = path.split('/').last
24
+ layout = site.layouts.find_by_identifier(identifier) || site.layouts.new(:identifier => identifier)
25
+
26
+ # updating attributes
27
+ if File.exists?(file_path = File.join(path, "_#{identifier}.yml"))
28
+ if layout.new_record? || File.mtime(file_path) > layout.updated_at || force_import
29
+ attributes = YAML.load_file(file_path).try(:symbolize_keys!) || { }
30
+ layout.label = attributes[:label] || identifier.titleize
31
+ layout.app_layout = attributes[:app_layout] || parent.try(:app_layout)
32
+ layout.position = attributes[:position] if attributes[:position]
33
+ end
34
+ elsif layout.new_record?
35
+ layout.label = identifier.titleize
36
+ layout.app_layout = parent.try(:app_layout)
37
+ end
38
+
39
+ # updating content
40
+ if File.exists?(file_path = File.join(path, 'content.html'))
41
+ if layout.new_record? || File.mtime(file_path) > layout.updated_at || force_import
42
+ layout.content = File.open(file_path).read
43
+ end
44
+ end
45
+ if File.exists?(file_path = File.join(path, 'css.css'))
46
+ if layout.new_record? || File.mtime(file_path) > layout.updated_at || force_import
47
+ layout.css = File.open(file_path).read
48
+ end
49
+ end
50
+ if File.exists?(file_path = File.join(path, 'js.js'))
51
+ if layout.new_record? || File.mtime(file_path) > layout.updated_at || force_import
52
+ layout.js = File.open(file_path).read
53
+ end
54
+ end
55
+
56
+ # saving
57
+ layout.parent = parent
58
+ if layout.changed?
59
+ if layout.save
60
+ ComfyPress.logger.warn("[Fixtures] Saved Layout {#{layout.identifier}}")
61
+ else
62
+ ComfyPress.logger.error("[Fixtures] Failed to save Layout {#{layout.errors.inspect}}")
63
+ next
64
+ end
65
+ end
66
+ layout_ids << layout.id
67
+
68
+ # checking for nested fixtures
69
+ layout_ids += import_layouts(to_site, from_folder, path, false, layout, layout_ids)
70
+ end
71
+
72
+ # removing all db entries that are not in fixtures
73
+ if root
74
+ site.layouts.where('id NOT IN (?)', layout_ids.uniq).each{ |l| l.destroy }
75
+ ComfyPress.logger.warn('Imported Layouts!')
76
+ end
77
+
78
+ # returning ids of layouts in fixtures
79
+ layout_ids.uniq
80
+ end
81
+
82
+ def self.import_pages(to_site, from_folder = nil, path = nil, root = true, parent = nil, page_ids = [], force_import = false)
83
+ site = Cms::Site.find_or_create_by_identifier(to_site)
84
+ unless path ||= find_fixtures_path((from_folder || to_site), 'pages')
85
+ ComfyPress.logger.warn('Cannot find Page fixtures')
86
+ return []
87
+ end
88
+
89
+ Dir.glob("#{path}/*").select{|f| File.directory?(f)}.each do |path|
90
+ slug = path.split('/').last
91
+ page = if parent
92
+ parent.children.find_by_slug(slug) || site.pages.new(:parent => parent, :slug => slug)
93
+ else
94
+ site.pages.root || site.pages.new(:slug => slug)
95
+ end
96
+
97
+ # updating attributes
98
+ if File.exists?(file_path = File.join(path, "_#{slug}.yml"))
99
+ if page.new_record? || File.mtime(file_path) > page.updated_at || force_import
100
+ attributes = YAML.load_file(file_path).try(:symbolize_keys!) || { }
101
+ page.label = attributes[:label] || slug.titleize
102
+ page.layout = site.layouts.find_by_identifier(attributes[:layout]) || parent.try(:layout)
103
+ page.target_page = site.pages.find_by_full_path(attributes[:target_page])
104
+ page.is_published = attributes[:is_published].nil?? true : attributes[:is_published]
105
+ page.position = attributes[:position] if attributes[:position]
106
+ end
107
+ elsif page.new_record?
108
+ page.label = slug.titleize
109
+ page.layout = parent.try(:layout)
110
+ end
111
+
112
+ # updating content
113
+ blocks_to_clear = page.blocks.collect(&:identifier)
114
+ blocks_attributes = [ ]
115
+ Dir.glob("#{path}/*.html").each do |file_path|
116
+ identifier = file_path.split('/').last.gsub(/\.html$/, '')
117
+ blocks_to_clear.delete(identifier)
118
+ if page.new_record? || File.mtime(file_path) > page.updated_at || force_import
119
+ blocks_attributes << {
120
+ :identifier => identifier,
121
+ :content => File.open(file_path).read
122
+ }
123
+ end
124
+ end
125
+
126
+ # clearing removed blocks
127
+ blocks_to_clear.each do |identifier|
128
+ blocks_attributes << {
129
+ :identifier => identifier,
130
+ :content => nil
131
+ }
132
+ end
133
+
134
+ # saving
135
+ page.blocks_attributes = blocks_attributes if blocks_attributes.present?
136
+ if page.changed? || blocks_attributes.present?
137
+ if page.save
138
+ ComfyPress.logger.warn("[Fixtures] Saved Page {#{page.full_path}}")
139
+ else
140
+ ComfyPress.logger.warn("[Fixtures] Failed to save Page {#{page.errors.inspect}}")
141
+ next
142
+ end
143
+ end
144
+ page_ids << page.id
145
+
146
+ # checking for nested fixtures
147
+ page_ids += import_pages(to_site, from_folder, path, false, page, page_ids)
148
+ end
149
+
150
+ # removing all db entries that are not in fixtures
151
+ if root
152
+ site.pages.where('id NOT IN (?)', page_ids.uniq).each{ |p| p.destroy }
153
+ ComfyPress.logger.warn('Imported Pages!')
154
+ end
155
+
156
+ # returning ids of layouts in fixtures
157
+ page_ids.uniq
158
+ end
159
+
160
+ def self.import_snippets(to_site, from_folder = nil, force_import = false)
161
+ site = Cms::Site.find_or_create_by_identifier(to_site)
162
+ unless path = find_fixtures_path((from_folder || to_site), 'snippets')
163
+ ComfyPress.logger.warn('Cannot find Snippet fixtures')
164
+ return []
165
+ end
166
+
167
+ snippet_ids = []
168
+ Dir.glob("#{path}/*").select{|f| File.directory?(f)}.each do |path|
169
+ identifier = path.split('/').last
170
+ snippet = site.snippets.find_by_identifier(identifier) || site.snippets.new(:identifier => identifier)
171
+
172
+ # updating attributes
173
+ if File.exists?(file_path = File.join(path, "_#{identifier}.yml"))
174
+ if snippet.new_record? || File.mtime(file_path) > snippet.updated_at || force_import
175
+ attributes = YAML.load_file(file_path).try(:symbolize_keys!) || { }
176
+ snippet.label = attributes[:label] || identifier.titleize
177
+ end
178
+ elsif snippet.new_record?
179
+ snippet.label = identifier.titleize
180
+ end
181
+
182
+ # updating content
183
+ if File.exists?(file_path = File.join(path, 'content.html'))
184
+ if snippet.new_record? || File.mtime(file_path) > snippet.updated_at || force_import
185
+ snippet.content = File.open(file_path).read
186
+ end
187
+ end
188
+
189
+ # saving
190
+ if snippet.changed?
191
+ if snippet.save
192
+ ComfyPress.logger.warn("[Fixtures] Saved Snippet {#{snippet.identifier}}")
193
+ else
194
+ ComfyPress.logger.warn("[Fixtures] Failed to save Snippet {#{snippet.errors.inspect}}")
195
+ next
196
+ end
197
+ end
198
+ snippet_ids << snippet.id
199
+ end
200
+
201
+ # removing all db entries that are not in fixtures
202
+ site.snippets.where('id NOT IN (?)', snippet_ids).each{ |s| s.destroy }
203
+ ComfyPress.logger.warn('Imported Snippets!')
204
+ end
205
+
206
+ def self.export_layouts(from_site, to_folder = nil)
207
+ return unless site = Cms::Site.find_by_identifier(from_site)
208
+ path = File.join(ComfyPress.config.fixtures_path, (to_folder || site.identifier), 'layouts')
209
+ FileUtils.rm_rf(path)
210
+ FileUtils.mkdir_p(path)
211
+
212
+ site.layouts.each do |layout|
213
+ layout_path = File.join(path, layout.ancestors.reverse.collect{|l| l.identifier}, layout.identifier)
214
+ FileUtils.mkdir_p(layout_path)
215
+
216
+ open(File.join(layout_path, "_#{layout.identifier}.yml"), 'w') do |f|
217
+ f.write({
218
+ 'label' => layout.label,
219
+ 'app_layout' => layout.app_layout,
220
+ 'parent' => layout.parent.try(:identifier),
221
+ 'position' => layout.position
222
+ }.to_yaml)
223
+ end
224
+ open(File.join(layout_path, 'content.html'), 'w') do |f|
225
+ f.write(layout.content)
226
+ end
227
+ open(File.join(layout_path, 'css.css'), 'w') do |f|
228
+ f.write(layout.css)
229
+ end
230
+ open(File.join(layout_path, 'js.js'), 'w') do |f|
231
+ f.write(layout.js)
232
+ end
233
+ end
234
+ end
235
+
236
+ def self.export_pages(from_site, to_folder = nil)
237
+ return unless site = Cms::Site.find_by_identifier(from_site)
238
+ path = File.join(ComfyPress.config.fixtures_path, (to_folder || site.identifier), 'pages')
239
+ FileUtils.rm_rf(path)
240
+ FileUtils.mkdir_p(path)
241
+
242
+ site.pages.each do |page|
243
+ page.slug = 'index' if page.slug.blank?
244
+ page_path = File.join(path, page.ancestors.reverse.collect{|p| p.slug.blank?? 'index' : p.slug}, page.slug)
245
+ FileUtils.mkdir_p(page_path)
246
+
247
+ open(File.join(page_path, "_#{page.slug}.yml"), 'w') do |f|
248
+ f.write({
249
+ 'label' => page.label,
250
+ 'layout' => page.layout.try(:identifier),
251
+ 'parent' => page.parent && (page.parent.slug.present?? page.parent.slug : 'index'),
252
+ 'target_page' => page.target_page.try(:slug),
253
+ 'is_published' => page.is_published,
254
+ 'position' => page.position
255
+ }.to_yaml)
256
+ end
257
+ page.blocks_attributes.each do |block|
258
+ open(File.join(page_path, "#{block[:identifier]}.html"), 'w') do |f|
259
+ f.write(block[:content])
260
+ end
261
+ end
262
+ end
263
+ end
264
+
265
+ def self.export_snippets(from_site, to_folder = nil)
266
+ return unless site = Cms::Site.find_by_identifier(from_site)
267
+ path = File.join(ComfyPress.config.fixtures_path, (to_folder || site.identifier), 'snippets')
268
+ FileUtils.rm_rf(path)
269
+ FileUtils.mkdir_p(path)
270
+
271
+ site.snippets.each do |snippet|
272
+ FileUtils.mkdir_p(snippet_path = File.join(path, snippet.identifier))
273
+ open(File.join(snippet_path, "_#{snippet.identifier}.yml"), 'w') do |f|
274
+ f.write({'label' => snippet.label}.to_yaml)
275
+ end
276
+ open(File.join(snippet_path, 'content.html'), 'w') do |f|
277
+ f.write(snippet.content)
278
+ end
279
+ end
280
+ end
281
+
282
+ protected
283
+
284
+ def self.find_fixtures_path(identifier, dir)
285
+ path = File.join(ComfyPress.config.fixtures_path, identifier, dir)
286
+ File.exists?(path) ? path : nil
287
+ end
288
+
289
+ end
@@ -0,0 +1,97 @@
1
+ class ComfyPress::FormBuilder < FormattedForm::FormBuilder
2
+
3
+ # -- Tag Field Fields -----------------------------------------------------
4
+ def default_tag_field(tag, index, method = :text_field_tag, options = {})
5
+
6
+ label = tag.page.class.human_attribute_name(tag.identifier.to_s)
7
+ css_class = tag.class.to_s.demodulize.underscore
8
+ content = ''
9
+
10
+ case method
11
+ when :file_field_tag
12
+ input_params = {:id => nil}
13
+ name = "page[blocks_attributes][#{index}][content]"
14
+
15
+ if options.delete(:multiple)
16
+ input_params.merge!(:multiple => true)
17
+ name << '[]'
18
+ end
19
+
20
+ content << @template.send(method, name, input_params)
21
+ content << @template.render(:partial => 'cms_admin/files/page_form', :object => tag.block)
22
+ else
23
+ content << @template.send(method, "page[blocks_attributes][#{index}][content]", tag.content, options)
24
+ end
25
+ content << @template.hidden_field_tag("page[blocks_attributes][#{index}][identifier]", tag.identifier, :id => nil)
26
+
27
+ element(label, content.html_safe)
28
+ end
29
+
30
+ def field_date_time(tag, index)
31
+ default_tag_field(tag, index, :text_field_tag, :data => {:datetime => true})
32
+ end
33
+
34
+ def field_integer(tag, index)
35
+ default_tag_field(tag, index, :number_field_tag)
36
+ end
37
+
38
+ def field_string(tag, index)
39
+ default_tag_field(tag, index)
40
+ end
41
+
42
+ def field_text(tag, index)
43
+ default_tag_field(tag, index, :text_area_tag, :data => {:cm_mode => 'text/html'})
44
+ end
45
+
46
+ def field_rich_text(tag, index)
47
+ default_tag_field(tag, index, :text_area_tag, :data => {:rich_text => true})
48
+ end
49
+
50
+ def page_date_time(tag, index)
51
+ default_tag_field(tag, index, :text_field_tag, :data => {:datetime => true})
52
+ end
53
+
54
+ def page_integer(tag, index)
55
+ default_tag_field(tag, index, :number_field_tag)
56
+ end
57
+
58
+ def page_string(tag, index)
59
+ default_tag_field(tag, index)
60
+ end
61
+
62
+ def page_text(tag, index)
63
+ default_tag_field(tag, index, :text_area_tag, :data => {:cm_mode => 'text/html'})
64
+ end
65
+
66
+ def page_rich_text(tag, index)
67
+ default_tag_field(tag, index, :text_area_tag, :data => {:rich_text => true})
68
+ end
69
+
70
+ def page_file(tag, index)
71
+ default_tag_field(tag, index, :file_field_tag)
72
+ end
73
+
74
+ def page_files(tag, index)
75
+ default_tag_field(tag, index, :file_field_tag, :multiple => true)
76
+ end
77
+
78
+ def page_markdown(tag, index)
79
+ default_tag_field(tag, index, :text_area_tag, :data => {:cm_mode => 'text/x-markdown'})
80
+ end
81
+
82
+ def collection(tag, index)
83
+ options = [["---- Select #{tag.collection_class.titleize} ----", nil]] +
84
+ tag.collection_objects.collect do |m|
85
+ [m.send(tag.collection_title), m.send(tag.collection_identifier)]
86
+ end
87
+
88
+ content = @template.select_tag(
89
+ "page[blocks_attributes][#{index}][content]",
90
+ @template.options_for_select(options, :selected => tag.content),
91
+ :id => nil
92
+ )
93
+ content << @template.hidden_field_tag("page[blocks_attributes][#{index}][identifier]", tag.identifier, :id => nil)
94
+ element(tag.identifier.titleize, content, :class => tag.class.to_s.demodulize.underscore )
95
+ end
96
+
97
+ end
@@ -0,0 +1,85 @@
1
+ module ComfyPress::RenderMethods
2
+
3
+ def self.included(base)
4
+
5
+ # If application controller doesn't have template associated with it
6
+ # CMS will attempt to find one. This is so you don't have to explicitly
7
+ # call render :cms_page => '/something'
8
+ base.rescue_from 'ActionView::MissingTemplate' do |e|
9
+ begin
10
+ render :cms_page => request.path
11
+ rescue ComfyPress::MissingPage
12
+ raise e
13
+ end
14
+ end
15
+
16
+ # Now you can render cms_page simply by calling:
17
+ # render :cms_page => '/path/to/page'
18
+ # This way application controllers can use CMS content while populating
19
+ # instance variables that can be used in partials (that are included by
20
+ # by the cms page and/or layout)
21
+ #
22
+ # Or how about not worrying about setting up CMS pages and rendering
23
+ # application view using a CMS layout?
24
+ # render :cms_layout => 'layout_slug', :cms_blocks => {
25
+ # :block_label_a => 'content text',
26
+ # :block_label_b => { :template => 'path/to/template' },
27
+ # :block_label_c => { :partial => 'path/to/partial' }
28
+ # }
29
+ #
30
+ # This way you are populating page block content and rendering
31
+ # an instantialized CMS page.
32
+ #
33
+ # Site is loaded automatically based on the request. However you can force
34
+ # it by passing :cms_site parameter with site's slug. For example:
35
+ # render :cms_page => '/path/to/page', :cms_site => 'default'
36
+ #
37
+ def render(options = {}, locals = {}, &block)
38
+
39
+ if options.is_a?(Hash) && identifier = options.delete(:cms_site)
40
+ unless @cms_site = Cms::Site.find_by_identifier(identifier)
41
+ raise ComfyPress::MissingSite.new(identifier)
42
+ end
43
+ end
44
+
45
+ if options.is_a?(Hash) && path = options.delete(:cms_page)
46
+ @cms_site ||= Cms::Site.find_site(request.host.downcase, request.fullpath)
47
+ if @cms_page = @cms_site && @cms_site.pages.find_by_full_path(path)
48
+ @cms_layout = @cms_page.layout
49
+ cms_app_layout = @cms_layout.try(:app_layout)
50
+ options[:layout] ||= cms_app_layout.blank?? nil : cms_app_layout
51
+ options[:inline] = @cms_page.content
52
+ super(options, locals, &block)
53
+ else
54
+ raise ComfyPress::MissingPage.new(path)
55
+ end
56
+
57
+ elsif options.is_a?(Hash) && identifier = options.delete(:cms_layout)
58
+ @cms_site ||= Cms::Site.find_site(request.host.downcase, request.fullpath)
59
+ if @cms_layout = @cms_site && @cms_site.layouts.find_by_identifier(identifier)
60
+ cms_app_layout = @cms_layout.try(:app_layout)
61
+ cms_page = @cms_site.pages.build(:layout => @cms_layout)
62
+ cms_blocks = options.delete(:cms_blocks) || { :content => render_to_string({ :layout => false }.merge(options)) }
63
+ cms_blocks.each do |identifier, value|
64
+ content = if value.is_a?(Hash)
65
+ render_to_string(value.keys.first.to_sym => value[value.keys.first], :layout => false)
66
+ else
67
+ value.to_s
68
+ end
69
+ cms_page.blocks.build(:identifier => identifier.to_s, :content => content)
70
+ end
71
+ options[:layout] ||= cms_app_layout.blank?? nil : cms_app_layout
72
+ options[:inline] = cms_page.content(true)
73
+ super(options, locals, &block)
74
+ else
75
+ raise ComfyPress::MissingLayout.new(identifier)
76
+ end
77
+
78
+ else
79
+ super(options, locals, &block)
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ ActionController::Base.send :include, ComfyPress::RenderMethods
@@ -0,0 +1,62 @@
1
+ module ComfyPress::Routing
2
+
3
+ def self.admin(options = {})
4
+ options[:path] ||= 'cms-admin'
5
+
6
+ Rails.application.routes.draw do
7
+ namespace :cms_admin, :path => options[:path], :except => :show do
8
+ get '/', :to => 'base#jump'
9
+ resources :sites do
10
+ resources :pages do
11
+ get :form_blocks, :on => :member
12
+ get :toggle_branch, :on => :member
13
+ put :reorder, :on => :collection
14
+ resources :revisions, :only => [:index, :show, :revert] do
15
+ put :revert, :on => :member
16
+ end
17
+ end
18
+ resources :files do
19
+ put :reorder, :on => :collection
20
+ end
21
+ resources :layouts do
22
+ put :reorder, :on => :collection
23
+ resources :revisions, :only => [:index, :show, :revert] do
24
+ put :revert, :on => :member
25
+ end
26
+ end
27
+ resources :snippets do
28
+ put :reorder, :on => :collection
29
+ resources :revisions, :only => [:index, :show, :revert] do
30
+ put :revert, :on => :member
31
+ end
32
+ end
33
+ resources :categories
34
+ resources :menus do
35
+ resources :menu_items
36
+ end
37
+ get 'dialog/:type' => 'dialogs#show', :as => 'dialog'
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ def self.content(options = {})
44
+
45
+ Rails.application.routes.draw do
46
+ namespace :cms_content, :path => options[:path] do
47
+ get 'cms-css/:site_id/:identifier' => :render_css, :as => 'css'
48
+ get 'cms-js/:site_id/:identifier' => :render_js, :as => 'js'
49
+
50
+ if options[:sitemap]
51
+ get '(:cms_path)/sitemap' => :render_sitemap,
52
+ :as => 'sitemap',
53
+ :constraints => {:format => /xml/},
54
+ :format => :xml
55
+ end
56
+
57
+ get '/' => :render_html, :as => 'html', :path => "(*cms_path)"
58
+ end
59
+ end
60
+ end
61
+
62
+ end