Bug 24156: Make sort order and number of items to display configurable (basket page)
[koha.git] / C4 / HTML5Media.pm
1 package C4::HTML5Media;
2
3 # Copyright 2012/2015 Mirko Tietgen
4 #
5 # This file is part of Koha.
6 #
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20 use strict;
21 use warnings;
22
23 use C4::Context;
24 use MARC::Field;
25 use Koha::UploadedFiles;
26
27 =head1 HTML5Media
28
29 C4::HTML5Media
30
31 =head1 Description
32
33 This module gets the relevant data from field 856 (MARC21/UNIMARC) to create a HTML5 audio or video element containing the file(s) catalogued in 856.
34
35 =cut
36
37 =head2 gethtml5media
38
39 Get all relevant data from field 856. Takes a $record in the subroutine call, sets appropriate params.
40
41 =cut
42
43 sub gethtml5media {
44     my $self = shift;
45     my $record = shift;
46     my @HTML5Media_sets = ();
47     my @HTML5Media_fields = $record->field(856);
48     my $HTML5MediaParent;
49     my $HTML5MediaWidth;
50     my @HTML5MediaExtensions = split( /\|/, C4::Context->preference("HTML5MediaExtensions") );
51     my $HTML5MediaYouTube    = C4::Context->preference("HTML5MediaYouTube");
52     my $marcflavour          = C4::Context->preference("marcflavour");
53     foreach my $HTML5Media_field (@HTML5Media_fields) {
54         my $is_youtube            = 0;
55         my %HTML5Media;
56         # protocol
57         if ( $HTML5Media_field->indicator(1) eq '1' ) {
58             $HTML5Media{protocol} = 'ftp';
59         }
60         elsif ( $HTML5Media_field->indicator(1) eq '4' ) {
61             $HTML5Media{protocol} = 'http';
62         }
63         elsif ( $HTML5Media_field->indicator(1) eq '7' ) {
64             if ($marcflavour eq 'MARC21' || $marcflavour eq 'NORMARC') {
65                 $HTML5Media{protocol} = $HTML5Media_field->subfield('2');
66             }
67             elsif ($marcflavour eq 'UNIMARC') {
68                 $HTML5Media{protocol} = $HTML5Media_field->subfield('y');
69             }
70         }
71         else {
72             $HTML5Media{protocol} = 'http';
73         }
74         # user
75         if ( $HTML5Media_field->subfield('l') ) {
76             $HTML5Media{username} = $HTML5Media_field->subfield('l'); # yes, that is arbitrary if h and l are not the same. originally i flipped a coin in that case.
77         }
78         elsif ( $HTML5Media_field->subfield('h') ) {
79             $HTML5Media{username} = $HTML5Media_field->subfield('h');
80         }
81         # user/pass
82         if ( $HTML5Media{username} && $HTML5Media_field->subfield('k') ) {
83             $HTML5Media{loginblock} = $HTML5Media{username} . ':' . $HTML5Media_field->subfield('k') . '@';
84         }
85         elsif ( $HTML5Media{username} ) {
86             $HTML5Media{loginblock} = $HTML5Media{username} . '@';
87         }
88         else {
89             $HTML5Media{loginblock} = '';
90         }
91         # port
92         if ( $HTML5Media_field->subfield('p') ) {
93             $HTML5Media{portblock} = ':' . $HTML5Media_field->subfield('k');
94         }
95         else {
96             $HTML5Media{portblock} = '';
97         }
98         # src
99         if ( $HTML5Media_field->subfield('u') ) {
100             $HTML5Media{srcblock} = $HTML5Media_field->subfield('u');
101             if (grep /youtu\.?be/, $HTML5Media_field->subfield('u') ) {
102                 if ($HTML5MediaYouTube == 1) {
103                     my $url = $HTML5Media_field->subfield('u');
104                     # Credit for regex goes to https://stackoverflow.com/questions/3452546/how-do-i-get-the-youtube-video-id-from-a-url
105                     next unless $url =~ m{^.*(youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*};
106                     my $video_id = $2;
107                     next unless length($video_id) == 11; # Youtube video ids are 11 chars length
108                     $HTML5Media{srcblock} = sprintf '%s://www.youtube.com/embed/%s', $HTML5Media{protocol}, $video_id;
109                     $HTML5Media{is_youtube} = 1;
110                     $is_youtube = 1;
111                 }
112                else {
113                    next; # do not embed youtube videos
114                }
115             }
116         }
117         elsif ( $HTML5Media_field->subfield('a') && $HTML5Media_field->subfield('d') && $HTML5Media_field->subfield('f') ) {
118             $HTML5Media{host}        = $HTML5Media_field->subfield('a');
119             $HTML5Media{host}        =~ s/(^\/|\/$)//g;
120             $HTML5Media{path}        = $HTML5Media_field->subfield('d');
121             $HTML5Media{path}        =~ s/(^\/|\/$)//g; # TODO we could check for youtube here too, but nobody uses these fields anyway…
122             $HTML5Media{file}        = $HTML5Media_field->subfield('f');
123             $HTML5Media{srcblock}    = $HTML5Media{protocol} . '://' . $HTML5Media{loginblock} . $HTML5Media{host} . $HTML5Media{portblock} . '/' . $HTML5Media{path} . '/' . $HTML5Media{file};
124         }
125         else {
126             next; # no file to play
127         }
128         # extension
129         # check uploaded files
130         if ( $HTML5Media{srcblock} =~ /\Qopac-retrieve-file.pl\E/ ) {
131             my ( undef, $id ) = split /id=/, $HTML5Media{srcblock};
132             next if !$id;
133             my %public = ( ( caller )[1] =~ /opac/ ) ? ( public => 1 ): ();
134             my $upload = Koha::UploadedFiles->search({
135                 hashvalue => $id, %public,
136             })->next;
137             next if !$upload || $upload->filename !~ /\./;
138             $HTML5Media{extension} = ( $upload->filename =~ m/([^.]+)$/ )[0];
139         }
140         # check remote files
141         else {
142             $HTML5Media{extension} = ($HTML5Media{srcblock} =~ m/([^.]+)$/)[0];
143         }
144         if ( ( !grep /\Q$HTML5Media{extension}\E/, @HTML5MediaExtensions ) && ( $is_youtube != 1) ) {
145             next; # not a specified media file
146         }
147         # youtube
148         if ($is_youtube == 1) {
149             $HTML5Media{mime} = 'video/webm';
150             $HTML5Media{type} = 'video';
151         }
152         # mime
153         if ( $HTML5Media_field->subfield('c') ) {
154             $HTML5Media{codecs} = $HTML5Media_field->subfield('c');
155         }
156         ### from subfield q…
157         if ( $HTML5Media_field->subfield('q') ) {
158             $HTML5Media{mime} = $HTML5Media_field->subfield('q');
159         }
160         ### …or from file extension and codecs…
161         elsif ( $HTML5Media{codecs} ) {
162             if ( $HTML5Media{codecs} =~ /theora.*vorbis/ ) {
163                 $HTML5Media{mime} = 'video/ogg';
164             }
165             elsif ( $HTML5Media{codecs} =~ /vp8.*vorbis/ ) {
166                 $HTML5Media{mime} = 'video/webm';
167             }
168             elsif ( ($HTML5Media{codecs} =~ /^vorbis$/) && ($HTML5Media{extension} eq 'ogg') ) {
169                 $HTML5Media{mime} = 'audio/ogg';
170             }
171             elsif ( ($HTML5Media{codecs} =~ /^vorbis$/) && ($HTML5Media{extension} eq 'webm') ) {
172                 $HTML5Media{mime} = 'audio/webm';
173             }
174         }
175         ### …or just from file extension
176         else {
177             if ( $HTML5Media{extension} eq 'ogv' ) {
178                 $HTML5Media{mime} = 'video/ogg';
179                 $HTML5Media{codecs} = 'theora,vorbis';
180             }
181             if ( $HTML5Media{extension} eq 'oga' ) {
182                 $HTML5Media{mime} = 'audio/ogg';
183                 $HTML5Media{codecs} = 'vorbis';
184             }
185             elsif ( $HTML5Media{extension} eq 'spx' ) {
186                 $HTML5Media{mime} = 'audio/ogg';
187                 $HTML5Media{codecs} = 'speex';
188             }
189             elsif ( $HTML5Media{extension} eq 'opus' ) {
190                 $HTML5Media{mime} = 'audio/ogg';
191                 $HTML5Media{codecs} = 'opus';
192             }
193             elsif ( $HTML5Media{extension} eq 'vtt' ) {
194                 $HTML5Media{mime} = 'text/vtt';
195             }
196         }
197         # codecs
198         if ( $HTML5Media{codecs} ) {
199             $HTML5Media{codecblock} = '; codecs="' . $HTML5Media{codecs} . '"';
200         }
201         else {
202             $HTML5Media{codecblock} = '';
203         }
204         # type
205         if ( $HTML5Media{mime} ) {
206             $HTML5Media{typeblock} = ' type=\'' . $HTML5Media{mime} . $HTML5Media{codecblock} . '\'';
207         }
208         else {
209           $HTML5Media{typeblock} = '';
210         }
211         # element
212         if ( $HTML5Media{mime} =~ /audio/ ) {
213             $HTML5Media{type} = 'audio';
214         }
215         elsif ( $HTML5Media{mime} =~ /video/ ) {
216             $HTML5Media{type} = 'video';
217         }
218         elsif ( $HTML5Media{mime} =~ /text/ ) {
219             $HTML5Media{type} = 'track';
220         }
221         # push
222         if ( $HTML5Media{srcblock} && $HTML5Media{type} ) {
223             push (@HTML5Media_sets, \%HTML5Media);
224         }
225     }
226     # parent element
227     for my $media ( @HTML5Media_sets ) {
228         if ( ($media->{mime}) && ($media->{mime} =~ /audio/) ) {
229             if ( $HTML5MediaParent ne 'video' ) {
230                 $HTML5MediaParent = 'audio';
231                 $HTML5MediaWidth = '';
232             }
233         }
234         elsif ( ($media->{mime}) && ($media->{mime} =~ /video/) ) {
235             $HTML5MediaParent = 'video';
236             $HTML5MediaWidth = ' width="480"';
237         }
238     }
239     # child element
240     for my $media ( @HTML5Media_sets ) {
241         if ( ($media->{type}) && ( ($media->{type} eq 'video') || ($media->{type} eq 'audio') ) ) {
242             if ( $media->{type} eq $HTML5MediaParent ) {
243                 $media->{child} = 'source';
244             }
245         }
246         else {
247             $media->{child} = $media->{type};
248         }
249     }
250
251     return (
252         HTML5MediaEnabled  => ( (scalar(@HTML5Media_sets) > 0) && ($HTML5MediaParent) ),
253         HTML5MediaSets     => \@HTML5Media_sets,
254         HTML5MediaParent   => $HTML5MediaParent,
255         HTML5MediaWidth    => $HTML5MediaWidth,
256     );
257 }
258
259 1;