1package File::Assets::Filter::Collect;
2
3use strict;
4use warnings;
5
6use base qw/File::Assets::Filter/;
7
8use Digest;
9use File::Assets;
10
11for my $ii (qw/fingerprint_digest fingerprint_digester/) {
12    no strict 'refs';
13    *$ii = sub {
14        my $self = shift;
15        return $self->stash->{$ii} unless @_;
16        return $self->stash->{$ii} = shift;
17    };
18}
19
20sub signature {
21    return "collect";
22}
23
24my %default = (qw/
25        skip_single 0
26        skip_if_exists 0
27        skip_inline 1
28        check_content 0
29        fingerprint_digest 1
30        check_age 1
31    /,
32);
33
34sub new {
35    my $class = shift;
36    my $self = $class->SUPER::new(@_);
37    local %_ = @_;
38    while (my ($setting, $value) = each %default) {
39        $self->cfg->{$setting} = exists $_{$setting} ? $_{$setting} : $value;
40    }
41    return $self;
42}
43
44sub pre {
45    my $self = shift;
46    $self->SUPER::pre(@_);
47
48    return 0 if $self->skip_if_exists;
49
50    if ($self->cfg->{fingerprint_digest}) {
51        $self->fingerprint_digester(File::Assets::Util->digest);
52    }
53
54    return 1;
55}
56
57sub process {
58    my $self = shift;
59    $self->SUPER::process(@_);
60    if (my $digester = $self->fingerprint_digester) {
61        my $asset = $_[0];
62        $digester->add($asset->digest."\n");
63    }
64}
65
66sub post {
67    my $self = shift;
68    $self->SUPER::post(@_);
69
70    my $matched = $self->matched;
71
72    return unless @$matched;
73
74    return if $self->cfg->{skip_single} && 1 == @$matched;
75
76    if (my $digester = $self->fingerprint_digester) {
77        $self->fingerprint_digest($digester->hexdigest);
78    }
79
80    return if $self->skip_if_exists;
81
82    my $build = $self->should_build;
83
84    if ($build) {
85        $self->build;
86    }
87
88    $self->substitute;
89}
90
91sub skip_if_exists {
92    my $self = shift;
93
94    if ($self->cfg->{skip_if_exists} && $self->asset) {
95        if (-e $self->asset->file && -s _) {
96            $self->replace;
97            return 1;
98        }
99    }
100    return 0;
101}
102
103sub should_build {
104    my $self = shift;
105
106#    if ($self->cfg->{check_content}) {
107#        my $digest = $self->fingerprint_digest;
108#        my $dir = $self->group->rsc->dir->subdir(".check-content-digest");
109#        my $file = $dir->file($digest);
110#        unless (-e $file) {
111#            $file->touch;
112#            return 1;
113#        }
114#        $file->touch;
115#    }
116
117    if ($self->cfg->{check_age}) {
118        my $mtime = $self->mtime;
119        return 1 if $mtime > $self->output_asset->file_mtime;
120    }
121
122#    if ($self->cfg->{check_digest}) {
123#        my $file = $self->check_digest_file;
124#        unless (-e $file) {
125#            return 1;
126#        }
127#    }
128
129    return 0;
130}
131
132sub match {
133    my $self = shift;
134    my $asset = shift;
135    my $match = shift;
136    return $self->SUPER::match($asset, $match &&
137        (! $asset->inline || ! $self->cfg->{skip_inline}) &&
138        (! $asset->outside)
139    );
140}
141
142#sub check_digest_file {
143#    my $self = shift;
144#    my $key_digest = $self->key_digest;
145#    my $dir = $self->assets->rsc->dir->subdir(".check-digest");
146#    $dir->mkpath unless -d $dir;
147#    my $file = $dir->file($key_digest);
148#    return $file;
149#}
150
151sub build {
152    my $self = shift;
153
154    my $content = $self->build_content;
155
156    my $output_asset = $self->output_asset;
157
158    $output_asset->write($content) if defined $content;
159
160    return $output_asset;
161}
162
163sub output_asset {
164    my $self = shift;
165    return $self->stash->{output_asset} ||= do {
166        $self->assets->output_asset($self);
167    };
168}
169
170sub substitute {
171    my $self = shift;
172    my $asset = shift || $self->output_asset;
173
174    my $slice = $self->slice;
175    my $matched = $self->matched;
176    my $top_match = $matched->[0];
177    my $top_asset = $top_match->{asset};
178
179    for my $match (reverse @$matched) {
180        my $rank = $match->{rank};
181        splice @$slice, $rank, 1, ();
182    }
183
184    splice @$slice, $top_match->{rank}, 0, $asset;
185}
186
187sub fingerprint {
188    return $_[0]->fingerprint_digest;
189}
190
1911;
192
193__END__
194
195sub find_type {
196    my $self = shift;
197    my $frob;
198    return $frob if $frob = $self->type;
199    return $frob if (($frob = $self->matched->[0]) && ($frob = $frob->{asset}->type));
200    return undef;
201}
202
203