bcms_ancestry 1.0.0

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.
@@ -0,0 +1,177 @@
1
+ class Section < SectionNode
2
+ flush_cache_on_change
3
+
4
+ #The node that links this section to its parent
5
+ # has_one :node, :class_name => "SectionNode", :as => :node, :dependent => :destroy
6
+
7
+ #The nodes that link this section to its children
8
+
9
+ # has_many :child_sections, :class_name => "SectionNode", :conditions => ["node_type = ?", "Section"], :order => 'section_nodes.position'
10
+
11
+ # has_many :pages, :through => :child_nodes, :source => :node, :source_type => 'Page', :order => 'section_nodes.position'
12
+ # has_many :sections, :through => :child_nodes, :source => :node, :source_type => 'Section', :order => 'section_nodes.position'
13
+
14
+ # named_scope :root, :conditions => ['root = ?', true]
15
+ named_scope :system, :conditions => {:name => 'system'}
16
+
17
+ named_scope :hidden, :conditions => {:hidden => true}
18
+ named_scope :not_hidden, :conditions => {:hidden => false}
19
+
20
+ named_scope :named, lambda{|name| {:conditions => ['sections.name = ?', name]}}
21
+ named_scope :with_path, lambda{|path| {:conditions => ['sections.path = ?', path]}}
22
+
23
+ #validates_presence_of :name, :path
24
+ #validates_presence_of :parent_id, :if => Proc.new {root.count > 0}, :message => "section is required"
25
+
26
+ is_versioned :version_foreign_key => :ancestry_section_node_id
27
+
28
+ # Disabling '/' in section name for interoperability with FCKEditor file browser
29
+ validates_format_of :name, :with => /\A[^\/]*\Z/, :message => "cannot contain '/'"
30
+
31
+ validate :path_not_reserved
32
+
33
+ before_destroy :deletable?
34
+
35
+ attr_accessor :full_path
36
+
37
+ def visible_child_nodes(options={})
38
+ children = child_nodes.of_type(["Section", "Page", "Link"]).all(:order => 'section_nodes.position')
39
+ visible_children = children.select{|sn| sn.visible?}
40
+ options[:limit] ? visible_children[0...options[:limit]] : visible_children
41
+ end
42
+
43
+ def all_children_with_name
44
+ child_sections.map do |s|
45
+ if s.node
46
+ s.node.full_path = root? ? s.node.name : "#{name} / #{s.node.name}"
47
+ [s.node] << s.node.all_children_with_name
48
+ end
49
+ end.flatten.compact
50
+ end
51
+
52
+ =begin
53
+ def parent_id
54
+ parent ? parent.id : nil
55
+ end
56
+
57
+ def parent
58
+ node ? node.section : nil
59
+ end
60
+
61
+ def parent_id=(sec_id)
62
+ self.parent = Section.find(sec_id)
63
+ end
64
+
65
+ def parent=(sec)
66
+ if node
67
+ node.move_to_end(sec)
68
+ else
69
+ build_node(:node => self, :section => sec)
70
+ end
71
+ end
72
+
73
+ def ancestors(options={})
74
+ ancs = node ? node.ancestors : []
75
+ options[:include_self] ? ancs + [self] : ancs
76
+ end
77
+
78
+ def with_ancestors(options = {})
79
+ options.merge! :include_self => true
80
+ self.ancestors(options)
81
+ end
82
+
83
+ def move_to(section)
84
+ if root?
85
+ false
86
+ else
87
+ node.move_to_end(section)
88
+ end
89
+ end
90
+
91
+ def public?
92
+ group_sections.each{ |x|
93
+ return true if x.code == "guest"
94
+ }
95
+ return false
96
+ #!!(groups.find_by_code('guest'))
97
+ end
98
+ =end
99
+ # def empty?
100
+ # child_nodes.reject{|n| n.orphaned?}.empty?
101
+ # end
102
+
103
+ def deletable?
104
+ !root? && empty?
105
+ end
106
+
107
+ def editable_by_group?(group)
108
+ group.editable_by_section(self)
109
+ end
110
+
111
+ def status
112
+ public? ? :unlocked : :locked
113
+ end
114
+
115
+ def self.find_by_name_path(name_path)
116
+ section = Section.root.first
117
+ children = name_path.split("/")[1..-1] || []
118
+ children.each do |name|
119
+ section = section.sections.first(:conditions => {:name => name})
120
+ end
121
+ section
122
+ end
123
+
124
+ #The first page that is a decendent of this section
125
+ def first_page_or_link
126
+ section_node = child_nodes.of_type(['Link', 'Page']).first(:order => "section_nodes.position")
127
+ return section_node.node if section_node
128
+ sections.each do |s|
129
+ node = s.first_page_or_link
130
+ return node if node
131
+ end
132
+ nil
133
+ end
134
+
135
+ def actual_path
136
+ if root?
137
+ "/"
138
+ else
139
+ p = first_page_or_link
140
+ p ? p.path : "#"
141
+ end
142
+ end
143
+
144
+ def path_not_reserved
145
+ if Cms.reserved_paths.include?(path)
146
+ errors.add(:path, "is invalid, '#{path}' a reserved path")
147
+ end
148
+ end
149
+
150
+ ##
151
+ # Set which groups are allowed to access this section.
152
+ # @params [Symbol] code Set of groups to allow (Options :all, :none) Defaults to :none
153
+ def allow_groups=(code=:none)
154
+ if code == :all
155
+ self.groups = Group.all
156
+ end
157
+ end
158
+
159
+
160
+
161
+ ######### proxys ########
162
+
163
+ def self.root
164
+ roots
165
+ end
166
+
167
+ def child_nodes
168
+ children.ordered
169
+ end
170
+
171
+ def child_sections
172
+ sections
173
+ end
174
+ def sections
175
+ children.ordered.scoped(:conditions => {:type => 'Section'})
176
+ end
177
+ end
@@ -0,0 +1,142 @@
1
+ class SectionNode < ActiveRecord::Base
2
+ set_table_name :ancestry_section_nodes
3
+ has_ancestry :cache_depth=>true
4
+
5
+ # belongs_to :section
6
+ # belongs_to :node, :polymorphic => :true
7
+
8
+ has_many :group_sections, :foreign_key => :section_id
9
+ has_many :groups, :through => :group_sections
10
+
11
+ acts_as_list :scope => 'ancestry = \'#{ancestry}\''
12
+ named_scope :ordered, :order => "ancestry is not null, ancestry, position ASC"
13
+
14
+ # wir machen alle versioned damit wir sie includen können
15
+ is_versioned :version_foreign_key => :ancestry_section_node_id
16
+ is_publishable
17
+ named_scope :for_sitemap, :include=>[:groups, :versions]
18
+
19
+ # named_scope :of_type, lambda{|types| {:conditions => ["section_nodes.node_type IN (?)", types]}}
20
+
21
+ def visible?
22
+ return false unless node
23
+ return false if(node.respond_to?(:hidden?) && node.hidden?)
24
+ return false if(node.respond_to?(:archived?) && node.archived?)
25
+ return false if(node.respond_to?(:published?) && !node.published?)
26
+ true
27
+ end
28
+
29
+ # def version_foreign_key
30
+ # :ancestry_section_node_id
31
+ # end
32
+ # def orphaned?
33
+ # !node || (node.class.uses_soft_delete? && node.deleted?)
34
+ # end
35
+
36
+ #Is this node a section
37
+ def section?
38
+ self.is_a?(Section)
39
+ end
40
+
41
+ #Is this node a page
42
+ def page?
43
+ self.is_a?(Page)
44
+ end
45
+
46
+ def move_to(sec, pos)
47
+ #logger.info "Moving Section Node ##{id} to Section ##{sec.id} Position #{pos}"
48
+ transaction do
49
+ if section != sec
50
+ remove_from_list
51
+ self.update_attribute(:parent, sec)
52
+ end
53
+ logger.info "dude: " + pos.to_s
54
+ if pos < 0
55
+ pos = 0
56
+ else
57
+ #This helps prevent the position from getting out of whack
58
+ #If you pass in a really high number for position,
59
+ #this just corrects it to the right number
60
+ node_count = sec.children.count
61
+ pos = node_count if pos > node_count
62
+ end
63
+ logger.info "hans: " + pos.to_s
64
+ insert_at_position(pos)
65
+ end
66
+ end
67
+
68
+ def move_before(section_node)
69
+ if section == section_node.section && position < section_node.position
70
+ pos = section_node.position - 1
71
+ else
72
+ pos = section_node.position
73
+ end
74
+ move_to(section_node.section, pos)
75
+ end
76
+
77
+ def move_after(section_node)
78
+ if section == section_node.section && position < section_node.position
79
+ pos = section_node.position
80
+ else
81
+ pos = section_node.position + 1
82
+ end
83
+ move_to(section_node.section, pos)
84
+ end
85
+
86
+ def move_to_beginning(sec)
87
+ move_to(sec, 0)
88
+ end
89
+
90
+ def move_to_end(sec)
91
+ #1.0/0 == Infinity
92
+ move_to(sec, 1.0/0)
93
+ end
94
+
95
+ =begin
96
+ def ancestors()
97
+ ancestors = []
98
+ fn = lambda do |sn|
99
+ ancestors << sn.section
100
+ if sn.section && !sn.section.root?
101
+ fn.call(sn.section.node)
102
+ end
103
+ end
104
+ fn.call(self)
105
+ ancestors.reverse
106
+ end
107
+ =end
108
+ ############# Proxy ############
109
+
110
+ def public?
111
+ groups.each{ |x|
112
+ return true if x.code == "guest"
113
+ }
114
+ return false
115
+ #!!(groups.find_by_code('guest'))
116
+ end
117
+ def node
118
+ self
119
+ end
120
+ def root?
121
+ is_root?
122
+ end
123
+ def path
124
+ read_attribute :path
125
+ end
126
+
127
+ def section_id
128
+ self.parent_id
129
+ end
130
+
131
+ def section
132
+ self.parent
133
+ end
134
+
135
+ def section_id=(sec_id)
136
+ self.parent_id = sec_id
137
+ end
138
+
139
+ def section=(sec)
140
+ self.parent = sec
141
+ end
142
+ end
@@ -0,0 +1,11 @@
1
+ <ul id="section_node_<%= section_node.id %>" class="section_node<%= " rootlet" if root %>" style="display: <%= display ? "''" : "none" %>">
2
+ <li>
3
+ <%= render :partial => "node", :locals => {
4
+ :node => node,
5
+ :node_type => "link",
6
+ :icon => action_icon(root ? :root_link : :link),
7
+ :published_status_icon => status_icon(node.status),
8
+ :published_status_label => node.published? ? "Published" : "Draft"
9
+ } %>
10
+ </li>
11
+ </ul>
@@ -0,0 +1,36 @@
1
+ <%
2
+ hidden = defined?(hidden) ? hidden : false
3
+ access_icon = defined?(access_icon) ? access_icon : nil
4
+ published_status_icon = defined?(published_status_icon) ? published_status_icon : nil
5
+ published_status_label = defined?(published_status_label) ? published_status_label : nil
6
+ %>
7
+
8
+
9
+ <div class="roundedcorners">
10
+ <table class="section_node <%= node_type %> <%= "movable" if current_user.able_to?(:publish_content) %>" width="100%" cellspacing="0" cellpadding="0">
11
+ <tr><td colspan="4" class="drop-before"></td></tr>
12
+ <tr<%= ' class="doubled"' if access_icon && hidden %>>
13
+ <td id="<%= node_type %>_<%= node.id %>" class="<%= node_type == "section" && node.root? ? 'root' : '' %> <%= node_type %> node <%= 'non-editable' unless current_user.able_to_edit?(node) %>">
14
+ <%= icon %>
15
+ <div><%= h(node.name) %></div>
16
+ </td>
17
+ <td class="sitemap_hidden divided">
18
+ <a href="#" class="hidden"><%= status_icon(:hidden) if hidden %><span>HIDDEN</span></a>
19
+ </td>
20
+ <td class="sitemap_access divided">
21
+ <%= access_icon ? access_icon : "&nbsp;" %>
22
+ </td>
23
+ <td class="sitemap_published_status">
24
+ <div>
25
+ <%= published_status_icon ? published_status_icon : "&nbsp;" %>
26
+ <div><%= published_status_label if published_status_label %></div>
27
+ </div>
28
+ </td>
29
+ </tr>
30
+ <tr><td colspan="4" class="drop-after"></td></tr>
31
+ </table>
32
+ <div class="stl"></div>
33
+ <div class="str"></div>
34
+ <div class="sbl"></div>
35
+ <div class="sbr"></div>
36
+ </div>
@@ -0,0 +1,14 @@
1
+ <% status = node.archived? ? :archived : node.status %>
2
+ <ul id="section_node_<%= section_node.id %>" class="section_node<%= " rootlet" if root %>" style="display: <%= display ? "''" : "none" %>">
3
+ <li>
4
+ <%= render :partial => "node", :locals => {
5
+ :node => node,
6
+ :node_type => "page",
7
+ :icon => action_icon(root ? :root_page : :page),
8
+ :hidden => node.hidden?,
9
+ :access_icon => status_icon(parent ? parent.status : ''),
10
+ :published_status_icon => status_icon(status),
11
+ :published_status_label => status.to_s.titleize
12
+ } %>
13
+ </li>
14
+ </ul>
@@ -0,0 +1,13 @@
1
+ <ul id="section_node_<%= section_node.id %>" class="section_node<%= " rootlet" if root %>" style="display: <%= display ? "''" : "none" %>">
2
+ <li>
3
+ <%= render :partial => "node", :locals => {
4
+ :node => node,
5
+ :node_type => "section",
6
+ :icon => "#{section_icons(node)} #{action_icon(root ? :root_folder : :folder, :class => "folder")}",
7
+ :hidden => node.hidden?,
8
+ :access_icon => status_icon(node.status),
9
+ } %>
10
+ <%= render :partial => "section_node", :collection => node.child_nodes, :locals => {:display => false} %>
11
+ </li>
12
+
13
+ </ul>
@@ -0,0 +1,27 @@
1
+
2
+ <%section_node.each do |node, children|%>
3
+ <% if node && %w[Link Page].include?(node.type.to_s) %>
4
+ <%= render :partial => node.type.to_s.underscore, :locals => {
5
+ :section_node => node,
6
+ :node => node,
7
+ :display => display,
8
+ :parent => parent,
9
+ :root => false,
10
+ :parent => parent
11
+ }
12
+ %>
13
+ <% elsif node && %w[Section].include?(node.type.to_s) %>
14
+ <ul id="section_node_<%= node.id %>" class="section_node<%= " rootlet" if node.root? %>" style="display: <%= display ? "''" : "none" %>">
15
+ <li>
16
+ <%= render :partial => "node", :locals => {
17
+ :node => node,
18
+ :node_type => "section",
19
+ :icon => "#{section_icons(node,children.empty?)} #{action_icon(node.root? ? :root_folder : :folder, :class => "folder")}",
20
+ :hidden => node.hidden?,
21
+ :access_icon => status_icon(node.status),
22
+ } %>
23
+ <%= render :partial => "section_node", :object => children, :locals => {:display => false, :parent => node} %>
24
+ </li>
25
+ </ul>
26
+ <%end%>
27
+ <%end%>
@@ -0,0 +1,99 @@
1
+ <%section_node = sitemap%>
2
+ <%section_node.each do |node, children|%>
3
+ <%section_node = node%>
4
+ <% if node.class == Link %>
5
+
6
+ <%
7
+ root = false
8
+ node_type = "link"
9
+
10
+ icon = action_icon(:link)
11
+ published_status_icon = status_icon(node.status)
12
+ published_status_label = node.published? ? "Published" : "Draft"
13
+
14
+ hidden = defined?(hidden) ? hidden : false
15
+ access_icon = defined?(access_icon) ? access_icon : nil
16
+ published_status_icon = defined?(published_status_icon) ? published_status_icon : nil
17
+ published_status_label = defined?(published_status_label) ? published_status_label : nil
18
+ %>
19
+
20
+ <% elsif node.class == Page %>
21
+
22
+ <%
23
+ root = false
24
+ node_type = "page"
25
+
26
+ status = node.archived? ? :archived : node.status
27
+ icon = action_icon(:page)
28
+ hidden = node.hidden?
29
+ access_icon = status_icon(parent ? parent.status : '')
30
+ published_status_icon = status_icon(status)
31
+ published_status_label = status.to_s.titleize
32
+ status = node.archived? ? :archived : node.status
33
+
34
+ hidden = defined?(hidden) ? hidden : false
35
+ access_icon = defined?(access_icon) ? access_icon : nil
36
+ published_status_icon = defined?(published_status_icon) ? published_status_icon : nil
37
+ published_status_label = defined?(published_status_label) ? published_status_label : nil
38
+
39
+
40
+ %>
41
+ <% elsif node.class == Section %>
42
+
43
+ <%
44
+ root = node.root?
45
+ node_type = "section"
46
+
47
+ icon = "#{section_icons(node,children.empty?)} #{action_icon(node.root? ? :root_folder : :folder, :class => "folder")}"
48
+ hidden = node.hidden?
49
+ access_icon = status_icon(node.status)
50
+
51
+ hidden = defined?(hidden) ? hidden : false
52
+ access_icon = defined?(access_icon) ? access_icon : nil
53
+ published_status_icon = defined?(published_status_icon) ? published_status_icon : nil
54
+ published_status_label = defined?(published_status_label) ? published_status_label : nil
55
+ %>
56
+ <%end%>
57
+
58
+
59
+ <ul id="section_node_<%= section_node.id %>" class="section_node<%= " rootlet" if root %>" style="display: <%= display ? "''" : "none" %>">
60
+ <li>
61
+
62
+
63
+
64
+ <div class="roundedcorners">
65
+ <table class="section_node <%= node_type %> <%= "movable" if current_user.able_to?(:publish_content) %>" width="100%" cellspacing="0" cellpadding="0">
66
+ <tr><td colspan="4" class="drop-before"></td></tr>
67
+ <tr<%= ' class="doubled"' if access_icon && hidden %>>
68
+ <td id="<%= node_type %>_<%= node.id %>" class="<%= node_type == "section" && node.root? ? 'root' : '' %> <%= node_type %> node <%= 'non-editable' unless false %>">
69
+ <%= icon %>
70
+ <div><%= h(node.name) %></div>
71
+ </td>
72
+ <td class="sitemap_hidden divided">
73
+ <a href="#" class="hidden"><%= status_icon(:hidden) if hidden %><span>HIDDEN</span></a>
74
+ </td>
75
+ <td class="sitemap_access divided">
76
+ <%= access_icon ? access_icon : "&nbsp;" %>
77
+ </td>
78
+ <td class="sitemap_published_status">
79
+ <div>
80
+ <%= published_status_icon ? published_status_icon : "&nbsp;" %>
81
+ <div><%= published_status_label if published_status_label %></div>
82
+ </div>
83
+ </td>
84
+ </tr>
85
+ <tr><td colspan="4" class="drop-after"></td></tr>
86
+ </table>
87
+ <div class="stl"></div>
88
+ <div class="str"></div>
89
+ <div class="sbl"></div>
90
+ <div class="sbr"></div>
91
+ </div>
92
+ <%= render :partial => "sitemap", :object => children, :locals => {:display => false, :parent => node} if node.class == Section %>
93
+ </li>
94
+ </ul>
95
+
96
+
97
+
98
+
99
+ <%end%>