Bug 16011: $VERSION - Remove the $VERSION init
[koha.git] / Koha / Misc / Files.pm
1 package Koha::Misc::Files;
2
3 # This file is part of Koha.
4 #
5 # Copyright 2012 Kyle M Hall
6 # Copyright 2014 Jacek Ablewicz
7 # Based on Koha/Borrower/Files.pm by Kyle M Hall
8 #
9 # Koha is free software; you can redistribute it and/or modify it
10 # under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 3 of the License, or
12 # (at your option) any later version.
13 #
14 # Koha is distributed in the hope that it will be useful, but
15 # WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with Koha; if not, see <http://www.gnu.org/licenses>.
21
22 use Modern::Perl;
23 use vars qw();
24
25 use C4::Context;
26 use C4::Output;
27
28 =head1 NAME
29
30 Koha::Misc::Files - module for managing miscellaneous files associated
31 with records from arbitrary tables
32
33 =head1 SYNOPSIS
34
35 use Koha::Misc::Files;
36
37 my $mf = Koha::Misc::Files->new( tabletag => $tablename,
38     recordid => $recordnumber );
39
40 =head1 FUNCTIONS
41
42 =over
43
44 =item new()
45
46 my $mf = Koha::Misc::Files->new( tabletag => $tablename,
47     recordid => $recordnumber );
48
49 Creates new Koha::Misc::Files object. Such object is essentially
50 a pair: in typical usage scenario, 'tabletag' parameter will be
51 a database table name, and 'recordid' an unique record ID number
52 from this table. However, this method does accept an arbitrary
53 string as 'tabletag', and an arbitrary integer as 'recordid'.
54
55 Particular Koha::Misc::Files object can have one or more file records
56 (actuall file contents + various file metadata) associated with it.
57
58 In case of an error (wrong parameter format) it returns undef.
59
60 =cut
61
62 sub new {
63     my ( $class, %args ) = @_;
64
65     my $recid = $args{'recordid'};
66     my $tag   = $args{'tabletag'};
67     ( defined($tag) && $tag ne '' && defined($recid) && $recid =~ /^\d+$/ )
68       || return ();
69
70     my $self = bless( {}, $class );
71
72     $self->{'table_tag'} = $tag;
73     $self->{'record_id'} = '' . ( 0 + $recid );
74
75     return $self;
76 }
77
78 =item GetFilesInfo()
79
80 my $files_descriptions = $mf->GetFilesInfo();
81
82 This method returns a reference to an array of hashes
83 containing files metadata (file_id, file_name, file_type,
84 file_description, file_size, date_uploaded) for all file records
85 associated with given $mf object, or an empty arrayref if there are
86 no such records yet.
87
88 In case of an error it returns undef.
89
90 =cut
91
92 sub GetFilesInfo {
93     my $self = shift;
94
95     my $dbh   = C4::Context->dbh;
96     my $query = '
97         SELECT
98             file_id,
99             file_name,
100             file_type,
101             file_description,
102             date_uploaded,
103             LENGTH(file_content) AS file_size
104         FROM misc_files
105         WHERE table_tag = ? AND record_id = ?
106         ORDER BY file_name, date_uploaded
107     ';
108     my $sth = $dbh->prepare($query);
109     $sth->execute( $self->{'table_tag'}, $self->{'record_id'} );
110     return $sth->fetchall_arrayref( {} );
111 }
112
113 =item AddFile()
114
115 $mf->AddFile( name => $filename, type => $mimetype,
116     description => $description, content => $content );
117
118 Adds a new file (we want to store for / associate with a given
119 object) to the database. Parameters 'name' and 'content' are mandatory.
120 Note: this method would (silently) fail if there is no 'name' given
121 or if the 'content' provided is empty.
122
123 =cut
124
125 sub AddFile {
126     my ( $self, %args ) = @_;
127
128     my $name        = $args{'name'};
129     my $type        = $args{'type'} // '';
130     my $description = $args{'description'};
131     my $content     = $args{'content'};
132
133     return unless ( defined($name) && $name ne '' && defined($content) && $content ne '' );
134
135     my $dbh   = C4::Context->dbh;
136     my $query = '
137         INSERT INTO misc_files ( table_tag, record_id, file_name, file_type, file_description, file_content )
138         VALUES ( ?,?,?,?,?,? )
139     ';
140     my $sth = $dbh->prepare($query);
141     $sth->execute( $self->{'table_tag'}, $self->{'record_id'}, $name, $type,
142         $description, $content );
143 }
144
145 =item GetFile()
146
147 my $file = $mf->GetFile( id => $file_id );
148
149 For an individual, specific file ID this method returns a hashref
150 containing all metadata (file_id, table_tag, record_id, file_name,
151 file_type, file_description, file_content, date_uploaded), plus
152 an actuall contents of a file (in 'file_content'). In typical usage
153 scenarios, for a given $mf object, specific file IDs have to be
154 obtained first by GetFilesInfo() call.
155
156 Returns undef in case when file ID specified as 'id' parameter was not
157 found in the database.
158
159 =cut
160
161 sub GetFile {
162     my ( $self, %args ) = @_;
163
164     my $file_id = $args{'id'};
165
166     my $dbh   = C4::Context->dbh;
167     my $query = '
168         SELECT * FROM misc_files WHERE file_id = ? AND table_tag = ? AND record_id = ?
169     ';
170     my $sth = $dbh->prepare($query);
171     $sth->execute( $file_id, $self->{'table_tag'}, $self->{'record_id'} );
172     return $sth->fetchrow_hashref();
173 }
174
175 =item DelFile()
176
177 $mf->DelFile( id => $file_id );
178
179 Deletes specific, individual file record (file contents and metadata)
180 from the database.
181
182 =cut
183
184 sub DelFile {
185     my ( $self, %args ) = @_;
186
187     my $file_id = $args{'id'};
188
189     my $dbh   = C4::Context->dbh;
190     my $query = '
191         DELETE FROM misc_files WHERE file_id = ? AND table_tag = ? AND record_id = ?
192     ';
193     my $sth = $dbh->prepare($query);
194     $sth->execute( $file_id, $self->{'table_tag'}, $self->{'record_id'} );
195 }
196
197 =item DelAllFiles()
198
199 $mf->DelAllFiles();
200
201 Deletes all file records associated with (stored for) a given $mf object.
202
203 =cut
204
205 sub DelAllFiles {
206     my ($self) = @_;
207
208     my $dbh   = C4::Context->dbh;
209     my $query = '
210         DELETE FROM misc_files WHERE table_tag = ? AND record_id = ?
211     ';
212     my $sth = $dbh->prepare($query);
213     $sth->execute( $self->{'table_tag'}, $self->{'record_id'} );
214 }
215
216 =item MergeFileRecIds()
217
218 $mf->MergeFileRecIds(@ids_to_be_merged);
219
220 This method re-associates all individuall file records associated with
221 some "parent" records IDs (provided in @ids_to_be_merged) with the given
222 single $mf object (which would be treated as a "parent" destination).
223
224 This a helper method; typically it needs to be called only in cases when
225 some "parent" records are being merged in the (external) 'tablename'
226 table.
227
228 =cut
229
230 sub MergeFileRecIds {
231     my ( $self, @ids_to_merge ) = @_;
232
233     my $dst_recid = $self->{'record_id'};
234     @ids_to_merge = map { ( $dst_recid == $_ ) ? () : ($_); } @ids_to_merge;
235     @ids_to_merge > 0 || return ();
236
237     my $dbh   = C4::Context->dbh;
238     my $query = '
239         UPDATE misc_files SET record_id = ?
240         WHERE table_tag = ? AND record_id = ?
241     ';
242     my $sth = $dbh->prepare($query);
243
244     for my $src_recid (@ids_to_merge) {
245         $sth->execute( $dst_recid, $self->{'table_tag'}, $src_recid );
246     }
247 }
248
249 1;
250
251 __END__
252
253 =back
254
255 =head1 SEE ALSO
256
257 Koha::Patron::Files
258
259 =head1 AUTHOR
260
261 Kyle M Hall E<lt>kyle.m.hall@gmail.comE<gt>,
262 Jacek Ablewicz E<lt>ablewicz@gmail.comE<gt>
263
264 =cut