cmor_cms 0.0.1.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +88 -0
- data/Rakefile +19 -0
- data/app/assets/javascripts/cmor/cms/application.js +1 -0
- data/app/assets/javascripts/cmor/cms/application/navigations.js.coffee +4 -0
- data/app/assets/javascripts/cmor_cms.js +1 -0
- data/app/assets/stylesheets/cmor/cms/application.css +3 -0
- data/app/assets/stylesheets/cmor/cms/application/keep.css +0 -0
- data/app/assets/stylesheets/cmor_cms.css +3 -0
- data/app/controllers/cmor/cms/page_controller.rb +54 -0
- data/app/importers/navigation.rb +27 -0
- data/app/importers/navigation_item.rb +61 -0
- data/app/importers/page.rb +38 -0
- data/app/models/cmor/cms/content_block.rb +14 -0
- data/app/models/cmor/cms/content_box.rb +12 -0
- data/app/models/cmor/cms/navigation.rb +18 -0
- data/app/models/cmor/cms/navigation_item.rb +86 -0
- data/app/models/cmor/cms/page.rb +29 -0
- data/app/models/cmor/cms/partial.rb +15 -0
- data/app/models/cmor/cms/template.rb +13 -0
- data/app/models/concerns/model/cmor/cms/navigation_item/properties_concern.rb +25 -0
- data/app/resolvers/cmor/cms/page_resolver.rb +61 -0
- data/app/resolvers/cmor/cms/partial_resolver.rb +29 -0
- data/app/resolvers/cmor/cms/template_resolver.rb +29 -0
- data/app/services/cmor/cms/add_homepages_service.rb +79 -0
- data/app/services/cmor/cms/create_navigation_service.rb +49 -0
- data/app/services/cmor/cms/import_partials_service.rb +126 -0
- data/app/template_handlers/action_view/template/handlers/textile.rb +26 -0
- data/app/view_helpers/cmor/cms/application_view_helper.rb +36 -0
- data/app/view_helpers/cmor/cms/navigation_view_helper.rb +87 -0
- data/app/view_helpers/cmor/cms/page_view_helper.rb +34 -0
- data/app/views/cmor/cms/_link_to_top.html.erb +5 -0
- data/app/views/cmor/cms/page/fallback.html.erb +2 -0
- data/app/views/cmor/cms/page/fallback.txt +1 -0
- data/config/initializers/assets.rb +1 -0
- data/config/initializers/mime_types.rb +1 -0
- data/config/initializers/simple_navigation.rb +1 -0
- data/config/initializers/textile_support.rb +3 -0
- data/config/locales/de.yml +140 -0
- data/config/locales/en.yml +140 -0
- data/config/navigation.rb +0 -0
- data/config/routes.rb +6 -0
- data/db/migrate/002_create_cmor_cms_pages.rb +17 -0
- data/db/migrate/003_create_cmor_cms_templates.rb +14 -0
- data/db/migrate/004_create_cmor_cms_partials.rb +15 -0
- data/db/migrate/005_create_cmor_cms_navigations.rb +13 -0
- data/db/migrate/006_create_cmor_cms_navigation_items.rb +29 -0
- data/db/migrate/007_create_cmor_cms_content_boxes.rb +9 -0
- data/db/migrate/008_create_cmor_cms_content_blocks.rb +15 -0
- data/lib/cmor/cms.rb +23 -0
- data/lib/cmor/cms/action_view/template_patch.rb +18 -0
- data/lib/cmor/cms/action_view/template_renderer_patch.rb +45 -0
- data/lib/cmor/cms/configuration.rb +35 -0
- data/lib/cmor/cms/controller_extensions/page_resolver.rb +12 -0
- data/lib/cmor/cms/controller_extensions/partial_resolver.rb +12 -0
- data/lib/cmor/cms/controller_extensions/template_resolver.rb +12 -0
- data/lib/cmor/cms/database_resolver.rb +99 -0
- data/lib/cmor/cms/database_template.rb +70 -0
- data/lib/cmor/cms/engine.rb +16 -0
- data/lib/cmor/cms/version.rb +7 -0
- data/lib/cmor_cms.rb +8 -0
- data/lib/generators/cmor/cms/install/install_generator.rb +34 -0
- data/lib/generators/cmor/cms/install/templates/initializer.rb +53 -0
- data/lib/generators/cmor/cms/install/templates/routes.source +4 -0
- data/lib/tasks/cmor_cms_tasks.rake +15 -0
- data/spec/factories/cmor/cms/content_block.rb +7 -0
- data/spec/factories/cmor/cms/content_box.rb +5 -0
- data/spec/factories/cmor/cms/navigation_items.rb +16 -0
- data/spec/factories/cmor/cms/navigations.rb +6 -0
- data/spec/factories/cmor/cms/pages.rb +8 -0
- data/spec/factories/cmor/cms/partials.rb +7 -0
- data/spec/factories/cmor/cms/templates.rb +7 -0
- metadata +465 -0
File without changes
|
data/config/routes.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
class CreateCmorCmsPages < ActiveRecord::Migration[4.2]
|
2
|
+
def change
|
3
|
+
create_table :cmor_cms_pages do |t|
|
4
|
+
t.string :basename
|
5
|
+
t.string :pathname
|
6
|
+
t.string :title
|
7
|
+
t.text :meta_description
|
8
|
+
t.text :body
|
9
|
+
t.string :layout
|
10
|
+
t.string :locale
|
11
|
+
t.string :format
|
12
|
+
t.string :handler
|
13
|
+
|
14
|
+
t.timestamps
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreateCmorCmsTemplates < ActiveRecord::Migration[4.2]
|
2
|
+
def change
|
3
|
+
create_table :cmor_cms_templates do |t|
|
4
|
+
t.string :basename
|
5
|
+
t.string :pathname
|
6
|
+
t.text :body
|
7
|
+
t.string :locale
|
8
|
+
t.string :format
|
9
|
+
t.string :handler
|
10
|
+
|
11
|
+
t.timestamps
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class CreateCmorCmsPartials < ActiveRecord::Migration[4.2]
|
2
|
+
def change
|
3
|
+
create_table :cmor_cms_partials do |t|
|
4
|
+
t.string :basename
|
5
|
+
t.string :pathname
|
6
|
+
t.text :body
|
7
|
+
t.string :layout
|
8
|
+
t.string :locale
|
9
|
+
t.string :format
|
10
|
+
t.string :handler
|
11
|
+
|
12
|
+
t.timestamps
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class CreateCmorCmsNavigationItems < ActiveRecord::Migration[4.2]
|
2
|
+
def change
|
3
|
+
create_table :cmor_cms_navigation_items do |t|
|
4
|
+
t.string :name
|
5
|
+
t.string :url
|
6
|
+
t.string :key
|
7
|
+
t.string :options
|
8
|
+
t.text :properties, null: true
|
9
|
+
|
10
|
+
# associations
|
11
|
+
t.references :navigation
|
12
|
+
t.references :page
|
13
|
+
|
14
|
+
# awesome nested set
|
15
|
+
t.references :parent
|
16
|
+
t.integer :children_count, default: 0, null: false
|
17
|
+
t.integer :lft
|
18
|
+
t.integer :rgt
|
19
|
+
t.integer :depth
|
20
|
+
|
21
|
+
# friendly id
|
22
|
+
t.string :slug
|
23
|
+
|
24
|
+
t.timestamps
|
25
|
+
end
|
26
|
+
add_index :cmor_cms_navigation_items, :navigation_id
|
27
|
+
add_index :cmor_cms_navigation_items, :parent_id
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class CreateCmorCmsContentBlocks < ActiveRecord::Migration[4.2]
|
2
|
+
def change
|
3
|
+
create_table :cmor_cms_content_blocks do |t|
|
4
|
+
t.text :body
|
5
|
+
|
6
|
+
# associations
|
7
|
+
t.references :page
|
8
|
+
t.references :content_box
|
9
|
+
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
add_index :cmor_cms_content_blocks, :page_id
|
13
|
+
add_index :cmor_cms_content_blocks, :content_box_id
|
14
|
+
end
|
15
|
+
end
|
data/lib/cmor/cms.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'cmor/cms/action_view/template_patch'
|
2
|
+
require 'cmor/cms/action_view/template_renderer_patch'
|
3
|
+
|
4
|
+
require 'cmor/cms/engine'
|
5
|
+
require 'cmor/cms/configuration'
|
6
|
+
|
7
|
+
require 'cmor/cms/database_template'
|
8
|
+
|
9
|
+
require 'cmor/cms/controller_extensions/page_resolver'
|
10
|
+
require 'cmor/cms/controller_extensions/partial_resolver'
|
11
|
+
require 'cmor/cms/controller_extensions/template_resolver'
|
12
|
+
|
13
|
+
module Cmor
|
14
|
+
module Cms
|
15
|
+
extend Configuration
|
16
|
+
|
17
|
+
def self.table_name_prefix
|
18
|
+
'cmor_cms_'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Cmor.configure { |c| c.register_configuration(:cms, Cmor::Cms) }
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module ActionView
|
2
|
+
module TemplatePatch
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
attr_accessor :layout
|
6
|
+
|
7
|
+
alias_method :original_initialize, :initialize
|
8
|
+
|
9
|
+
def initialize(source, identifier, handler, details)
|
10
|
+
@layout = details[:layout] if details.key?(:layout)
|
11
|
+
original_initialize(source, identifier, handler, details)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
ActionView::Template.send(:include, ActionView::TemplatePatch)
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module ActionView
|
2
|
+
module TemplateRendererPatch
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
alias_method :original_render, :render
|
6
|
+
if Rails::VERSION::MAJOR < 4
|
7
|
+
def render(context, options)
|
8
|
+
@view = context
|
9
|
+
@details = extract_details(options)
|
10
|
+
extract_format(options[:file] || options[:template], @details)
|
11
|
+
template = determine_template(options)
|
12
|
+
context = @lookup_context
|
13
|
+
|
14
|
+
unless context.rendered_format
|
15
|
+
context.formats = template.formats unless template.formats.empty?
|
16
|
+
context.rendered_format = context.formats.first
|
17
|
+
end
|
18
|
+
|
19
|
+
layout = template.layout if template.respond_to?(:layout)
|
20
|
+
layout ||= options[:layout]
|
21
|
+
|
22
|
+
render_template(template, layout, options[:locals])
|
23
|
+
end
|
24
|
+
elsif Rails::VERSION::MAJOR < 5
|
25
|
+
def render(context, options)
|
26
|
+
@view = context
|
27
|
+
@details = extract_details(options)
|
28
|
+
template = determine_template(options)
|
29
|
+
|
30
|
+
prepend_formats(template.formats)
|
31
|
+
|
32
|
+
@lookup_context.rendered_format ||= (template.formats.first || formats.first)
|
33
|
+
|
34
|
+
layout = template.layout if template.respond_to?(:layout)
|
35
|
+
layout ||= options[:layout]
|
36
|
+
|
37
|
+
render_template(template, layout, options[:locals])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
ActionView::TemplateRenderer.send(:include, ActionView::TemplateRendererPatch)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'active_support/core_ext/module/delegation'
|
2
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
3
|
+
require 'active_support/hash_with_indifferent_access'
|
4
|
+
|
5
|
+
module Cmor
|
6
|
+
module Cms
|
7
|
+
module Configuration
|
8
|
+
def configure
|
9
|
+
yield self
|
10
|
+
end
|
11
|
+
|
12
|
+
mattr_accessor :base_controller do
|
13
|
+
'ApplicationController'
|
14
|
+
end
|
15
|
+
|
16
|
+
mattr_accessor :default_handlers do
|
17
|
+
HashWithIndifferentAccess.new
|
18
|
+
end
|
19
|
+
|
20
|
+
mattr_accessor :site_title do
|
21
|
+
''
|
22
|
+
end
|
23
|
+
|
24
|
+
mattr_accessor :navigation_item_properties do
|
25
|
+
[]
|
26
|
+
end
|
27
|
+
|
28
|
+
mattr_accessor(:navigation_locale_fallback) { ->(navigation_name, locale) {false} }
|
29
|
+
|
30
|
+
def default_handlers=(default_handlers)
|
31
|
+
@@default_handlers = HashWithIndifferentAccess.new(default_handlers)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Cmor
|
2
|
+
module Cms
|
3
|
+
module ControllerExtensions
|
4
|
+
module PageResolver
|
5
|
+
def self.included(base)
|
6
|
+
# add the page resolver
|
7
|
+
base.prepend_view_path ::Cmor::Cms::PageResolver.instance unless base.view_paths.include?(::Cmor::Cms::PageResolver.instance)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Cmor
|
2
|
+
module Cms
|
3
|
+
module ControllerExtensions
|
4
|
+
module PartialResolver
|
5
|
+
def self.included(base)
|
6
|
+
# add the partial resolver
|
7
|
+
base.prepend_view_path ::Cmor::Cms::PartialResolver.instance unless base.view_paths.include?(::Cmor::Cms::PartialResolver.instance)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Cmor
|
2
|
+
module Cms
|
3
|
+
module ControllerExtensions
|
4
|
+
module TemplateResolver
|
5
|
+
def self.included(base)
|
6
|
+
# add the template resolver
|
7
|
+
base.prepend_view_path ::Cmor::Cms::TemplateResolver.instance unless base.view_paths.include?(::Cmor::Cms::TemplateResolver.instance)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Cmor
|
2
|
+
module Cms
|
3
|
+
module DatabaseResolver
|
4
|
+
# Include hook for class methods
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
# class methods go here
|
10
|
+
module ClassMethods
|
11
|
+
end
|
12
|
+
|
13
|
+
# instance methods go here
|
14
|
+
def find_templates(name, prefix, partial, details, outside_app_allowed = false)
|
15
|
+
return [] unless resolve(partial)
|
16
|
+
|
17
|
+
conditions = {
|
18
|
+
pathname: assert_slashs(prefix.to_s),
|
19
|
+
basename: normalize_basename(name),
|
20
|
+
locale: normalize_array(details[:locale]).first,
|
21
|
+
format: normalize_array(details[:formats]).first,
|
22
|
+
handler: normalize_array(details[:handlers])
|
23
|
+
}
|
24
|
+
|
25
|
+
format = conditions.delete(:format)
|
26
|
+
locale = conditions.delete(:locale)
|
27
|
+
|
28
|
+
query = template_class.constantize.where(conditions)
|
29
|
+
|
30
|
+
# 2) Check for templates with the given format or format is nil
|
31
|
+
query = query.where(["format = ? OR format = '' OR format IS NULL", format])
|
32
|
+
|
33
|
+
# 3) Ensure templates with format come first
|
34
|
+
query = query.order('format DESC')
|
35
|
+
|
36
|
+
# 4) Check for templates with the given locale or locale is nil
|
37
|
+
query = query.where(["locale = ? OR locale = '' OR locale IS NULL", locale])
|
38
|
+
|
39
|
+
# 5) Ensure templates with locale come first
|
40
|
+
query = query.order('locale DESC')
|
41
|
+
|
42
|
+
# 6) Now trigger the query passing on conditions to initialization
|
43
|
+
query.map do |record|
|
44
|
+
initialize_template(record, details)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Initialize an ActionView::Template object based on the record found.
|
49
|
+
def initialize_template(record, details)
|
50
|
+
source = build_source(record)
|
51
|
+
identifier = "#{record.class} - #{record.id} - #{record.pathname}#{record.basename}"
|
52
|
+
handler = ::ActionView::Template.registered_template_handler(record.handler)
|
53
|
+
|
54
|
+
# 5) Check for the record.format, if none is given, try the template
|
55
|
+
# handler format and fallback to the one given on conditions
|
56
|
+
format = record.format && Mime[record.format]
|
57
|
+
format ||= handler.default_format if handler.respond_to?(:default_format)
|
58
|
+
format ||= details[:formats]
|
59
|
+
details = {
|
60
|
+
format: format,
|
61
|
+
updated_at: record.updated_at,
|
62
|
+
virtual_path: "#{record.pathname}#{record.basename}"
|
63
|
+
}
|
64
|
+
|
65
|
+
details[:layout] = record.layout if record.respond_to?(:layout) && record.layout.present?
|
66
|
+
|
67
|
+
::ActionView::Template.new(source, identifier, handler, details)
|
68
|
+
end
|
69
|
+
|
70
|
+
def assert_slashs(prefix)
|
71
|
+
output = prefix.dup
|
72
|
+
output << '/' unless output.end_with?('/')
|
73
|
+
output = '/' << output unless output.start_with?('/')
|
74
|
+
output
|
75
|
+
end
|
76
|
+
|
77
|
+
# Normalize arrays by converting all symbols to strings.
|
78
|
+
def normalize_array(array)
|
79
|
+
array.map(&:to_s)
|
80
|
+
end
|
81
|
+
|
82
|
+
def build_source
|
83
|
+
fail 'call to abstract method #build_source'
|
84
|
+
end
|
85
|
+
|
86
|
+
def normalize_basename(_basename)
|
87
|
+
fail 'call to abstract method #normalize_basename'
|
88
|
+
end
|
89
|
+
|
90
|
+
def resolve(_partial_flag)
|
91
|
+
fail 'call to abstract method #resolve'
|
92
|
+
end
|
93
|
+
|
94
|
+
def template_class
|
95
|
+
fail 'call to abstract method #template_class'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Cmor
|
2
|
+
module Cms
|
3
|
+
module DatabaseTemplate
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
|
7
|
+
# associations
|
8
|
+
base.belongs_to :cmor_cms_folder,
|
9
|
+
class_name: 'Cmor::Cms::Folder',
|
10
|
+
foreign_key: 'cmor_cms_folder_id',
|
11
|
+
optional: true
|
12
|
+
|
13
|
+
# callbacks
|
14
|
+
base.after_initialize :set_defaults
|
15
|
+
base.before_validation :assert_trailing_slash_on_pathname
|
16
|
+
base.after_save :clear_resolver_cache
|
17
|
+
|
18
|
+
# validations
|
19
|
+
base.validates :basename, presence: true,
|
20
|
+
uniqueness: { scope: [:pathname, :locale, :format, :handler] }
|
21
|
+
base.validates :handler, inclusion: ActionView::Template::Handlers.extensions.map(&:to_s)
|
22
|
+
base.validates :locale, inclusion: I18n.available_locales.map(&:to_s),
|
23
|
+
allow_nil: true,
|
24
|
+
allow_blank: true
|
25
|
+
base.validates :format, inclusion: Mime::SET.symbols.map(&:to_s),
|
26
|
+
allow_nil: true,
|
27
|
+
allow_blank: true
|
28
|
+
base.validates :pathname, presence: true
|
29
|
+
end
|
30
|
+
|
31
|
+
module ClassMethods
|
32
|
+
end
|
33
|
+
|
34
|
+
def human
|
35
|
+
"#{self.class.name}: #{path_and_filename}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def filename
|
39
|
+
filename = basename.nil? ? '' : basename.dup
|
40
|
+
filename << ".#{locale}" if locale.present?
|
41
|
+
filename << ".#{format}" if format.present?
|
42
|
+
filename << ".#{handler}" if handler.present?
|
43
|
+
filename
|
44
|
+
end
|
45
|
+
|
46
|
+
def path_and_filename
|
47
|
+
"#{pathname}#{filename}"
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def assert_trailing_slash_on_pathname
|
53
|
+
self.pathname = '/' and return if pathname.blank?
|
54
|
+
pathname << '/' unless pathname.end_with?('/')
|
55
|
+
end
|
56
|
+
|
57
|
+
def clear_resolver_cache
|
58
|
+
klass = "#{self.class.name}Resolver"
|
59
|
+
klass.constantize.instance.clear_cache
|
60
|
+
end
|
61
|
+
|
62
|
+
def set_defaults
|
63
|
+
if new_record?
|
64
|
+
self.locale ||= I18n.default_locale.to_s
|
65
|
+
self.handler ||= Cmor::Cms::Configuration.default_handlers[self.class.name.demodulize.underscore.to_sym].to_s
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|