Class: Category

Inherits:
KitIndexed show all
Defined in:
app/models/category.rb

Constant Summary collapse

@@perms_cache =
{}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from KitIndexed

do_indexing, indexed_columns, paginate

Instance Attribute Details

#parent_ofObject

Returns the value of attribute parent_of.



27
28
29
# File 'app/models/category.rb', line 27

def parent_of
  @parent_of
end

Class Method Details

.build_permission_cache(sid) ⇒ Object



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'app/models/category.rb', line 182

def self.build_permission_cache(sid)
  @@perms_cache[sid] = {}
  all_groups = {}
  Group.where(:system_id=>sid).all.collect { |g| all_groups[g.id] = g.name }
  Category.tree_by_depth(sid).each do |cat|
    permissions = @@perms_cache[sid][cat.parent_id] ? @@perms_cache[sid][cat.parent_id].clone : { :read_groups=>{}, :write_groups=>{} } # start with permissions of parent

    read_groups = {}
    write_groups = {}
    cat.category_groups.each do |g| 
      read_groups[g.group_id] = all_groups[g.group_id] if g.can_read==1
      write_groups[g.group_id] = all_groups[g.group_id] if g.can_write==1
    end 
    permissions[:read_groups] = read_groups
    permissions[:write_groups] = write_groups

    @@perms_cache[sid][cat.id] = permissions
  end

  return @@perms_cache[sid]
end

.cache_key(sid) ⇒ Object



44
45
46
# File 'app/models/category.rb', line 44

def Category.cache_key(sid)
  return "_tree-#{sid}"
end

.clear_cache(sid) ⇒ Object



48
49
50
# File 'app/models/category.rb', line 48

def Category.clear_cache(sid)
  Rails.cache.delete(Category.cache_key(sid))
end

.create_default(sid) ⇒ Object



330
331
332
# File 'app/models/category.rb', line 330

def self.create_default(sid)
  Category.create(:name=>"/", :parent_id=>0, :is_visible=>1, :path=>"/", :is_readable_anon=>1, :system_id=>sid)
end

.permission_cache(sid) ⇒ Object



178
179
180
# File 'app/models/category.rb', line 178

def self.permission_cache(sid)
  @@perms_cache[sid] || Category.build_permission_cache(sid)
end

.randomObject



209
210
211
212
213
214
215
216
217
218
219
220
# File 'app/models/category.rb', line 209

def Category.random
  c = Category.new
  c.name = rand(100000).to_s
  c.parent_id = 1 
  c.is_visible = true
  c.is_readable_anon = true
  c.save!
  c.name = "cat-#{c.id}"
  c.save!

  return c
end

.root(sid) ⇒ Object



253
254
255
# File 'app/models/category.rb', line 253

def Category.root(sid)
  Category.find_by_parent_id_and_system_id(0,sid)
end

.tree_by_depth(sid) ⇒ Object

all categories, in depth order (root at the top)



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'app/models/category.rb', line 93

def self.tree_by_depth(sid)
  Category.sys(sid).includes(:category_groups).all.sort do |a,b| 
    if a.depth < b.depth
      -1
    elsif a.depth > b.depth
      1
    else
      if a.name < b.name
        -1
      elsif a.name > b.name
        1
      else
        0
      end
    end
  end
end

.tree_by_parent(sid) ⇒ Object

all categories, in a hash keyed by parent_id



112
113
114
115
116
117
118
119
120
121
# File 'app/models/category.rb', line 112

def self.tree_by_parent(sid)
  tree = {}

  Category.sys(sid).all.each do |c|
    tree[c.parent_id] ||= []
    tree[c.parent_id] << c
  end 

  return tree
end

.tree_with_children(sid) ⇒ Object

all categories, in a hash keyed by category_id, with “parent_of” attribute populated with a list of child categories AND child documents



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'app/models/category.rb', line 124

