Bug 22294: Check return of as_isbn10 before calling methods on it
[srvgit] / Koha / IssuingRules.pm
index 3c588f7..608b4ed 100644 (file)
@@ -21,11 +21,14 @@ package Koha::IssuingRules;
 use Modern::Perl;
 
 use Koha::Database;
+use Koha::Caches;
 
 use Koha::IssuingRule;
 
 use base qw(Koha::Objects);
 
+use constant GUESSED_ITEMTYPES_KEY => 'Koha_IssuingRules_last_guess';
+
 =head1 NAME
 
 Koha::IssuingRules - Koha IssuingRule Object set class
@@ -44,73 +47,144 @@ sub get_effective_issuing_rule {
     my $itemtype     = $params->{itemtype};
     my $branchcode   = $params->{branchcode};
 
-    my $rule = $self->find($params);
-    return $rule if $rule;
+    my $search_categorycode = $default;
+    my $search_itemtype     = $default;
+    my $search_branchcode   = $default;
+
+    if ($categorycode) {
+        $search_categorycode = { 'in' => [ $categorycode, $default ] };
+    }
+    if ($itemtype) {
+        $search_itemtype = { 'in' => [ $itemtype, $default ] };
+    }
+    if ($branchcode) {
+        $search_branchcode = { 'in' => [ $branchcode, $default ] };
+    }
+
+    my $rule = $self->search({
+        categorycode => $search_categorycode,
+        itemtype     => $search_itemtype,
+        branchcode   => $search_branchcode,
+    }, {
+        order_by => {
+            -desc => ['branchcode', 'categorycode', 'itemtype']
+        },
+        rows => 1,
+    })->single;
+    return $rule;
+}
 
-    $rule = $self->find(
-        {
-            categorycode => $categorycode,
-            itemtype     => $default,
-            branchcode   => $branchcode
-        }
-    );
-    return $rule if $rule;
+=head3 get_opacitemholds_policy
 
-    $rule = $self->find(
-        {
-            categorycode => $default,
-            itemtype     => $itemtype,
-            branchcode   => $branchcode
-        }
-    );
-    return $rule if $rule;
+my $can_place_a_hold_at_item_level = Koha::IssuingRules->get_opacitemholds_policy( { patron => $patron, item => $item } );
 
-    $rule = $self->find(
-        {
-            categorycode => $default,
-            itemtype     => $default,
-            branchcode   => $branchcode
-        }
-    );
-    return $rule if $rule;
+Return 'Y' or 'F' if the patron can place a hold on this item according to the issuing rules
+and the "Item level holds" (opacitemholds).
+Can be 'N' - Don't allow, 'Y' - Allow, and 'F' - Force
 
-    $rule = $self->find(
-        {
-            categorycode => $categorycode,
-            itemtype     => $itemtype,
-            branchcode   => $default
-        }
-    );
-    return $rule if $rule;
+=cut
 
-    $rule = $self->find(
-        {
-            categorycode => $categorycode,
-            itemtype     => $default,
-            branchcode   => $default
-        }
-    );
-    return $rule if $rule;
+sub get_opacitemholds_policy {
+    my ( $class, $params ) = @_;
+
+    my $item   = $params->{item};
+    my $patron = $params->{patron};
 
-    $rule = $self->find(
+    return unless $item or $patron;
+
+    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
         {
-            categorycode => $default,
-            itemtype     => $itemtype,
-            branchcode   => $default
+            categorycode => $patron->categorycode,
+            itemtype     => $item->effective_itemtype,
+            branchcode   => $item->homebranch,
         }
     );
-    return $rule if $rule;
 
-    $rule = $self->find(
+    return $issuing_rule ? $issuing_rule->opacitemholds : undef;
+}
+
+=head3 get_onshelfholds_policy
+
+    my $on_shelf_holds = Koha::IssuingRules->get_onshelfholds_policy({ item => $item, patron => $patron });
+
+=cut
+
+sub get_onshelfholds_policy {
+    my ( $class, $params ) = @_;
+    my $item = $params->{item};
+    my $itemtype = $item->effective_itemtype;
+    my $patron = $params->{patron};
+    my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
         {
-            categorycode => $default,
-            itemtype     => $default,
-            branchcode   => $default
+            ( $patron ? ( categorycode => $patron->categorycode ) : () ),
+            itemtype   => $itemtype,
+            branchcode => $item->holdingbranch
         }
     );
-    return $rule if $rule;
+    return $issuing_rule ? $issuing_rule->onshelfholds : undef;
+}
+
+=head3 article_requestable_rules
+
+    Return rules that allow article requests, optionally filtered by
+    patron categorycode.
+
+    Use with care; see guess_article_requestable_itemtypes.
+
+=cut
+
+sub article_requestable_rules {
+    my ( $class, $params ) = @_;
+    my $category = $params->{categorycode};
+
+    return if !C4::Context->preference('ArticleRequests');
+    return $class->search({
+        $category ? ( categorycode => [ $category, '*' ] ) : (),
+        article_requests => { '!=' => 'no' },
+    });
+}
+
+=head3 guess_article_requestable_itemtypes
+
+    Return item types in a hashref that are likely possible to be
+    'article requested'. Constructed by an intelligent guess in the
+    issuing rules (see article_requestable_rules).
+
+    Note: pref ArticleRequestsLinkControl overrides the algorithm.
+
+    Optional parameters: categorycode.
+
+    Note: the routine is used in opac-search to obtain a reasonable
+    estimate within performance borders (not looking at all items but
+    just using default itemtype). Also we are not looking at the
+    branchcode here, since home or holding branch of the item is
+    leading and branch may be unknown too (anonymous opac session).
+
+=cut
 
-    return;
+sub guess_article_requestable_itemtypes {
+    my ( $class, $params ) = @_;
+    my $category = $params->{categorycode};
+    return {} if !C4::Context->preference('ArticleRequests');
+    return { '*' => 1 } if C4::Context->preference('ArticleRequestsLinkControl') eq 'always';
+
+    my $cache = Koha::Caches->get_instance;
+    my $last_article_requestable_guesses = $cache->get_from_cache(GUESSED_ITEMTYPES_KEY);
+    my $key = $category || '*';
+    return $last_article_requestable_guesses->{$key}
+        if $last_article_requestable_guesses && exists $last_article_requestable_guesses->{$key};
+
+    my $res = {};
+    my $rules = $class->article_requestable_rules({
+        $category ? ( categorycode => $category ) : (),
+    });
+    return $res if !$rules;
+    foreach my $rule ( $rules->as_list ) {
+        $res->{ $rule->itemtype } = 1;
+    }
+    $last_article_requestable_guesses->{$key} = $res;
+    $cache->set_in_cache(GUESSED_ITEMTYPES_KEY, $last_article_requestable_guesses);
+    return $res;
 }
 
 =head3 type