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

(-)a/Koha/FloatingMatrix.pm (-20 / +5 lines)
Lines 235-261 Static method Link Here
235
sub _CheckConditionalFloat {
235
sub _CheckConditionalFloat {
236
    my ($item, $branchRule) = @_;
236
    my ($item, $branchRule) = @_;
237
237
238
    my $conditionRules = $branchRule->getConditionRules();
238
    my $evalCondition = $branchRule->getConditionRulesParsed();
239
239
240
    my $evalCondition = '';
240
    # $item must be in the current scope, as it is hard-coded into the eval'ld condition
241
    if (my @conds = $conditionRules =~ /(\w+)\s+(ne|eq|gt|lt|<|>|==|!=)\s+(\w+)\s*(and|or|xor|&&|\|\|)?/ig) {
242
        #Iterate the condition quads, with the fourth index being the logical join operator.
243
        for (my $i=0 ; $i<scalar(@conds) ; $i+=4) {
244
            my $column = $conds[$i];
245
            my $operator = $conds[$i+1];
246
            my $value = $conds[$i+2];
247
            my $join = $conds[$i+3] || '';
248
249
            $evalCondition .= join(' ',"\$item->$column",$operator,"'$value'",$join,'');
250
        }
251
    }
252
    else {
253
        warn "Koha::FloatingMatrix::_CheckConditionalFloat():> Bad condition rules '$conditionRules' couldn't be parsed\n";
254
        return undef;
255
    }
256
    my $ok = eval("return 1 if($evalCondition);");
241
    my $ok = eval("return 1 if($evalCondition);");
257
    if ($@) {
242
    if ($@) {
258
        warn "Koha::FloatingMatrix::_CheckConditionalFloat():> Something bad hapened when trying to evaluate the dynamic conditional:\n$@\n";
243
        warn "Koha::FloatingMatrix::_CheckConditionalFloat():> Something bad hapened when trying to evaluate the dynamic conditional: '$evalCondition'\n\n$@\n";
259
        return undef;
244
        return undef;
260
    }
245
    }
261
    return $ok;
246
    return $ok;
Lines 476-479 sub _createModificationBuffer { Link Here
476
    return undef;
461
    return undef;
477
}
462
}
478
463
479
1; #Satisfy the compiler
464
1; #Satisfy the compiler
(-)a/Koha/FloatingMatrix/BranchRule.pm (-25 / +21 lines)
Lines 44-50 use Koha::Exceptions::BadParameter; Link Here
44
                                    fromBranch => 'CPL',
44
                                    fromBranch => 'CPL',
45
                                    toBranch => 'FFL',
45
                                    toBranch => 'FFL',
46
                                    floating => ['ALWAYS'|'POSSIBLE'|'CONDITIONAL'],
46
                                    floating => ['ALWAYS'|'POSSIBLE'|'CONDITIONAL'],
47
                                    conditionRules => "items->{itype} eq 'BK' && $items->{permanent_location} eq 'CART'"
47
                                    conditionRules => "items->{itype} eq 'BK' && $items->{permanent_location} =~ 'CART'"
48
                                });
48
                                });
49
49
50
BranchRule defines the floating rule for one transfer route.
50
BranchRule defines the floating rule for one transfer route.
Lines 59-67 We check if there is a floating rule for that fromBranch-toBranch -combination a Link Here
59
sub new {
59
sub new {
60
    my ($class, $params) = @_;
60
    my ($class, $params) = @_;
61
61
62
    bless $params, $class;
62
    ValidateParams($params);
63
    ValidateParams($params);
63
64
64
    bless $params, $class;
65
    return $params;
65
    return $params;
66
}
66
}
67
67
Lines 124-130 sub ValidateParams { Link Here
124
        $errorMsg = "'conditionRules' text is too long. Maximum length is '$maximumConditionRulesDatabaseLength' characters";
124
        $errorMsg = "'conditionRules' text is too long. Maximum length is '$maximumConditionRulesDatabaseLength' characters";
125
    }
125
    }
126
    elsif ($params->{conditionRules}) {
126
    elsif ($params->{conditionRules}) {
127
        ParseConditionRules(undef, $params->{conditionRules});
127
        $params->setConditionRules($params->{conditionRules});
128
    }
128
    }
