File Coverage

blib/lib/Template/Plexsite/URLTable.pm
Criterion Covered Total %
statement 84 185 45.4
branch 3 36 8.3
condition 1 14 7.1
subroutine 23 28 82.1
pod 3 9 33.3
total 114 272 41.9


line stmt bran cond sub pod time code
1             package Template::Plexsite::URLTable;
2 1     1   212389 use v5.36;
  1         4  
3 1     1   8 use feature qw;
  1         2  
  1         173  
4 1     1   7 no warnings "experimental";
  1         2  
  1         54  
5              
6 1     1   8 use Scalar::Util qw;
  1         2  
  1         91  
7              
8              
9 1     1   8 use File::Basename qw;
  1         20  
  1         68  
10 1     1   7 use Log::ger;
  1         3  
  1         6  
11 1     1   1737 use Log::OK;
  1         2  
  1         9  
12              
13 1     1   4576 use Template::Plex;
  1         33071  
  1         42  
14 1     1   764 use Template::Plexsite;
  1         5  
  1         63  
15              
16 1     1   6 use File::Basename qw;
  1         3  
  1         69  
17 1     1   6 use File::Spec::Functions qw;
  1         2  
  1         55  
18 1     1   7 use File::Path qw;
  1         2  
  1         60  
19 1     1   691 use File::Copy;
  1         4370  
  1         106  
20             #use Data::Dumper;
21              
22 1     1   8 use constant::more ("root_=0", qw);
  1         2  
  1         10  
