ecm_cms 0.0.1.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +55 -0
  3. data/Rakefile +27 -0
  4. data/app/assets/stylesheets/ecm_cms.css.less +3 -0
  5. data/app/controllers/ecm/cms/page_controller.rb +11 -0
  6. data/app/helpers/ecm/cms_helper.rb +42 -0
  7. data/app/models/ecm/cms.rb +5 -0
  8. data/app/models/ecm/cms/folder.rb +31 -0
  9. data/app/models/ecm/cms/navigation.rb +24 -0
  10. data/app/models/ecm/cms/navigation_item.rb +93 -0
  11. data/app/models/ecm/cms/page.rb +42 -0
  12. data/app/models/ecm/cms/partial.rb +31 -0
  13. data/app/models/ecm/cms/template.rb +31 -0
  14. data/config/locales/ecm.cms.de.yml +17 -0
  15. data/config/locales/ecm.cms.en.yml +17 -0
  16. data/config/locales/ecm.cms.navigation.de.yml +16 -0
  17. data/config/locales/ecm.cms.navigation.en.yml +16 -0
  18. data/config/locales/ecm.cms.navigation_item.de.yml +23 -0
  19. data/config/locales/ecm.cms.navigation_item.en.yml +23 -0
  20. data/config/locales/ecm.cms.page.de.yml +26 -0
  21. data/config/locales/ecm.cms.page.en.yml +26 -0
  22. data/config/locales/ecm.cms.partial.de.yml +22 -0
  23. data/config/locales/ecm.cms.partial.en.yml +22 -0
  24. data/config/locales/ecm.cms.template.de.yml +22 -0
  25. data/config/locales/ecm.cms.template.en.yml +22 -0
  26. data/db/migrate/001_create_ecm_cms_folders.rb +21 -0
  27. data/db/migrate/002_create_ecm_cms_pages.rb +19 -0
  28. data/db/migrate/003_create_ecm_cms_templates.rb +18 -0
  29. data/db/migrate/004_create_ecm_cms_partials.rb +19 -0
  30. data/db/migrate/005_create_ecm_cms_navigations.rb +13 -0
  31. data/db/migrate/006_create_ecm_cms_navigation_items.rb +28 -0
  32. data/lib/ecm/cms/action_view/template/handlers/textile.rb +18 -0
  33. data/lib/ecm/cms/action_view/template_patch.rb +19 -0
  34. data/lib/ecm/cms/action_view/template_renderer_patch.rb +30 -0
  35. data/lib/ecm/cms/active_admin/ecm_cms_navigation_items.rb +45 -0
  36. data/lib/ecm/cms/active_admin/ecm_cms_navigations.rb +61 -0
  37. data/lib/ecm/cms/active_admin/ecm_cms_pages.rb +70 -0
  38. data/lib/ecm/cms/active_admin/ecm_cms_partials.rb +47 -0
  39. data/lib/ecm/cms/active_admin/ecm_cms_templates.rb +46 -0
  40. data/lib/ecm/cms/configuration.rb +22 -0
  41. data/lib/ecm/cms/database_resolver.rb +101 -0
  42. data/lib/ecm/cms/database_template.rb +67 -0
  43. data/lib/ecm/cms/engine.rb +22 -0
  44. data/lib/ecm/cms/resolvers/ecm/cms/page_resolver.rb +37 -0
  45. data/lib/ecm/cms/resolvers/ecm/cms/partial_resolver.rb +30 -0
  46. data/lib/ecm/cms/resolvers/ecm/cms/template_resolver.rb +30 -0
  47. data/lib/ecm/cms/routing.rb +13 -0
  48. data/lib/ecm/cms/version.rb +5 -0
  49. data/lib/ecm_cms.rb +30 -0
  50. data/lib/generators/ecm/cms/install/install_generator.rb +15 -0
  51. data/lib/generators/ecm/cms/install/templates/ecm_cms.rb +7 -0
  52. data/lib/generators/ecm/cms/locales/locales_generator.rb +32 -0
  53. data/lib/rails_tools/i18n_controller.rb +24 -0
  54. data/lib/tasks/ecm_cms_tasks.rake +171 -0
  55. metadata +463 -0
