#!/usr/bin/env ruby require 'pathname' require 'configurability' require 'strelka' require 'strelka/cms' unless defined?( Strelka::CMS ) require 'strelka/cms/page' unless defined?( Strelka::CMS::Page ) # A catalog of Strelka::CMS::Page objects. It provides a collection interface # over a group of pages, suitable for searching for, or iterating over # pages matching one or more criteria. class Strelka::CMS::PageCatalog extend Loggability include Enumerable # Loggability API -- log to the deveiate logger log_to :strelka_cms # The default glob pattern to match pages. DEFAULT_GLOB_PATTERN = '**/*.page' ################################################################# ### I N S T A N C E M E T H O D S ################################################################# ### Create a new PageCatalog that will find and read pages from the configured ### directory. def initialize( basedir=Pathname.pwd, pattern=DEFAULT_GLOB_PATTERN ) pattern.slice!( 0, 1 ) if pattern.start_with?( '/' ) self.log.debug "New catalog for pages matching: %s in: %s" % [ pattern, basedir ] @basedir = Pathname( basedir ) @pageglob = pattern end ###### public ###### # The base directory of the catalog attr_reader :basedir # The glob pattern that will match a collection of one or more pages attr_reader :pageglob ### Return the glob pattern for pages in this catalog. def glob return (self.basedir + self.pageglob).to_s end ### Enumerable interface -- if called with a block, load and yield each page matching the ### #pageglob. If called without a block, return an Enumerator. def each iter = self.page_enumerator if block_given? block = Proc.new iter.each( &block ) else return iter end end ### Return a clone of the directory that will limit the pages in the catalog to those ### under the given +dir+. def relative_to( dir ) dir = dir.to_s dir.slice!( 0, 1 ) if dir.start_with?( '/' ) self.log.debug "Build new catalog for %p relative to %s" % [ dir, self.basedir ] self.class.new( self.basedir + dir, self.pageglob ) end ### Return a clone of the directory that will use the specified +pattern+ to find pages ### instead of the original. def matching_pattern( pattern ) self.class.new( self.basedir, pattern ) end ### Return the catalog object as a human-readable string. def inspect "#<%s:0x%0x %s, %d documents>" % [ self.class.name, self.object_id / 2, self.glob, self.page_path_enumerator.count, ] end ######### protected ######### ### Return an Enumerator that will yield a Pathname for each page matching the #pageglob def page_path_enumerator self.log.debug "Fetching an enumerator for %s" % [ self.glob ] Pathname.glob( self.glob ).each end ### Return an Enumerator that will yield a Strelka::CMS::Page object for each page matching ### the #pageglob. def page_enumerator Enumerator.new do |yielder| self.page_path_enumerator.each do |path| page = Strelka::CMS::Page.load( path, self ) yielder.yield( page ) end end end end # class Strelka::CMS::PageCatalog