Provided by: libbadger-perl_0.16-3_all bug

NAME

       Badger::Config::Filesystem - reads configuration files in a directory

SYNOPSIS

           use Badger::Config::Filesystem;

           my $config = Badger::Config::Filesystem->new(
               root => 'path/to/some/dir'
           );

           # Fetch the data in user.[yaml|json] in above dir
           my $user = $config->get('user')
               || die "user: not found";

           # Fetch sub-data items using dotted syntax
           print $config->get('user.name');
           print $config->get('user.emails.0');

DESCRIPTION

       This module is a subclass of Badger::Config for reading data from configuration files in a
       directory.

       Consider a directory that contains the following files and sub-directories:

           config/
               site.yaml
               style.yaml
               pages.yaml
               pages/
                   admin.yaml
                   developer.yaml

       We can create a Badger::Config::Filesystem object to read the configuration data from the
       files in this directory like so:

           my $config = Badger::Config::Filesystem->new(
               root => 'config'
           );

       Reading the data from "site.yaml" is as simple as this:

           my $site = $config->get('site');

       Note that the file extension is not required.  You can have either a "site.yaml" or a
       "site.json" file in the directory and the module will load whichever one it finds first.
       It's possible to add other data codecs if you want to use something other than YAML or
       JSON.

       You can also access data from within a configuration file.  If the "site.yaml" file
       contains the following:

           name:    My Site
           version: 314
           author:
             name:  Andy Wardley
             email: abw@wardley.org

       Then we can read the version and author name like so:

           print $config->get('site.version');
           print $config->get('author.name');

       If the configuration directory contains a sub-directory with the same name as the data
       file being loaded (minus the extension) then any files under that directory will also be
       loaded.  Going back to our earlier example, the "pages" item is such a case:

           config/
               site.yaml
               style.yaml
               pages.yaml
               pages/
                   admin.yaml
                   developer.yaml

       There are three files relevant to "pages" here.  Let's assume the content of each is as
       follow:

       pages.yaml:

           one:        Page One
           two:        Page Two

       pages/admin.yaml:

           three:      Page Three
           four:       Page Four

       pages/developer.yaml:

           five:       Page Five

       When we load the "pages" data like so:

           my $pages = $config->get('pages');

       We end up with a data structure like this:

           {
               one   => 'Page One',
               two   => 'Page Two',
               admin => {
                   three => 'Page Three',
                   four  => 'Page Four',
               },
               developer => {
                   five  => 'Page Five',
               },
           }

       Note how the "admin" and "developer" items have been nested into the data.  The filename
       base (e.g. "admin", "developer") is used to define an entry in the "parent" hash array
       containing the data in the "child" data file.

       The "tree_type" option can be used to change the way that this data is merged.  To use
       this option, put it in a "schema" section in the top level configuration file, e.g. the
       "pages.yaml":

       pages.yaml:

           one:        Page One
           two:        Page Two
           schema:
             tree_type: flat

       If you don't want the data nested at all then specify a "flat" value for "tree_type".
       This would return the following data:

           {
               one   => 'Page One',
               two   => 'Page Two',
               three => 'Page Three',
               four  => 'Page Four',
               five  => 'Page Five',
           }

       The "join" type collapses the nested data files by joining the file path (without
       extension) onto the data items contain therein. e.g.

           {
               one             => 'Page One',
               two             => 'Page Two',
               admin_three     => 'Page Three',
               admin_four      => 'Page Four',
               developer_five  => 'Page Five',
           }

       You can specify a different character sequence to join paths via the "tree_joint" option,
       e.g.

           schema:
             tree_type:  join
             tree_joint: '-'

       That would producing this data structure:

           {
               one             => 'Page One',
               two             => 'Page Two',
               admin-three     => 'Page Three',
               admin-four      => 'Page Four',
               developer-five  => 'Page Five',
           }

       The "uri" type is a slightly smarter version of the "join" type.  It joins path elements
       with the "/" character to create URI paths.

           {
               one             => 'Page One',
               two             => 'Page Two',
               admin/three     => 'Page Three',
               admin/four      => 'Page Four',
               developer/five  => 'Page Five',
           }

       What makes it special is that it follows the standard rules for URI resolution and
       recognises a path with a leading slash to be absolute rather than relative to the current
       location.

       For example, the pages/admin.yaml file could contain something like this:

       pages/admin.yaml:

           three:      Page Three
           /four:      Page Four

       The "three" entry is considered to be relative to the "admin" file so results in a final
       path of "admin/three" as before.  However, "/four" is an absolute path so the "admin" path
       is ignored.  The end result is a data structure like this:

           {
               one             => 'Page One',
               two             => 'Page Two',
               admin/three     => 'Page Three',
               /four           => 'Page Four',
               developer/five  => 'Page Five',
           }

       In this example we've ended up with an annoying inconsistency in that our "/four" path has
       a leading slash when the other items don't.  The "uri_paths" option can be set to
       "relative" or "absolute" to remove or add leading slashes respectively, effectively
       standardising all paths as one or the other.

           schema:
             tree_type:  uri
             uri_paths:  absolute

       The data would then be returned like so:

           {
               /one            => 'Page One',
               /two            => 'Page Two',
               /admin/three    => 'Page Three',
               /four           => 'Page Four',
               /developer/five => 'Page Five',
           }

