module SitemapGenerator
class SitemapLocation < Hash
[:host, :adapter].each do |method|
define_method(method) do
raise SitemapGenerator::SitemapError, "No value set for #{method}" unless self[method]
self[method]
end
end
[:public_path, :sitemaps_path].each do |method|
define_method(method) do
Pathname.new(SitemapGenerator::Utilities.append_slash(self[method]))
end
end
# If no +filename+ or +namer+ is provided, the default namer is used, which
# generates names like sitemap.xml.gz, sitemap1.xml.gz, sitemap2.xml.gz and so on.
#
# === Options
# * adapter - SitemapGenerator::Adapter subclass
# * filename - full name of the file e.g. 'sitemap1.xml.gz'
# * host - host name for URLs. The full URL to the file is then constructed from
# the host, sitemaps_path and filename
# * namer - a SitemapGenerator::SimpleNamer instance. Can be passed instead of +filename+.
# * public_path - path to the "public" directory, or the directory you want to
# write sitemaps in. Default is a directory public/
# in the current working directory, or relative to the Rails root
# directory if running under Rails.
# * sitemaps_path - gives the path relative to the public_path in which to
# write sitemaps e.g. sitemaps/.
# * verbose - whether to output summary into to STDOUT. Default +false+.
# * create_index - whether to create a sitemap index. Default `:auto`. See LinkSet.
# Only applies to the SitemapIndexLocation object.
def initialize(opts={})
SitemapGenerator::Utilities.assert_valid_keys(opts, [:adapter, :public_path, :sitemaps_path, :host, :filename, :namer, :verbose, :create_index])
opts[:adapter] ||= SitemapGenerator::FileAdapter.new
opts[:public_path] ||= SitemapGenerator.app.root + 'public/'
opts[:namer] = SitemapGenerator::SitemapNamer.new(:sitemap) if !opts[:filename] && !opts[:namer]
opts[:verbose] = !!opts[:verbose]
self.merge!(opts)
end
# Return a new Location instance with the given options merged in
def with(opts={})
self.merge(opts)
end
# Full path to the directory of the file.
def directory
(public_path + sitemaps_path).expand_path.to_s
end
# Full path of the file including the filename.
def path
(public_path + sitemaps_path + filename).expand_path.to_s
end
# Relative path of the file (including the filename) relative to public_path
def path_in_public
(sitemaps_path + filename).to_s
end
# Full URL of the file.
def url
URI.join(host, sitemaps_path.to_s, filename.to_s).to_s
end
# Return the size of the file at path
def filesize
File.size?(path)
end
# Return the filename. Raises an exception if no filename or namer is set.
# If using a namer once the filename has been retrieved from the namer its
# value is locked so that it is unaffected by further changes to the namer.
def filename
raise SitemapGenerator::SitemapError, "No filename or namer set" unless self[:filename] || self[:namer]
unless self[:filename]
self.send(:[]=, :filename, self[:namer].to_s, :super => true)
end
self[:filename]
end
# If a namer is set, reserve the filename and increment the namer.
# Returns the reserved name.
def reserve_name
if self[:namer]
filename
self[:namer].next
end
self[:filename]
end
# Return true if this location has a fixed filename. If no name has been
# reserved from the namer, for instance, returns false.
def reserved_name?
!!self[:filename]
end
def namer
self[:namer]
end
def verbose?
self[:verbose]
end
# If you set the filename, clear the namer and vice versa.
def []=(key, value, opts={})
if !opts[:super]
case key
when :namer
super(:filename, nil)
when :filename
super(:namer, nil)
end
end
super(key, value)
end
def write(data)
adapter.write(self, data)
end
end
class SitemapIndexLocation < SitemapLocation
def initialize(opts={})
if !opts[:filename] && !opts[:namer]
opts[:namer] = SitemapGenerator::SitemapIndexNamer.new(:sitemap)
end
super(opts)
end
# Really just a placeholder for an option which should really go into some
# kind of options class.
def create_index
self[:create_index]
end
end
end