Config-Extend-MySQL

 view release on metacpan or  search on metacpan

lib/Config/Extend/MySQL.pm  view on Meta::CPAN

B<Examples>

    # read MySQL config using Config::IniFiles
    my $config = Config::Extend::MySQL->new({ from => $file, using => "Config::IniFiles" });
    # $config ISA Config::Extend::MySQL, ISA Config::IniFiles

    # read MySQL config using Config::Tiny
    my $config = Config::Extend::MySQL->new({ from => $file, using => "Config::Tiny" });
    # $config ISA Config::Extend::MySQL, ISA Config::Tiny

=cut

sub new {
    my ($class, $args) = @_;

    croak "error: Arguments must be given as a hash reference"
        unless ref $args eq "HASH";
    croak "error: Missing required argument 'from'"
        unless exists $args->{from};
    croak "error: Empty argument 'from'"
        unless defined $args->{from} and length $args->{from};

    # check that the file exists and contains something
    my $file = $args->{from};
    croak "fatal: No such file '$file'" unless -f $file;
    carp "warning: File '$file' is empty" and return if -s _ == 0;

    # read the file and resolve the MySQL-isms
    my $content = __read_config(file => $file);

    my $fh = undef;
    if (USE_IO_STRING) {
        require IO::String;
        $fh = IO::String->new(\$content);
    }
    else {
        open($fh, "<", \$content)
            or croak "fatal: Can't read in-memory buffer: $!";
    }

    # create the object using the given Config:: module
    my $backend = defined $args->{using} ? $args->{using} : "Config::Tiny";
    $backend->require or croak "fatal: Can't load module $args->{using}: $@";
    @Config::Extend::MySQL::ISA = ($backend);
    my $self = __new_from($backend, $fh, \$content)
        or croak "fatal: Backend module failed to parse '$file'";
    bless $self, $class;

    # store the names to skip when reading directories
    my @skip_names = qw(. .. CVS);
    @skip{@skip_names} = (1) x @skip_names;

    return $self
}


sub __new_from {
    my ($backend, $fh, $content_r) = @_;

    if ($backend eq "Config::IniFiles") {
        local $SIG{__WARN__} = sub {}; # avoid a warning from stat() on this $fh
        local *IO::String::FILENO = sub { -1 };
        return Config::IniFiles->new(-file => $fh)
    }
    elsif ($backend eq "Config::Format::Ini") {
        local $SIG{__WARN__} = sub {}; # avoid "slurp redefined" warning
        local *Config::Format::Ini::slurp = sub { return ${$_[0]} };
        return Config::Format::Ini::read_ini($content_r)
    }
    elsif ($backend eq "Config::Simple") {
        # can't get Config::Simple to play nicely because it want to 
        # seek() and flock() the filehandle. seek() works on in-memory
        # filehandles, but flock() doesn't, and can't be faked/replaced

        #my $obj = Config::Simple->new(syntax => "ini");
        #$obj->{_DATA} = $obj->parse_ini_file($fh);
        #return $obj

        return Config::Simple->new($fh)
    }
    elsif ($backend eq "Config::Tiny" or $backend eq "Config::INI::Reader") {
        return $backend->read_string($$content_r)
    }
}


sub __read_config {
    my ($what, $path) = @_;
    my $content = "";
    my $opts = {}; #{ err_mode => "quiet" };

    if ($what eq "file") {
        my $base_dir = dirname($path);
        $content = read_file($opts, $path);

        # handle single param (without value)
        $content =~ s{^ \s* (\w+ (?:-\w+)* ) \s* $}{$1 = yes}xgm;

        # handle includes
        $content =~ s{^ \s* !include(dir)? \s+ (.+) \s* $}
                     { __read_config($1 || "file", rel2abs($2, $base_dir)) }xgme;
    }
    elsif ($what eq "dir") {
        opendir(my $dirh, $path) or return "";

        while (my $file = readdir($dirh)) {
            # skip invisible files and directories we shouldn't 
            # recurse into, like ../ or CVS/
            next if $skip{$file} or index($file, ".") == 0;

            my $filepath = catfile($path, $file);

            if (-f $filepath) {
                $content .= __read_config(file => $filepath)
            }
            elsif (-d _) {
                $content .= __read_config(dir => $filepath)
            }
        }

        closedir($dirh);



( run in 0.787 second using v1.01-cache-2.11-cpan-99c4e6809bf )