CONFIGURATION OPTIONS

   root / directory / dir
       The "root" (or "directory" or "dir" if you prefer) option must be provided to specify the
       directory that the module should load configuration files from.  Directories can be
       specified as absolute paths or relative to the current working directory.

           my $config = Badger::Config::Filesystem->new(
               dir => 'path/to/config/dir'
           );

   data
       Any additional configuration data can be provided via the "data" named parameter:

           my $config = Badger::Config::Filesystem->new(
               dir  => 'path/to/config/dir'
               data => {
                   name  => 'Arthur Dent',
                   email => 'arthur@dent.org',
               },
           );

   encoding
       The character encoding of the configuration files.  Defaults to "utf8".

   extensions
       A list of file extensions to try in addition to "yaml" and "json".  Note that you may also
       need to define a "codecs" entry to map the file extension to a data encoder/decoder
       module.

           my $config = Badger::Config::Filesystem->new(
               dir        => 'path/to/config/dir'
               extensions => ['str'],
               codecs     => {
                   str    => 'storable',
               }
           );

   codecs
       File extensions like ".yaml" and ".json" are recognised by Badger::Codecs which can then
       provide the appropriate Badger::Codec module to handle the encoding and decoding of data
       in the file.  The codecs options can be used to provide mapping from other file extensions
       to Badger::Codec modules.

           my $config = Badger::Config::Filesystem->new(
               dir        => 'path/to/config/dir'
               extensions => ['str'],
               codecs     => {
                   str    => 'storable',   # *.str files loaded via storable codec
               }
           );

       You may need to write a simple codec module yourself if there isn't one for the data
       format you want, but it's usually just a few lines of code that are required to provide
       the Badger::Codec wrapper module around whatever other Perl module or custom code you've
       using to load and save the data format.

   schemas
       TODO: document specification of item schemas.  The items below (tree_type through
       uri_paths) must now be defined in a schema.  Support for a default schema has temporarily
       been disabled/broken.

   tree_type
       This option can be used to sets the default tree type for any configuration items that
       don't explicitly declare it by other means.  The default tree type is "nest".

       NOTE: this has been changed.  Don't trust these docs.

       The following tree types are supported:

       nest

       This is the default tree type, creating nested hash arrays of data.

       flat

       Creates a flat hash array by merging all nested hash array of data into one.

       join

       Joins data paths together using the "tree_joint" string which is "_" by default.

       uri

       Joins data paths together using slash characters to create URI paths.  An item in a sub-
       directory can have a leading slash (i.e. an absolute path) and it will be promoted to the
       top-level data hash.

       e.g.

           foo/bar + baz  = foo/bar/baz
           foo/bar + /bam = /bam

       none

       No tree is created.  No sub-directories are scanned.   You never saw me.  I wasn't here.

   tree_joint
       This option can be used to set the default character sequence for joining paths

   uri_paths
       This option can be used to set the default "uri_paths" option for joining paths as URIs.
       It should be set to "relative" or "absolute".  It can be over-ridden in a "schema" section
       of a top-level configuration file.

