Skip to content

Commit

Permalink
Merge pull request #5 from matthiaslegac/background_job_pdftocover
Browse files Browse the repository at this point in the history
Version 2.0 background job
  • Loading branch information
philblou authored Mar 18, 2024
2 parents cc2b871 + 679489f commit fd6d759
Show file tree
Hide file tree
Showing 5 changed files with 314 additions and 70 deletions.
107 changes: 56 additions & 51 deletions Koha/Plugin/PDFtoCover.pm
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package Koha::Plugin::PDFtoCover;
# with Koha; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
use Modern::Perl;
use Try::Tiny;
use strict;
use warnings;
use CGI;
Expand All @@ -33,11 +34,13 @@ use C4::Context;
use File::Spec;
use JSON qw( encode_json );
use URI::Escape;
use Koha::Plugin::PDFtoCover::PDFtoCoverGreeter;
use Koha::BackgroundJobs;

BEGIN {
my $kohaversion = Koha::version;
$kohaversion =~ s/(.*\..*)\.(.*)\.(.*)/$1$2$3/;
my $module = $kohaversion < 21.0508000 ? "C4::Images" : "Koha::CoverImages";
my $module = "Koha::CoverImages";
my $file = $module;
$file =~ s[::][/]g;
$file .= '.pm';
Expand All @@ -46,15 +49,16 @@ BEGIN {
}

our $dbh = C4::Context->dbh();
our $VERSION = 1.9;
our $VERSION = 2.0;
our $metadata = {
name => 'PDFtoCover',
author => 'Mehdi Hamidi, Bouzid Fergani, Arthur Bousquet, The Minh Luong',
description => 'Creates cover images for documents missing one',
date_authored => '2016-06-08',
date_updated => '2023-06-15',
minimum_version => '17.05',
date_updated => '2024-03-18',
minimum_version => '23.05',
version => $VERSION,
namespace => 'pdftocover',
};

sub new {
Expand All @@ -68,53 +72,49 @@ sub new {

sub tool {
my ( $self, $args ) = @_;
my $cgi = $self->{'cgi'};
my $op = $cgi->param('op');

my $lock_path = File::Spec->catdir( File::Spec->rootdir(), "tmp", ".Koha.PDFtoCover.lock" );
my $lock = (-e $lock_path) ? 1 : 0;

my $cgi = $self->{'cgi'};

my $poppler = "/usr/bin/pdftocairo";
unless (-e $poppler){
$self->missingModule();
}
elsif ( $op && $op eq 'valide' ) {

if ( $cgi->param('greet') ) {
my $pdf = $self->displayAffected();
$self->store_data({ to_process => $pdf });

my $pid = fork();
if ($pid) {
my $template = $self->retrieve_template('step_1');
$template->param( pdf => $pdf );
$template->param( wait => 1 );
$template->param( done => 0 );
print $cgi->header( -type => 'text/html', -charset => 'utf-8' );
print $template->output();
exit 0;
}
$self->{greeter} = Koha::Plugin::PDFtoCover::PDFtoCoverGreeter->new;
$self->{greeter}->enqueue( { size => $pdf, one_image => 0 } );
my $id_job = $self->{greeter}->id;

open my $fh, ">", $lock_path;
close $fh;
$self->genererVignette();
unlink($lock_path);
$self->store_data({ errors => '' });
$self->step_1(1, 0, 0, $id_job, '');

exit 0;
}
else {
$self->step_1($lock);
} elsif ( $cgi->param('stop') ) {
my $id_job = $cgi->param('id_job');
Koha::BackgroundJobs->search({ id => $id_job })->next->cancel;
$self->step_1(0, 0, 1, '', $self->retrieve_data('errors'));
} elsif ( $cgi->param('done') ) {
$self->step_1(0, 1, 0, '', $self->retrieve_data('errors'));
} else {
$self->step_1(0, 0, 0, '', '');
}
}

sub step_1 {
my ( $self, $lock ) = @_;
my ( $self, $wait, $done, $cancel, $id_job, $errors ) = @_;
my $cgi = $self->{'cgi'};
my $pdf = $self->displayAffected();

my $template = $self->retrieve_template('step_1');
$template->param( pdf => $pdf );
$template->param( wait => $lock );
$template->param( done => $cgi->param('done') || 0 );
$template->param( wait => $wait );
$template->param( done => $done );
$template->param( cancel => $cancel );
$template->param( id_job => $id_job );
$template->param( errors => [split(',', $errors)] );
print $cgi->header( -type => 'text/html', -charset => 'utf-8' );
print $template->output();
}
Expand All @@ -137,8 +137,7 @@ sub getKohaVersion {

sub displayAffected {
my ( $self, $args ) = @_;
my $table = getKohaVersion() < 21.0508000 ? "biblioimages" : "cover_images";
my $query = "SELECT count(*) as count FROM biblio_metadata AS a WHERE EXTRACTVALUE(a.metadata,\"record/datafield[\@tag='856']/subfield[\@code='u']\") <> '' and a.biblionumber not in (select biblionumber from $table);";
my $query = "SELECT count(*) as count FROM biblio_metadata AS a WHERE EXTRACTVALUE(a.metadata,\"record/datafield[\@tag='856']/subfield[\@code='u']\") <> '' and a.biblionumber not in (select biblionumber from cover_images);";
my $stmt = $dbh->prepare($query);
$stmt->execute();

Expand All @@ -152,7 +151,7 @@ sub genererVignette {
# methode appelée si on génère les vignettes pour toutes les notices
my ( $self, $args ) = @_;
my $ua = LWP::UserAgent->new( timeout => "5" );
my $table = getKohaVersion() < 21.0508000 ? "biblioimages" : "cover_images";
my $table = "cover_images";
my $query = "SELECT a.biblionumber, EXTRACTVALUE(a.metadata,\"record/datafield[\@tag='856']/subfield[\@code='u']\") AS url FROM biblio_metadata AS a WHERE EXTRACTVALUE(a.metadata,\"record/datafield[\@tag='856']/subfield[\@code='u']\") <> '' and a.biblionumber not in (select biblionumber from $table);";

# Retourne 856$u, qui est le(s) URI(s) d'une ressource numérique
Expand All @@ -175,31 +174,32 @@ sub genererUneVignette {
my $stmt = $dbh->prepare($query);
$stmt->execute($biblionumber)
}
my @uris = $self->getUrisByBiblioNumber($biblionumber);
$self->genererVignetteParUris($biblionumber, @uris);
Koha::Plugin::PDFtoCover::PDFtoCoverGreeter->new->enqueue( { size => 1, biblionumber => $biblionumber, one_image => 1 } );
sleep(10);
print $self->{cgi}->redirect(-url => '/cgi-bin/koha/catalogue/detail.pl?biblionumber=' . $biblionumber);
exit 0;
}

sub genererVignetteParUris {
my ( $self, $biblionumber, @uris) = @_;
my $not_pdf = 1;
foreach my $url (@uris) {
if ( $self->isPdfResource($url) ) {
my @filestodelete = ();
my $save = C4::Context->temporary_directory();
$save =~ s/\/*$/\//;
$save .= $biblionumber;
if ( is_success( getstore( $url, $save ) ) ) {
push @filestodelete, $save;
`pdftocairo "$save" -png "$save" -singlefile 2>&1`; # Conversion de pdf à png, seulement pour la première page
my $imageFile = $save . ".png";
push @filestodelete, $imageFile;

my $srcimage = GD::Image->new($imageFile);
my $replace = 1;
if(getKohaVersion() < 21.0508000){
C4::Images::PutImage( $biblionumber, $srcimage, $replace );
}else{
try {
$not_pdf = 0;
push @filestodelete, $save;
`pdftocairo "$save" -png "$save" -singlefile 2>&1`; # Conversion de pdf à png, seulement pour la première page
my $imageFile = $save . ".png";
push @filestodelete, $imageFile;

my $srcimage = GD::Image->new($imageFile);
my $replace = 1;

my $input = CGI->new;
my $itemnumber = $input->param('itemnumber');
Koha::CoverImage->new(
Expand All @@ -209,15 +209,20 @@ sub genererVignetteParUris {
src_image => $srcimage
}
)->store;
}
foreach my $file (@filestodelete) {
unlink $file or warn "Could not unlink $file: $!\nNo more images to import.Exiting.";
}

foreach my $file (@filestodelete) {
unlink $file or warn "Could not unlink $file: $!\nNo more images to import.Exiting.";
}
} catch {
my $error = $_;
warn "Invalid $url: $error\n";
die $error;
};
}
last;
}
}
return 0;
return $not_pdf;
}

sub getUrisByBiblioNumber {
Expand Down Expand Up @@ -262,7 +267,7 @@ sub hasPdfResource {

sub hasAlreadyLocalImage {
my ( $self, $biblionumber ) = @_;
my $table = getKohaVersion() < 21.0508000 ? "biblioimages" : "cover_images";
my $table = "cover_images";
my $query = "select count(*) as count from $table where biblionumber = ? ;";

my $stmt = $dbh->prepare($query);
Expand Down
149 changes: 149 additions & 0 deletions Koha/Plugin/PDFtoCover/PDFtoCoverGreeter.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package Koha::Plugin::PDFtoCover::PDFtoCoverGreeter;

# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Koha is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Koha; if not, see <http://www.gnu.org/licenses>.

use Modern::Perl;
use Try::Tiny;
use C4::Context;
use Koha::Plugin::PDFtoCover;
use Koha::BackgroundJobs;

use base 'Koha::BackgroundJob';

our $dbh = C4::Context->dbh();

=head1 NAME
PDFtoCover::PDFtoCoverGreeter - Background task for greeting in the logs
This is a subclass of Koha::BackgroundJob.
=head1 API
=head2 Class methods
=head3 job_type
Define the job type of this job: greeter
=cut

sub job_type {
return 'plugin_pdftocover_greeter';
}

=head3 process
Process the modification.
=cut

sub process {
my ( $self, $args ) = @_;

$self->start;

my @messages;
my $report = {
total_greets => $self->size,
total_success => 0,
};

my $pdfToCover = Koha::Plugin::PDFtoCover->new();
if ( $args->{one_image}) {
my $biblionumber = $args->{biblionumber};
my @uris = $pdfToCover->getUrisByBiblioNumber($biblionumber);
$pdfToCover->genererVignetteParUris($biblionumber, @uris);
$self->step;
$report->{total_success}++;
} else {
my $ua = LWP::UserAgent->new( timeout => "5" );
my $query = "SELECT a.biblionumber, EXTRACTVALUE(a.metadata,\"record/datafield[\@tag='856']/subfield[\@code='u']\") AS url FROM biblio_metadata AS a WHERE EXTRACTVALUE(a.metadata,\"record/datafield[\@tag='856']/subfield[\@code='u']\") <> '' and a.biblionumber not in (select biblionumber from cover_images);";

my $sthSelectPdfUri = $dbh->prepare($query);
$sthSelectPdfUri->execute();

while ( my ( $biblionumber, $urifield ) = $sthSelectPdfUri->fetchrow_array() ) {
Koha::BackgroundJobs->search({ id => $self->id })->next->status eq 'cancelled' and last;
try {
my @uris = split / /, $urifield;
my $no_pdf = $pdfToCover->genererVignetteParUris($biblionumber, @uris);
$pdfToCover->store_data({ to_process => $pdfToCover->retrieve_data('to_process') - 1 });

if ( $no_pdf ) {
my $error = 'No PDF url found or bad PDF url for biblionumber ' . $biblionumber;
warn "$error\n";
push @messages, {
type => 'error',
code => 'image_generation_failed_for_bilio_' . $biblionumber,
error => $error,
};
} else {
$report->{total_success}++;
}

$self->step;
} catch {
push @messages, {
type => 'error',
code => 'image_generation_failed_for_bilio_' . $biblionumber,
error => $_,
};
};
}

my $messages_string = join("\n", map { $_->{type} . ": " . $_->{error} . "," } @messages);
$pdfToCover->store_data({ errors => $messages_string });
$pdfToCover->store_data({ to_process => 0 });
}

my $data = $self->decoded_data;
$data->{report} = $report;

$self->finish($data);
}

=head3 enqueue
Enqueue the new job
=cut

sub enqueue {
my ( $self, $args ) = @_;

$self->SUPER::enqueue(
{
job_size => $args->{size} // 5,
job_args => $args,
job_queue => 'long_tasks',
}
);
}

=head3 cancel
Cancel the job
=cut

sub cancel {
my ( $self ) = @_;

$self->SUPER::cancel;
}

1;
Loading

0 comments on commit fd6d759

Please sign in to comment.