trusty-cms 3.1.8 → 3.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -1
  3. data/Gemfile.lock +13 -9
  4. data/app/assets/images/admin/move_higher.png +0 -0
  5. data/app/assets/images/admin/move_lower.png +0 -0
  6. data/app/assets/images/admin/move_to_bottom.png +0 -0
  7. data/app/assets/images/admin/move_to_top.png +0 -0
  8. data/app/assets/images/admin/remove.png +0 -0
  9. data/app/assets/stylesheets/admin/_multi_site_main.scss +85 -0
  10. data/app/assets/stylesheets/admin/_site_chooser.scss +76 -0
  11. data/app/assets/stylesheets/admin/main.scss +3 -0
  12. data/app/controllers/admin/sites_controller.rb +14 -0
  13. data/app/helpers/scoped_helper.rb +19 -0
  14. data/app/helpers/sites_helper.rb +10 -0
  15. data/app/models/site.rb +86 -0
  16. data/app/models/snippet.rb +23 -0
  17. data/app/models/snippet_finder.rb +24 -0
  18. data/app/models/snippet_tags.rb +80 -0
  19. data/app/users/_choose_site.html.haml +8 -0
  20. data/app/views/admin/layouts/_choose_site.html.haml +8 -0
  21. data/app/views/admin/layouts/_site_chooser.html.haml +11 -0
  22. data/app/views/admin/sites/_form.haml +50 -0
  23. data/app/views/admin/sites/edit.haml +7 -0
  24. data/app/views/admin/sites/index.haml +43 -0
  25. data/app/views/admin/sites/new.haml +7 -0
  26. data/app/views/admin/snippets/_choose_site.html.haml +6 -0
  27. data/app/views/{snippets → admin/snippets}/_form.html.haml +0 -0
  28. data/app/views/{snippets → admin/snippets}/_popups.html.haml +0 -0
  29. data/app/views/{snippets → admin/snippets}/edit.html.haml +0 -0
  30. data/app/views/{snippets → admin/snippets}/index.html.haml +0 -0
  31. data/app/views/{snippets → admin/snippets}/new.html.haml +0 -0
  32. data/app/views/{snippets → admin/snippets}/remove.html.haml +0 -0
  33. data/app/views/admin/users/_choose_site.html.haml +8 -0
  34. data/config/application.rb +0 -2
  35. data/config/initializers/trusty_cms_config.rb +6 -0
  36. data/config/routes.rb +8 -0
  37. data/coverage/index.html +3837 -2759
  38. data/db/migrate/006_remove_user_login_index.rb +8 -0
  39. data/db/migrate/010_create_sites.rb +13 -0
  40. data/db/migrate/011_add_order_to_sites.rb +9 -0
  41. data/db/migrate/022_add_admin_fields_to_sites.rb +17 -0
  42. data/db/migrate/023_add_sites.rb +13 -0
  43. data/db/migrate/024_site_abbreviation.rb +9 -0
  44. data/db/migrate/025_recreate_non_unique_index_on_snippets_name.rb +11 -0
  45. data/db/migrate/026_add_site_id_to_pages.rb +24 -0
  46. data/db/migrate/027_add_base_domain_to_sites.rb +9 -0
  47. data/lib/trusty_cms.rb +1 -1
  48. data/spec/dummy/db/schema.rb +20 -2
  49. data/spec/dummy/log/test.log +44621 -0
  50. data/spec/dummy/node_modules/jquery/AUTHORS.txt +301 -0
  51. data/spec/dummy/node_modules/jquery/LICENSE.txt +36 -0
  52. data/spec/dummy/node_modules/jquery/README.md +67 -0
  53. data/spec/dummy/node_modules/jquery/bower.json +14 -0
  54. data/spec/dummy/node_modules/jquery/dist/core.js +476 -0
  55. data/spec/dummy/node_modules/jquery/dist/jquery.js +10253 -0
  56. data/spec/dummy/node_modules/jquery/dist/jquery.min.js +4 -0
  57. data/spec/dummy/node_modules/jquery/dist/jquery.min.map +1 -0
  58. data/spec/dummy/node_modules/jquery/dist/jquery.slim.js +8160 -0
  59. data/spec/dummy/node_modules/jquery/dist/jquery.slim.min.js +4 -0
  60. data/spec/dummy/node_modules/jquery/dist/jquery.slim.min.map +1 -0
  61. data/spec/dummy/node_modules/jquery/external/sizzle/LICENSE.txt +36 -0
  62. data/spec/dummy/node_modules/jquery/external/sizzle/dist/sizzle.js +2272 -0
  63. data/spec/dummy/node_modules/jquery/external/sizzle/dist/sizzle.min.js +3 -0
  64. data/spec/dummy/node_modules/jquery/external/sizzle/dist/sizzle.min.map +1 -0
  65. data/spec/dummy/node_modules/jquery/package.json +97 -0
  66. data/spec/dummy/node_modules/jquery/src/ajax/jsonp.js +102 -0
  67. data/spec/dummy/node_modules/jquery/src/ajax/load.js +76 -0
  68. data/spec/dummy/node_modules/jquery/src/ajax/parseXML.js +30 -0
  69. data/spec/dummy/node_modules/jquery/src/ajax/script.js +77 -0
  70. data/spec/dummy/node_modules/jquery/src/ajax/var/location.js +5 -0
  71. data/spec/dummy/node_modules/jquery/src/ajax/var/nonce.js +7 -0
  72. data/spec/dummy/node_modules/jquery/src/ajax/var/rquery.js +5 -0
  73. data/spec/dummy/node_modules/jquery/src/ajax/xhr.js +169 -0
  74. data/spec/dummy/node_modules/jquery/src/ajax.js +855 -0
  75. data/spec/dummy/node_modules/jquery/src/attributes/attr.js +141 -0
  76. data/spec/dummy/node_modules/jquery/src/attributes/classes.js +174 -0
  77. data/spec/dummy/node_modules/jquery/src/attributes/prop.js +143 -0
  78. data/spec/dummy/node_modules/jquery/src/attributes/support.js +33 -0
  79. data/spec/dummy/node_modules/jquery/src/attributes/val.js +190 -0
  80. data/spec/dummy/node_modules/jquery/src/attributes.js +13 -0
  81. data/spec/dummy/node_modules/jquery/src/callbacks.js +234 -0
  82. data/spec/dummy/node_modules/jquery/src/core/DOMEval.js +16 -0
  83. data/spec/dummy/node_modules/jquery/src/core/access.js +70 -0
  84. data/spec/dummy/node_modules/jquery/src/core/init.js +128 -0
  85. data/spec/dummy/node_modules/jquery/src/core/nodeName.js +13 -0
  86. data/spec/dummy/node_modules/jquery/src/core/parseHTML.js +65 -0
  87. data/spec/dummy/node_modules/jquery/src/core/ready-no-deferred.js +96 -0
  88. data/spec/dummy/node_modules/jquery/src/core/ready.js +86 -0
  89. data/spec/dummy/node_modules/jquery/src/core/readyException.js +13 -0
  90. data/spec/dummy/node_modules/jquery/src/core/stripAndCollapse.js +14 -0
  91. data/spec/dummy/node_modules/jquery/src/core/support.js +20 -0
  92. data/spec/dummy/node_modules/jquery/src/core/var/rsingleTag.js +6 -0
  93. data/spec/dummy/node_modules/jquery/src/core.js +476 -0
  94. data/spec/dummy/node_modules/jquery/src/css/addGetHookIf.js +26 -0
  95. data/spec/dummy/node_modules/jquery/src/css/adjustCSS.js +71 -0
  96. data/spec/dummy/node_modules/jquery/src/css/curCSS.js +65 -0
  97. data/spec/dummy/node_modules/jquery/src/css/hiddenVisibleSelectors.js +15 -0
  98. data/spec/dummy/node_modules/jquery/src/css/showHide.js +105 -0
  99. data/spec/dummy/node_modules/jquery/src/css/support.js +89 -0
  100. data/spec/dummy/node_modules/jquery/src/css/var/cssExpand.js +5 -0
  101. data/spec/dummy/node_modules/jquery/src/css/var/getStyles.js +17 -0
  102. data/spec/dummy/node_modules/jquery/src/css/var/isHiddenWithinTree.js +34 -0
  103. data/spec/dummy/node_modules/jquery/src/css/var/rmargin.js +5 -0
  104. data/spec/dummy/node_modules/jquery/src/css/var/rnumnonpx.js +7 -0
  105. data/spec/dummy/node_modules/jquery/src/css/var/swap.js +26 -0
  106. data/spec/dummy/node_modules/jquery/src/css.js +438 -0
  107. data/spec/dummy/node_modules/jquery/src/data/Data.js +161 -0
  108. data/spec/dummy/node_modules/jquery/src/data/var/acceptData.js +19 -0
  109. data/spec/dummy/node_modules/jquery/src/data/var/dataPriv.js +7 -0
  110. data/spec/dummy/node_modules/jquery/src/data/var/dataUser.js +7 -0
  111. data/spec/dummy/node_modules/jquery/src/data.js +179 -0
  112. data/spec/dummy/node_modules/jquery/src/deferred/exceptionHook.js +21 -0
  113. data/spec/dummy/node_modules/jquery/src/deferred.js +391 -0
  114. data/spec/dummy/node_modules/jquery/src/deprecated.js +40 -0
  115. data/spec/dummy/node_modules/jquery/src/dimensions.js +56 -0
  116. data/spec/dummy/node_modules/jquery/src/effects/Tween.js +123 -0
  117. data/spec/dummy/node_modules/jquery/src/effects/animatedSelector.js +15 -0
  118. data/spec/dummy/node_modules/jquery/src/effects.js +699 -0
  119. data/spec/dummy/node_modules/jquery/src/event/ajax.js +22 -0
  120. data/spec/dummy/node_modules/jquery/src/event/alias.js +29 -0
  121. data/spec/dummy/node_modules/jquery/src/event/focusin.js +55 -0
  122. data/spec/dummy/node_modules/jquery/src/event/support.js +11 -0
  123. data/spec/dummy/node_modules/jquery/src/event/trigger.js +185 -0
  124. data/spec/dummy/node_modules/jquery/src/event.js +746 -0
  125. data/spec/dummy/node_modules/jquery/src/exports/amd.js +26 -0
  126. data/spec/dummy/node_modules/jquery/src/exports/global.js +34 -0
  127. data/spec/dummy/node_modules/jquery/src/jquery.js +41 -0
  128. data/spec/dummy/node_modules/jquery/src/manipulation/_evalUrl.js +23 -0
  129. data/spec/dummy/node_modules/jquery/src/manipulation/buildFragment.js +104 -0
  130. data/spec/dummy/node_modules/jquery/src/manipulation/getAll.js +32 -0
  131. data/spec/dummy/node_modules/jquery/src/manipulation/setGlobalEval.js +22 -0
  132. data/spec/dummy/node_modules/jquery/src/manipulation/support.js +35 -0
  133. data/spec/dummy/node_modules/jquery/src/manipulation/var/rcheckableType.js +5 -0
  134. data/spec/dummy/node_modules/jquery/src/manipulation/var/rscriptType.js +5 -0
  135. data/spec/dummy/node_modules/jquery/src/manipulation/var/rtagName.js +5 -0
  136. data/spec/dummy/node_modules/jquery/src/manipulation/wrapMap.js +29 -0
  137. data/spec/dummy/node_modules/jquery/src/manipulation.js +488 -0
  138. data/spec/dummy/node_modules/jquery/src/offset.js +229 -0
  139. data/spec/dummy/node_modules/jquery/src/queue/delay.js +24 -0
  140. data/spec/dummy/node_modules/jquery/src/queue.js +145 -0
  141. data/spec/dummy/node_modules/jquery/src/selector-native.js +237 -0
  142. data/spec/dummy/node_modules/jquery/src/selector-sizzle.js +19 -0
  143. data/spec/dummy/node_modules/jquery/src/selector.js +3 -0
  144. data/spec/dummy/node_modules/jquery/src/serialize.js +130 -0
  145. data/spec/dummy/node_modules/jquery/src/traversing/findFilter.js +106 -0
  146. data/spec/dummy/node_modules/jquery/src/traversing/var/dir.js +22 -0
  147. data/spec/dummy/node_modules/jquery/src/traversing/var/rneedsContext.js +8 -0
  148. data/spec/dummy/node_modules/jquery/src/traversing/var/siblings.js +17 -0
  149. data/spec/dummy/node_modules/jquery/src/traversing.js +191 -0
  150. data/spec/dummy/node_modules/jquery/src/var/ObjectFunctionString.js +7 -0
  151. data/spec/dummy/node_modules/jquery/src/var/arr.js +5 -0
  152. data/spec/dummy/node_modules/jquery/src/var/class2type.js +6 -0
  153. data/spec/dummy/node_modules/jquery/src/var/concat.js +7 -0
  154. data/spec/dummy/node_modules/jquery/src/var/document.js +5 -0
  155. data/spec/dummy/node_modules/jquery/src/var/documentElement.js +7 -0
  156. data/spec/dummy/node_modules/jquery/src/var/fnToString.js +7 -0
  157. data/spec/dummy/node_modules/jquery/src/var/getProto.js +5 -0
  158. data/spec/dummy/node_modules/jquery/src/var/hasOwn.js +7 -0
  159. data/spec/dummy/node_modules/jquery/src/var/indexOf.js +7 -0
  160. data/spec/dummy/node_modules/jquery/src/var/pnum.js +5 -0
  161. data/spec/dummy/node_modules/jquery/src/var/push.js +7 -0
  162. data/spec/dummy/node_modules/jquery/src/var/rcssNum.js +9 -0
  163. data/spec/dummy/node_modules/jquery/src/var/rnothtmlwhite.js +8 -0
  164. data/spec/dummy/node_modules/jquery/src/var/slice.js +7 -0
  165. data/spec/dummy/node_modules/jquery/src/var/support.js +6 -0
  166. data/spec/dummy/node_modules/jquery/src/var/toString.js +7 -0
  167. data/spec/dummy/node_modules/jquery/src/wrap.js +77 -0
  168. data/spec/dummy/node_modules/jquery-ui-bundle/AUTHORS.txt +333 -0
  169. data/spec/dummy/node_modules/jquery-ui-bundle/LICENSE.txt +43 -0
  170. data/spec/dummy/node_modules/jquery-ui-bundle/external/jquery/jquery.js +11008 -0
  171. data/spec/dummy/node_modules/jquery-ui-bundle/images/ui-icons_444444_256x240.png +0 -0
  172. data/spec/dummy/node_modules/jquery-ui-bundle/images/ui-icons_555555_256x240.png +0 -0
  173. data/spec/dummy/node_modules/jquery-ui-bundle/images/ui-icons_777620_256x240.png +0 -0
  174. data/spec/dummy/node_modules/jquery-ui-bundle/images/ui-icons_777777_256x240.png +0 -0
  175. data/spec/dummy/node_modules/jquery-ui-bundle/images/ui-icons_cc0000_256x240.png +0 -0
  176. data/spec/dummy/node_modules/jquery-ui-bundle/images/ui-icons_ffffff_256x240.png +0 -0
  177. data/spec/dummy/node_modules/jquery-ui-bundle/index.html +559 -0
  178. data/spec/dummy/node_modules/jquery-ui-bundle/jquery-ui.css +1312 -0
  179. data/spec/dummy/node_modules/jquery-ui-bundle/jquery-ui.js +18706 -0
  180. data/spec/dummy/node_modules/jquery-ui-bundle/jquery-ui.min.css +7 -0
  181. data/spec/dummy/node_modules/jquery-ui-bundle/jquery-ui.min.js +13 -0
  182. data/spec/dummy/node_modules/jquery-ui-bundle/jquery-ui.structure.css +886 -0
  183. data/spec/dummy/node_modules/jquery-ui-bundle/jquery-ui.structure.min.css +5 -0
  184. data/spec/dummy/node_modules/jquery-ui-bundle/jquery-ui.theme.css +443 -0
  185. data/spec/dummy/node_modules/jquery-ui-bundle/jquery-ui.theme.min.css +5 -0
  186. data/spec/dummy/node_modules/jquery-ui-bundle/package.json +33 -0
  187. data/spec/dummy/node_modules/jquery-ujs/CONTRIBUTING.md +109 -0
  188. data/spec/dummy/node_modules/jquery-ujs/MIT-LICENSE +20 -0
  189. data/spec/dummy/node_modules/jquery-ujs/README.md +86 -0
  190. data/spec/dummy/node_modules/jquery-ujs/RELEASE.md +23 -0
  191. data/spec/dummy/node_modules/jquery-ujs/bower.json +19 -0
  192. data/spec/dummy/node_modules/jquery-ujs/package.json +26 -0
  193. data/spec/dummy/node_modules/jquery-ujs/src/rails.js +555 -0
  194. data/spec/dummy/tmp/cache/747/A70/TrustyCms%3A%3AConfig +0 -0
  195. data/spec/dummy/tmp/cache/85C/FA0/TrustyCms.cache_mtime +0 -0
  196. data/vendor/extensions/multi-site-extension/lib/multi_site/admin_ui.rb +45 -0
  197. data/vendor/extensions/multi-site-extension/lib/multi_site/application_controller_extensions.rb +40 -0
  198. data/vendor/extensions/multi-site-extension/lib/multi_site/application_controller_filter_extensions.rb +22 -0
  199. data/vendor/extensions/multi-site-extension/lib/multi_site/engine.rb +10 -0
  200. data/vendor/extensions/multi-site-extension/lib/multi_site/page_extensions.rb +81 -0
  201. data/vendor/extensions/multi-site-extension/lib/multi_site/pages_controller_extensions.rb +55 -0
  202. data/vendor/extensions/multi-site-extension/lib/multi_site/resource_controller_extensions.rb +42 -0
  203. data/vendor/extensions/multi-site-extension/lib/multi_site/route_extensions.rb +22 -0
  204. data/vendor/extensions/multi-site-extension/lib/multi_site/route_set_extensions.rb +17 -0
  205. data/vendor/extensions/multi-site-extension/lib/multi_site/scoped_model.rb +133 -0
  206. data/vendor/extensions/multi-site-extension/lib/multi_site/scoped_validation.rb +33 -0
  207. data/vendor/extensions/multi-site-extension/lib/multi_site/site_chooser_helper.rb +14 -0
  208. data/vendor/extensions/multi-site-extension/lib/multi_site/site_controller_extensions.rb +30 -0
  209. data/vendor/extensions/multi-site-extension/lib/tasks/multi_site_extension_tasks.rake +28 -0
  210. data/vendor/extensions/multi-site-extension/lib/tasks/scoped_admin_extension_tasks.rake +28 -0
  211. data/vendor/extensions/multi-site-extension/lib/trusty-multi-site-extension.rb +1 -0
  212. data/vendor/extensions/multi-site-extension/multi_site_extension.rb +61 -0
  213. data/vendor/extensions/snippets-extension/lib/trusty-snippets-extension.rb +0 -0
  214. data/vendor/extensions/snippets-extension/snippets_extension.rb +46 -0
  215. metadata +347 -8
