aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/FixMyStreet/PhotoStorage/FileSystem.pm
blob: 0600f867d8607bad71489244c3a114f4ec7d812e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package FixMyStreet::PhotoStorage::FileSystem;

use Moose;
use parent 'FixMyStreet::PhotoStorage';

use Path::Tiny 'path';


has upload_dir => (
    is => 'ro',
    lazy => 1,
    default => sub {
        my $dir = FixMyStreet->config('PHOTO_STORAGE_OPTIONS')->{UPLOAD_DIR} ||
                  FixMyStreet->config('UPLOAD_DIR');
        return path($dir)->absolute(FixMyStreet->path_to());
    },
);


=head2 get_file

Returns a Path::Tiny path to a file on disk identified by an ID and type.
File may or may not exist. This handle is then used to read photo data or
write to disk.

=cut

sub get_file {
    my ($self, $fileid, $type) = @_;
    my $cache_dir = $self->upload_dir;
    return path( $cache_dir, "$fileid.$type" );
}


=head2 store_photo

Stores a blob of binary data representing a photo on disk.
Returns a key which is used in the future to get the contents of the file.

=cut

sub store_photo {
    my ($self, $photo_blob) = @_;

    my $type = $self->detect_type($photo_blob) || 'jpeg';
    my $fileid = $self->get_fileid($photo_blob);
    my $file = $self->get_file($fileid, $type);
    $file->spew_raw($photo_blob);

    return $file->basename;
}


=head2 retrieve_photo

Fetches the file content of a particular photo from storage.
Returns the binary blob and the filetype, if the photo exists in storage.

=cut

sub retrieve_photo {
    my ($self, $filename) = @_;

    my ($fileid, $type) = split /\./, $filename;
    my $file = $self->get_file($fileid, $type);
    if ($file->exists) {
        my $photo = $file->slurp_raw;
        return ($photo, $type);
    }
}


=head2 validate_key

A long-running FMS instance might have reports whose photo IDs in the DB
don't include the file extension. This function takes a value from the DB and
returns a 'tidied' version that can be used when calling photo_exists
or retrieve_photo.

If the passed key doesn't seem like it'll result in a valid filename (i.e.
it's not a 40-char SHA1 hash) returns undef.

=cut

sub validate_key {
    my ($self, $key) = @_;

    my ($fileid, $type) = split /\./, $key;
    $type ||= 'jpeg';
    if ($fileid && length($fileid) == 40) {
        return "$fileid.$type";
    }
}

1;