def self.tree_with_children(sid)
  lookup = { }
  cats = Category.sys(sid).order(:name).all
  
  cats.each do |cat|
    cat.parent_of = []
    lookup[cat.id] = cat
  end 

  cats.each do |cat|
    next if cat.is_root?

    lookup[cat.parent_id].parent_of << cat
  end

  Page.sys(sid).order(:name).includes(:status).find_each do |page|
    lookup[page.category_id].parent_of << page
  end
 
 return lookup 
end

.update_all_paths(sid) ⇒ Object



247
248
249
250
251
# File 'app/models/category.rb', line 247

def Category.update_all_paths(sid)
  Category.sys(sid).find_each do |c|
    c.save!
  end
end

Instance Method Details

#clear_cacheObject



40
41
42
# File 'app/models/category.rb', line 40

def clear_cache
  Category.clear_cache(self.system_id)
end

#copy_permissions_to_subsObject



52
53
54
55
56
57
58
59
60
61
62
63
# File 'app/models/category.rb', line 52

def copy_permissions_to_subs
  Category.where(:parent_id=>self.id).all.each do |child|
    child.is_readable_anon = self.is_readable_anon
    child.save
    CategoryGroup.delete_all(["category_id = ?", child.id])
    category_groups.each do |cg|
      CategoryGroup.create(:category_id=>child.id, :group_id=>cg.group_id, :can_read=>cg.can_read, :can_write=>cg.can_write)
    end
    child.copy_permissions_to_subs
  end    
  Category.build_permission_cache(self.system_id)
end

#copy_to(category, deep = false) ⇒ Object



266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'app/models/category.rb', line 266

def copy_to(category, deep = false) 
  new_cat = self.dup
  new_cat.save

  new_cat.make_child_of(category)

  if deep
    self.children.each do |child_cat|
      child_cat.copy_to(new_cat, true)
    end 
    self.pages.each do |page|
      page.copy_to(new_cat) 
    end
  end

  return new_cat.id 
end

#depthObject



204
205
206
# File 'app/models/category.rb', line 204

def depth
  self.parent_id==0 ? 0 : self.path.split("/").size-1
end

#documents(order = 'name') ⇒ Object



243
244
245
# File 'app/models/category.rb', line 243

def documents(order = 'name')
  Page.where(:category_id=>self.id).order(order).all
end

#full_pathObject



36
37
38
# File 'app/models/category.rb', line 36

def full_path 
  self.path
end

#get_full_pathObject



307
308
309
# File 'app/models/category.rb', line 307

def get_full_path
  "/" + self.get_parent_path.reverse.join('/')
end

#get_parent_pathObject



311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
# File 'app/models/category.rb', line 311

def get_parent_path
  
  path = []
  c = self
  
  done = false
  
  while !done
    if c.parent_id == 0
      done = true
    else
      path << c.name
      c = c.parent
    end
  end
  
  return path
end

#grant_permissions_to_new_categoryObject



65
66
67
68
69
70
# File 'app/models/category.rb', line 65

def grant_permissions_to_new_category
  CategoryGroup.where(:category_id=>self.parent_id).all.each do |cg|
    CategoryGroup.create(:category_id=>self.id, :group_id=>cg.group_id, :can_read=>cg.can_read, :can_write=>cg.can_write)
  end
  Category.build_permission_cache(self.system_id)
end

#grant_read_permissions_to_all_groupsObject



72
73
74
75
76
77
# File 'app/models/category.rb', line 72

def grant_read_permissions_to_all_groups
  Group.all.each do |group|
    CategoryGroup.create(:group_id=>group.id, :category_id=>self.id, :can_read=>1, :can_write=>0)
  end
  Category.build_permission_cache(self.system_id)
end

#group_can?(group, perm) ⇒ Boolean

Returns:

  • (Boolean)


166
167
168
169
170
171
172
173
174
175
176
# File 'app/models/category.rb', line 166