129
129
130
    if ($errorMsg) {
130
    if ($errorMsg) {
Lines 138-164 sub ValidateParams { Link Here
138
138
139
=head parseConditionRules, Static method
139
=head parseConditionRules, Static method
140
140
141
    my $evalCondition = ParseConditionRules($item, $conditionRules);
141
    my $evalCondition = ParseConditionRules($conditionRules);
142
    my $evalCondition = ParseConditionRules(undef, $conditionRules);
142
    my $evalCondition = ParseConditionRules($conditionRules);
143
143
144
Parses the given Perl boolean expression into an eval()-able expression.
144
Parses the given Perl boolean expression into an eval()-able expression.
145
If Item is given, uses the Item's columns to create a executable expression to check for
145
If Item is given, uses the Item's columns to create a executable expression to check for
146
conditional floating for this specific Item.
146
conditional floating for this specific Item.
147
147
148
@PARAM1 {Reference to HASH of koha.items-row} Item to check for conditional floating.
148
@PARAM1 {String koha.floating_matrix.condition_rules} The boolean expression to turn
149
@PARAM2 {String koha.floating_matrix.condition_rules} The boolean expression to turn
150
                    into a Perl code to check the floating condition.
149
                    into a Perl code to check the floating condition.
151
@THROWS Koha::Exceptions::BadParameter, if the conditionRules couldn't be parsed.
150
@THROWS Koha::Exceptions::BadParameter, if the conditionRules couldn't be parsed.
152
=cut
151
=cut
153
sub ParseConditionRules {
152
sub ParseConditionRules {
154
    my ($item, $conditionRulesString) = @_;
153
    my ($conditionRulesString) = @_;
155
    my $evalCondition = '';
154
    my $evalCondition = '';
156
    if (my @conds = $conditionRulesString =~ /(\w+)\s+(ne|eq|gt|lt|<|>|==|!=)\s+(\w+)\s*(and|or|xor|&&|\|\|)?/ig) {
155
    if (my @conds = $conditionRulesString =~ /(\w+)\s+(ne|eq|gt|lt|=~|<|>|==|!=)\s+(\S+)\s*(and|or|xor|&&|\|\|)?/ig) {
157
158
        #If we haven't got no Item, simply stop here to aknowledge that the given condition logic is valid (atleast parseable)
159
        return undef unless $item;
160
161
        #If we have an Item, then prepare and return an eval-expression to test if the Item should float.
162
        #Iterate the condition quads, with the fourth index being the logical join operator.
156
        #Iterate the condition quads, with the fourth index being the logical join operator.
163
        for (my $i=0 ; $i<scalar(@conds) ; $i+=4) {
157
        for (my $i=0 ; $i<scalar(@conds) ; $i+=4) {
164
            my $column = $conds[$i];
158
            my $column = $conds[$i];
Lines 166-181 sub ParseConditionRules { Link Here
166
            my $value = $conds[$i+2];
160
            my $value = $conds[$i+2];
167
            my $join = $conds[$i+3] || '';
161
            my $join = $conds[$i+3] || '';
168
162
169
            $evalCondition .= join(' ',"\$item->{'$column'}",$operator,"'$value'",$join,'');
163
            if ($operator eq '=~') {
164
                $value = qr($value);
165
                $evalCondition .= "\$item->$column $operator /$value/ $join ";
166
            } else {
167
                $evalCondition .= "\$item->$column $operator '$value' $join ";
168
            }
170
        }
169
        }
171
172
        return $evalCondition;
173
    }
170
    }
174
    else {
171
    else {
175
        Koha::Exceptions::BadParameter->throw(error =>
172
        Koha::Exceptions::BadParameter->throw(error =>
176
                    "Koha::FloatingMatrix::parseConditionRules():> Bad condition rules '$conditionRulesString' couldn't be parsed\n".
173
                    "Koha::FloatingMatrix::BranchRule::ParseConditionRules():> Bad condition rules '$conditionRulesString' couldn't be parsed.\n"
177
                    "See 'Help' for more info");
174
        );
178
    }
175
    }
176
    return $evalCondition;
179
}
177
}
180
178
181
=head replace
179
=head replace
Lines 301-313 See parseConditionRules() Link Here
301
sub setConditionRules {
299
sub setConditionRules {
302
    my ($self, $val) = @_;
300
    my ($self, $val) = @_;
303
    #Validate the conditinal rules.
301
    #Validate the conditinal rules.
304
    ParseConditionRules(undef, $val);
302
    $self->{conditionRulesParsed} = ParseConditionRules($val);
305
    $self->{conditionRules} = $val;
303
    $self->{conditionRules} = $val;
306
}
304
}
307
sub getConditionRules {
305
sub getConditionRules { return shift->{conditionRules}; }
308
    my ($self) = @_;
306
sub getConditionRulesParsed { return shift->{conditionRulesParsed}; }
309
    return $self->{conditionRules};
310
}
311
307
312
=head toString
308
=head toString
313
309
Lines 339-342 sub TO_JSON { Link Here
339
    return $json;
335
    return $json;
340
}
336
}
341
337
342
1; #Satisfy the compiler
338
1; #Satisfy the compiler
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/floating-matrix.tt (-1 / +2 lines)
Lines 35-40 Link Here
35
                                    itype eq BK or itype eq CR - this will always float all Items with item type 'BK' or 'CR'<br/>
35
                                    itype eq BK or itype eq CR - this will always float all Items with item type 'BK' or 'CR'<br/>
36
                                    ccode eq FLOAT - this will float all Items with a collection code 'FLOAT'<br/>
36
                                    ccode eq FLOAT - this will float all Items with a collection code 'FLOAT'<br/>
37
                                    itype ne CR and permanent_location eq CART  - this will float all Items not of item type CR and whose permanent location (set when the Item's location is set) is 'CART'<br/>
37
                                    itype ne CR and permanent_location eq CART  - this will float all Items not of item type CR and whose permanent location (set when the Item's location is set) is 'CART'<br/>
38
                                    itype =~ (CR|DV|BK) - Using a regular expression to match against the Item attribute. Floats item types CR or DV or BK. Refraing from using complex regexps as those can smash the system.<br/>
38
                                    <i>These boolean statements are actually evaluable Perl boolean expressions and target the columns in the koha.items-table. See <a href="http://schema.koha-community.org/tables/items.html">here</a> for available data columns.</i>
39
                                    <i>These boolean statements are actually evaluable Perl boolean expressions and target the columns in the koha.items-table. See <a href="http://schema.koha-community.org/tables/items.html">here</a> for available data columns.</i>
39
                                </p>
40
                                </p>
40
                            </li>
41
                            </li>
Lines 125-128 Link Here
125
126
126
127
127
[% Asset.js("js/floating-matrix.js") | $raw %]
128
[% Asset.js("js/floating-matrix.js") | $raw %]
128
[% INCLUDE 'intranet-bottom.inc' %]
129
[% INCLUDE 'intranet-bottom.inc' %]
(-)a/t/Koha/FloatingMatrix.t (-1 / +105 lines)
Line 0 Link Here
0
- 
1
# Copyright 2017 KohaSuomi
2
#
3
# This file is part of Koha.
4
#
5
6
use Modern::Perl;
7
use Scalar::Util qw(blessed);
8
use Try::Tiny;
9
10
use Test::More;
11
12
use Koha::FloatingMatrix;
13
use Koha::FloatingMatrix::BranchRule;
14
15
16
17
subtest "Feature: Conditional float statement", \&_CheckConditionalFloat;
18
sub _CheckConditionalFloat {
19
  my ($item, $branchRule);
20
  $branchRule = {
21
      fromBranch => 'CPL',
22
      toBranch => 'FFL',
23
      floating => 'CONDITIONAL',
24
  };
25
26
  eval {
27
28
    ok($branchRule->{conditionRules} =
29
        "itype ne LEHTI and ccode ne PILA and location ne VIM and location ne MVIM and location ne NWN",
30
      "Given a basic BranchRule with lots of exclusion");
31
    ok($item = {
32
                itype => 'KOIRA',
33
                ccode => 'CODE',
34
                location => 'SHELF',
35
               },
36
      "And a simple Item");
37
38
    ok(Koha::FloatingMatrix::_CheckConditionalFloat(
39
           $item,
40
           Koha::FloatingMatrix::BranchRule->new($branchRule)),
41
      "Then the Item does float");
42
43
44
45
    ok($branchRule->{conditionRules} =
46
        "itype ne LEHTI xor itype ne KIRJA",
47
      "Given a basic BranchRule with xor");
48
49
    ok(! Koha::FloatingMatrix::_CheckConditionalFloat(
50
           $item,
51
           Koha::FloatingMatrix::BranchRule->new($branchRule)),
52
      "Then the Item doesn't float");
53
54
55
56
    ok($branchRule->{conditionRules} =
57
        'itype =~ LEHTI$ or itype =~ ^KOIRA',
58
      "Given a BranchRule using a regexp");
59
60
    ok(Koha::FloatingMatrix::_CheckConditionalFloat(
61
           $item,
62
           Koha::FloatingMatrix::BranchRule->new($branchRule)),
63
      "Then the Item does float");
64
65
66
67
    ok($branchRule->{conditionRules} =
68
        'itype =~ KOIRA$ or itype =~ ^KISSA',
69
      "Given a BranchRule using a regexp with a \$");
70
71
    ok(Koha::FloatingMatrix::_CheckConditionalFloat(
72
           $item,
73
           Koha::FloatingMatrix::BranchRule->new($branchRule)),
74
      "Then the Item does float");
75
76
77
78
    ok($branchRule->{conditionRules} =
79
        'itype =~ KOIRA or itype =~ ^KISSA and ccode eq CODE',
80
      "Given a BranchRule using a regexp and simple matching");
81
82
    ok(Koha::FloatingMatrix::_CheckConditionalFloat(
83
           $item,
84
           Koha::FloatingMatrix::BranchRule->new($branchRule)),
85
      "Then the Item does float");
86
87
88
89
    ok($branchRule->{conditionRules} =
90
        'itype =~ (KOIRA|KISSA|HAUVA) or location ne RAMPA',
91
      "Given a BranchRule using a regexp with round brackets");
92
93
    ok(Koha::FloatingMatrix::_CheckConditionalFloat(
94
           $item,
95
           Koha::FloatingMatrix::BranchRule->new($branchRule)),
96
      "Then the Item does float");
97
98
99
100
  };
101
  if ($@) { ok (0, $@); }
102
}
103
104
105
done_testing();

Return to bug 9525