File Coverage

blib/lib/WWW/Shopify/Liquid/Optimizer.pm
Criterion Covered Total %
statement 56 63 88.8
branch 18 30 60.0
condition 1 3 33.3
subroutine 16 20 80.0
pod 0 13 0.0
total 91 129 70.5


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3 37     37   272 use strict;
  37         105  
  37         1130  
4 37     37   237 use warnings;
  37         100  
  37         1092  
5              
6 37     37   246 use WWW::Shopify::Liquid;
  37         101  
  37         1315  
7              
8             package WWW::Shopify::Liquid::Optimizer;
9 37     37   239 use base 'WWW::Shopify::Liquid::Pipeline';
  37         134  
  37         3810  
10 37     37   11928 use WWW::Shopify::Liquid::Security;
  37         127  
  37         1109  
11              
12 37     37   270 use Clone qw(clone);
  37         102  
  37         28364  
13             sub new {
14 85     85 0 295 my $package = shift;
15 85         493 my $self = bless {
16             clone_hash => 1,
17             remove_assignment => 0,
18             max_unrolling => 1000,
19             max_inclusion_depth => 5,
20             timeout => undef,
21             inclusion_context => undef,
22             inclusion_depth => 0,
23             security => WWW::Shopify::Liquid::Security->new,
24             conditional_state => [],
25             @_
26             }, $package;
27 85         838 return $self;
28             }
29 110 50   110 0 312 sub clone_hash { $_[0]->{clone_hash} = $_[1] if defined $_[1]; return $_[0]->{clone_hash}; }
  110         1593  
30 24 100   24 0 96 sub security { $_[0]->{security} = $_[1] if defined $_[1]; return $_[0]->{security}; }
  24         205  
31 0 0   0 0 0 sub max_inclusion_depth { $_[0]->{max_inclusion_depth} = $_[1] if defined $_[1]; return $_[0]->{max_inclusion_depth}; }
  0         0  
32 0 0   0 0 0 sub inclusion_context { $_[0]->{inclusion_context} = $_[1] if defined $_[1]; return $_[0]->{inclusion_context}; }
  0         0  
33 0 0   0 0 0 sub inclusion_depth { $_[0]->{inclusion_depth} = $_[1] if defined $_[1]; return $_[0]->{inclusion_depth}; }
  0         0  
34             # If we're inside a non-fully-resolved branch, then this is flagged as true; means we can't actually assign things.
35             sub push_conditional_state {
36 33     33 0 91 my ($self) = @_;
37 33         64 push(@{$self->{conditional_state}}, { });
  33         132  
38             }
39             sub conditional_state {
40 30 100   30 0 72 return undef unless int(@{$_[0]->{conditional_state}}) > 0;
  30         177  
41 5         16 return $_[0]->{conditional_state}->[-1];
42             }
43             # Removes the variable from the hash, preventing further optimization, as post unevaluated conditional block, the status of the variable will be uncertain.
44             sub flag_conditional_uncertainty {
45 27     27 0 105 my ($self, $idarray) = @_;
46 27         124 my $state = $self->conditional_state;
47 27 100       120 return undef unless defined $state;
48 5         21 my $id = join(".", @$idarray);
49 5         23 $state->{$id} = $idarray;
50             }
51             sub pop_conditional_state {
52 33     33 0 98 my ($self, $hash) = @_;
53 33         63 my $state = pop(@{$self->{conditional_state}});
  33         99  
54 33         184 for (values(%$state)) {
55 5         32 my ($reference, $parent) = $self->variable_reference($hash, $_);
56             # If the parent is a hash, remove the element from the hash.
57 5 50       44 delete $parent->{$_->[-1]} if ref($parent) eq 'HASH';
58             }
59             }
60             # Depending on the type of optimization, you may or may not want to remove assignment or capture blocks.
61             # In cases where this liquid may be inserted inside other liquid, you may want to set this to 0, as the assignments may affect external objects.
62             # In cases where the liquid is the only thing being evaluated, with no outside context, it's fine to set this 1.
63 33 100   33 0 9006 sub remove_assignment { $_[0]->{remove_assignment} = $_[1] if defined $_[1]; return $_[0]->{remove_assignment}; }
  33         180  
64 55 50   55 0 207 sub timeout { $_[0]->{timeout} = $_[1] if defined $_[1]; return $_[0]->{timeout}; }
  55         210  
65              
66             sub optimize {
67 55     55 0 10063 my ($self, $hash, $ast) = @_;
68 55 50       226 return undef unless $ast;
69 55 50 33     301 my $hash_clone = $self->clone_hash && $self->clone_hash == 1 ? clone($hash) : $hash;
70 55         184 my $result;
71             {
72 55     0   114 local $SIG{ALRM} = sub { die new WWW::Shopify::Liquid::Exception::Timeout(); };
  55         1017  
  0         0  
73 55 50       305 alarm $self->timeout if $self->timeout;
74 55         350 $result = $ast->optimize($self, $hash_clone);
75 54         823 alarm 0;
76             }
77 54 100       422 return !ref($result) ? WWW::Shopify::Liquid::Token::Text->new(undef, defined $result ? $result : '') : $result;
    100          
78             }
79              
80             1;