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.
- checksums.yaml +4 -4
- data/Gemfile +2 -1
- data/Gemfile.lock +13 -9
- data/app/assets/images/admin/move_higher.png +0 -0
- data/app/assets/images/admin/move_lower.png +0 -0
- data/app/assets/images/admin/move_to_bottom.png +0 -0
- data/app/assets/images/admin/move_to_top.png +0 -0
- data/app/assets/images/admin/remove.png +0 -0
- data/app/assets/stylesheets/admin/_multi_site_main.scss +85 -0
- data/app/assets/stylesheets/admin/_site_chooser.scss +76 -0
- data/app/assets/stylesheets/admin/main.scss +3 -0
- data/app/controllers/admin/sites_controller.rb +14 -0
- data/app/helpers/scoped_helper.rb +19 -0
- data/app/helpers/sites_helper.rb +10 -0
- data/app/models/site.rb +86 -0
- data/app/models/snippet.rb +23 -0
- data/app/models/snippet_finder.rb +24 -0
- data/app/models/snippet_tags.rb +80 -0
- data/app/users/_choose_site.html.haml +8 -0
- data/app/views/admin/layouts/_choose_site.html.haml +8 -0
- data/app/views/admin/layouts/_site_chooser.html.haml +11 -0
- data/app/views/admin/sites/_form.haml +50 -0
- data/app/views/admin/sites/edit.haml +7 -0
- data/app/views/admin/sites/index.haml +43 -0
- data/app/views/admin/sites/new.haml +7 -0
- data/app/views/admin/snippets/_choose_site.html.haml +6 -0
- data/app/views/{snippets → admin/snippets}/_form.html.haml +0 -0
- data/app/views/{snippets → admin/snippets}/_popups.html.haml +0 -0
- data/app/views/{snippets → admin/snippets}/edit.html.haml +0 -0
- data/app/views/{snippets → admin/snippets}/index.html.haml +0 -0
- data/app/views/{snippets → admin/snippets}/new.html.haml +0 -0
- data/app/views/{snippets → admin/snippets}/remove.html.haml +0 -0
- data/app/views/admin/users/_choose_site.html.haml +8 -0
- data/config/application.rb +0 -2
- data/config/initializers/trusty_cms_config.rb +6 -0
- data/config/routes.rb +8 -0
- data/coverage/index.html +3837 -2759
- data/db/migrate/006_remove_user_login_index.rb +8 -0
- data/db/migrate/010_create_sites.rb +13 -0
- data/db/migrate/011_add_order_to_sites.rb +9 -0
- data/db/migrate/022_add_admin_fields_to_sites.rb +17 -0
- data/db/migrate/023_add_sites.rb +13 -0
- data/db/migrate/024_site_abbreviation.rb +9 -0
- data/db/migrate/025_recreate_non_unique_index_on_snippets_name.rb +11 -0
- data/db/migrate/026_add_site_id_to_pages.rb +24 -0
- data/db/migrate/027_add_base_domain_to_sites.rb +9 -0
- data/lib/trusty_cms.rb +1 -1
- data/spec/dummy/db/schema.rb +20 -2
- data/spec/dummy/log/test.log +44621 -0
- data/spec/dummy/node_modules/jquery/AUTHORS.txt +301 -0
- data/spec/dummy/node_modules/jquery/LICENSE.txt +36 -0
- data/spec/dummy/node_modules/jquery/README.md +67 -0
- data/spec/dummy/node_modules/jquery/bower.json +14 -0
- data/spec/dummy/node_modules/jquery/dist/core.js +476 -0
- data/spec/dummy/node_modules/jquery/dist/jquery.js +10253 -0
- data/spec/dummy/node_modules/jquery/dist/jquery.min.js +4 -0
- data/spec/dummy/node_modules/jquery/dist/jquery.min.map +1 -0
- data/spec/dummy/node_modules/jquery/dist/jquery.slim.js +8160 -0
- data/spec/dummy/node_modules/jquery/dist/jquery.slim.min.js +4 -0
- data/spec/dummy/node_modules/jquery/dist/jquery.slim.min.map +1 -0
- data/spec/dummy/node_modules/jquery/external/sizzle/LICENSE.txt +36 -0
- data/spec/dummy/node_modules/jquery/external/sizzle/dist/sizzle.js +2272 -0
- data/spec/dummy/node_modules/jquery/external/sizzle/dist/sizzle.min.js +3 -0
- data/spec/dummy/node_modules/jquery/external/sizzle/dist/sizzle.min.map +1 -0
- data/spec/dummy/node_modules/jquery/package.json +97 -0
- data/spec/dummy/node_modules/jquery/src/ajax/jsonp.js +102 -0
- data/spec/dummy/node_modules/jquery/src/ajax/load.js +76 -0
- data/spec/dummy/node_modules/jquery/src/ajax/parseXML.js +30 -0
- data/spec/dummy/node_modules/jquery/src/ajax/script.js +77 -0
- data/spec/dummy/node_modules/jquery/src/ajax/var/location.js +5 -0
- data/spec/dummy/node_modules/jquery/src/ajax/var/nonce.js +7 -0
- data/spec/dummy/node_modules/jquery/src/ajax/var/rquery.js +5 -0
- data/spec/dummy/node_modules/jquery/src/ajax/xhr.js +169 -0
- data/spec/dummy/node_modules/jquery/src/ajax.js +855 -0
- data/spec/dummy/node_modules/jquery/src/attributes/attr.js +141 -0
- data/spec/dummy/node_modules/jquery/src/attributes/classes.js +174 -0
- data/spec/dummy/node_modules/jquery/src/attributes/prop.js +143 -0
- data/spec/dummy/node_modules/jquery/src/attributes/support.js +33 -0
- data/spec/dummy/node_modules/jquery/src/attributes/val.js +190 -0
- data/spec/dummy/node_modules/jquery/src/attributes.js +13 -0
- data/spec/dummy/node_modules/jquery/src/callbacks.js +234 -0
- data/spec/dummy/node_modules/jquery/src/core/DOMEval.js +16 -0
- data/spec/dummy/node_modules/jquery/src/core/access.js +70 -0
- data/spec/dummy/node_modules/jquery/src/core/init.js +128 -0
- data/spec/dummy/node_modules/jquery/src/core/nodeName.js +13 -0
- data/spec/dummy/node_modules/jquery/src/core/parseHTML.js +65 -0
- data/spec/dummy/node_modules/jquery/src/core/ready-no-deferred.js +96 -0
- data/spec/dummy/node_modules/jquery/src/core/ready.js +86 -0
- data/spec/dummy/node_modules/jquery/src/core/readyException.js +13 -0
- data/spec/dummy/node_modules/jquery/src/core/stripAndCollapse.js +14 -0
- data/spec/dummy/node_modules/jquery/src/core/support.js +20 -0
- data/spec/dummy/node_modules/jquery/src/core/var/rsingleTag.js +6 -0
- data/spec/dummy/node_modules/jquery/src/core.js +476 -0
- data/spec/dummy/node_modules/jquery/src/css/addGetHookIf.js +26 -0
- data/spec/dummy/node_modules/jquery/src/css/adjustCSS.js +71 -0
- data/spec/dummy/node_modules/jquery/src/css/curCSS.js +65 -0
- data/spec/dummy/node_modules/jquery/src/css/hiddenVisibleSelectors.js +15 -0
- data/spec/dummy/node_modules/jquery/src/css/showHide.js +105 -0
- data/spec/dummy/node_modules/jquery/src/css/support.js +89 -0
- data/spec/dummy/node_modules/jquery/src/css/var/cssExpand.js +5 -0
- data/spec/dummy/node_modules/jquery/src/css/var/getStyles.js +17 -0
- data/spec/dummy/node_modules/jquery/src/css/var/isHiddenWithinTree.js +34 -0
- data/spec/dummy/node_modules/jquery/src/css/var/rmargin.js +5 -0
- data/spec/dummy/node_modules/jquery/src/css/var/rnumnonpx.js +7 -0
- data/spec/dummy/node_modules/jquery/src/css/var/swap.js +26 -0
- data/spec/dummy/node_modules/jquery/src/css.js +438 -0
- data/spec/dummy/node_modules/jquery/src/data/Data.js +161 -0
- data/spec/dummy/node_modules/jquery/src/data/var/acceptData.js +19 -0
- data/spec/dummy/node_modules/jquery/src/data/var/dataPriv.js +7 -0
- data/spec/dummy/node_modules/jquery/src/data/var/dataUser.js +7 -0
- data/spec/dummy/node_modules/jquery/src/data.js +179 -0
- data/spec/dummy/node_modules/jquery/src/deferred/exceptionHook.js +21 -0
- data/spec/dummy/node_modules/jquery/src/deferred.js +391 -0
- data/spec/dummy/node_modules/jquery/src/deprecated.js +40 -0
- data/spec/dummy/node_modules/jquery/src/dimensions.js +56 -0
- data/spec/dummy/node_modules/jquery/src/effects/Tween.js +123 -0
- data/spec/dummy/node_modules/jquery/src/effects/animatedSelector.js +15 -0
- data/spec/dummy/node_modules/jquery/src/effects.js +699 -0
- data/spec/dummy/node_modules/jquery/src/event/ajax.js +22 -0
- data/spec/dummy/node_modules/jquery/src/event/alias.js +29 -0
- data/spec/dummy/node_modules/jquery/src/event/focusin.js +55 -0
- data/spec/dummy/node_modules/jquery/src/event/support.js +11 -0
- data/spec/dummy/node_modules/jquery/src/event/trigger.js +185 -0
- data/spec/dummy/node_modules/jquery/src/event.js +746 -0
- data/spec/dummy/node_modules/jquery/src/exports/amd.js +26 -0
- data/spec/dummy/node_modules/jquery/src/exports/global.js +34 -0
- data/spec/dummy/node_modules/jquery/src/jquery.js +41 -0
- data/spec/dummy/node_modules/jquery/src/manipulation/_evalUrl.js +23 -0
- data/spec/dummy/node_modules/jquery/src/manipulation/buildFragment.js +104 -0
- data/spec/dummy/node_modules/jquery/src/manipulation/getAll.js +32 -0
- data/spec/dummy/node_modules/jquery/src/manipulation/setGlobalEval.js +22 -0
- data/spec/dummy/node_modules/jquery/src/manipulation/support.js +35 -0
- data/spec/dummy/node_modules/jquery/src/manipulation/var/rcheckableType.js +5 -0
- data/spec/dummy/node_modules/jquery/src/manipulation/var/rscriptType.js +5 -0
- data/spec/dummy/node_modules/jquery/src/manipulation/var/rtagName.js +5 -0
- data/spec/dummy/node_modules/jquery/src/manipulation/wrapMap.js +29 -0
- data/spec/dummy/node_modules/jquery/src/manipulation.js +488 -0
- data/spec/dummy/node_modules/jquery/src/offset.js +229 -0
- data/spec/dummy/node_modules/jquery/src/queue/delay.js +24 -0
- data/spec/dummy/node_modules/jquery/src/queue.js +145 -0
- data/spec/dummy/node_modules/jquery/src/selector-native.js +237 -0
- data/spec/dummy/node_modules/jquery/src/selector-sizzle.js +19 -0
- data/spec/dummy/node_modules/jquery/src/selector.js +3 -0
- data/spec/dummy/node_modules/jquery/src/serialize.js +130 -0
- data/spec/dummy/node_modules/jquery/src/traversing/findFilter.js +106 -0
- data/spec/dummy/node_modules/jquery/src/traversing/var/dir.js +22 -0
- data/spec/dummy/node_modules/jquery/src/traversing/var/rneedsContext.js +8 -0
- data/spec/dummy/node_modules/jquery/src/traversing/var/siblings.js +17 -0
- data/spec/dummy/node_modules/jquery/src/traversing.js +191 -0
- data/spec/dummy/node_modules/jquery/src/var/ObjectFunctionString.js +7 -0
- data/spec/dummy/node_modules/jquery/src/var/arr.js +5 -0
- data/spec/dummy/node_modules/jquery/src/var/class2type.js +6 -0
- data/spec/dummy/node_modules/jquery/src/var/concat.js +7 -0
- data/spec/dummy/node_modules/jquery/src/var/document.js +5 -0
- data/spec/dummy/node_modules/jquery/src/var/documentElement.js +7 -0
- data/spec/dummy/node_modules/jquery/src/var/fnToString.js +7 -0
- data/spec/dummy/node_modules/jquery/src/var/getProto.js +5 -0
- data/spec/dummy/node_modules/jquery/src/var/hasOwn.js +7 -0
- data/spec/dummy/node_modules/jquery/src/var/indexOf.js +7 -0
- data/spec/dummy/node_modules/jquery/src/var/pnum.js +5 -0
- data/spec/dummy/node_modules/jquery/src/var/push.js +7 -0
- data/spec/dummy/node_modules/jquery/src/var/rcssNum.js +9 -0
- data/spec/dummy/node_modules/jquery/src/var/rnothtmlwhite.js +8 -0
- data/spec/dummy/node_modules/jquery/src/var/slice.js +7 -0
- data/spec/dummy/node_modules/jquery/src/var/support.js +6 -0
- data/spec/dummy/node_modules/jquery/src/var/toString.js +7 -0
- data/spec/dummy/node_modules/jquery/src/wrap.js +77 -0
- data/spec/dummy/node_modules/jquery-ui-bundle/AUTHORS.txt +333 -0
- data/spec/dummy/node_modules/jquery-ui-bundle/LICENSE.txt +43 -0
- data/spec/dummy/node_modules/jquery-ui-bundle/external/jquery/jquery.js +11008 -0
- data/spec/dummy/node_modules/jquery-ui-bundle/images/ui-icons_444444_256x240.png +0 -0
- data/spec/dummy/node_modules/jquery-ui-bundle/images/ui-icons_555555_256x240.png +0 -0
- data/spec/dummy/node_modules/jquery-ui-bundle/images/ui-icons_777620_256x240.png +0 -0
- data/spec/dummy/node_modules/jquery-ui-bundle/images/ui-icons_777777_256x240.png +0 -0
- data/spec/dummy/node_modules/jquery-ui-bundle/images/ui-icons_cc0000_256x240.png +0 -0
- data/spec/dummy/node_modules/jquery-ui-bundle/images/ui-icons_ffffff_256x240.png +0 -0
- data/spec/dummy/node_modules/jquery-ui-bundle/index.html +559 -0
- data/spec/dummy/node_modules/jquery-ui-bundle/jquery-ui.css +1312 -0
- data/spec/dummy/node_modules/jquery-ui-bundle/jquery-ui.js +18706 -0
- data/spec/dummy/node_modules/jquery-ui-bundle/jquery-ui.min.css +7 -0
- data/spec/dummy/node_modules/jquery-ui-bundle/jquery-ui.min.js +13 -0
- data/spec/dummy/node_modules/jquery-ui-bundle/jquery-ui.structure.css +886 -0
- data/spec/dummy/node_modules/jquery-ui-bundle/jquery-ui.structure.min.css +5 -0
- data/spec/dummy/node_modules/jquery-ui-bundle/jquery-ui.theme.css +443 -0
- data/spec/dummy/node_modules/jquery-ui-bundle/jquery-ui.theme.min.css +5 -0
- data/spec/dummy/node_modules/jquery-ui-bundle/package.json +33 -0
- data/spec/dummy/node_modules/jquery-ujs/CONTRIBUTING.md +109 -0
- data/spec/dummy/node_modules/jquery-ujs/MIT-LICENSE +20 -0
- data/spec/dummy/node_modules/jquery-ujs/README.md +86 -0
- data/spec/dummy/node_modules/jquery-ujs/RELEASE.md +23 -0
- data/spec/dummy/node_modules/jquery-ujs/bower.json +19 -0
- data/spec/dummy/node_modules/jquery-ujs/package.json +26 -0
- data/spec/dummy/node_modules/jquery-ujs/src/rails.js +555 -0
- data/spec/dummy/tmp/cache/747/A70/TrustyCms%3A%3AConfig +0 -0
- data/spec/dummy/tmp/cache/85C/FA0/TrustyCms.cache_mtime +0 -0
- data/vendor/extensions/multi-site-extension/lib/multi_site/admin_ui.rb +45 -0
- data/vendor/extensions/multi-site-extension/lib/multi_site/application_controller_extensions.rb +40 -0
- data/vendor/extensions/multi-site-extension/lib/multi_site/application_controller_filter_extensions.rb +22 -0
- data/vendor/extensions/multi-site-extension/lib/multi_site/engine.rb +10 -0
- data/vendor/extensions/multi-site-extension/lib/multi_site/page_extensions.rb +81 -0
- data/vendor/extensions/multi-site-extension/lib/multi_site/pages_controller_extensions.rb +55 -0
- data/vendor/extensions/multi-site-extension/lib/multi_site/resource_controller_extensions.rb +42 -0
- data/vendor/extensions/multi-site-extension/lib/multi_site/route_extensions.rb +22 -0
- data/vendor/extensions/multi-site-extension/lib/multi_site/route_set_extensions.rb +17 -0
- data/vendor/extensions/multi-site-extension/lib/multi_site/scoped_model.rb +133 -0
- data/vendor/extensions/multi-site-extension/lib/multi_site/scoped_validation.rb +33 -0
- data/vendor/extensions/multi-site-extension/lib/multi_site/site_chooser_helper.rb +14 -0
- data/vendor/extensions/multi-site-extension/lib/multi_site/site_controller_extensions.rb +30 -0
- data/vendor/extensions/multi-site-extension/lib/tasks/multi_site_extension_tasks.rake +28 -0
- data/vendor/extensions/multi-site-extension/lib/tasks/scoped_admin_extension_tasks.rake +28 -0
- data/vendor/extensions/multi-site-extension/lib/trusty-multi-site-extension.rb +1 -0
- data/vendor/extensions/multi-site-extension/multi_site_extension.rb +61 -0
- data/vendor/extensions/snippets-extension/lib/trusty-snippets-extension.rb +0 -0
- data/vendor/extensions/snippets-extension/snippets_extension.rb +46 -0
- 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 @@
|
|
|
1
|
+
# Nothing to see here
|
|
@@ -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
|
|
File without changes
|
|
@@ -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
|