File Coverage

blib/lib/Template/LiquidX/Tag/Include.pm
Criterion Covered Total %
statement 29 30 96.6
branch 11 18 61.1
condition 4 16 25.0
subroutine 7 7 100.0
pod 0 2 0.0
total 51 73 69.8


line stmt bran cond sub pod time code
1             package Template::LiquidX::Tag::Include;
2             our $VERSION = '1.0.5';
3 2     2   50595 use Template::Liquid;
  2         20761  
  2         69  
4             require Template::Liquid::Error;
5             require Template::Liquid::Utility;
6 2     2   10 use File::Spec;
  2         2  
  2         35  
7 2     2   18 use base 'Template::Liquid::Tag';
  2         1  
  2         1555  
8             my $base_dir;
9              
10             sub import {
11 2 50   2   17 $base_dir = $_[1] ? $_[1] : '_includes/';
12 2         7 Template::Liquid::register_tag('include');
13             }
14              
15             sub new {
16 4     4 0 1990 my ($class, $args) = @_;
17             raise Template::Liquid::Error {type => 'Context',
18             message => 'Missing template argument',
19             fatal => 1
20             }
21 4 50       11 if !defined $args->{'template'};
22             raise Template::Liquid::Error {type => 'Context',
23             message => 'Missing parent argument',
24             fatal => 1
25             }
26 4 50       5 if !defined $args->{'parent'};
27             raise Template::Liquid::Error {
28             type => 'Syntax',
29             message => 'Missing argument list in ' . $args->{'markup'},
30             fatal => 1
31             }
32 4 50       8 if !defined $args->{'attrs'};
33             return
34             bless {name => 'inc-' . $args->{'attrs'},
35             file => $args->{'attrs'},
36             parent => $args->{'parent'},
37             template => $args->{'template'},
38             tag_name => $args->{'tag_name'},
39 4         20 markup => $args->{'markup'},
40             }, $class;
41             }
42              
43             sub render {
44 4     4 0 156 my ($s) = @_;
45 4         10 my $file = $s->{template}{context}->get($s->{'file'});
46 4 100 50     73 raise Template::Liquid::Error {
47             type => 'Argument',
48             message => 'Error: Missing or undefined argument passed to include'
49             }
50             && return
51             if !defined $file;
52 3 50 33     26 if ( $file !~ m[^[\w\\/\.-_]+$]io
      33        
53             || $file =~ m[\.[\\/]]o
54             || $file =~ m[[//\\]\.]o)
55 0   0     0 { raise Template::Liquid::Error {
56             type => 'Argument',
57             message => sprintf
58             q[Error: Include file '%s' contains invalid characters or sequiences],
59             $file} && return;
60             }
61 3         25 $file = File::Spec->catdir(
62              
63             # $s->{template}{context}->registers->{'site'}->source,
64             $base_dir,
65             $file
66             );
67 3 100 50     51 raise Template::Liquid::Error {
68             type => 'I/O',
69             message => sprintf 'Error: Included file %s not found',
70             $file
71             }
72             && return
73             if !-f $file;
74 2 50 0     49 open(my ($FH), '<', $file)
75             || raise Template::Liquid::Error {
76             type => 'I/O',
77             message => sprintf 'Error: Cannot include file %s: %s',
78             $file, $!
79             }
80             && return;
81 2 50 0     24 sysread($FH, my ($DATA), -s $FH) == -s $FH
82             || raise Template::Liquid::Error {
83             type => 'I/O',
84             message => sprintf
85             'Error: Cannot include file %s (Failed to read %d bytes): %s',
86             $file, -s $FH, $!
87             }
88             && return;
89 2         8 my $partial = Template::Liquid->parse($DATA);
90 2         98 $partial->{'context'} = $s->{template}{context};
91 2     2   9 my $return = $partial->{context}->stack(sub { $partial->render(); });
  2         71  
92 2         61 return $return;
93             }
94             1;
95              
96             =pod
97              
98             =head1 NAME
99              
100             Template::LiquidX::Tag::Include - Include another file (Functioning Custom Tag Example)
101              
102             =head1 Synopsis
103            
104             {% include 'comments.inc' %}
105              
106             =head1 Description
107              
108             This is a demonstration of
109             L.
110              
111             If you find yourself using the same snippet of code or text in several
112             templates, you may consider making the snippet an include.
113              
114             You include static filenames...
115              
116             use Template::Liquid;
117             use Template::LiquidX::Tag::Include;
118             Template::Liquid->parse("{%include 'my.inc'%}")->render();
119              
120             ...or 'dynamic' filenames (for example, based on a variable)...
121              
122             use Template::Liquid;
123             use Template::LiquidX::Tag::Include;
124             Template::Liquid->parse('{%include inc%}')->render(inc => 'my.inc');
125              
126             =head1 Notes
127              
128             The default directory searched for includes is C<./_includes/> but this can be
129             changed in the include statement...
130              
131             use Template::LiquidX::Tag::Include '~/my_site/templates/includes';
132              
133             This mimics Jekyll's include statement and was a 15m hack so it's subject to
134             change ...and may be completly broken.
135              
136             =head1 See Also
137              
138             Liquid for Designers: http://wiki.github.com/tobi/liquid/liquid-for-designers
139              
140             L's section on
141             custom tags.
142              
143             =head1 Author
144              
145             Sanko Robinson - http://sankorobinson.com/
146              
147             =head1 License and Legal
148              
149             Copyright (C) 2009-2016 by Sanko Robinson Esanko@cpan.orgE
150              
151             This program is free software; you can redistribute it and/or modify it under
152             the terms of The Artistic License 2.0. See the F file included with
153             this distribution or http://www.perlfoundation.org/artistic_license_2_0. For
154             clarification, see http://www.perlfoundation.org/artistic_2_0_notes.
155              
156             When separated from the distribution, all original POD documentation is
157             covered by the Creative Commons Attribution-Share Alike 3.0 License. See
158             http://creativecommons.org/licenses/by-sa/3.0/us/legalcode. For
159             clarification, see http://creativecommons.org/licenses/by-sa/3.0/us/.
160              
161             =cut