Bug 42529: Add Koha::Policy::Biblio::AgeRestriction
This patch adds age restriction handling to the Koha namespace: - Koha::Biblio->age_restriction: metadata extractor that parses the agerestriction field using the AgeRestrictionMarker system preference. Returns the numeric age or undef. Uses single return with last pattern. - Koha::Policy::Biblio::AgeRestriction->check($biblio, $patron): policy class that evaluates whether a patron meets the age restriction. Returns a Koha::Result::Boolean (with payload on restriction). Test plan: 1. Apply this patch 2. Run: $ ktd --shell k$ prove t/db_dependent/Koha/Policy/Biblio/AgeRestriction.t => SUCCESS: Tests pass! 3. Sign off :-D Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk> Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org> Signed-off-by: Pedro Amorim <pedro.amorim@openfifth.co.uk>
This commit is contained in:
parent
51e3d5435a
commit
8ebf3436cb
|
|
@ -2154,6 +2154,51 @@ sub link_marc_host {
|
|||
return $self;
|
||||
}
|
||||
|
||||
=head3 age_restriction
|
||||
|
||||
my $age = $biblio->age_restriction;
|
||||
|
||||
Extracts the numeric age restriction from the biblio's agerestriction field
|
||||
using the AgeRestrictionMarker system preference.
|
||||
|
||||
Returns the age (integer) or undef if no restriction is found.
|
||||
|
||||
=cut
|
||||
|
||||
sub age_restriction {
|
||||
my ($self) = @_;
|
||||
|
||||
my $restriction_string = $self->biblioitem->agerestriction;
|
||||
return unless $restriction_string;
|
||||
|
||||
my @values = split ' ', uc($restriction_string);
|
||||
return unless @values;
|
||||
|
||||
my @markers = map { my $m = uc($_); $m =~ s/^\s+//; $m =~ s/\s+$//; $m }
|
||||
@{ C4::Context->multivalue_preference('AgeRestrictionMarker') };
|
||||
return unless @markers;
|
||||
|
||||
my $index = 0;
|
||||
my $restriction_age = 0;
|
||||
for my $value (@values) {
|
||||
$index++;
|
||||
for my $marker (@markers) {
|
||||
if ( $marker eq $value ) {
|
||||
if ( $index <= $#values ) {
|
||||
$restriction_age += $values[$index];
|
||||
}
|
||||
last;
|
||||
} elsif ( $value =~ /^\Q$marker\E(\d+)$/ ) {
|
||||
$restriction_age += $1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
last if ( $restriction_age > 0 );
|
||||
}
|
||||
|
||||
return $restriction_age || undef;
|
||||
}
|
||||
|
||||
=head3 recalls
|
||||
|
||||
my $recalls = $biblio->recalls;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
package Koha::Policy::Biblio::AgeRestriction;
|
||||
|
||||
# Copyright 2026 Theke Solutions
|
||||
#
|
||||
# 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 <https://www.gnu.org/licenses>.
|
||||
|
||||
use Modern::Perl;
|
||||
|
||||
use Koha::Result::Boolean;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Koha::Policy::Biblio::AgeRestriction - age restriction policy checks
|
||||
|
||||
=head1 API
|
||||
|
||||
=head2 Class methods
|
||||
|
||||
=head3 check
|
||||
|
||||
my $result = Koha::Policy::Biblio::AgeRestriction->check( $biblio, $patron );
|
||||
|
||||
Checks whether a patron meets the age restriction for a biblio.
|
||||
|
||||
Returns undef if there is no restriction or it cannot be evaluated
|
||||
(e.g. patron has no date of birth). Otherwise returns a L<Koha::Result::Boolean>:
|
||||
true if the patron meets the restriction, false (with message) if not.
|
||||
|
||||
=cut
|
||||
|
||||
sub check {
|
||||
my ( $class, $biblio, $patron ) = @_;
|
||||
|
||||
my $restriction_age = $biblio->age_restriction;
|
||||
return Koha::Result::Boolean->new(1) unless $restriction_age;
|
||||
return Koha::Result::Boolean->new(1) unless $patron->dateofbirth;
|
||||
|
||||
return $restriction_age > $patron->get_age
|
||||
? Koha::Result::Boolean->new(0)
|
||||
->add_message( { message => 'age_restricted', payload => { restriction_age => $restriction_age } } )
|
||||
: Koha::Result::Boolean->new(1);
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
#!/usr/bin/env perl
|
||||
|
||||
# This file is part of Koha.
|
||||
#
|
||||
# Copyright 2015 Koha Development Team
|
||||
# Copyright 2026 Theke Solutions
|
||||
#
|
||||
# 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 <https://www.gnu.org/licenses>.
|
||||
|
||||
use Modern::Perl;
|
||||
|
||||
use Test::More tests => 3;
|
||||
use Test::NoWarnings;
|
||||
|
||||
use t::lib::Mocks;
|
||||
use t::lib::TestBuilder;
|
||||
|
||||
use Koha::Database;
|
||||
use Koha::Policy::Biblio::AgeRestriction;
|
||||
|
||||
my $schema = Koha::Database->new->schema;
|
||||
my $builder = t::lib::TestBuilder->new;
|
||||
|
||||
t::lib::Mocks::mock_preference( 'AgeRestrictionMarker', 'FSK|PEGI|Age|K' );
|
||||
|
||||
subtest 'Koha::Biblio->age_restriction' => sub {
|
||||
plan tests => 7;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
my $biblio_fsk = $builder->build_sample_biblio;
|
||||
$biblio_fsk->biblioitem->agerestriction('FSK 16')->store;
|
||||
is( $biblio_fsk->age_restriction, 16, 'FSK 16 returns 16' );
|
||||
|
||||
my $biblio_pegi = $builder->build_sample_biblio;
|
||||
$biblio_pegi->biblioitem->agerestriction('PEGI 16')->store;
|
||||
is( $biblio_pegi->age_restriction, 16, 'PEGI 16 returns 16' );
|
||||
|
||||
my $biblio_pegi_no_space = $builder->build_sample_biblio;
|
||||
$biblio_pegi_no_space->biblioitem->agerestriction('PEGI16')->store;
|
||||
is( $biblio_pegi_no_space->age_restriction, 16, 'PEGI16 returns 16' );
|
||||
|
||||
my $biblio_age = $builder->build_sample_biblio;
|
||||
$biblio_age->biblioitem->agerestriction('Age 16')->store;
|
||||
is( $biblio_age->age_restriction, 16, 'Age 16 returns 16' );
|
||||
|
||||
my $biblio_k = $builder->build_sample_biblio;
|
||||
$biblio_k->biblioitem->agerestriction('K16')->store;
|
||||
is( $biblio_k->age_restriction, 16, 'K16 returns 16' );
|
||||
|
||||
my $biblio_none = $builder->build_sample_biblio;
|
||||
$biblio_none->biblioitem->agerestriction(undef)->store;
|
||||
is( $biblio_none->age_restriction, undef, 'No restriction returns undef' );
|
||||
|
||||
my $biblio_empty = $builder->build_sample_biblio;
|
||||
$biblio_empty->biblioitem->agerestriction('')->store;
|
||||
is( $biblio_empty->age_restriction, undef, 'Empty restriction returns undef' );
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
subtest 'Koha::Policy::Biblio::AgeRestriction->check' => sub {
|
||||
plan tests => 6;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
my $biblio = $builder->build_sample_biblio;
|
||||
$biblio->biblioitem->agerestriction('FSK 16')->store;
|
||||
|
||||
my $young_patron = $builder->build_object( { class => 'Koha::Patrons', value => { dateofbirth => '2016-01-01' } } );
|
||||
my $adult_patron = $builder->build_object( { class => 'Koha::Patrons', value => { dateofbirth => '1990-01-01' } } );
|
||||
my $no_dob_patron = $builder->build_object( { class => 'Koha::Patrons', value => { dateofbirth => undef } } );
|
||||
|
||||
my $result = Koha::Policy::Biblio::AgeRestriction->check( $biblio, $young_patron );
|
||||
ok( defined $result && !$result, 'Young patron is restricted' );
|
||||
is( $result->messages->[0]->message, 'age_restricted', 'Message is age_restricted' );
|
||||
is( $result->messages->[0]->payload->{restriction_age}, 16, 'Restriction age in message payload' );
|
||||
|
||||
$result = Koha::Policy::Biblio::AgeRestriction->check( $biblio, $adult_patron );
|
||||
ok( $result, 'Adult patron is not restricted' );
|
||||
|
||||
$result = Koha::Policy::Biblio::AgeRestriction->check( $biblio, $no_dob_patron );
|
||||
ok( $result, 'No date of birth returns true (permissive)' );
|
||||
|
||||
my $biblio_no_restriction = $builder->build_sample_biblio;
|
||||
$result = Koha::Policy::Biblio::AgeRestriction->check( $biblio_no_restriction, $young_patron );
|
||||
ok( $result, 'No restriction returns true (permissive)' );
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
Loading…
Reference in New Issue