@@ -0,0 +1,81 @@
1
+ # Unlike other scoped classes, there is no site association in the Page class. Instead, Site has a homepage association and Page has some retrieval methods that turn a page request into site information.
2
+
3
+ module MultiSite::PageExtensions
4
+ def self.included(base)
5
+ base.class_eval {
6
+ include InstanceMethods
7
+ alias_method :url_without_sites, :url
8
+ alias_method :url, :url_with_sites
9
+ mattr_accessor :current_site
10
+ belongs_to :site
11
+ before_create :associate_with_site
12
+ }
13
+ base.extend ClassMethods
14
+ class << base
15
+
16
+ def find_by_path(path, live=true)
17
+ root = homepage
18
+ raise Page::MissingRootPageError unless root
19
+ path = root.path if clean_path(path) == "/"
20
+ result = root.find_by_path(path, live)
21
+
22
+ # If the result is a FileNotFoundPage and it
23
+ # doesn't match the current site, try to find one that does.
24
+ if result.is_a?(FileNotFoundPage) && result.site_id != homepage.site_id
25
+ get_site_specific_file_not_found(result)
26
+
27
+ # Otherwise, just go with it.
28
+ else
29
+ result
30
+ end
31
+ end
32
+
33
+ def current_site
34
+ @current_site ||= Site.default
35
+ end
36
+ def current_site=(site)
37
+ @current_site = site
38
+ end
39
+ def clean_path(path)
40
+ "/#{ path.to_s.strip }/".gsub(%r{//+}, '/')
41
+ end
42
+
43
+ # if the result is a FileNotFoundPage, try to find the one for this site.
44
+ # if you can't, return the initial result
45
+ def get_site_specific_file_not_found(result)
46
+ site_file_not_founds = FileNotFoundPage.where(site_id: homepage.site_id)
47
+ site_file_not_founds.any? ? site_file_not_founds.first : result
48
+ end
49
+
50
+ end
51
+ end
52
+
53
+ module InstanceMethods
54
+ def associate_with_site
55
+ self.site_id = self.parent.site.id if self.site_id.nil?
56
+ end
57
+ end
58
+
59
+ module ClassMethods
60
+
61
+ def find_by_slug_for_site(slug)
62
+ self.where(slug: slug, site_id: Page.current_site.id)
63
+ end
64
+
65
+ def homepage
66
+ if current_site.is_a?(Site)
67
+ homepage = self.current_site.homepage
68
+ end
69
+ homepage ||= find_by_parent_id(nil)
70
+ end
71
+ end
72
+
73
+ def url_with_sites
74
+ if parent
75
+ parent.child_url(self)
76
+ else
77
+ "/"
78
+ end
79
+ end
80
+
81
+ end
@@ -0,0 +1,55 @@
1
+ module MultiSite::PagesControllerExtensions
2
+ def self.included(base)
3
+ base.class_eval {
4
+ alias_method :discover_current_site_without_root, :discover_current_site
5
+ alias_method :discover_current_site, :discover_current_site_with_root
6
+
7
+ alias_method :index_without_site, :index
8
+ alias_method :index, :index_with_site
9
+
10
+ alias_method :continue_url_without_site, :continue_url
11
+ alias_method :continue_url, :continue_url_with_site
12
+
13
+ alias_method :remove_without_back, :remove
14
+ alias_method :remove, :remove_with_back
15
+ responses.destroy.default do
16
+ return_url = session[:came_from]
17
+ session[:came_from] = nil
18
+ if model.class == Page or model.class < Page
19
+ redirect_to return_url || admin_pages_url(:site_id => model.site.id)
20
+ else
21
+ redirect_to continue_url(params)
22
+ end
23
+ end
24
+ }
25
+ end
26
+
27
+ # for compatibility with the standard issue of multi_site,
28
+ # a root parameter overrides other ways of setting site
29
+
30
+ def discover_current_site_with_root
31
+ site_from_root || discover_current_site_without_root
32
+ end
33
+
34
+ def site_from_root
35
+ if params[:root] && @homepage = Page.find(params[:root])
36
+ @site = @homepage.root.site
37
+ end
38
+ end
39
+
40
+ def index_with_site
41
+ @site ||= Page.current_site
42
+ @homepage ||= @site.homepage if @site
43
+ @homepage ||= Page.homepage
44
+ response_for :plural
45
+ end
46
+
47
+ def remove_with_back
48
+ session[:came_from] = request.env["HTTP_REFERER"]
49
+ remove_without_back
50
+ end
51
+
52
+ def continue_url_with_site(options={})
53
+ options[:redirect_to] || (params[:continue] ? edit_admin_page_url(model) : admin_pages_url(:site_id => model.site.id))
54
+ end
55
+ end
@@ -0,0 +1,42 @@
1
+ module MultiSite::ResourceControllerExtensions
2
+
3
+ def self.included(base)
4
+ base.class_eval {
5
+ alias_method :discover_current_site_without_input, :discover_current_site
6
+ alias_method :discover_current_site, :discover_current_site_with_input
7
+ }
8
+ end
9
+
10
+ def current_site=(site=nil)
11
+ Page.current_site = site
12
+ set_session_site
13
+ end
14
+
15
+ # among other things this determines whether the site chooser is shown in the submenu
16
+
17
+ def sited_model?
18
+ model_class == Page || model_class.is_site_scoped?
19
+ end
20
+
21
+ protected
22
+
23
+ def discover_current_site_with_input
24
+ site_from_param || site_from_session || discover_current_site_without_input
25
+ end
26
+
27
+ # for interface consistency we want to be able to remember site choices between requests
28
+
29
+ def set_session_site(site_id=nil)
30
+ site_id ||= current_site.id.to_s if current_site.is_a? Site
31
+ session[:site_id] = site_id
32
+ end
33
+
34
+ def site_from_session
35
+ session[:site_id] && Site.find(session[:site_id]) rescue nil
36
+ end
37
+
38
+ def site_from_param
39
+ params[:site_id] && Site.find(params[:site_id]) rescue nil
40
+ end
41
+
42
+ end
@@ -0,0 +1,22 @@
1
+ module MultiSite
2
+ module RouteExtensions
3
+
4
+ def self.included(base)
5
+ base.alias_method :recognition_conditions_without_site, :recognition_conditions
6
+ base.alias_method :recognition_conditions, :recognition_conditions_with_site
7
+ end
8
+
9
+ def recognition_conditions_with_site
10
+ result = recognition_conditions_without_site
11
+ if site_names = conditions.delete(:site)
12
+ domains = [*site_names].map{ |site| Regexp.compile(::Site.find_by_name(site).domain) }
13
+ conditions[:site] = Regexp.union(*domains)
14
+ result << "conditions[:site] === env[:site]"
15
+ end
16
+ result
17
+ end
18
+
19
+ end
20
+ end
21
+
22
+ ActionController::Routing::Route.send :include, MultiSite::RouteExtensions
@@ -0,0 +1,17 @@
1
+ module MultiSite
2
+ module RouteSetExtensions
3
+
4
+ def self.included(base)
5
+ base.alias_method :extract_request_environment_without_site, :extract_request_environment
6
+ base.alias_method :extract_request_environment, :extract_request_environment_with_site
7
+ end
8
+
9
+ def extract_request_environment_with_site(request)
10
+ env = extract_request_environment_without_site(request)
11
+ env.merge! :site => request.host
12
+ end
13
+
14
+ end
15
+ end
16
+
17
+ ActionController::Routing::RouteSet.send :include, MultiSite::RouteSetExtensions
@@ -0,0 +1,133 @@
1
+ module MultiSite
2
+
3
+ module ScopedModel
4
+ def self.included(base)
5
+ base.extend ClassMethods
6
+ end
7
+
8
+ module ClassMethods
9
+ def is_site_scoped?
10
+ false
11
+ end
12
+
13
+ # only option at the moment is :shareable, which we take to mean that sites are optional:
14
+ # if true it causes us not to set the site automatically or to validate its presence,
15
+ # and to extend the scoping conditions so that objects with no site are returned as
16
+ # well as objects with the specified site
17
+ # that is, anything without a site is considered to be shared among all sites
18
+ # the default is false
19
+
20
+ def is_site_scoped(options={})
21
+ return if is_site_scoped?
22
+
23
+ options = {
24
+ :shareable => false
25
+ }.merge(options)
26
+
27
+ class_eval <<-EO
28
+ default_scope {where(site_scope_condition)}
29
+ extend MultiSite::ScopedModel::ScopedClassMethods
30
+ include MultiSite::ScopedModel::ScopedInstanceMethods
31
+ EO
32
+
33
+ belongs_to :site
34
+ Site.send(:has_many, plural_symbol_for_class)
35
+
36
+ before_validation :set_site
37
+ validates_presence_of :site unless options[:shareable]
38
+
39
+ class << self
40
+ attr_accessor :shareable
41
+ alias_method :paginate_without_site, :paginate
42
+ alias_method :paginate, :paginate_with_site
43
+ %w{count average minimum maximum sum}.each do |getter|
44
+ alias_method "#{getter}_without_site".intern, getter.intern
45
+ alias_method getter.intern, "#{getter}_with_site".intern
46
+ end
47
+ end
48
+
49
+ self.shareable = options[:shareable]
50
+ end
51
+ end
52
+
53
+ module ScopedClassMethods
54
+
55
+
56
+ def paginate_with_site(options={})
57
+ return paginate_without_site(options) unless sites?
58
+ where(site_scope_condition) do
59
+ paginate_without_site(options)
60
+ end
61
+ end
62
+
63
+ %w{count average minimum maximum sum}.each do |getter|
64
+ define_method("#{getter}_with_site") do |*args|
65
+ return send("#{getter}_without_site".intern, *args) unless sites?
66
+ with_scope(:find => {:conditions => site_scope_condition}) do
67
+ send "#{getter}_without_site".intern, *args
68
+ end
69
+ end
70
+ end
71
+
72
+ # this only works with :all and :first
73
+ # and should only be used in odd cases like migration.
74
+ def find_without_site(*args)
75
+ options = args.extract_options!
76
+ #set_readonly_option!(options)
77
+
78
+ case args.first
79
+ when :first then find_initial_without_site(options) # defined here
80
+ when :all then all_without_site(options) # already defined by the alias chain
81
+ end
82
+ end
83
+
84
+ def find_initial_without_site(options)
85
+ options.update(:limit => 1)
86
+ all_without_site(options).first
87
+ end
88
+
89
+ def sites?
90
+ Site.table_exists? && Site.several?
91
+ end
92
+
93
+ def current_site!
94
+ raise(ActiveRecord::SiteNotFound, "#{self} is site-scoped but current_site is #{self.current_site.inspect}", caller) if sites? && !self.current_site && !self.is_shareable?
95
+ self.current_site
96
+ end
97
+
98
+ def current_site
99
+ Page.current_site
100
+ end
101
+
102
+ def site_scope_condition
103
+ if self.shareable
104
+ condition = ""
105
+ condition << "#{self.table_name}.site_id = #{self.current_site.id} OR " if self.current_site
106
+ condition << "#{self.table_name}.site_id IS NULL"
107
+ else
108
+ condition = "#{self.table_name}.site_id = #{self.current_site!.id}"
109
+ end
110
+ condition
111
+ end
112
+
113
+ def plural_symbol_for_class
114
+ self.to_s.pluralize.underscore.intern
115
+ end
116
+
117
+ def is_site_scoped?
118
+ true
119
+ end
120
+
121
+ def is_shareable?
122
+ !!self.shareable
123
+ end
124
+ end
125
+
126
+ module ScopedInstanceMethods
127
+ protected
128
+ def set_site
129
+ self.site ||= self.class.current_site! unless self.class.is_shareable?
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,33 @@
1
+ module MultiSite::ScopedValidation
2
+
3
+ def self.included(base)
4
+
5
+ base.class_eval do
6
+ # scoping validations to the site should be very simple
7
+ # all you would normally need is something like this:
8
+ #
9
+ # validates_uniqueness_of :email, :scope => :site_id
10
+ #
11
+ # but if you want to scope core trusty classes, you have a problem:
12
+ # their uniqueness validations have already been declared
13
+ # The only answer is to reach right back and change the validates_uniqueness_of method
14
+ # and to make it more awkward, that has to happen so early that we can't reflect on the site association.
15
+ # Hence the check for a site_id column. It's a hack, but a fairly harmless one.
16
+
17
+ def validates_uniqueness_of_with_site(*attr)
18
+ if table_exists? && column_names.include?('site_id')
19
+ configuration = attr.extract_options!
20
+ configuration[:scope] ||= :site_id
21
+ attr.push(configuration)
22
+ end
23
+ validates_uniqueness_of_without_site(*attr)
24
+ end
25
+
26
+ alias_method :validates_uniqueness_of_without_site, :validates_uniqueness_of
27
+ alias_method :validates_uniqueness_of, :validates_uniqueness_of_with_site
28
+ end
29
+
30
+ end
31
+ end
32
+
33
+ ActiveRecord::Validations::ClassMethods.send :include, MultiSite::ScopedValidation
@@ -0,0 +1,14 @@
1
+ module MultiSite::SiteChooserHelper
2
+
3
+ def sites_chooser_thing
4
+ return "" unless admin? && defined?(Site) && defined?(controller) && controller.sited_model? && controller.template_name == 'index' && Site.several?
5
+ options = Site.all.map{ |site| "<li>" + link_to( site.name, "#{request.path}?site_id=#{site.id}", :class => site == current_site ? 'fg' : '') + "</li>" }.join("")
6
+ chooser = %{<div id="site_chooser">}
7
+ #chooser << link_to("sites", admin_sites_url, {:id => 'show_site_list', :class => 'expandable'})
8
+ chooser << %{<ul id="nav"><li>Current Site: #{current_site.name}}
9
+ chooser << %{<ul class="expansion">#{options}</ul></li></ul>}
10
+ chooser << %{</div>}
11
+ chooser
12
+ end
13
+
14
+ end
@@ -0,0 +1,30 @@
1
+ module MultiSite::SiteControllerExtensions
2
+ def self.included(base)
3
+ base.class_eval do
4
+ before_action :set_site
5
+ alias_method :process_page_without_home_path, :process_page
6
+ alias_method :process_page, :process_page_with_home_path
7
+ end
8
+ end
9
+
10
+ # If it's a file not found page and the path doesn't include
11
+ # the site's homepage path, try redirecting to include it.
12
+ def process_page_with_home_path(page)
13
+ homepage = Page.current_site.homepage
14
+ if page.is_a?(FileNotFoundPage) && !params[:url].include?(homepage.slug)
15
+ if homepage.slug != "/"
16
+ false if redirect_to "/#{homepage.slug}/#{params[:url]}"
17
+ else
18
+ process_page_without_home_path(page)
19
+ end
20
+ else
21
+ process_page_without_home_path(page)
22
+ end
23
+
24
+ end
25
+
26
+ def set_site
27
+ Page.current_site = Site.find_for_host(request.host)
28
+ true
29
+ end
30
+ end
@@ -0,0 +1,28 @@
1
+ namespace :trusty do
2
+ namespace :extensions do
3
+ namespace :multi_site do
4
+
5
+ desc "Runs the migration of the Multi Site extension"
6
+ task :migrate => :environment do
7
+ require 'trusty_cms/extension_migrator'
8
+ if ENV["VERSION"]
9
+ MultiSiteExtension.migrator.migrate(ENV["VERSION"].to_i)
10
+ else
11
+ MultiSiteExtension.migrator.migrate
12
+ end
13
+ end
14
+
15
+ desc "Copies public assets of the Multi Site to the instance public/ directory."
16
+ task :update => :environment do
17
+ is_svn_or_dir = proc {|path| path =~ /\.svn/ || File.directory?(path) }
18
+ puts "Copying assets from MultiSiteExtension"
19
+ Dir[MultiSiteExtension.root + "/public/**/*"].reject(&is_svn_or_dir).each do |file|
20
+ path = file.sub(MultiSiteExtension.root, '')
21
+ directory = File.dirname(path)
22
+ mkdir_p RAILS_ROOT + directory, :verbose => false
23
+ cp file, RAILS_ROOT + path, :verbose => false
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ namespace :radiant do
2
+ namespace :extensions do
3
+ namespace :scoped_admin do
4
+
5
+ desc "Runs the migration of the Scoped Admin extension"
6
+ task :migrate => :environment do
7
+ require 'radiant/extension_migrator'
8
+ if ENV["VERSION"]
9
+ ScopedAdminExtension.migrator.migrate(ENV["VERSION"].to_i)
10
+ else
11
+ ScopedAdminExtension.migrator.migrate
12
+ end
13
+ end
14
+
15
+ desc "Copies public assets of the Scoped Admin to the instance public/ directory."
16
+ task :update => :environment do
17
+ is_svn_or_dir = proc {|path| path =~ /\.svn/ || File.directory?(path) }
18
+ puts "Copying assets from ScopedAdminExtension"
19
+ Dir[ScopedAdminExtension.root + "/public/**/*"].reject(&is_svn_or_dir).each do |file|
20
+ path = file.sub(ScopedAdminExtension.root, '')
21
+ directory = File.dirname(path)
22
+ mkdir_p RAILS_ROOT + directory
23
+ cp file, RAILS_ROOT + path
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,61 @@
1
+ require_dependency 'application_controller'
2
+
3
+ class MultiSiteExtension < TrustyCms::Extension
4
+ version "3.0.2"
5
+ description %{ Enables virtual sites to be created with associated domain names.
6
+ Also scopes the sitemap view to any given page (or the root of an
7
+ individual site) and allows model classes to be scoped by site. }
8
+ url "http://trustarts.org/"
9
+
10
+
11
+ def activate
12
+
13
+ # Model extensions
14
+ ActiveRecord::Base.send :include, MultiSite::ScopedModel
15
+ Page.send :include, MultiSite::PageExtensions
16
+
17
+ # Controller extensions
18
+ ApplicationController.send :include, MultiSite::ApplicationControllerExtensions
19
+ Admin::ResourceController.send :include, MultiSite::ApplicationControllerExtensions
20
+ ApplicationController.send :include, MultiSite::ApplicationControllerFilterExtensions
21
+
22
+ #ActionController::Base.send :include, MultiSite::ApplicationControllerExtensions
23
+ SiteController.send :include, MultiSite::SiteControllerExtensions
24
+ Admin::ResourceController.send :include, MultiSite::ResourceControllerExtensions
25
+ Admin::PagesController.send :include, MultiSite::PagesControllerExtensions
26
+ Admin::ResourceController.send :helper, MultiSite::SiteChooserHelper
27
+ Admin::PagesController.send :helper, MultiSite::SiteChooserHelper
28
+ admin.layouts.index.add(:before_nav, "admin/layouts/site_chooser")
29
+ admin.pages.index.add(:before_nav, "admin/layouts/site_chooser")
30
+ admin.snippets.index.add(:before_nav, "admin/layouts/site_chooser")
31
+ Layout.send :is_site_scoped
32
+ Snippet.send :is_site_scoped
33
+ User.send :is_site_scoped, :shareable => true
34
+ ApplicationHelper.send :include, ScopedHelper
35
+
36
+ unless admin.users.edit.form && admin.users.edit.form.include?('choose_site')
37
+ admin.users.edit.add :form, "choose_site", :after => "edit_roles"
38
+ admin.layouts.edit.add :form, "choose_site", :before => "edit_timestamp"
39
+ admin.snippets.edit.add :form, "choose_site", :before => "edit_filter" unless admin.snippets.edit.form.include?("choose_site")
40
+ end
41
+
42
+
43
+ unless defined? admin.site
44
+ TrustyCms::AdminUI.send :include, MultiSite::AdminUI
45
+ admin.site = TrustyCms::AdminUI.load_default_site_regions
46
+ end
47
+
48
+ if respond_to?(:tab)
49
+ tab("Settings") do
50
+ add_item "Sites", "/admin/sites", :after => "Extensions", :visibility => [:admin]
51
+ end
52
+ else
53
+ admin.tabs.add "Sites", "/admin/sites", :visibility => [:admin]
54
+ end
55
+ end
56
+
57
+ def deactivate
58
+ end
59
+ end
60
+
61
+ class ActiveRecord::SiteNotFound < Exception; end
@@ -0,0 +1,46 @@
1
+ class SnippetsExtension < TrustyCms::Extension
2
+
3
+ def activate
4
+ if defined?(Radiant::Exporter)
5
+ TrustyCms::Exporter.exportable_models << Snippet
6
+ TrustyCms::Exporter.template_models << Snippet
7
+ end
8
+
9
+ Page.class_eval do
10
+ include SnippetTags
11
+ end
12
+
13
+ TrustyCms::AdminUI.class_eval do
14
+ attr_accessor :snippet
15
+
16
+ alias_method :snippets, :snippet
17
+
18
+ def load_default_snippet_regions
19
+ OpenStruct.new.tap do |snippet|
20
+ snippet.edit = TrustyCms::AdminUI::RegionSet.new do |edit|
21
+ edit.main.concat %w{edit_header edit_form}
22
+ edit.form.concat %w{edit_title edit_content edit_filter}
23
+ edit.form_bottom.concat %w{edit_buttons edit_timestamp}
24
+ end
25
+ snippet.index = TrustyCms::AdminUI::RegionSet.new do |index|
26
+ index.top.concat %w{}
27
+ index.thead.concat %w{title_header actions_header}
28
+ index.tbody.concat %w{title_cell actions_cell}
29
+ index.bottom.concat %w{new_button}
30
+ end
31
+ snippet.new = snippet.edit
32
+ snippet.remove = snippet.edit
33
+ end
34
+ end
35
+ end
36
+
37
+ admin.snippet ||= TrustyCms::AdminUI.load_default_snippet_regions
38
+
39
+ UserActionObserver.instance.send :add_observer!, ::Snippet
40
+
41
+ tab 'Design' do
42
+ add_item "Snippets", "/admin/snippets"
43
+ end
44
+
45
+ end
46
+ end