File Coverage

lib/Templer/Plugin/FileGlob.pm
Criterion Covered Total %
statement 55 64 85.9
branch 9 18 50.0
condition 3 6 50.0
subroutine 6 6 100.0
pod 1 2 50.0
total 74 96 77.0


line stmt bran cond sub pod time code
1              
2             =head1 NAME
3              
4             Templer::Plugin::FileGlob - A plugin to expand file globs.
5              
6             =cut
7              
8             =head1 SYNOPSIS
9              
10             The following is a good example use of this plugin
11              
12             title: Images of cats
13             images: file_glob( img/candid*.jpg )
14             ----
15            
  • 16            
    17            
  • Animal & Pet Photography, Edinburgh
  • 18            
    19            
    20              
    21             =cut
    22              
    23             =head1 DESCRIPTION
    24              
    25             This plugin operates on file-patterns and populates loops refering
    26             to the specified pattern.
    27              
    28             The intended use-case is inline-gallery generation, but more uses
    29             would surely be discovered.
    30              
    31             For each loop created there will be the variables:
    32              
    33             =over 8
    34              
    35             =item file
    36              
    37             The name of the file.
    38              
    39             =item height
    40              
    41             The height of the image, if the file is an image and L is available.
    42              
    43             =item width
    44              
    45             The width of the image, if the file is an image and L is available.
    46              
    47             =item contents
    48              
    49             The content of the file if the file is not an image and not a templer input file.
    50              
    51             =item dirname
    52              
    53             The directory part of the file name.
    54              
    55             =item basename
    56              
    57             The basename of the file (without extension).
    58              
    59             =item extension
    60              
    61             The extension (everything after the last period) of the file name.
    62              
    63             =back
    64              
    65             If matching files are templer input files then all templer variables are also
    66             populated.
    67              
    68             =cut
    69              
    70             =head1 LICENSE
    71              
    72             This module is free software; you can redistribute it and/or modify it
    73             under the terms of either:
    74              
    75             a) the GNU General Public License as published by the Free Software
    76             Foundation; either version 2, or (at your option) any later version,
    77             or
    78              
    79             b) the Perl "Artistic License".
    80              
    81             =cut
    82              
    83             =head1 AUTHOR
    84              
    85             Steve Kemp
    86              
    87             =cut
    88              
    89             =head1 COPYRIGHT AND LICENSE
    90              
    91             Copyright (C) 2012-2018 Steve Kemp .
    92              
    93             This library is free software. You can modify and or distribute it under
    94             the same terms as Perl itself.
    95              
    96             =cut
    97              
    98             =head1 METHODS
    99              
    100             =cut
    101              
    102              
    103 11     11   5204 use strict;
      11         19  
      11         263  
    104 11     11   44 use warnings;
      11         15  
      11         306  
    105              
    106              
    107             package Templer::Plugin::FileGlob;
    108              
    109 11     11   58 use Cwd;
      11         15  
      11         583  
    110 11     11   57 use File::Basename;
      11         13  
      11         7506  
    111              
    112              
    113             =head2
    114              
    115             Constructor. No arguments are required/supported.
    116              
    117             =cut
    118              
    119             sub new
    120             {
    121 11     11 0 22 my ( $proto, %supplied ) = (@_);
    122 11   33     58 my $class = ref($proto) || $proto;
    123              
    124 11         49 my $self = {};
    125 11         21 bless( $self, $class );
    126 11         91 return $self;
    127             }
    128              
    129              
    130              
    131             =head2 expand_variables
    132              
    133             This is the method which is called by the L
    134             to expand the variables contained in a L object.
    135              
    136             Variables are written in the file in the form "key: value", and are
    137             internally stored within the Page object as a hash.
    138              
    139             This method iterates over each key & value and updates any that
    140             seem to refer to file-globs.
    141              
    142             =cut
    143              
    144             sub expand_variables
    145             {
    146 9     9 1 30 my ( $self, $site, $page, $data ) = (@_);
    147              
    148             #
    149             # Get the page-variables in the template.
    150             #
    151 9         58 my %hash = %$data;
    152              
    153             #
    154             # Look for a value of "file_glob" in each key.
    155             #
    156 9         44 foreach my $key ( keys %hash )
    157             {
    158 66 100       138 if ( $hash{ $key } =~ /^file_glob\((.*)\)/ )
    159             {
    160              
    161             #
    162             # Populate an array of hash-refs referring to files which match
    163             # a particular glob.
    164             #
    165             # Could be used for many things, will be used for image-gallaries.
    166             #
    167              
    168             #
    169             # Get the pattern and strip leading/trailing quotes and whitespace.
    170             #
    171 1         3 my $pattern = $1;
    172 1         2 $pattern =~ s/['"]//g;
    173 1         6 $pattern =~ s/^\s+|\s+$//g;
    174              
    175             #
    176             # Make sure we're relative to the directory containing
    177             # the actual input-page.
    178             #
    179             # This way globs will match what the author expected.
    180             #
    181 1         3 my $dirName = $page->source();
    182 1 50       5 if ( $dirName =~ /^(.*)\/(.*)$/ )
    183             {
    184 1         2 $dirName = $1;
    185             }
    186 1         3439 my $pwd = Cwd::cwd();
    187 1         32 chdir( $dirName . "/" );
    188              
    189             #
    190             # The value we'll set the variable to.
    191             #
    192 1         5 my $ref;
    193              
    194             #
    195             # The suffix of files that are Templer input-files.
    196             #
    197 1         11 my $suffix = $site->{ suffix };
    198              
    199              
    200             #
    201             # Run the glob.
    202             #
    203 1         131 foreach my $file ( glob($pattern) )
    204             {
    205              
    206             #
    207             # The page dependency also includes the matching filename now.
    208             #
    209 5 50       31 if ( $file =~ m{^/} )
    210             {
    211 0         0 $page->add_dependency($file);
    212             }
    213             else
    214             {
    215 5         46 $page->add_dependency( $dirName . "/" . $file );
    216             }
    217              
    218             #
    219             # Data reference - moved here so we can add height/width if the
    220             # glob refers to an image, and if we have Image::Size installed.
    221             #
    222 5         19 my %meta = ( file => $file );
    223              
    224             #
    225             # Populate filename parts.
    226             #
    227 5         121 my ( $basename, $dirname, $extension ) = fileparse($file);
    228 5         30 ( $meta{ 'dirname' } = $dirname ) =~ s{/$}{};
    229 5         30 ( $meta{ 'basename' } = $basename ) =~ s{(.*)\.([^.]*)$}{$1};
    230 5         22 $meta{ 'extension' } = $2;
    231              
    232             #
    233             # If the file is an image AND we have Image::Size
    234             # then populate the height/width too.
    235             #
    236 5 50 66     71 if ( $file =~ /\.(jpe?g|png|gif)$/i )
        100          
    237             {
    238 0         0 my $module = "use Image::Size;";
    239             ## no critic (Eval)
    240 0         0 eval($module);
    241             ## use critic
    242 0 0       0 if ( !$@ )
    243             {
    244 0 0       0 if ( -e $file )
    245             {
    246 0         0 ( $meta{ 'width' }, $meta{ 'height' } ) =
    247             imgsize($file);
    248             }
    249             else
    250             {
    251 0         0 print
    252             "WARNING: Attempting to invoke Image::Size on a file that doesn't exist: $file\n";
    253             }
    254             }
    255             }
    256             elsif ( ($suffix) && ( $file =~ /$suffix$/i ) )
    257             {
    258              
    259             #
    260             # If the file is a Templer input file
    261             # then populate templer variables
    262             #
    263 1         8 my $pageClass = ref $page;
    264 1         19 my $globPage = $pageClass->new( file => $file );
    265 1         7 while ( my ( $k, $v ) = each %{ $globPage } )
      5         19  
    266             {
    267 4         7 $meta{ $k } = $v;
    268             }
    269             }
    270             else
    271             {
    272              
    273             #
    274             # If it isn't an image we'll make the content available
    275             #
    276 4 50       173 if ( open( my $handle, "<:utf8", $file ) )
    277             {
    278 4         16 binmode( $handle, ":utf8" );
    279 4         82 while ( my $line = <$handle> )
    280             {
    281 4         24 $meta{ 'contents' } .= $line;
    282             }
    283 4         36 close($handle);
    284             }
    285             }
    286              
    287 5         37 push( @$ref, \%meta );
    288             }
    289              
    290             #
    291             # If we found at least one file then we'll update
    292             # the variable value to refer to the populated structure.
    293             #
    294 1 50       7 if ($ref)
    295             {
    296 1         7 $hash{ $key } = $ref;
    297             }
    298             else
    299             {
    300 0         0 print
    301             "WARNING: pattern '$pattern' matched zero files for page " .
    302             $page->source() . "\n";
    303 0         0 delete $hash{ $key };
    304             }
    305              
    306             #
    307             # Restore the PWD.
    308             #
    309 1         9 chdir($pwd);
    310             }
    311             }
    312              
    313 9         32 return ( \%hash );
    314             }
    315              
    316              
    317             #
    318             # Register the plugin.
    319             #
    320             Templer::Plugin::Factory->new()->register_plugin("Templer::Plugin::FileGlob");