View | Details | Raw Unified | Return to bug 32476
Collapse All | Expand All

(-)a/C4/Circulation.pm (-3 / +3 lines)
Lines 2946-2952 sub CanBookBeRenewed { Link Here
2946
        my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
2946
        my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
2947
        $patron         = Koha::Patrons->find($borrowernumber); # FIXME Is this really useful?
2947
        $patron         = Koha::Patrons->find($borrowernumber); # FIXME Is this really useful?
2948
        my $restricted  = $patron->is_debarred;
2948
        my $restricted  = $patron->is_debarred;
2949
        my $hasoverdues = $patron->has_overdues;
2949
        my $hasoverdues = $patron->has_overdues({ cache => 1 });
2950
2950
2951
        if ( $restricted and $restrictionblockrenewing ) {
2951
        if ( $restricted and $restrictionblockrenewing ) {
2952
            return ( 0, 'restriction');
2952
            return ( 0, 'restriction');
Lines 3236-3242 sub AddRenewal { Link Here
3236
        my $overdue_restrictions = $patron->restrictions->search({ type => 'OVERDUES' });
3236
        my $overdue_restrictions = $patron->restrictions->search({ type => 'OVERDUES' });
3237
        if ( $patron
3237
        if ( $patron
3238
          && $patron->is_debarred
3238
          && $patron->is_debarred
3239
          && ! $patron->has_overdues
3239
          && !$patron->has_overdues
3240
          && $overdue_restrictions->count
3240
          && $overdue_restrictions->count
3241
        ) {
3241
        ) {
3242
            DelUniqueDebarment({ borrowernumber => $borrowernumber, type => 'OVERDUES' });
3242
            DelUniqueDebarment({ borrowernumber => $borrowernumber, type => 'OVERDUES' });
Lines 4456-4462 sub _CanBookBeAutoRenewed { Link Here
4456
        }
4456
        }
4457
    );
4457
    );
4458
4458
4459
    if ( $patron->category->effective_BlockExpiredPatronOpacActions and $patron->is_expired ) {
4459
    if ( $patron->is_expired({ cache => 1 }) && $patron->category->effective_BlockExpiredPatronOpacActions ) {
4460
        return 'auto_account_expired';
4460
        return 'auto_account_expired';
4461
    }
4461
    }
4462
4462
(-)a/Koha/Object.pm (+87 lines)
Lines 88-93 sub new { Link Here
88
88
89
}
89
}
90
90
91
=head3 Koha::Object->_instance_cache_key();
92
93
my $instance_cache_key = Koha::Object->_instance_cache_key($key);
94
95
=cut
96
97
sub _instance_cache_key {
98
    my ($self, $key) = @_;
99
    warn "_instance_cache_key must not be called on object that has not been stored" unless $self->id;
100
    return $self->_type . ':' . $self->id  . ':' . $key;
101
}
102
103
=head3 Koha::Object->_instance_cache_get();
104
105
my $value = Koha::Object->_instance_cache_get($cache_key);
106
107
=cut
108
109
sub _instance_cache_get {
110
    my ($self, $key) = @_;
111
    return unless $self->id;
112
    return Koha::Cache::Memory::Lite->get_instance->get_from_cache(
113
        $self->_instance_cache_key($key)
114
    );
115
}
116
117
=head3 Koha::Object->_instance_cache_set();
118
119
Koha::Object->_instance_cache_set($cache_key, $value);
120
121
=cut
122
123
sub _instance_cache_set {
124
    my ($self, $key, $value) = @_;
125
    return unless $self->id;
126
    $self->{_cache}->{$key} = $value;
127
    return Koha::Cache::Memory::Lite->get_instance->set_in_cache(
128
        $self->_instance_cache_key($key),
129
        $value
130
    );
131
}
132
133
=head3 Koha::Object->_instance_cache_clear($cache_key);
134
135
Koha::Object->_instance_cache_clear($cache_key);
136
Koha::Object->_instance_cache_clear();
137
138
=cut
139
140
sub _instance_cache_clear {
141
    my ($self, $key) = @_;
142
    return unless $self->id;
143
    Koha::Cache::Memory::Lite->get_instance->clear_from_cache(
144
        $self->_instance_cache_key($key)
145
    )
146
}
147
148
=head3 Koha::Object->_accessor_cache($method_name);
149
150
my $value = Koha::Object->_accessor_cache($method_name);
151
152
=cut
153
154
sub _accessor_cache {
155
    my ($self, $method_name) = @_;
156
157
    my $value = $self->_instance_cache_get($method_name);
158
159
    return $value if defined $value;
160
161
    $value = $self->$method_name();
162
    $self->_instance_cache_set($method_name, $value);
163
164
    return $value;
165
}
166
167
=head3 Koha::Object->accessor_cache_clear($method_name);
168
169
Koha::Object->accessor_cache_clear($method_name);
170
171
=cut
172
173
sub accessor_cache_clear {
174
    my ($self, $method_name) = @_;
175
    $self->_instance_cache_clear($method_name);
176
}
177
91
=head3 Koha::Object->_new_from_dbic();
178
=head3 Koha::Object->_new_from_dbic();
92
179
93
my $object = Koha::Object->_new_from_dbic($dbic_row);
180
my $object = Koha::Object->_new_from_dbic($dbic_row);
(-)a/Koha/Patron.pm (-6 / +44 lines)
Lines 776-795 sub is_debarred { Link Here
776
    return;
776
    return;
777
}
777
}
778
778
779
=head3 dateexpiry
780
781
Override Patron::dateexpiry to invalidate Patron::is_expired cache.
782
783
=cut
784
785
sub dateexpiry {
786
    my $self = shift @_;
787
    if (@_) {
788
        $self->_instance_cache_clear('is_expired');
789
    }
790
    return $self->SUPER::dateexpiry(@_);
791
}
792
793
=head3 set
794
795
Override Patron::set to invalidate Patron::is_expired cache if dateexpiry is set.
796
797
=cut
798
799
sub set {
800
    my $self = shift @_;
801
    my ($properties) = @_;
802
    if (exists $properties->{dateexpiry}) {
803
        $self->_instance_cache_clear('is_expired');
804
    }
805
    return $self->SUPER::set(@_);
806
}
807
779
=head3 is_expired
808
=head3 is_expired
780
809
781
my $is_expired = $patron->is_expired;
810
my $is_expired = $patron->is_expired;
811
my $is_expired = $patron->is_expired({ cache => 1});
782
812
783
Returns 1 if the patron is expired or 0;
813
Returns 1 if the patron is expired or 0;
784
814
785
=cut
815
=cut
786
816
787
sub is_expired {
817
sub is_expired {
788
    my ($self) = @_;
818
    my ($self, $params) = @_;
789
    return 0 unless $self->dateexpiry;
819
    $params //= {};
790
    return 0 if $self->dateexpiry =~ '^9999';
820
    return $self->_accessor_cache('is_expired') if $params->{cache};
791
    return 1 if dt_from_string( $self->dateexpiry ) < dt_from_string->truncate( to => 'day' );
821
792
    return 0;
822
    $self->_instance_cache_clear('is_expired');
823
    return $self->dateexpiry &&
824
        $self->dateexpiry !~ '^9999' &&
825
        dt_from_string( $self->dateexpiry ) < dt_from_string->truncate( to => 'day' ) ? 1 : 0;
793
}
826
}
794
827
795
=head3 password_expired
828
=head3 password_expired
Lines 987-999 sub renew_account { Link Here
987
=head3 has_overdues
1020
=head3 has_overdues
988
1021
989
my $has_overdues = $patron->has_overdues;
1022
my $has_overdues = $patron->has_overdues;
1023
my $has_overdues = $patron->has_overdues({ cache => 1 });
990
1024
991
Returns the number of patron's overdues
1025
Returns the number of patron's overdues
992
1026
993
=cut
1027
=cut
994
1028
995
sub has_overdues {
1029
sub has_overdues {
996
    my ($self) = @_;
1030
    my ($self, $params) = @_;
1031
    $params //= {};
1032
    return $self->_accessor_cache('has_overdues') if $params->{cache};
1033
1034
    $self->_instance_cache_clear('has_overdues');
997
    my $dtf = Koha::Database->new->schema->storage->datetime_parser;
1035
    my $dtf = Koha::Database->new->schema->storage->datetime_parser;
998
    return $self->_result->issues->search({ date_due => { '<' => $dtf->format_datetime( dt_from_string() ) } })->count;
1036
    return $self->_result->issues->search({ date_due => { '<' => $dtf->format_datetime( dt_from_string() ) } })->count;
999
}
1037
}
(-)a/t/db_dependent/Koha/Patrons.t (-7 / +55 lines)
Lines 264-270 subtest 'siblings' => sub { Link Here
264
};
264
};
265
265
266
subtest 'has_overdues' => sub {
266
subtest 'has_overdues' => sub {
267
    plan tests => 3;
267
    plan tests => 12;
268
268
269
    my $item_1 = $builder->build_sample_item;
269
    my $item_1 = $builder->build_sample_item;
270
    my $retrieved_patron = Koha::Patrons->find( $new_patron_1->borrowernumber );
270
    my $retrieved_patron = Koha::Patrons->find( $new_patron_1->borrowernumber );
Lines 273-298 subtest 'has_overdues' => sub { Link Here
273
    my $tomorrow = DateTime->today( time_zone => C4::Context->tz() )->add( days => 1 );
273
    my $tomorrow = DateTime->today( time_zone => C4::Context->tz() )->add( days => 1 );
274
    my $issue = Koha::Checkout->new({ borrowernumber => $new_patron_1->id, itemnumber => $item_1->itemnumber, date_due => $tomorrow, branchcode => $library->{branchcode} })->store();
274
    my $issue = Koha::Checkout->new({ borrowernumber => $new_patron_1->id, itemnumber => $item_1->itemnumber, date_due => $tomorrow, branchcode => $library->{branchcode} })->store();
275
    is( $retrieved_patron->has_overdues, 0, );
275
    is( $retrieved_patron->has_overdues, 0, );
276
277
    # Cache is set
278
    is( $retrieved_patron->has_overdues({ cache => 1}), 0, );
279
    is( $retrieved_patron->_instance_cache_get('has_overdues'), 0, 'has_overdues cache has been set');
280
    # Cache is used
281
    is( $retrieved_patron->has_overdues({ cache => 1}), 0, 'has_overdues cache is used');
282
276
    $issue->delete();
283
    $issue->delete();
277
    my $yesterday = DateTime->today(time_zone => C4::Context->tz())->add( days => -1 );
284
    my $yesterday = DateTime->today(time_zone => C4::Context->tz())->add( days => -1 );
278
    $issue = Koha::Checkout->new({ borrowernumber => $new_patron_1->id, itemnumber => $item_1->itemnumber, date_due => $yesterday, branchcode => $library->{branchcode} })->store();
285
    $issue = Koha::Checkout->new({ borrowernumber => $new_patron_1->id, itemnumber => $item_1->itemnumber, date_due => $yesterday, branchcode => $library->{branchcode} })->store();
279
    $retrieved_patron = Koha::Patrons->find( $new_patron_1->borrowernumber );
286
    $retrieved_patron = Koha::Patrons->find( $new_patron_1->borrowernumber );
280
    is( $retrieved_patron->has_overdues, 1, );
287
    is( $retrieved_patron->has_overdues, 1, );
288
    is( $retrieved_patron->_instance_cache_get('has_overdues'), undef, 'has_overdues cache has been invalidated' );
289
    # Cache is set
290
    is( $retrieved_patron->has_overdues({ cache => 1}), 1, );
291
    is ( $retrieved_patron->_instance_cache_get('has_overdues'), 1, 'has_overdues cache has been set' );
292
    # Cache is used
293
    is( $retrieved_patron->has_overdues({ cache => 1}), 1, 'has_overdues cache is used');
294
281
    $issue->delete();
295
    $issue->delete();
296
297
    # Cache is used (with stale entry, flushing cache must be handled manually as automatic invalidation is
298
    # complex and probably not worth the effort)
299
    is( $retrieved_patron->has_overdues({ cache => 1}), 1, );
300
301
    # Cache has been invalidated
302
    is( $retrieved_patron->has_overdues, 0, );
282
};
303
};
283
304
284
subtest 'is_expired' => sub {
305
subtest 'is_expired' => sub {
285
    plan tests => 4;
306
    plan tests => 15;
286
    my $patron = $builder->build({ source => 'Borrower' });
307
    my $patron = $builder->build({ source => 'Borrower' });
287
    $patron = Koha::Patrons->find( $patron->{borrowernumber} );
308
    $patron = Koha::Patrons->find( $patron->{borrowernumber} );
288
    $patron->dateexpiry( undef )->store->discard_changes;
309
    $patron->dateexpiry( undef )->store->discard_changes;
289
    is( $patron->is_expired, 0, 'Patron should not be considered expired if dateexpiry is not set');
310
    is( $patron->is_expired, 0, 'Patron should not be considered expired if dateexpiry is not set' );
290
    $patron->dateexpiry( dt_from_string )->store->discard_changes;
311
    $patron->dateexpiry( dt_from_string )->store->discard_changes;
291
    is( $patron->is_expired, 0, 'Patron should not be considered expired if dateexpiry is today');
312
    is( $patron->is_expired, 0, 'Patron should not be considered expired if dateexpiry is today' );
292
    $patron->dateexpiry( dt_from_string->add( days => 1 ) )->store->discard_changes;
313
    $patron->dateexpiry( dt_from_string->add( days => 1 ) )->store->discard_changes;
293
    is( $patron->is_expired, 0, 'Patron should not be considered expired if dateexpiry is tomorrow');
314
    is( $patron->is_expired, 0, 'Patron should not be considered expired if dateexpiry is tomorrow' );
315
    $patron->dateexpiry( dt_from_string->add( days => -1 ) )->store->discard_changes;
316
    is( $patron->is_expired, 1, 'Patron should be considered expired if dateexpiry is yesterday' );
317
318
    # Test is_expired cache
319
    $patron->dateexpiry( undef )->store->discard_changes;
320
    # Set cache
321
    is( $patron->is_expired({ cache => 1 }), 0, 'Patron should not be considered expired if dateexpiry is not set, with caching enabled' );
322
    is( $patron->_instance_cache_get('is_expired'), 0, 'is_expired cache has been set');
323
    is( $patron->is_expired({ cache => 1 }), 0, 'Patron should not be considered expired if dateexpiry is not set, with caching enabled and cache hit' );
294
    $patron->dateexpiry( dt_from_string->add( days => -1 ) )->store->discard_changes;
324
    $patron->dateexpiry( dt_from_string->add( days => -1 ) )->store->discard_changes;
295
    is( $patron->is_expired, 1, 'Patron should be considered expired if dateexpiry is yesterday');
325
    is( $patron->is_expired({ cache => 1 }), 1, 'Patron should be considered expired if dateexpiry is yesterday, cache has been invalidated' );
326
    is( $patron->_instance_cache_get('is_expired'), 1, 'is_expired cache has been set');
327
    is( $patron->is_expired({ cache => 1 }), 1, 'Patron should be considered expired if dateexpiry is yesterday, on cache hit' );
328
329
    $patron->{dateexpiry} = undef;
330
    # Checking cache is really utilized by setting dateexpiry property without using accessor method
331
    is( $patron->is_expired({ cache => 1 }), 1, 'Cache is used with stale value' );
332
333
    $patron->set({ dateexpiry => undef })->store->discard_changes;
334
    is( $patron->is_expired({ cache => 1 }), 0, 'Patron should not be considered expired if dateexpiry is not set, cache has been invalidated' );
335
    is( $patron->is_expired({ cache => 1 }), 0, 'Patron should not be considered expired if dateexpiry is not set, on cache hit' );
336
337
    $patron->is_expired;
338
    is( $patron->_instance_cache_get('is_expired'), undef , 'Cache has been invalidated after calling is_expired without caching enabled' );
339
340
    # Set cache
341
    $patron->is_expired({ cache => 1 });
342
    # Clear cache using public method accessor_cache_clear
343
    $patron->accessor_cache_clear('is_expired');
344
    is( $patron->_instance_cache_get('is_expired'), undef , 'Cache has been invalidated after calling accessor_cache_clear' );
296
345
297
    $patron->delete;
346
    $patron->delete;
298
};
347
};
299
- 

Return to bug 32476