Class: Site

Inherits:
ActiveRecord::Base
  • Object
show all
Includes:
Property, Property::Serialization::JSON, RubyLess, Zena::Use::MLIndex::SiteMethods
Defined in:
app/models/site.rb

Overview

A zena installation supports many sites. Each site is uniquely identified by it’s host name. The #Site model holds configuration information for a site:

host

Unique host name. (teti.ch, zenadmin.org, dev.example.org, …)

orphan_id

Site seed node id. This is the only node in the site without a parent.

root_id

This is the apparent root of the site.

anon_id

Anonymous user id. This user is the ‘public’ user of the site. Even if authorize is set to true, this user is needed to configure the defaults for all newly created users.

public_group_id

Id of the ‘public’ group. Every user of the site (with ‘anonymous user’) belongs to this group.

site_group_id

Id of the ‘site’ group. Every user except anonymous are part of this group. This group can be seen as the ‘logged in users’ group.

name

Site name (used to display grouped information for cross sites users).

authorize

If this is set to true a login is required: anonymous visitor will not be allowed to browse the site as there is no login/password for the ‘anonymous user’.

languages

A comma separated list of the languages used for the current site. Do not insert spaces in this list.

default_lang

The default language of the site.

Constant Summary collapse

CLEANUP_SQL =
[
  ['attachments'         , 'site_id = ?'],
  ['cached_pages'        , 'site_id = ?'],
  ['cached_pages_nodes'  , 'node_id IN (SELECT id FROM nodes WHERE site_id = ?)'],
  ['caches'              , 'site_id = ?'],
  ['columns'             , 'site_id = ?'],
  ['comments'            , 'site_id = ?'],
  ['data_entries'        , 'site_id = ?'],
  ['discussions'         , 'site_id = ?'],
  ['groups_users'        , 'group_id IN (SELECT id FROM groups WHERE site_id = ?)'],
  ['groups'              , 'site_id = ?'],

  ['idx_nodes_datetimes' , 'node_id IN (SELECT id FROM nodes WHERE site_id = ?)'],
  ['idx_nodes_floats'    , 'node_id IN (SELECT id FROM nodes WHERE site_id = ?)'],
  ['idx_nodes_integers'  , 'node_id IN (SELECT id FROM nodes WHERE site_id = ?)'],
  ['idx_nodes_ml_strings', 'node_id IN (SELECT id FROM nodes WHERE site_id = ?)'],
  ['idx_nodes_strings'   , 'node_id IN (SELECT id FROM nodes WHERE site_id = ?)'],
  ['idx_projects'        , 'node_id IN (SELECT id FROM nodes WHERE site_id = ?)'],
  ['idx_templates'       , 'node_id IN (SELECT id FROM nodes WHERE site_id = ?)'],

  ['iformats'            , 'site_id = ?'],
  ['links'               , 'source_id IN (SELECT id FROM nodes WHERE site_id = ?)'],
  ['links'               , 'target_id IN (SELECT id FROM nodes WHERE site_id = ?)'],

  ['nodes_roles'         , 'node_id IN (SELECT id FROM nodes WHERE site_id = ?)'],
  ['relations'           , 'site_id = ?'],
  ['roles'               , 'site_id = ?'],
  ['sites'               , 'id = ?'],
  ['users'               , 'site_id = ?'],
  ['versions'            , 'site_id = ?'],
  ['zips'                , 'site_id = ?'],
  ['nodes'               , 'site_id = ?'],
]
ACTIONS =
%w{clear_cache rebuild_index}
PUBLIC_PATH =
Bricks.raw_config['public_path'] || '/public'
CACHE_PATH =
Bricks.raw_config['cache_path']  || '/public'
@@attributes_for_form =
{
  :bool => %w{authentication http_auth auto_publish ssl_on_auth},
  :text => %w{languages default_lang},
}
@@alias_attributes_for_form =
{
  :bool => %w{authentication auto_publish ssl_on_auth},
  :text => %w{},
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Zena::Use::MLIndex::SiteMethods

included

Instance Attribute Details

#aliasObject

site alias (different settings + domain)



20
21
22
# File 'app/models/site.rb', line 20

def alias
  @alias
end

Class Method Details

.attributes_for_form(is_alias = false) ⇒ Object

List of attributes that can be configured in the admin form



242
243
244
# File 'app/models/site.rb', line 242

def attributes_for_form(is_alias = false)
  is_alias ? @@alias_attributes_for_form : @@attributes_for_form
end

.create_for_host(host, su_password, opts = {}) ⇒ Object

Create a new site in the database. This should not be called directly. Use rake zena:mksite HOST= instead

Raises:

  • (Exception)


92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'app/models/site.rb', line 92

def create_for_host(host, su_password, opts={})
  params = {
    :name                      => host.split('.').first,
    :authentication            => false,
    :auto_publish              => true,
    :redit_time                => '2h',
    :languages                 => '',
    :default_lang              => "en",
    :usr_prototype_attributes  => "{'klass' => 'Contact'}"
  }.merge(opts)
  langs = params[:languages].split(',').map(&:strip)
  langs += [params[:default_lang]] unless langs.include?(params[:default_lang])
  params[:languages] = langs.map{|l| l[0..1]}.join(',')
  params[:default_lang] = params[:default_lang][0..1]


  site      = self.new(params)
  site.host = host
  site.save
  site.instance_variable_set(:@being_created, true)

  if site.new_record?
    return site
  end

  # =========== CREATE zip counter ==========================
  connection.execute "INSERT INTO zips (site_id, zip) VALUES (#{site[:id]},0)"

  # =========== CREATE Admin User ===========================

  # create admin user
  admin_user = User.new_no_defaults(
    :login => 'admin',           :password => su_password,
    :lang  => site.default_lang, :status => User::Status[:admin])
  admin_user.site = site

  setup_visitor(admin_user, site)

  unless admin_user.save
    # rollback
    Zena::Db.execute "DELETE FROM #{Site.table_name} WHERE id = #{site.id}"
    Zena::Db.execute "DELETE FROM zips WHERE site_id = #{site.id}"
    raise Exception.new("Could not create admin user for site [#{host}] (site#{site[:id]})\n#{admin_user.errors.map{|k,v| "[#{k}] #{v}"}.join("\n")}")
  end

  # =========== CREATE PUBLIC, ADMIN, SITE GROUPS ===========
  # create public group
  pub = site.send(:secure,Group) { Group.create(:name => 'public') }
  raise Exception.new("Could not create public group for site [#{host}] (site#{site[:id]})\n#{pub.errors.map{|k,v| "[#{k}] #{v}"}.join("\n")}") if pub.new_record?

  # create admin group
  editors = site.send(:secure,Group) { Group.create( :name => 'editors') }
  raise Exception.new("Could not create editors group for site [#{host}] (site#{site[:id]})\n#{editors.errors.map{|k,v| "[#{k}] #{v}"}.join("\n")}") if editors.new_record?

  # add admin to the 'editors group'
  editors.users << admin_user

  # create site group
  sgroup = site.send(:secure,Group) { Group.create( :name => 'logged-in') }
  raise Exception.new("Could not create logged-in group for site [#{host}] (site#{site[:id]})\n#{sgroup.errors.map{|k,v| "[#{k}] #{v}"}.join("\n")}") if sgroup.new_record?

  site.public_group_id = pub[:id]
  site.site_group_id   = sgroup[:id]
  site.groups << pub << sgroup << editors

  # Reload group_ids in admin
  admin_user.instance_variable_set(:@group_ids, nil)

  # =========== CREATE Anonymous User =====================
  # create anon user

  anon = site.send(:secure, User) do
    User.new_no_defaults( :login => nil, :password => nil,
    :lang => site.default_lang, :status => User::Status[:moderated])
  end

  anon.site = site
  raise Exception.new("Could not create anonymous user for site [#{host}] (site#{site[:id]})\n#{anon.errors.map{|k,v| "[#{k}] #{v}"}.join("\n")}") unless anon.save
  site[:anon_id] = anon[:id]

  # =========== CREATE ROOT NODE ============================

  root = site.send(:secure,Project) do
    Project.create( :title => site.name, :rgroup_id => pub[:id], :wgroup_id => sgroup[:id], :dgroup_id => editors[:id], :title => site.name, :v_status => Zena::Status::Pub)
  end

  raise Exception.new("Could not create root node for site [#{host}] (site#{site[:id]})\n#{root.errors.map{|k,v| "[#{k}] #{v}"}.join("\n")}") if root.new_record?

  Node.connection.execute "UPDATE nodes SET section_id = id, project_id = id WHERE id = '#{root[:id]}'"

  raise Exception.new("Could not publish root node for site [#{host}] (site#{site[:id]})\n#{root.errors.map{|k,v| "[#{k}] #{v}"}.join("\n")}") unless (root.v_status == Zena::Status::Pub || root.publish)

  site.root_id = root[:id]
  site.orphan_id = root[:id]
  
  # Make sure safe definitions on Time/Array/String are available on prop_eval validation.
  Zena::Use::ZafuSafeDefinitions
  # Should not be needed since we load PropEval in Node, but it does not work
  # without when doing 'mksite' (works in tests).
  Node.safe_method :now => {:class => Time, :method => 'Time.now'}

  # =========== UPDATE SITE =================================
  # save site definition
  raise Exception.new("Could not save site definition for site [#{host}] (site#{site[:id]})\n#{site.errors.map{|k,v| "[#{k}] #{v}"}.join("\n")}") unless site.save

  # =========== LOAD INITIAL DATA (default skin + roles) =============

  nodes = site.send(:secure, Node) { Node.create_nodes_from_folder(:folder => File.join(Zena::ROOT, 'db', 'init', 'base'), :parent_id => root[:id], :defaults => { :v_status => Zena::Status::Pub, :rgroup_id => pub[:id], :wgroup_id => sgroup[:id], :dgroup_id => editors[:id] } ) }.values
  # == set skin id to 'default' for all elements in the site == #
  skin = nodes.detect {|n| n.kind_of?(Skin) }
  Node.connection.execute "UPDATE nodes SET skin_id = '#{skin.id}' WHERE site_id = '#{site[:id]}'"

  # =========== CREATE CONTACT PAGES ==============
  {
    admin_user => {'first_name' => 'Admin',     'last_name' => 'User'},
    anon       => {'first_name' => 'Anonymous', 'last_name' => 'User'}
  }.each do |user, attrs|
    # forces @node creation
    user.node_attributes = attrs
    user.send(:create_node)
    user.save!
  end

  # == done.
  Site.logger.info "=========================================================="
  Site.logger.info "  NEW SITE CREATED FOR [#{host}] (site#{site[:id]})"
  Site.logger.info "=========================================================="

  site.instance_variable_set(:@being_created, false)
  site
end

.find_by_host(host) ⇒ Object



228
229
230
231
232
233
234
235
236
237
238
239
# File 'app/models/site.rb', line 228

def find_by_host(host)
  host = $1 if host =~ /^(.*)\.$/
  if site = self.find(:first, :conditions => ['host = ?', host]) rescue nil
    if id = site.master_id
      # The loaded site is an alias, load master site.
      master = self.find(:first, :conditions => ['id = ?', id])
      master.alias = site
      site = master
    end
  end
  site
end

.master_sitesObject



224
225
226
# File 'app/models/site.rb', line 224

def master_sites
  Site.all(:conditions => ['master_id is NULL'])
end

Instance Method Details

#admin_user_idsObject

Return the ids of the administrators of the current site.



322
323
324
325
# File 'app/models/site.rb', line 322

def admin_user_ids
  # TODO: PERFORMANCE admin_user_ids could be cached in the 'site' record.
  @admin_user_ids ||= secure!(User) { User.find(:all, :conditions => "status >= #{User::Status[:admin]}") }.map {|r| r[:id]}
end

#anonObject

Return the anonymous user, the one used by anonymous visitors to visit the public part of the site.



281
282
283
# File 'app/models/site.rb', line 281

def anon
  @anon ||= User.find_by_id_and_site_id(self[:anon_id], self.id)
end

#any_adminObject

Return an admin user, this user is used to rebuild index/vhash/etc.



286
287
288
# File 'app/models/site.rb', line 286

def any_admin
  @any_admin ||= User.find_by_status_and_site_id(User::Status[:admin], self.id)
end

#api_groupObject

Return the API group: the one in which API visitors must be to use the API.



312
313
314
# File 'app/models/site.rb', line 312

def api_group
  @api_group ||= secure(Group) { Group.find_by_id(self[:api_group_id]) }
end

#authentication?Boolean

Return true if the site is configured to force authentication

Returns:

  • (Boolean)


382
383
384
# File 'app/models/site.rb', line 382

def authentication?
  @alias && @alias[:authentication] || self[:authentication]
end

#auto_publish?Boolean

Return true if the site is configured to automatically publish redactions

Returns:

  • (Boolean)


377
378
379
# File 'app/models/site.rb', line 377

def auto_publish?
  @alias && @alias[:auto_publish] || self[:auto_publish]
end

#being_created?Boolean

Returns:

  • (Boolean)


415
416
417
# File 'app/models/site.rb', line 415

def being_created?
  @being_created
end

#cache_pathObject

This is the place where cached files should be stored in case we do not want to store the cached file inside the public directory.



264
265
266
# File 'app/models/site.rb', line 264

def cache_path
  "/#{host}#{CACHE_PATH}"
end

#clear_cache(clear_zafu = true) ⇒ Object



459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
# File 'app/models/site.rb', line 459

def clear_cache(clear_zafu = true)
  paths = ["#{SITES_ROOT}#{self.cache_path}"]
  aliases = Site.all(:conditions => {:master_id => self.id})
  aliases.each do |site|
    paths << "#{SITES_ROOT}#{site.cache_path}"
  end
  Site.logger.error("\n-----------------\nCLEAR CACHE FOR SITE #{host} (#{aliases.map(&:host).join(', ')})\n-----------------\n")

  paths.each do |path|
    if File.exist?(path)
      Dir.foreach(path) do |elem|
        next unless elem =~ /^(\w\w\.html|\w\w|login\.html)$/
        FileUtils.rmtree(File.join(path, elem))
      end

      Zena::Db.execute "DELETE FROM caches WHERE site_id = #{self[:id]}"
      Zena::Db.execute "DELETE FROM cached_pages_nodes WHERE cached_pages_nodes.node_id IN (SELECT nodes.id FROM nodes WHERE nodes.site_id = #{self[:id]})"
      Zena::Db.execute "DELETE FROM cached_pages WHERE site_id = #{self[:id]}"
    end
  end
  
  # Clear zafu
  if clear_zafu
    paths = ["#{SITES_ROOT}#{self.zafu_path}"]
    aliases.each do |site|
      paths << "#{SITES_ROOT}#{site.cache_path}"
    end
    paths.each do |path|
      if File.exist?(path)
        FileUtils.rmtree(path)
      end
    end
  end

  true
end

#create_alias(hostname) ⇒ Object



402
403
404
405
406
407
408
409
410
411
412
# File 'app/models/site.rb', line 402

def create_alias(hostname)
  raise "Hostname '#{hostname}' already exists" if Site.find_by_host(hostname)
  ali = Site.new(self.attributes)
  ali.host = hostname
  ali.master_id = self.id
  ali.orphan_id = self.orphan_id
  ali.root_id   = self.root_id
  ali.prop      = self.prop
  ali.save
  ali
end

#data_pathObject

Return path for documents data: RAILS_ROOT/sites/host/data You can symlink the ‘data’ directory if you need to keep the data in some other place.



270
271
272
# File 'app/models/site.rb', line 270

def data_path
  "/#{master_host}/data"
end

#hostObject

Host with aliasing (returns alias host if alias is loaded)



368
369
370
# File 'app/models/site.rb', line 368

def host
  @alias && @alias.host || master_host
end

#iformatsObject



423
424
425
426
427
428
429
430
431
432
# File 'app/models/site.rb', line 423

def iformats
 @iformats ||= begin
   $iformats ||= {} # mem cache
   site_formats = $iformats[self[:id]]
   if !site_formats || self[:formats_updated_at] != site_formats[:updated_at]
     site_formats = $iformats[self[:id]] = Iformat.formats_for_site(self[:id]) # reload
   end
   site_formats
  end
end

#iformats_updated!Object



434
435
436
437
438
439
# File 'app/models/site.rb', line 434

def iformats_updated!
  Zena::Db.execute "UPDATE sites SET formats_updated_at = (SELECT updated_at FROM iformats WHERE site_id = #{self[:id]} ORDER BY iformats.updated_at DESC LIMIT 1) WHERE id = #{self[:id]}"
  if $iformats
    $iformats[self[:id]] = @iformats = nil
  end
end

#is_admin?(user) ⇒ Boolean

Return true if the given user is an administrator for this site.

Returns:

  • (Boolean)


317
318
319
# File 'app/models/site.rb', line 317

def is_admin?(user)
  admin_user_ids.include?(user[:id])
end

#is_alias?Boolean

Alias handling

Returns:

  • (Boolean)


358
359
360
# File 'app/models/site.rb', line 358

def is_alias?
  !self[:master_id].blank?
end

#lang_listObject

Return an array with the languages for the site.



353
354
355
# File 'app/models/site.rb', line 353

def lang_list
  (self[:languages] || "").split(',').map(&:strip)
end

#languages=(s) ⇒ Object



419
420
421
# File 'app/models/site.rb', line 419

def languages=(s)
  self[:languages] = s.split(',').map(&:strip).join(',')
end

#master_hostObject

This is the host of the master site.



363
364
365
# File 'app/models/site.rb', line 363

def master_host
  self[:host]
end

#orphan_nodeObject

Return the orphan node.



297
298
299
# File 'app/models/site.rb', line 297

def orphan_node
  @orphan ||= secure(Node) { Node.find(orphan_id) } || Node.new(:title => host)
end

#protected_group_idsObject

ids of the groups that cannot be removed



343
344
345
# File 'app/models/site.rb', line 343

def protected_group_ids
  [site_group_id, public_group_id]
end

#protected_user_idsObject

ids of the users that cannot be removed



348
349
350
# File 'app/models/site.rb', line 348

def protected_user_ids
  [anon_id, visitor.id] # cannot remove self
end

#public_groupObject

Return the public group: the one in which every visitor belongs.



302
303
304
# File 'app/models/site.rb', line 302

def public_group
  @public_group ||= secure(Group) { Group.find(self[:public_group_id]) }
end

#public_pathObject

Return path for static/cached content served by proxy: RAILS_ROOT/sites/host/public If you need to serve from another directory, we do not store the path into the sites table for security reasons. The easiest way around this limitation is to symlink the ‘public’ directory.



258
259
260
# File 'app/models/site.rb', line 258

def public_path
  "/#{host}#{PUBLIC_PATH}"
end

#rebuild_fullpath(parent_id = nil, parent_fullpath = "", parent_basepath = "", start = []) ⇒ Object

Recreates the fullpath (‘/zip/zip/zip’). TODO: find a way to use SiteWorker (need to remove get_nodes): fix rake when this is done.



515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
# File 'app/models/site.rb', line 515

def rebuild_fullpath(parent_id = nil, parent_fullpath = "", parent_basepath = "", start=[])
  raise Zena::InvalidRecord, "Infinit loop in 'ancestors' (#{start.inspect} --> #{parent_id})" if start.include?(parent_id)
  start += [parent_id]
  i = 0
  batch_size = 100
  children = []
  while true
    rec = Zena::Db.fetch_attributes(['id', 'fullpath', 'basepath', 'custom_base', 'zip'], 'nodes', "parent_id #{parent_id ? "= #{parent_id}" : "IS NULL"} AND site_id = #{self.id} ORDER BY id ASC LIMIT #{batch_size} OFFSET #{i * batch_size}")
    break if rec.empty?
    rec.each do |rec|
      if parent_id
        rec['fullpath'] = parent_fullpath == '' ? rec['zip'] : "#{parent_fullpath}/#{rec['zip']}"
      else
        # root node
        rec['fullpath'] = ''
      end

      if rec['custom_base'] == Zena::Db::TRUE_RESULT
        rec['basepath'] = rec['fullpath']
      else
        rec['basepath'] = parent_basepath
      end

      id = rec.delete('id')
      children << [id, rec['fullpath'], rec['basepath'], start]
      Zena::Db.execute "UPDATE nodes SET #{rec.map {|k,v| "#{Zena::Db.connection.quote_column_name(k)}=#{Zena::Db.quote(v)}"}.join(', ')} WHERE id = #{id}"
    end
    # 50 more
    i += 1
  end
  children.each do |child|
    rebuild_fullpath(*child)
  end

  true
end

#rebuild_index(nodes = nil, page = nil, page_count = nil) ⇒ Object

Rebuild property indices for the Site. This method uses the Worker thread to rebuild and works on chunks of 50 nodes.

The visitor used during index rebuild should be an admin user (to index unpublished templates).



557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
# File 'app/models/site.rb', line 557

def rebuild_index(nodes = nil, page = nil, page_count = nil)
  if !page
    Zena::SiteWorker.perform(self, :rebuild_index)
  else
    if page == 1
      Site.logger.error("\n----------------- REBUILD INDEX FOR SITE #{host} -----------------\n")
      # Reset reference to cache origin to make sure it is always overwritten
      Zena::Use::ScopeIndex::AVAILABLE_MODELS.each do |klass|
        changes = klass.column_names.select{|n| n =~ %r{(.*)_id}}.reject {|n| %w{node_id site_id}.include?(n)}.map do |c|
          "#{c} = NULL"
        end.join(', ')
        Site.logger.error("#{klass.name}: reset #{changes}\n")
        Zena::Db.execute "UPDATE #{klass.table_name} SET #{changes} WHERE site_id = #{id}"
      end
    end
    # do things
    nodes.each do |node|
      node.rebuild_index!
    end
  end

  true
end

#rebuild_vhash(nodes = nil, page = nil, page_count = nil) ⇒ Object

Rebuild vhash indices for the Site. This method uses the Worker thread to rebuild and works on chunks of 50 nodes.



498
499
500
501
502
503
504
505
506
507
508
509
510
511
# File 'app/models/site.rb', line 498

def rebuild_vhash(nodes = nil, page = nil, page_count = nil)
  if !nodes
    Site.logger.error("\n----------------- REBUILD VHASH FOR SITE #{host} -----------------\n")
    Zena::SiteWorker.perform(self, :rebuild_vhash)
  else
    # do things
    nodes.each do |node|
      node.rebuild_vhash
      Node.connection.execute "UPDATE nodes SET publish_from = #{Node.connection.quote(node.publish_from)}, vhash = #{Node.connection.quote(node.vhash.to_json)} WHERE id = #{node.id}"
    end
  end

  true
end

#redit_timeObject

Return the time between version updates below which no new version is created. This returns a string of the form “3 hours 45 minutes”



338
339
340
# File 'app/models/site.rb', line 338

def redit_time
  (self[:redit_time] || 0).as_duration
end

#redit_time=(val) ⇒ Object

Set redit time from a string of the form “1d 4h 5s” or “4 days”



328
329
330
331
332
333
334
# File 'app/models/site.rb', line 328

def redit_time=(val)
  if val.kind_of?(String)
    self[:redit_time] = val.to_duration
  else
    self[:redit_time] = val
  end
end

#remove_from_dbObject

This is only called from the console (not accessible through controllers)



582
583
584
585
586
587
588
589
590
591
592
593
594
# File 'app/models/site.rb', line 582

def remove_from_db
  node_cleanup = nil
  site_id = self.id.to_s
  CLEANUP_SQL.each do |table, clause|
    clause = clause.gsub('?', site_id)
    begin
      Zena::Db.execute("DELETE FROM #{table} WHERE (#{clause})")
    rescue => err
      puts clause
      puts err
    end
  end
end

#root_idObject



386
387
388
# File 'app/models/site.rb', line 386

def root_id
  @root_id ||= @alias && @alias[:root_id] || self[:root_id]
end

#root_nodeObject

Return the root node or a dummy if the visitor cannot view root node (such as during a 404 or login rendering).



292
293
294
# File 'app/models/site.rb', line 292

def root_node
  @root ||= secure(Node) { Node.find(root_id) } || Node.new(:title => host)
end

#root_zipObject



390
391
392
# File 'app/models/site.rb', line 390

def root_zip
  root_node.zip
end

#root_zip=(zip) ⇒ Object



394
395
396
397
398
399
400
# File 'app/models/site.rb', line 394

def root_zip=(zip)
  if id = secure(Node) { Node.translate_pseudo_id(zip) }
    self[:root_id] = id
  else
    @root_zip_error = _('could not be found')
  end
end

#site_groupObject

Return the site group: the one in which every visitor except ‘anonymous’ belongs (= all logged in users).



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

def site_group
  @site_group ||= secure(Group) { Group.find(self[:site_group_id]) }
end

#ssl_on_authObject



372
373
374
# File 'app/models/site.rb', line 372

def ssl_on_auth
  @alias && @alias.prop['ssl_on_auth'] || self.prop['ssl_on_auth']
end

#virtual_classesObject



441
442
443
444
445
446
447
448
449
450
# File 'app/models/site.rb', line 441

def virtual_classes
 @iformats ||= begin
   $iformats ||= {} # mem cache
   site_formats = $iformats[self[:id]]
   if !site_formats || self[:formats_updated_at] != site_formats[:updated_at]
     site_formats = $iformats[self[:id]] = Iformat.formats_for_site(self[:id]) # reload
   end
   site_formats
  end
end

#zafu_pathObject

Return the path for zafu rendered templates: RAILS_ROOT/sites/host/zafu



275
276
277
# File 'app/models/site.rb', line 275

def zafu_path
  "/#{master_host}/zafu"
end