23              
24             sub new {
25 1     1 0 290346 my $package=shift;
26 1         3 my $self=[];
27 1         8 my %options=@_;
28 1         6 $self->[root_]=$options{src};
29 1         5 $self->[html_root_]=$options{html_root};
30 1         3 $self->[table_]={};
31 1         4 $self->[locale_]=$options{locale};
32 1         9 $self->[nav_]={
33             _data=>{
34             label=>"/",
35             href=>undef,
36             }
37             };
38              
39 1         6 bless $self, $package;
40             }
41              
42              
43             #Adds a resource with input relative to project root (src dir).
44             #Absolute paths are converted into relative paths from project root.
45             #Options gives output and mode
46             #if input is a dir all items are added
47             sub add_resource {
48 1     1 1 4478 my ($self, $input, %options)=@_;
49            
50 1         4 my $root=$self->[root_];
51 1         4 \my %table=$self->[table_];
52              
53 1         3 my $return;
54              
55              
56             my $path;
57 1 50       7 if($input=~m|^/|){
58 0         0 $input=abs2rel $input, $root;
59 0         0 say STDERR "Relateive path from abs input PLEXSITE";
60 0         0 say STDERR $input;
61             }
62              
63 1         2 $path=$root."/".$input;
64              
65             #Show warning if resource is already included
66             #
67 1 50       5 if($table{$input}){
68 0         0 Log::OK::WARN and log_warn "Resource: input $input already exists in table. Skipping";
69 0         0 say STDERR $table{$input}{output};
70 0         0 $return=$input;;#$input;
71 0         0 goto OUTPUT;
72             #return $input;
73             }
74              
75             #TODO: add filter to options for restricting file types
76            
77              
78              
79             #test if input actually exists
80 1 50       69 unless( -e $path){
81 1         10 Log::OK::WARN and log_warn __PACKAGE__." Resource: input $path does not exist.";
82 1         118 return undef;
83             }
84              
85             #Test if input is in fact a plain dir or a plt template
86             #
87 0 0 0     0 if(-d $path and $path =~ /plt$/){
    0          
88 0         0 $return=$self->_add_template($input, %options);
89 0         0 goto OUTPUT;
90              
91             }
92             elsif(-d $path){
93 0         0 my @stack;
94             my @inputs;
95             #recursivy add resources
96             #
97 0         0 push @stack, $path;
98            
99             #TODO: need to check that the file does not represent a html template
100 0         0 while(@stack){
101 0         0 my $item=pop @stack;
102             #Log::OK::DEBUG and log_debug "Plexsite: TESTING item $item";
103 0 0       0 if( -d $item){
104             #TODO: filter with filter in options
105 0         0 push @stack, <"$item/*">;
106             }
107             else {
108 0         0 push @inputs, $item;
109             }
110             }
111            
112 0         0 for(@inputs){
113             #strip root from working dir relative paths from globbing
114             #s/^$root\///;
115 0         0 say STDERR "INPUT is: $_";
116 0         0 say STDERR "ROOT is: $_";
117 0         0 $_=abs2rel $_, $root;
118 0         0 say STDERR "NEW INPUT is: $_";
119 0         0 my %opts=%options;
120 0         0 $opts{output}=$_;
121              
122 0         0 $table{$_}=\%opts;
123             }
124 0         0 $return=\@inputs;
125 0         0 goto OUTPUT;
126              
127             }
128             else {
129             #Assume a file
130             #add to url table
131 0 0       0 unless($options{output}){
132 0         0 $options{output}=$input; #$t_out->{location}."/".$input;
133             }
134              
135 0         0 my $in=$input;
136 0         0 $table{$in}=\%options;
137 0         0 Log::OK::INFO and log_info "Resource: Adding $in => $table{$in}{output}";
138 0         0 $return=$in;#$options{output}//$in;
139 0         0 goto OUTPUT;
140             }
141              
142             OUTPUT:
143 0 0       0 if(ref($return) eq "ARRAY"){
144 0         0 return $return->@*;
145             }
146 0         0 return $return
147             #return 1;
148             }
149              
150              
151             #setup config/vars for template
152             #setup table entry
153             #
154             sub _add_template {
155 0     0   0 my ($self, $input, %options)=@_;
156              
157 0         0 Log::OK::INFO and log_info("Resource: Adding template $input");
158 0         0 Log::OK::INFO and log_info("Resource: locale set to: $self->[locale_]");
159              
160 0         0 my $root=$self->[root_];
161              
162 0         0 my %opts;
163 0         0 $opts{base}="Template::Plexsite";
164 0         0 $opts{use}=["Template::Plexsite"];
165 0         0 $opts{root}=$self->[root_];
166              
167             my %entry=(
168             template=> {
169             config=>{ # config is the hash used for lexical binding
170             target=>$options{target}, # relative path to document. overrides plt for nav
171 0         0 plexsite=>{},
172             menu=>undef, #Templates spec on menu (stage 1)
173             nav=>$self->[nav_], #Acculated menu tree (stage 2)
174             output=>undef, #Templates spec on output (state 1)
175             locale=>$self->[locale_], #Input local (stage 1)
176             #url_table=>{}, #DIR relative url lookup table (stage 2)
177             res=>{}, #Alias for above
178             table=>$self, #Input URLTable object
179              
180             parent=>undef,
181             slots=>{},
182             plt=>$input, #Path to the input plt
183             html_root=>$self->[html_root_]
184             },
185             template=>undef
186             },
187              
188             output=>"", #main
189             input=>$input,
190             );
191              
192 0         0 weaken $entry{template}{config}{table};
193              
194 0         0 my ($index_file)= <"$root/$input/index.*" >;
195            
196              
197             #strip $root from glob result for inputs
198             #my $src=$index_file=~s|^$root/||r;
199 0         0 my $src=abs2rel($index_file, $root);
200              
201             #strip plex $input and extension if present
202             #my $target=$src=~s/\.plex$|\.plx$//r;
203             #$target=~s|$input/||;
204              
205             #Alias %config
206 0         0 \my %config=$entry{template}{config};
207              
208 0         0 $self->[table_]{$input}=\%entry; #Add before load
209              
210             #Inputs are dirs with plt extensions. A index.html page exists inside
211 0         0 my $template=Template::Plexsite->load($input, \%config, %opts);
212              
213             #If Output variable is set, we can add it to the list
214 0 0       0 if(defined $config{output}{location}){
215            
216             #add entry to output file table
217             #$entry{output}=$config{locale}."/".$config{output}{location}."/".$target;
218              
219 0         0 $entry{template}{template}=$template;
220             #$entry{output}=$template->output_path;
221 0         0 return $input;
222             }
223             else {
224             #say "LOCATION NOT SET for ",$src;
225             }
226              
227 0         0 return undef;
228             }
229              
230             #Do a lookup of an input resource to find the resulting output url
231             sub lookup {
232 1     1 1 8 my ($self,$input)=@_;
233 1         48 $self->[table_]{$input};
234             }
235              
236              
237             ##############################################################################
238             # #src and dest are input paths #
239             # sub path_from_to { #
240             # my ($self, $src, $dest)=@_; #
241             # #Input is relative to root #
242             # my $src_entry=$self->[table_]{$src}; #
243             # my $dest_entry=$self->[table_]{$dest}; #
244             # #
245             # if($src_entry and $dest_entry){ #
246             # #build output path based on options in entry #
247             # my $src_output=$src_entry->{output}; #
248             # my $dir=dirname $src_output; #
249             # #
250             # my $dest_output=$dest_entry->{output}; #
251             # my $rel=abs2rel($dest_output, $dir); #
252             # return $rel; #
253             # } #
254             # undef; #
255             # } #
256             # #
257             # ## Create url tables which create outputs relative to output directories #
258             # # The relative table is passed to the template at that dir level to allow #
259             # # correct relative resolving of resources #
260             # sub permute { #
261             # my $self=shift; #
262             # my $force=shift; #
263             # return $self->[dir_table_] if $self->[dir_table_] and not $force; #
264             # Log::OK::INFO and log_info "Permuting outputs relative to inputs"; #
265             # \my %table=$self->[table_]; #
266             # my %dir_table; #
267             # #
268             # for my $input_path(keys %table){ #
269             # my $options=$table{$input_path}; #
270             # my $output_path=$options->{output}; #
271             # #
272             # my $dir=dirname $output_path; #
273             # next if $dir_table{$dir}; #
274             # my $base=basename $output_path; #
275             # for my $input_path (keys %table){ #
276             # my $options=$table{$input_path}; #
277             # my $output_path=$options->{output}; #
278             # my $rel=abs2rel($output_path, $dir); #
279             # $dir_table{$dir}{$input_path}=$rel; #
280             # } #
281             # } #
282             # $self->[dir_table_]=\%dir_table; #
283             # } #
284             ##############################################################################
285              
286             # Returns the relative path between two items in output name space, given the
287             # input name space target and reference
288             #
289             # If input is undefined, returns the relative "." path
290             #
291             sub map_input_to_output {
292 0     0 0 0 my ($self, $target, $reference)=@_;
293 0 0       0 return "." unless $target;
294              
295              
296             # remove any fragments for lookup
297 0         0 my ($input, $frag1)=split "#", $target;
298 0         0 my ($input_reference, $frag2)=split "#", $reference;
299              
300              
301              
302              
303 0         0 my $ref_entry=$self->table->{$reference};
304              
305 0         0 my $output_reference=$ref_entry->{output};
306              
307 0         0 my $input_entry=$self->table->{$input};
308 0         0 my $output=$input_entry->{output};
309              
310             #make relative path from output reference to output
311 0         0 my $o=abs2rel($output,dirname $output_reference);
312 0 0       0 $o=$o."#".$frag1 if $frag1;
313 0         0 $o;
314              
315            
316              
317              
318             }
319              
320              
321             #Generate sitemap xml file
322       0 0   sub site_map {
323              
324             }
325              
326             #copy/move/link resources into output locations
327             sub build {
328             #Use options to direct execution
329             #if render field is a string, it can be
330             # none => do nothing with input
331             # copy => copy input to output location if input older than output
332             # link => link input to output location
333             # filter => contents of file filtered through sub routine
334            
335             #if render field is a sub, it is called with the entry for processing
336             #ie this could be a template
337 1     1 1 10 my ($self)=@_;
338            
339              
340 1         4 $self->_render_templates;
341 1         5 $self->_static_files;
342 1         4 $self->_site_map;
343             }
344              
345             sub _site_map {
346 1     1   20 my ($self)=@_;
347              
348             }
349             sub _static_files {
350 1     1   3 my ($self)=@_;
351 1         4 my $root=$self->[root_];
352 1         3 my $html_root=$self->[html_root_];
353              
354             #Process only entries with no template
355 1         4 for my $input (keys $self->[table_]->%*){
356 0         0 my $entry=$self->[table_]{$input};
357 0 0       0 next if $entry->{template};
358 0         0 Log::OK::TRACE and log_trace __PACKAGE__." static files: processing $input";
359              
360              
361 0         0 $input=$root."/".$input;
362 0         0 my $output=$html_root."/".$entry->{output};
363              
364 0         0 mkpath dirname $output;
365              
366 0         0 my @stat_in=stat $input;
367 0         0 my @stat_out=stat $output;
368 0 0       0 unless(@stat_in){
369 0         0 Log::OK::WARN and log_warn "Could not locate input: $input";
370 0         0 next;
371             }
372              
373 0 0 0     0 if(!$stat_out[9] or $stat_out[9] < $stat_in[9]){
374 0         0 Log::OK::INFO and log_info("COPY $input=> $output");
375 0         0 copy $input, $output;
376             }
377             else {
378 0         0 Log::OK::DEBUG and log_debug("Upto date: $input=> $output");
379             }
380              
381              
382             }
383            
384             }
385              
386             #Work all template resources
387             # Does a lookup on the permuted output dirs
388             sub _render_templates {
389 1     1   3 my ($self)=@_;
390 1         4 Log::OK::TRACE and log_trace "URLTable: _render_templates";
391              
392             # Sort the templates by relative rendering order of output
393             # This gives accumulation type templates to work
394              
395 1         43 my @templates=$self->ordered_entries;
396             #use Data::Dumper;
397              
398             #render all resources
399             #for my $input (keys $self->[table_]->%*){
400             #my $entry= $self->[table_]{$input};
401 1         3 for my $entry(@templates){
402 0 0       0 next unless $entry->{template};
403 0         0 try {
404 0         0 my $template=$entry->{template}{template};
405 0 0       0 if(defined $template){
406             #Log::OK::INFO and log_info "Rendering template $input => ".$template->output_path;
407 0         0 Log::OK::INFO and log_info "Rendering template => ".$template->output_path;
408              
409 0         0 $template->build;
410             }
411             else {
412 0         0 Log::OK::INFO and log_info "No output location for template $entry->{template}{config}{plt}. Ignoring";
413            
414             }
415             }
416             catch($e){
417             #Log::OK::ERROR and log_error __PACKAGE__." Could not render $input: $e";
418 0         0 Log::OK::ERROR and log_error $e;
419             };
420             }
421             }
422              
423             # Sort template entries by the specified render order
424             sub ordered_entries {
425 1     1 0 4 my ($self)=@_;
426              
427             # First it gives entries an order if not already set
428              
429             #find the current max order
430 1         2 my $max;
431 1     1   4099 use List::Util qw;
  1         2  
  1         700  
432             my @pairs=
433 1         14 grep {defined $_->[1]{template}}
  0         0  
434             pairs $self->[table_]->%*;
435              
436              
437 1         4 for my $p (@pairs){
438 0         0 for($p->[1]{template}{config}{output}{order}){
439            
440 0 0       0 unless(defined($max)){
441 0         0 $max=$_;
442 0         0 next;
443             }
444 0 0 0     0 $max=$_ if defined($_) and $_>$max;
445             }
446             }
447 1   50     10 $max//=0;
448              
449              
450              
451             #sort {$a->{template}{config}{output}{order} <=> $b->{template}{config}{output}{order}} values $self->[table_]->%*;
452             map $_->[1],
453 0           sort {$a->[1]{template}{config}{output}{order} <=> $b->[1]{template}{config}{output}{order}}
454 1   0     5 map {$_->[1]{template}{config}{output}{order}//= ++$max; $_; }
  0            
  0            
455             @pairs;
456             }
457              
458             sub clear {
459 0     0 0   $_[0][table_]={};
460             }
461              
462             sub table{
463 0     0 0   $_[0][table_];
464             }
465             1;