def group_can?(group, perm)
  if @@perms_cache[self.system_id]==nil
    @@perms_cache[self.system_id] = Category.build_permission_cache(self.system_id)
  end

  if @@perms_cache[self.system_id][self.id][perm][group.id]
    return true
  else
    return false
  end
end

#group_can_read?(group) ⇒ Boolean

Returns:

  • (Boolean)


158
159
160
# File 'app/models/category.rb', line 158

def group_can_read?(group)
  group_can?(group, :read_groups)
end

#group_can_write(group) ⇒ Object



162
163
164
# File 'app/models/category.rb', line 162

def group_can_write(group)
  group_can?(group, :write_groups)
end

#has_contents?Boolean

Returns:

  • (Boolean)


237
238
239
240
241
# File 'app/models/category.rb', line 237

def has_contents?
  return true if children.count > 0
  return true if Page.where(:category_id=>self.id).limit(1).first
  return false
end

#is_root?Boolean

Returns:

  • (Boolean)


257
258
259
# File 'app/models/category.rb', line 257

def is_root?
  self.parent_id == 0
end

#make_child_of(new_parent) ⇒ Object



284
285
286
287
288
289
290
291
# File 'app/models/category.rb', line 284

def make_child_of(new_parent) 
  self.parent = new_parent
  self.save

  tree_with_children = Category.tree_with_children(self.system_id)  
  self.update_path_of_offspring(tree_with_children)

end

#name_must_be_uniqueObject



29
30
31
32
33
34
# File 'app/models/category.rb', line 29

def name_must_be_unique
  cnt = Category.sys(self.system_id).where(:name=>self.name).where(:parent_id=>self.parent_id).where(["id<>?", self.new_record? ? -1 : self.id]).count
  if cnt > 0
    errors.add(:name, "not unique within this category")
  end
end

#remove_permissions_to_this_categoryObject



87
88
89
90
# File 'app/models/category.rb', line 87

def remove_permissions_to_this_category
  CategoryGroup.delete_all("category_id = #{self.id}")
  Category.build_permission_cache(self.system_id)
end

#set_readable_anon(readable) ⇒ Object



80
81
82
83
84
85
# File 'app/models/category.rb', line 80

def set_readable_anon(readable)
  self.is_readable_anon = readable

  self.save
 Category.build_permission_cache(self.system_id)
end

#update_page_pathsObject



230
231
232
233
234
235
# File 'app/models/category.rb', line 230

def update_page_paths
  Page.where(:category_id=>self.id).all.each do |p|
    p.skip_history = true
    p.save! 
  end
end

#update_pathObject



261
262
263
264
# File 'app/models/category.rb', line 261

def update_path
  # walk up path of parents until we reach the root
  self.path = self.get_full_path
end

#update_path_of_offspring(tree) ⇒ Object

relies on category.parent_of being populated, as it is by tree_with_children



294
295
296
297
298
299
300
301
302
303
304
305
# File 'app/models/category.rb', line 294

def update_path_of_offspring(tree)

  cat = tree[self.id]

  cat.parent_of.each do |item|
    # update me, then things I'm parent of
    logger.debug("Doing item #{item.id} which is a #{item.class.name}")
    item.skip_history = true if item.instance_of?(Page)
    item.save(:validate=>false) # force a path update
    item.update_path_of_offspring(tree) if item.instance_of?(Category)
  end 
end

#update_pathsObject



222
223
224
225
226
227
228
# File 'app/models/category.rb', line 222

def update_paths
  self.update_page_paths

  children.all.each do |cat|
    cat.update_paths
  end
end

#user_can_read?(user) ⇒ Boolean

Returns:

  • (Boolean)


148
149
150
151
152
153
154
155
156
# File 'app/models/category.rb', line 148

def user_can_read?(user)
  return true if self.is_readable_anon==1
  return false unless user
  user.groups.each { |group| 
    return true if group_can_read?(group) 
  }
  return true if user.superadmin?
  return false
end