Bug 25663: Add unit tests
[koha.git] / Koha / Misc / Files.pm
bloba107441b6d680cb9a07b1c529d226fded4709b23
1 package Koha::Misc::Files;
3 # This file is part of Koha.
5 # Copyright 2012 Kyle M Hall
6 # Copyright 2014 Jacek Ablewicz
7 # Based on Koha/Borrower/Files.pm by Kyle M Hall
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.
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.
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>.
22 use Modern::Perl;
24 use C4::Context;
25 use C4::Output;
27 =head1 NAME
29 Koha::Misc::Files - module for managing miscellaneous files associated
30 with records from arbitrary tables
32 =head1 SYNOPSIS
34 use Koha::Misc::Files;
36 my $mf = Koha::Misc::Files->new( tabletag => $tablename,
37 recordid => $recordnumber );
39 =head1 FUNCTIONS
41 =over
43 =item new()
45 my $mf = Koha::Misc::Files->new( tabletag => $tablename,
46 recordid => $recordnumber );
48 Creates new Koha::Misc::Files object. Such object is essentially
49 a pair: in typical usage scenario, 'tabletag' parameter will be
50 a database table name, and 'recordid' an unique record ID number
51 from this table. However, this method does accept an arbitrary
52 string as 'tabletag', and an arbitrary integer as 'recordid'.
54 Particular Koha::Misc::Files object can have one or more file records
55 (actuall file contents + various file metadata) associated with it.
57 In case of an error (wrong parameter format) it returns undef.
59 =cut
61 sub new {
62 my ( $class, %args ) = @_;
64 my $recid = $args{'recordid'};
65 my $tag = $args{'tabletag'};
66 ( defined($tag) && $tag ne '' && defined($recid) && $recid =~ /^\d+$/ )
67 || return ();
69 my $self = bless( {}, $class );
71 $self->{'table_tag'} = $tag;
72 $self->{'record_id'} = '' . ( 0 + $recid );
74 return $self;
77 =item GetFilesInfo()
79 my $files_descriptions = $mf->GetFilesInfo();
81 This method returns a reference to an array of hashes
82 containing files metadata (file_id, file_name, file_type,
83 file_description, file_size, date_uploaded) for all file records
84 associated with given $mf object, or an empty arrayref if there are
85 no such records yet.
87 In case of an error it returns undef.
89 =cut
91 sub GetFilesInfo {
92 my $self = shift;
94 my $dbh = C4::Context->dbh;
95 my $query = '
96 SELECT
97 file_id,
98 file_name,
99 file_type,
100 file_description,
101 date_uploaded,
102 LENGTH(file_content) AS file_size
103 FROM misc_files
104 WHERE table_tag = ? AND record_id = ?
105 ORDER BY file_name, date_uploaded
107 my $sth = $dbh->prepare($query);
108 $sth->execute( $self->{'table_tag'}, $self->{'record_id'} );
109 return $sth->fetchall_arrayref( {} );
112 =item AddFile()
114 $mf->AddFile( name => $filename, type => $mimetype,
115 description => $description, content => $content );
117 Adds a new file (we want to store for / associate with a given
118 object) to the database. Parameters 'name' and 'content' are mandatory.
119 Note: this method would (silently) fail if there is no 'name' given
120 or if the 'content' provided is empty.
122 =cut
124 sub AddFile {
125 my ( $self, %args ) = @_;
127 my $name = $args{'name'};
128 my $type = $args{'type'} // '';
129 my $description = $args{'description'};
130 my $content = $args{'content'};
132 return unless ( defined($name) && $name ne '' && defined($content) && $content ne '' );
134 my $dbh = C4::Context->dbh;
135 my $query = '
136 INSERT INTO misc_files ( table_tag, record_id, file_name, file_type, file_description, file_content )
137 VALUES ( ?,?,?,?,?,? )
139 my $sth = $dbh->prepare($query);
140 $sth->execute( $self->{'table_tag'}, $self->{'record_id'}, $name, $type,
141 $description, $content );
144 =item GetFile()
146 my $file = $mf->GetFile( id => $file_id );
148 For an individual, specific file ID this method returns a hashref
149 containing all metadata (file_id, table_tag, record_id, file_name,
150 file_type, file_description, file_content, date_uploaded), plus
151 an actuall contents of a file (in 'file_content'). In typical usage
152 scenarios, for a given $mf object, specific file IDs have to be
153 obtained first by GetFilesInfo() call.
155 Returns undef in case when file ID specified as 'id' parameter was not
156 found in the database.
158 =cut
160 sub GetFile {
161 my ( $self, %args ) = @_;
163 my $file_id = $args{'id'};
165 my $dbh = C4::Context->dbh;
166 my $query = '
167 SELECT * FROM misc_files WHERE file_id = ? AND table_tag = ? AND record_id = ?
169 my $sth = $dbh->prepare($query);
170 $sth->execute( $file_id, $self->{'table_tag'}, $self->{'record_id'} );
171 return $sth->fetchrow_hashref();
174 =item DelFile()
176 $mf->DelFile( id => $file_id );
178 Deletes specific, individual file record (file contents and metadata)
179 from the database.
181 =cut
183 sub DelFile {
184 my ( $self, %args ) = @_;
186 my $file_id = $args{'id'};
188 my $dbh = C4::Context->dbh;
189 my $query = '
190 DELETE FROM misc_files WHERE file_id = ? AND table_tag = ? AND record_id = ?
192 my $sth = $dbh->prepare($query);
193 $sth->execute( $file_id, $self->{'table_tag'}, $self->{'record_id'} );
196 =item DelAllFiles()
198 $mf->DelAllFiles();
200 Deletes all file records associated with (stored for) a given $mf object.
202 =cut
204 sub DelAllFiles {
205 my ($self) = @_;
207 my $dbh = C4::Context->dbh;
208 my $query = '
209 DELETE FROM misc_files WHERE table_tag = ? AND record_id = ?
211 my $sth = $dbh->prepare($query);
212 $sth->execute( $self->{'table_tag'}, $self->{'record_id'} );
215 =item MergeFileRecIds()
217 $mf->MergeFileRecIds(@ids_to_be_merged);
219 This method re-associates all individuall file records associated with
220 some "parent" records IDs (provided in @ids_to_be_merged) with the given
221 single $mf object (which would be treated as a "parent" destination).
223 This a helper method; typically it needs to be called only in cases when
224 some "parent" records are being merged in the (external) 'tablename'
225 table.
227 =cut
229 sub MergeFileRecIds {
230 my ( $self, @ids_to_merge ) = @_;
232 my $dst_recid = $self->{'record_id'};
233 @ids_to_merge = map { ( $dst_recid == $_ ) ? () : ($_); } @ids_to_merge;
234 @ids_to_merge > 0 || return ();
236 my $dbh = C4::Context->dbh;
237 my $query = '
238 UPDATE misc_files SET record_id = ?
239 WHERE table_tag = ? AND record_id = ?
241 my $sth = $dbh->prepare($query);
243 for my $src_recid (@ids_to_merge) {
244 $sth->execute( $dst_recid, $self->{'table_tag'}, $src_recid );
250 __END__
252 =back
254 =head1 SEE ALSO
256 Koha::Patron::Files
258 =head1 AUTHOR
260 Kyle M Hall E<lt>kyle.m.hall@gmail.comE<gt>,
261 Jacek Ablewicz E<lt>ablewicz@gmail.comE<gt>
263 =cut