METHODS

       The module inherits all methods defined in the Badger::Config and Badger::Workplace base
       classes.

INTERNAL METHODS

       The following methods are defined for internal use.

   init($config)
       This overrides the default initialisation method inherited from Badger::Config.  It calls
       the init_config() method to perform the base class Badger::Config initialisation and then
       the init_filesystem() method to perform initialisation specific to the
       Badger::Config::Filesystem module.

   init_filesystem($config)
       This performs the initialisation of the object specific to the filesystem object.

   head($item)
       This redefines the head() method in the Badger::Config base class.  The method is called
       by get() to fetch a top-level data item (e.g. "user" in "$config->get('user.name')").
       This implementation looks for existing data items as usual, but additionally falls back on
       a call to fetch($item) to load additional data (or attempt to load it).

   tail($item, $data)
       This is a do-nothing stub for subclasses to redefine.  It is called after a successful
       call to fetch().

   fetch($item)
       This is the main method called to load a configuration file (or tree of files) from the
       filesystem.  It looks to see if a configuration file (with one of the known extensions
       appended, e.g. "$item.yaml", "$item.json", etc) exists and/or a directory named $item.

       If the file exists but the directory doesn't then the configuration data is read from the
       file.  If the directory exists

   config_tree($item, $file, $dir)
       This scans a configuration tree comprising of a configuration file and/or a directory.
       The $file and $dir arguments are optional and are only supported as an internal
       optimisation.  The method can safely be called with a single $item argument and the
       relevant file and directory will be determined automatically.

       The configuration file is loaded (via scan_config_file()).  If the directory exists then
       it is also scanned (via scan_config_dir()) and the files contained therein are loaded.

   scan_config_file($file, $data, $path, $schema, $binder)
       Loads the data in a configuration $file and merges it into the common $data hash under the
       $path prefix (a reference to an array).  The $schema contains any schema rules for this
       data item.  The $binder is a reference to a tree_binder() method to handle the data merge.

   scan_config_dir($dir, $data, $path, $schema, $binder)
       Scans the diles in a configuration directory, $dir and recursively calls scan_config_dir()
       for each sub-directory found, and scan_config_file() for each file.

   tree_binder($name)
       This method returns a reference to one of the binder methods below based on the $name
       parameter provided.

           # returns a reference to the nest_binder() method
           my $binder = $config->tree_binder('nest');

       If no $name is specified then it uses the default "tree_type" of "nest".  This can be
       changed via the tree_type configuration option.

   nest_tree_binder($parent, $path, $child, $schema)
       This handles the merging of data for the nest tree_type.

   flat_tree_binder($parent, $path, $child, $schema)
       This handles the merging of data for the flat tree_type.

   uri_tree_binder($parent, $path, $child, $schema)
       This handles the merging of data for the uri tree_type.

   join_tree_binder($parent, $path, $child, $schema)
       This handles the merging of data for the join tree_type.

   config_file($name)
       This method returns a Badger::Filesystem::File object representing a configuration file in
       the configuration directory.  It will automatically have the correct filename extension
       added (via a call to config_filename) and the correct "codec" and "encoding" parameters
       set (via a call to config_filespec) so that the data in the configuration file can be
       automatically loaded (see config_data($name)).

   config_file_data($name)
       This method fetches a configuration file via a call to config_file() and then returns the
       data contained therein.

   config_filespec($params)
       Returns a reference to a hash array containing appropriate initialisation parameters for
       Badger::Filesystem::File objects created to read general and resource-specific
       configuration files.  The parameters are  constructed from the "codecs" (default: "yaml")
       and "encoding" (default: "utf8") configuration options.  These can be overridden or
       augmented by extra parameters passed as arguments.

AUTHOR

       Andy Wardley <http://wardley.org/>

COPYRIGHT

       Copyright (C) 2008-2014 Andy Wardley.  All Rights Reserved.

       This module is free software; you can redistribute it and/or modify it under the same
       terms as Perl itself.