149 lines
4.7 KiB
Perl
149 lines
4.7 KiB
Perl
package Koha::Notice::Util;
|
|
|
|
# Copyright Rijksmuseum 2023
|
|
#
|
|
# 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 Data::Dumper qw/Dumper/;
|
|
|
|
use C4::Context;
|
|
use Koha::DateUtils qw/dt_from_string/;
|
|
use Koha::Notice::Messages;
|
|
|
|
=head1 NAME
|
|
|
|
Koha::Notice::Util - Utility class related to Koha notice messages
|
|
|
|
=head1 CLASS METHODS
|
|
|
|
=head2 load_domain_limits
|
|
|
|
my $domain_limits = Koha::Notice::Util->load_domain_limits;
|
|
|
|
=cut
|
|
|
|
sub load_domain_limits {
|
|
my ($class) = @_;
|
|
|
|
my $domain_limits;
|
|
my $entry = C4::Context->config('message_domain_limits');
|
|
if ( ref($entry) eq 'HASH' ) {
|
|
if ( exists $entry->{domain} ) {
|
|
|
|
# Turn single hash entry into array
|
|
$domain_limits =
|
|
ref( $entry->{domain} ) eq 'HASH'
|
|
? [ $entry->{domain} ]
|
|
: $entry->{domain};
|
|
|
|
# Convert to hash structure by domain name
|
|
$domain_limits = { map { _init_domain_entry($_); } @$domain_limits };
|
|
}
|
|
}
|
|
return $domain_limits;
|
|
}
|
|
|
|
sub _init_domain_entry {
|
|
my ($config_entry) = @_;
|
|
|
|
# Return either a hash like ( name => { limit => , unit =>, count => } ) for regular entries
|
|
# or return a hash like ( name => { belongs_to => } ) for a domain that is part of a group
|
|
|
|
return if ref($config_entry) ne 'HASH' || !exists $config_entry->{name};
|
|
my $elements;
|
|
if ( $config_entry->{belongs_to} ) {
|
|
$elements = { belongs_to => lc $config_entry->{belongs_to} };
|
|
} else {
|
|
$elements = { limit => $config_entry->{limit}, unit => $config_entry->{unit}, count => undef };
|
|
}
|
|
return ( lc $config_entry->{name}, $elements );
|
|
}
|
|
|
|
=head2 exceeds_limit
|
|
|
|
my $boolean = Koha::Notice::Util->exceeds_limit({ to => $to_address, limits => $domain_limits, incr => 1|0 });
|
|
|
|
=cut
|
|
|
|
sub exceeds_limit {
|
|
my ( $class, $params ) = @_;
|
|
my $domain_limits = $params->{limits} or return 0; # no limits at all
|
|
my $to_address = $params->{to} or return 0; # no address, no limit exceeded
|
|
my $incr = $params->{incr} // 1; # by default we increment
|
|
|
|
my $domain = q{};
|
|
$domain = lc $1 if $to_address && $to_address =~ /@(\H+)/;
|
|
return 0 if !$domain || !exists $domain_limits->{$domain};
|
|
|
|
# Keep in mind that domain may be part of group count
|
|
my $group = $domain_limits->{$domain}->{belongs_to} // $domain;
|
|
_get_domain_count( $domain, $group, $domain_limits ) if !defined $domain_limits->{$group}->{count};
|
|
return 1 if $domain_limits->{$group}->{count} >= $domain_limits->{$group}->{limit};
|
|
|
|
if ($incr) {
|
|
$domain_limits->{$group}->{count}++;
|
|
warn "Sending messages: domain $group reached limit of "
|
|
. $domain_limits->{$group}->{limit} . '/'
|
|
. $domain_limits->{$group}->{unit}
|
|
if $domain_limits->{$group}->{count} == $domain_limits->{$group}->{limit};
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
=head1 PRIVATE METHODS
|
|
|
|
=cut
|
|
|
|
sub _get_domain_count {
|
|
my ( $domain, $group, $limits ) = @_;
|
|
|
|
# Check if there are group members too
|
|
my @domains;
|
|
push @domains, $domain if $domain eq $group;
|
|
push @domains, map {
|
|
my $belongs = $limits->{$_}->{belongs_to} // q{};
|
|
$belongs eq $group ? $_ : ();
|
|
} keys %$limits;
|
|
|
|
my $sum = 0;
|
|
my $start_dt = _convert_unit( undef, $limits->{$group}->{unit} );
|
|
foreach my $domain (@domains) {
|
|
$sum += Koha::Notice::Messages->search(
|
|
{
|
|
message_transport_type => 'email',
|
|
status => 'sent',
|
|
to_address => { 'LIKE', '%' . $domain },
|
|
}
|
|
)->filter_by_last_update( { timestamp_column_name => 'updated_on', from => $start_dt } )->count;
|
|
}
|
|
$limits->{$group}->{count} = $sum;
|
|
}
|
|
|
|
sub _convert_unit { # unit should be like \d+(m|h|d)
|
|
my ( $dt, $unit ) = @_;
|
|
$dt //= dt_from_string();
|
|
if ( $unit && $unit =~ /(\d+)([mhd])/ ) {
|
|
my $abbrev = { m => 'minutes', h => 'hours', d => 'days' };
|
|
foreach my $h ( 0, 1 ) { # try hour before too when subtract fails (like: change to summertime)
|
|
eval { $dt->subtract( hours => $h )->subtract( $abbrev->{$2} => $1 ) } and last;
|
|
}
|
|
}
|
|
return $dt;
|
|
}
|
|
|
|
1;
|