@@ -0,0 +1,20 @@
1
+ Copyright 2012 Roberto Vasquez Angel
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,55 @@
1
+ = ECM Module Template
2
+
3
+ = Prerequisites
4
+
5
+ * rails ~> 3.2.8
6
+ * active admin ~> 0.5.0
7
+
8
+ = Installation
9
+
10
+ Add it to your bundle:
11
+
12
+ # Gemfile:
13
+ gem 'ecm_cms'
14
+
15
+ Install your bundle:
16
+
17
+ > bundle install
18
+
19
+ Install the intializer:
20
+
21
+ > rails g ecm:cms:install
22
+
23
+ Install the locales
24
+
25
+ > rails g ecm:cms:locales
26
+
27
+ Generate migrations and migrate:
28
+
29
+ > rake ecm_cms_engine:install:migrations
30
+ > rake db:migrate
31
+
32
+ = Configuring localized routing
33
+
34
+ Add the routes to your routing file:
35
+
36
+ # config/routes.rb:
37
+ localized(I18n.available_locales) do
38
+ scope "/:i18n_locale", :constraints => {:i18n_locale => /#{I18n.available_locales.join('|')}/} do
39
+ # ECM CMS
40
+ Ecm::Cms::Routing.routes(self)
41
+ end
42
+ end
43
+ match "/", :to => redirect("/#{I18n.locale}")
44
+
45
+ = Optional: Generating example/default data
46
+
47
+ There is a task to prepopulate your database tables with example data.
48
+
49
+ Warning: *RUNNING THIS WILL DELETE ALL OF YOUR CMS DATA AND REPLACE IT WITH EXAMPLE DATA!*
50
+
51
+ > rake ecm:cms:db:populate!
52
+
53
+ = License
54
+
55
+ This project rocks and uses MIT-LICENSE.
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'EcmCms'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+
25
+
26
+ Bundler::GemHelper.install_tasks
27
+
@@ -0,0 +1,3 @@
1
+ body.active_admin textarea#ecm_cms_page_body, body.active_admin textarea#ecm_cms_template_body, body.active_admin textarea#ecm_cms_partial_body {
2
+ font-family: Consolas, Monaco,Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace;
3
+ }
@@ -0,0 +1,11 @@
1
+ class Ecm::Cms::PageController < ApplicationController
2
+ # inject locale to params and vice versa
3
+ include RailsTools::I18nController
4
+
5
+ # add the page resolver
6
+ append_view_path Ecm::Cms::PageResolver.instance unless view_paths.include?(Ecm::Cms::PageResolver.instance)
7
+
8
+ def respond
9
+ render :template => params[:page]
10
+ end
11
+ end
@@ -0,0 +1,42 @@
1
+ module Ecm::CmsHelper
2
+ def cms_render_navigation(name, options = {})
3
+ options.reverse_merge! :renderer => :bootstrap, :expand_all => true
4
+ navigation = Ecm::Cms::Navigation.where(:name => name.to_s, :locale => I18n.locale.to_s).first
5
+
6
+ return I18n.t('ecm.cms.navigation.messages.not_found', {:lang => I18n.locale.to_s, :name => name.to_s}) unless navigation
7
+
8
+ options[:items] = []
9
+ navigation.ecm_cms_navigation_items.roots.all.each do |ni|
10
+ options[:items] << build_navigation(ni)
11
+ end
12
+
13
+ return I18n.t('ecm.cms.navigation.messages.empty', :lang => I18n.locale.to_s, :name => name) if options[:items].empty?
14
+ options[:items].first[:options] = {} if options[:items].first[:options].nil?
15
+ options[:items].first[:options].reverse_merge! :container_class => 'nav'
16
+ render_navigation(options)
17
+ end
18
+
19
+ def build_navigation(navigation_item)
20
+ if navigation_item.children.count > 0
21
+ items = []
22
+ navigation_item.children.each do |child|
23
+ items << build_navigation(child)
24
+ end
25
+ #output = { :key => navigation_item.key, :name => navigation_item.name, :url => eval(navigation_item.url), :items => items }
26
+ output = { :key => navigation_item.key, :name => navigation_item.name, :url => navigation_item.url, :items => items }
27
+ else
28
+ #output = { :key => navigation_item.key, :name => navigation_item.name, :url => eval(navigation_item.url) }
29
+ output = { :key => navigation_item.key, :name => navigation_item.name, :url => navigation_item.url }
30
+ end
31
+
32
+ begin
33
+ options = eval(navigation_item.options)
34
+ output[:options] = options if options.is_a?(Hash)
35
+ rescue
36
+ logger.debug "Invalid navigation item options: #{navigation_item.options}"
37
+ end
38
+
39
+ return output
40
+ end
41
+ end
42
+
@@ -0,0 +1,5 @@
1
+ module Ecm::Cms
2
+ def self.table_name_prefix
3
+ 'ecm_cms_'
4
+ end
5
+ end
@@ -0,0 +1,31 @@
1
+ class Ecm::Cms::Folder < ActiveRecord::Base
2
+ self.table_name = 'ecm_cms_folders'
3
+
4
+ # associations
5
+ has_many :ecm_cms_pages,
6
+ :class_name => 'Ecm::Cms::Page',
7
+ :dependent => :destroy,
8
+ :foreign_key => 'ecm_cms_folder_id'
9
+ has_many :ecm_cms_partials,
10
+ :class_name => 'Ecm::Cms::Partial',
11
+ :dependent => :destroy,
12
+ :foreign_key => 'ecm_cms_folder_id'
13
+ has_many :ecm_cms_templates,
14
+ :class_name => 'Ecm::Cms::Template',
15
+ :dependent => :destroy,
16
+ :foreign_key => 'ecm_cms_folder_id'
17
+
18
+ # attributes
19
+ attr_accessible :basename,
20
+ :children_count,
21
+ :depth,
22
+ :ecm_cms_templates_count,
23
+ :lft,
24
+ :pathname,
25
+ :rgt
26
+
27
+ # validations
28
+ validates :basename, :presence => true
29
+ validates :pathname, :presence => true
30
+ end
31
+
@@ -0,0 +1,24 @@
1
+ class Ecm::Cms::Navigation < ActiveRecord::Base
2
+ self.table_name = 'ecm_cms_navigations'
3
+
4
+ # associations
5
+ has_many :ecm_cms_navigation_items,
6
+ :class_name => 'Ecm::Cms::NavigationItem',
7
+ :dependent => :destroy,
8
+ :foreign_key => 'ecm_cms_navigation_id'
9
+
10
+ # attributes
11
+ attr_accessible :locale,
12
+ :name,
13
+ :slug
14
+
15
+ # validations
16
+ validates :locale, :inclusion => I18n.available_locales.map(&:to_s),
17
+ :allow_nil => true
18
+ validates :name, :presence => true,
19
+ :uniqueness => { :scope => [ :locale ] }
20
+
21
+ def to_s
22
+ "#{self.name} (#{self.locale})"
23
+ end
24
+ end
@@ -0,0 +1,93 @@
1
+ class Ecm::Cms::NavigationItem < ActiveRecord::Base
2
+ self.table_name = 'ecm_cms_navigation_items'
3
+
4
+ # associations
5
+ belongs_to :ecm_cms_navigation,
6
+ :class_name => 'Ecm::Cms::Navigation',
7
+ :foreign_key => 'ecm_cms_navigation_id'
8
+ belongs_to :ecm_cms_page,
9
+ :class_name => 'Ecm::Cms::Page',
10
+ :foreign_key => 'ecm_cms_page_id'
11
+
12
+ # attributes
13
+ attr_accessible :depth,
14
+ :key,
15
+ :name,
16
+ :options,
17
+ :string,
18
+ :url
19
+ attr_protected :lgt,
20
+ :rgt
21
+
22
+ # awesome nested set
23
+ acts_as_nested_set :dependent => :destroy, :counter_cache => :children_count, :scope => :ecm_cms_navigation_id
24
+
25
+ # callbacks
26
+ before_validation :update_navigation_from_parent, :if => Proc.new { |ni| ni.child? }
27
+ before_validation :update_url_form_page, :if => Proc.new { |ni| ni.ecm_cms_page.present? && ni.url.blank? }
28
+ after_save :update_children_navigations!
29
+
30
+ # default_scope
31
+ default_scope :order => [:ecm_cms_navigation_id, :lft]
32
+
33
+ # validations
34
+ validates :key, :presence => true
35
+ validates :name, :presence => true
36
+ validates :url, :presence => true
37
+ validates :ecm_cms_navigation, :presence => true, :if => :root?
38
+
39
+ def params_for_new_page
40
+ return {} if self.new_record?
41
+ match = self.url.scan(/(#{I18n.available_locales.join('|')})$/)
42
+ return { :locale => match[0][0], :pathname => '/', :basename => 'home', :title => self.name, :ecm_cms_navigation_item_ids => [ self.to_param ] } if match.size > 0
43
+ match = self.url.scan(/(#{I18n.available_locales.join('|')})(.*)\/(.*)/)
44
+ return {} unless match.first.respond_to?(:size) # && match.first.size != 3
45
+ params = match.first
46
+ return {} if params.size != 3
47
+ params[1] << '/' unless params[1].end_with?('/')
48
+ return { :locale => params[0], :pathname => params[1], :basename => params[2], :title => self.name, :ecm_cms_navigation_item_ids => [ self.to_param ] }
49
+ end
50
+
51
+ # @TODO: test
52
+ def to_label
53
+ if depth > 0
54
+ "#{'&nbsp;' * depth} &#9654; #{name}".html_safe
55
+ else
56
+ name
57
+ end
58
+ end
59
+
60
+ def update_navigation_from_parent!
61
+ self.update_navigation_from_parent
62
+ self.save!
63
+ end
64
+
65
+ def update_children_navigations!
66
+ self.descendants.map(&:"update_navigation_from_parent!")
67
+ end
68
+
69
+ def update_url_form_page!
70
+ # self.url = build_url_from_page(ecm_cms_page.locale, ecm_cms_page.pathname, ecm_cms_page.basename, ecm_cms_page.home_page?)
71
+ update_url_form_page
72
+ save!
73
+ end
74
+
75
+ private
76
+
77
+ def build_url_from_page(locale, pathname, basename, is_home_page)
78
+ if is_home_page
79
+ "/#{locale}"
80
+ else
81
+ "/#{locale}#{pathname}#{basename}"
82
+ end
83
+ end
84
+
85
+ def update_navigation_from_parent
86
+ self.ecm_cms_navigation = self.parent.ecm_cms_navigation
87
+ end
88
+
89
+ def update_url_form_page
90
+ self.url = build_url_from_page(ecm_cms_page.locale, ecm_cms_page.pathname, ecm_cms_page.basename, ecm_cms_page.home_page?)
91
+ end
92
+ end
93
+
@@ -0,0 +1,42 @@
1
+ class Ecm::Cms::Page < ActiveRecord::Base
2
+ self.table_name = 'ecm_cms_pages'
3
+
4
+ # add shared behaviour for database backed templates
5
+ include Ecm::Cms::DatabaseTemplate
6
+
7
+ # associations
8
+ has_many :ecm_cms_navigation_items,
9
+ :class_name => 'Ecm::Cms::NavigationItem',
10
+ :dependent => :nullify,
11
+ :foreign_key => 'ecm_cms_page_id'
12
+
13
+ # attributes
14
+ attr_accessible :basename,
15
+ :body,
16
+ :ecm_cms_folder_id,
17
+ :ecm_cms_navigation_item_ids,
18
+ :format,
19
+ :handler,
20
+ :layout,
21
+ :locale,
22
+ :meta_description,
23
+ :pathname,
24
+ :title
25
+
26
+ # callbacks
27
+ after_save :touch_navigation_items # , :if => Proc.new { |page| page.locale_changed? || page.pathname_changed? || page.basename_changed? }
28
+
29
+ # validations
30
+ validates :title, :presence => true
31
+
32
+ def home_page?
33
+ p self.pathname
34
+ p self.basename
35
+ return self.pathname == '/' && self.basename == 'home'
36
+ end
37
+
38
+ def touch_navigation_items
39
+ self.ecm_cms_navigation_items.map(&:update_url_form_page!)
40
+ end
41
+ end
42
+
@@ -0,0 +1,31 @@
1
+ class Ecm::Cms::Partial < ActiveRecord::Base
2
+ self.table_name = 'ecm_cms_partials'
3
+
4
+ # add shared behaviour for database backed templates
5
+ include Ecm::Cms::DatabaseTemplate
6
+
7
+ # associations
8
+ # belongs_to :ecm_cms_folder,
9
+ # :class_name => 'Ecm::Cms::Folder',
10
+ # :foreign_key => 'ecm_cms_folder_id'
11
+
12
+ # attributes
13
+ attr_accessible :basename,
14
+ :body,
15
+ :ecm_cms_folder_id,
16
+ :format,
17
+ :handler,
18
+ :layout,
19
+ :locale,
20
+ :pathname
21
+
22
+ # callbacks
23
+ before_validation :ensure_basename_starts_with_underscore, :if => Proc.new { |t| t.basename.present? }
24
+
25
+ private
26
+
27
+ def ensure_basename_starts_with_underscore
28
+ self.basename.insert(0, '_') unless self.basename.start_with?('_')
29
+ end
30
+ end
31
+
@@ -0,0 +1,31 @@
1
+ class Ecm::Cms::Template < ActiveRecord::Base
2
+ self.table_name = 'ecm_cms_templates'
3
+
4
+ # add shared behaviour for database backed templates
5
+ include Ecm::Cms::DatabaseTemplate
6
+
7
+ # associations
8
+ belongs_to :ecm_cms_folder,
9
+ :class_name => 'Ecm::Cms::Folder',
10
+ :foreign_key => 'ecm_cms_folder_id'
11
+
12
+ # attributes
13
+ attr_accessible :basename,
14
+ :body,
15
+ :ecm_cms_folder_id,
16
+ :format,
17
+ :handler,
18
+ :layout,
19
+ :locale,
20
+ :pathname
21
+
22
+ # callbacks
23
+ before_validation :ensure_basename_starts_without_underscore, :if => Proc.new { |t| t.basename.present? }
24
+
25
+ private
26
+
27
+ def ensure_basename_starts_without_underscore
28
+ self.basename.slice!(0) if self.basename.start_with?('_')
29
+ end
30
+ end
31
+
@@ -0,0 +1,17 @@
1
+ de:
2
+ ecm:
3
+ cms:
4
+ active_admin:
5
+ menu: CMS
6
+ navigation:
7
+ messages:
8
+ empty: Navigation %{name} (%{lang}) ist leer
9
+ not_found: Navigation %{name} (%{lang}) nicht gefunden
10
+ resources:
11
+ ecm_cms_folders: ordner
12
+ ecm_cms_navigations: navigationen
13
+ ecm_cms_navigation_items: navigationenseintraege
14
+ ecm_cms_pages: seiten
15
+ ecm_cms_partials: fragmente
16
+ ecm_cms_templates: vorlagen
17
+